Commit 8e09151a authored by fit2cloud-fengyi's avatar fit2cloud-fengyi

Merge branch 'docs' of https://github.com/jumpserver/jumpserver into docs

parents 18841d6c 3fe5dade
......@@ -19,7 +19,7 @@ from rest_framework.response import Response
from rest_framework_bulk import BulkModelViewSet
from django.utils.translation import ugettext_lazy as _
from common.utils import get_logger
from common.utils import get_logger, get_object_or_none
from ..hands import IsSuperUser
from ..models import Node
from .. import serializers
......@@ -29,6 +29,7 @@ logger = get_logger(__file__)
__all__ = [
'NodeViewSet', 'NodeChildrenApi',
'NodeAddAssetsApi', 'NodeRemoveAssetsApi',
'NodeAddChildrenApi',
]
......@@ -75,6 +76,24 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView):
return Response(response, status=200)
class NodeAddChildrenApi(generics.UpdateAPIView):
queryset = Node.objects.all()
permission_classes = (IsSuperUser,)
serializer_class = serializers.NodeAddChildrenSerializer
instance = None
def put(self, request, *args, **kwargs):
instance = self.get_object()
nodes_id = request.data.get("nodes")
children = [get_object_or_none(Node, id=pk) for pk in nodes_id]
for node in children:
if not node:
continue
node.parent = instance
node.save()
return Response("OK")
class NodeAddAssetsApi(generics.UpdateAPIView):
serializer_class = serializers.NodeAssetsSerializer
queryset = Node.objects.all()
......
......@@ -15,7 +15,7 @@ class AssetCreateForm(forms.ModelForm):
model = Asset
fields = [
'hostname', 'ip', 'public_ip', 'port', 'comment',
'nodes', 'is_active', 'admin_user', 'labels',
'nodes', 'is_active', 'admin_user', 'labels', 'platform',
]
widgets = {
......@@ -44,7 +44,7 @@ class AssetUpdateForm(forms.ModelForm):
class Meta:
model = Asset
fields = [
'hostname', 'ip', 'port', 'nodes', 'is_active',
'hostname', 'ip', 'port', 'nodes', 'is_active', 'platform',
'public_ip', 'number', 'comment', 'admin_user', 'labels',
]
widgets = {
......
......@@ -38,6 +38,14 @@ def default_node():
class Asset(models.Model):
# Important
PLATFORM_CHOICES = (
('Linux', 'Linux'),
('Unix', 'Unix'),
('MacOS', 'MacOS'),
('BSD', 'BSD'),
('Windows', 'Windows'),
('Other', 'Other'),
)
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
ip = models.GenericIPAddressField(max_length=32, verbose_name=_('IP'), db_index=True)
hostname = models.CharField(max_length=128, unique=True, verbose_name=_('Hostname'))
......@@ -64,7 +72,7 @@ class Asset(models.Model):
disk_total = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('Disk total'))
disk_info = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('Disk info'))
platform = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('Platform'))
platform = models.CharField(max_length=128, choices=PLATFORM_CHOICES, default='Linux', verbose_name=_('Platform'))
os = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('OS'))
os_version = models.CharField(max_length=16, null=True, blank=True, verbose_name=_('OS version'))
os_arch = models.CharField(max_length=16, blank=True, null=True, verbose_name=_('OS arch'))
......@@ -87,6 +95,12 @@ class Asset(models.Model):
return True, ''
return False, warning
def is_unixlike(self):
if self.platform not in ("Windows", "Other"):
return True
else:
return False
@property
def hardware_info(self):
if self.cpu_count:
......@@ -99,6 +113,8 @@ class Asset(models.Model):
@property
def is_connective(self):
if not self.is_unixlike():
return True
val = cache.get(ASSET_ADMIN_CONN_CACHE_KEY.format(self.hostname))
if val == 1:
return True
......
......@@ -61,6 +61,9 @@ class Node(models.Model):
assets = Asset.objects.filter(nodes__id=self.id)
return assets
def get_active_assets(self):
return self.get_assets().filter(is_active=True)
def get_all_assets(self):
from .asset import Asset
if self.is_root():
......@@ -70,6 +73,9 @@ class Node(models.Model):
assets = Asset.objects.filter(nodes__in=nodes)
return assets
def get_all_active_assets(self):
return self.get_all_assets().filter(is_active=True)
def is_root(self):
return self.key == '0'
......@@ -88,6 +94,10 @@ class Node(models.Model):
else:
return parent
@parent.setter
def parent(self, parent):
self.key = parent.get_next_child_key()
@property
def ancestor(self):
if self.parent == self.__class__.root():
......
......@@ -26,14 +26,14 @@ signer = get_signer()
class AssetUser(models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
name = models.CharField(max_length=128, unique=True, verbose_name=_('Name'))
username = models.CharField(max_length=16, verbose_name=_('Username'))
username = models.CharField(max_length=128, verbose_name=_('Username'))
_password = models.CharField(max_length=256, blank=True, null=True, verbose_name=_('Password'))
_private_key = models.TextField(max_length=4096, blank=True, null=True, verbose_name=_('SSH private key'), validators=[private_key_validator, ])
_public_key = models.TextField(max_length=4096, blank=True, verbose_name=_('SSH public key'))
comment = models.TextField(blank=True, verbose_name=_('Comment'))
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
created_by = models.CharField(max_length=32, null=True, verbose_name=_('Created by'))
created_by = models.CharField(max_length=128, null=True, verbose_name=_('Created by'))
@property
def password(self):
......@@ -175,15 +175,12 @@ class AdminUser(AssetUser):
return info
def get_related_assets(self):
assets = []
for cluster in self.cluster_set.all():
assets.extend(cluster.assets.all())
assets.extend(self.asset_set.all())
return list(set(assets))
assets = self.asset_set.all()
return assets
@property
def assets_amount(self):
return len(self.get_related_assets())
return self.get_related_assets().count()
class Meta:
ordering = ['name']
......
......@@ -65,4 +65,8 @@ class NodeAssetsSerializer(serializers.ModelSerializer):
class Meta:
model = Node
fields = ['assets']
\ No newline at end of file
fields = ['assets']
class NodeAddChildrenSerializer(serializers.Serializer):
nodes = serializers.ListField()
......@@ -13,7 +13,7 @@
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>{% trans 'Create system user' %}</h5>
<h5>{{ action }}</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
......@@ -81,6 +81,14 @@
{% block custom_foot_js %}
<script>
var auto_generate_key = '#'+'{{ form.auto_generate_key.id_for_label }}';
var protocol_id = '#' + '{{ form.protocol.id_for_label }}';
var password_id = '#' + '{{ form.password.id_for_label }}';
var private_key_id = '#' + '{{ form.private_key_file.id_for_label }}';
var sudo_id = '#' + '{{ form.sudo.id_for_label }}';
var shell_id = '#' + '{{ form.shell.id_for_label }}';
var need_change_field = [auto_generate_key, private_key_id, sudo_id, shell_id] ;
function authFieldsDisplay() {
if ($(auto_generate_key).prop('checked')) {
$('.auth-fields').addClass('hidden');
......@@ -88,9 +96,23 @@
$('.auth-fields').removeClass('hidden');
}
}
function protocolChange() {
if ($(protocol_id).attr('value') === 'rdp') {
$.each(need_change_field, function (index, value) {
$(value).addClass('hidden')
});
$(password_id).removeClass('hidden')
} else {
$.each(need_change_field, function (index, value) {
$(value).removeClass('hidden')
});
}
}
$(document).ready(function () {
$('.select2').select2();
authFieldsDisplay();
protocolChange();
$(auto_generate_key).change(function () {
authFieldsDisplay();
});
......
......@@ -13,7 +13,7 @@
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>{% trans 'Create admin user' %}</h5>
<h5>{{ action }}</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
......
......@@ -17,6 +17,7 @@
{% bootstrap_field form.hostname layout="horizontal" %}
{% bootstrap_field form.ip layout="horizontal" %}
{% bootstrap_field form.port layout="horizontal" %}
{% bootstrap_field form.platform layout="horizontal" %}
{% bootstrap_field form.public_ip layout="horizontal" %}
<div class="hr-line-dashed"></div>
......
......@@ -2,6 +2,12 @@
{% load static %}
{% load i18n %}
{% block help_message %}
<div class="alert alert-info help-message">
左侧是资产树,右击可以新建、删除、更改树节点,授权资产也是以节点方式组织的,右侧是属于该节点下的资产
</div>
{% endblock %}
{% block custom_head_css_js %}
<link href="{% static 'css/plugins/ztree/awesomeStyle/awesome.css' %}" rel="stylesheet">
<script type="text/javascript" src="{% static 'js/plugins/ztree/jquery.ztree.all.min.js' %}"></script>
......@@ -224,6 +230,9 @@ function editTreeNode() {
if (!current_node){
return
}
if (current_node.value) {
current_node.name = current_node.value;
}
zTree.editName(current_node);
}
......@@ -308,6 +317,42 @@ function selectQueryNode() {
}
}
function beforeDrag() {
return true
}
function beforeDrop(treeId, treeNodes, targetNode, moveType) {
var treeNodesNames = [];
$.each(treeNodes, function (index, value) {
treeNodesNames.push(value.value);
});
var msg = "你想移动节点: `" + treeNodesNames.join(",") + "` 到 `" + targetNode.value + "` 下吗?";
if (confirm(msg)){
return true
} else {
return false
}
}
function onDrag(event, treeId, treeNodes) {
}
function onDrop(event, treeId, treeNodes, targetNode, moveType) {
var treeNodesIds = [];
$.each(treeNodes, function (index, value) {
treeNodesIds.push(value.id);
});
var the_url = "{% url 'api-assets:node-add-children' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", targetNode.id);
var body = {nodes: treeNodesIds};
APIUpdateAttr({
url: the_url,
method: "PUT",
body: JSON.stringify(body)
})
}
function initTree() {
var setting = {
view: {
......@@ -319,11 +364,24 @@ function initTree() {
enable: true
}
},
edit: {
enable: true,
showRemoveBtn: false,
showRenameBtn: false,
drag: {
isCopy: true,
isMove: true
}
},
callback: {
onRightClick: OnRightClick,
beforeClick: beforeClick,
onRename: onRename,
onSelected: onSelected
onSelected: onSelected,
beforeDrag: beforeDrag,
onDrag: onDrag,
beforeDrop: beforeDrop,
onDrop: onDrop
}
};
......@@ -334,7 +392,8 @@ function initTree() {
{#if (value["key"] === "0") {#}
value["open"] = true;
{# }#}
value["name"] = value["value"] + ' (' + value['assets_amount'] + ')'
value["name"] = value["value"] + ' (' + value['assets_amount'] + ')';
value['value'] = value['value'];
});
zNodes = data;
$.fn.zTree.init($("#assetTree"), setting, zNodes);
......@@ -415,7 +474,7 @@ $(document).ready(function(){
current_node = nodes[0];
url += "?node_id=" + current_node.id;
}
window.open(url);
window.open(url, '_self');
})
.on('click', '.btn_asset_delete', function () {
var $this = $(this);
......
......@@ -22,6 +22,7 @@
{% bootstrap_field form.hostname layout="horizontal" %}
{% bootstrap_field form.ip layout="horizontal" %}
{% bootstrap_field form.port layout="horizontal" %}
{% bootstrap_field form.platform layout="horizontal" %}
{% bootstrap_field form.public_ip layout="horizontal" %}
<div class="hr-line-dashed"></div>
......
......@@ -44,6 +44,7 @@ urlpatterns = [
url(r'^v1/system-user/(?P<pk>[0-9a-zA-Z\-]{36})/connective/$',
api.SystemUserTestConnectiveApi.as_view(), name='system-user-connective'),
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/children/$', api.NodeChildrenApi.as_view(), name='node-children'),
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/children/add/$', api.NodeAddChildrenApi.as_view(), name='node-add-children'),
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/add/$', api.NodeAddAssetsApi.as_view(), name='node-add-assets'),
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/remove/$', api.NodeRemoveAssetsApi.as_view(), name='node-remove-assets'),
]
......
......@@ -58,8 +58,7 @@ class UserAssetListView(LoginRequiredMixin, TemplateView):
def get_context_data(self, **kwargs):
context = {
'app': _('Assets'),
'action': _('Asset list'),
'action': _('My assets'),
'system_users': SystemUser.objects.all(),
}
kwargs.update(context)
......@@ -248,6 +247,7 @@ class BulkImportAssetView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
f = form.cleaned_data['file']
det_result = chardet.detect(f.read())
f.seek(0) # reset file seek index
file_data = f.read().decode(det_result['encoding']).strip(codecs.BOM_UTF8.decode())
csv_file = StringIO(file_data)
reader = csv.reader(csv_file)
......
......@@ -68,10 +68,10 @@ class BaseForm(forms.Form):
class BasicSettingForm(BaseForm):
SITE_URL = forms.URLField(
label=_("Current SITE URL"),
help_text="http://jumpserver.abc.com:8080"
help_text="eg: http://jumpserver.abc.com:8080"
)
USER_GUIDE_URL = forms.URLField(
label=_("User Guide URL"),
label=_("User Guide URL"), required=False,
help_text=_("User first login update profile done redirect to it")
)
EMAIL_SUBJECT_PREFIX = forms.CharField(
......@@ -135,7 +135,7 @@ class LDAPSettingForm(BaseForm):
AUTH_LDAP_START_TLS = forms.BooleanField(
label=_("Use SSL"), initial=False, required=False
)
AUTH_LDAP = forms.BooleanField(label=_("Enable LDAP auth"), initial=False)
AUTH_LDAP = forms.BooleanField(label=_("Enable LDAP auth"), initial=False, required=False)
class TerminalSettingForm(BaseForm):
......
......@@ -99,9 +99,8 @@ class DatetimeSearchMixin:
if date_from_s:
date_from = timezone.datetime.strptime(date_from_s, self.date_format)
self.date_from = date_from.replace(
tzinfo=timezone.get_current_timezone()
)
tz = timezone.get_current_timezone()
self.date_from = tz.localize(date_from)
else:
self.date_from = timezone.now() - timezone.timedelta(7)
......
......@@ -73,17 +73,20 @@ def to_html(s):
@register.filter
def time_util_with_seconds(date_from, date_to):
if date_from and date_to:
delta = date_to - date_from
seconds = delta.seconds
if seconds < 60:
return '{} s'.format(seconds)
elif seconds < 60*60:
return '{} m'.format(seconds//60)
else:
return '{} h'.format(seconds//3600)
else:
if not date_from:
return ''
if not date_to:
return ''
date_to = timezone.now()
delta = date_to - date_from
seconds = delta.seconds
if seconds < 60:
return '{} s'.format(seconds)
elif seconds < 60*60:
return '{} m'.format(seconds//60)
else:
return '{} h'.format(seconds//3600)
@register.filter
......
......@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Jumpserver 0.3.3\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-02-26 16:54+0800\n"
"POT-Creation-Date: 2018-03-06 17:57+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: Jumpserver team<ibuler@qq.com>\n"
......@@ -17,12 +17,12 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: assets/api/node.py:54
#: assets/api/node.py:55
msgid "New node {}"
msgstr "新节点 {}"
#: assets/forms/asset.py:23 assets/forms/asset.py:52 assets/forms/user.py:125
#: assets/models/asset.py:45 assets/models/user.py:221
#: assets/models/asset.py:53 assets/models/user.py:218
#: assets/templates/assets/asset_detail.html:181
#: assets/templates/assets/asset_detail.html:189
#: assets/templates/assets/system_user_detail.html:164
......@@ -30,16 +30,16 @@ msgid "Nodes"
msgstr "节点管理"
#: assets/forms/asset.py:26 assets/forms/asset.py:55 assets/forms/asset.py:90
#: assets/forms/asset.py:94 assets/models/asset.py:49
#: assets/models/cluster.py:19 assets/models/user.py:190
#: assets/templates/assets/asset_detail.html:73 templates/_nav.html:23
#: assets/forms/asset.py:94 assets/models/asset.py:57
#: assets/models/cluster.py:19 assets/models/user.py:187
#: assets/templates/assets/asset_detail.html:73 templates/_nav.html:24
msgid "Admin user"
msgstr "管理用户"
#: assets/forms/asset.py:29 assets/forms/asset.py:58 assets/models/asset.py:73
#: assets/templates/assets/asset_create.html:31
#: assets/forms/asset.py:29 assets/forms/asset.py:58 assets/models/asset.py:81
#: assets/templates/assets/asset_create.html:32
#: assets/templates/assets/asset_detail.html:218
#: assets/templates/assets/asset_update.html:36 templates/_nav.html:25
#: assets/templates/assets/asset_update.html:37 templates/_nav.html:26
msgid "Labels"
msgstr "标签管理"
......@@ -54,7 +54,7 @@ msgstr "管理用户是资产上已经存在的特权用户,如 root或者其
msgid "Select assets"
msgstr "选择资产"
#: assets/forms/asset.py:86 assets/models/asset.py:44
#: assets/forms/asset.py:86 assets/models/asset.py:52
#: assets/templates/assets/admin_user_assets.html:53
#: assets/templates/assets/asset_detail.html:69
#: assets/templates/assets/system_user_asset.html:51
......@@ -62,7 +62,7 @@ msgstr "选择资产"
msgid "Port"
msgstr "端口"
#: assets/forms/asset.py:106 assets/templates/assets/asset_create.html:35
#: assets/forms/asset.py:106 assets/templates/assets/asset_create.html:36
msgid "Select labels"
msgstr "选择标签"
......@@ -70,11 +70,11 @@ msgstr "选择标签"
msgid "Select nodes"
msgstr "选择节点"
#: assets/forms/label.py:13 assets/models/asset.py:137
#: assets/forms/label.py:13 assets/models/asset.py:153
#: assets/templates/assets/admin_user_list.html:24
#: assets/templates/assets/label_list.html:16
#: assets/templates/assets/system_user_list.html:26 perms/models.py:17
#: terminal/backends/command/models.py:11 terminal/models.py:116
#: terminal/backends/command/models.py:11 terminal/models.py:123
#: terminal/templates/terminal/command_list.html:40
#: terminal/templates/terminal/command_list.html:73
#: terminal/templates/terminal/session_list.html:41
......@@ -84,10 +84,10 @@ msgstr "资产"
#: assets/forms/user.py:24
msgid "Password or private key passphrase"
msgstr "密码或钥密码"
msgstr "密码或钥密码"
#: assets/forms/user.py:25 assets/models/user.py:30 common/forms.py:113
#: users/forms.py:16 users/forms.py:24 users/templates/users/login.html:56
#: users/forms.py:16 users/forms.py:24 users/templates/users/login.html:59
#: users/templates/users/reset_password.html:52
#: users/templates/users/user_create.html:11
#: users/templates/users/user_password_update.html:40
......@@ -116,11 +116,11 @@ msgstr "密码和私钥, 必须输入一个"
#: assets/templates/assets/system_user_detail.html:58
#: assets/templates/assets/system_user_list.html:24 common/models.py:26
#: common/templates/common/terminal_setting.html:67
#: common/templates/common/terminal_setting.html:88 ops/models.py:31
#: common/templates/common/terminal_setting.html:85 ops/models.py:31
#: ops/templates/ops/task_detail.html:56 ops/templates/ops/task_list.html:34
#: perms/models.py:14 perms/templates/perms/asset_permission_detail.html:62
#: perms/templates/perms/asset_permission_user.html:54 terminal/models.py:15
#: terminal/models.py:141 terminal/templates/terminal/terminal_detail.html:43
#: perms/templates/perms/asset_permission_user.html:54 terminal/models.py:16
#: terminal/models.py:149 terminal/templates/terminal/terminal_detail.html:43
#: terminal/templates/terminal/terminal_list.html:29 users/models/group.py:14
#: users/models/user.py:35 users/templates/users/_select_user_modal.html:13
#: users/templates/users/user_detail.html:63
......@@ -138,9 +138,9 @@ msgstr "名称"
#: assets/templates/assets/system_user_detail.html:62
#: assets/templates/assets/system_user_list.html:25
#: perms/templates/perms/asset_permission_user.html:55 users/forms.py:14
#: users/models/authentication.py:44 users/models/user.py:34
#: users/models/authentication.py:45 users/models/user.py:34
#: users/templates/users/_select_user_modal.html:14
#: users/templates/users/login.html:53
#: users/templates/users/login.html:56
#: users/templates/users/login_log_list.html:49
#: users/templates/users/user_detail.html:67
#: users/templates/users/user_list.html:24
......@@ -162,10 +162,10 @@ msgid ""
"than 2 system user"
msgstr "高优先级的系统用户将会作为默认登录用户"
#: assets/models/asset.py:42 assets/templates/assets/_asset_list_modal.html:21
#: assets/models/asset.py:50 assets/templates/assets/_asset_list_modal.html:21
#: assets/templates/assets/admin_user_assets.html:52
#: assets/templates/assets/asset_detail.html:61
#: assets/templates/assets/asset_list.html:81
#: assets/templates/assets/asset_list.html:87
#: assets/templates/assets/system_user_asset.html:50
#: assets/templates/assets/user_asset_list.html:20 common/forms.py:144
#: perms/templates/perms/asset_permission_asset.html:55
......@@ -175,10 +175,10 @@ msgstr "高优先级的系统用户将会作为默认登录用户"
msgid "IP"
msgstr "IP"
#: assets/models/asset.py:43 assets/templates/assets/_asset_list_modal.html:20
#: assets/models/asset.py:51 assets/templates/assets/_asset_list_modal.html:20
#: assets/templates/assets/admin_user_assets.html:51
#: assets/templates/assets/asset_detail.html:57
#: assets/templates/assets/asset_list.html:80
#: assets/templates/assets/asset_list.html:86
#: assets/templates/assets/system_user_asset.html:49
#: assets/templates/assets/user_asset_list.html:19 common/forms.py:143
#: perms/templates/perms/asset_permission_asset.html:54
......@@ -187,77 +187,77 @@ msgstr "IP"
msgid "Hostname"
msgstr "主机名"
#: assets/models/asset.py:46 assets/models/label.py:20
#: assets/models/asset.py:54 assets/models/label.py:20
#: assets/templates/assets/asset_detail.html:105
#: perms/templates/perms/asset_permission_list.html:70
msgid "Is active"
msgstr "激活"
#: assets/models/asset.py:52 assets/templates/assets/asset_detail.html:65
#: assets/models/asset.py:60 assets/templates/assets/asset_detail.html:65
msgid "Public IP"
msgstr "公网IP"
#: assets/models/asset.py:53 assets/templates/assets/asset_detail.html:113
#: assets/models/asset.py:61 assets/templates/assets/asset_detail.html:113
msgid "Asset number"
msgstr "资产编号"
#: assets/models/asset.py:56 assets/templates/assets/asset_detail.html:77
#: assets/models/asset.py:64 assets/templates/assets/asset_detail.html:77
msgid "Vendor"
msgstr "制造商"
#: assets/models/asset.py:57 assets/templates/assets/asset_detail.html:81
#: assets/models/asset.py:65 assets/templates/assets/asset_detail.html:81
msgid "Model"
msgstr "型号"
#: assets/models/asset.py:58 assets/templates/assets/asset_detail.html:109
#: assets/models/asset.py:66 assets/templates/assets/asset_detail.html:109
msgid "Serial number"
msgstr "序列号"
#: assets/models/asset.py:60
#: assets/models/asset.py:68
msgid "CPU model"
msgstr "CPU型号"
#: assets/models/asset.py:61
#: assets/models/asset.py:69
msgid "CPU count"
msgstr "CPU数量"
#: assets/models/asset.py:62
#: assets/models/asset.py:70
msgid "CPU cores"
msgstr "CPU核数"
#: assets/models/asset.py:63 assets/templates/assets/asset_detail.html:89
#: assets/models/asset.py:71 assets/templates/assets/asset_detail.html:89
msgid "Memory"
msgstr "内存"
#: assets/models/asset.py:64
#: assets/models/asset.py:72
msgid "Disk total"
msgstr "硬盘大小"
#: assets/models/asset.py:65
#: assets/models/asset.py:73
msgid "Disk info"
msgstr "硬盘信息"
#: assets/models/asset.py:67 assets/templates/assets/asset_detail.html:97
#: assets/models/asset.py:75 assets/templates/assets/asset_detail.html:97
msgid "Platform"
msgstr "系统平台"
#: assets/models/asset.py:68 assets/templates/assets/asset_detail.html:101
#: assets/models/asset.py:76 assets/templates/assets/asset_detail.html:101
msgid "OS"
msgstr "操作系统"
#: assets/models/asset.py:69
#: assets/models/asset.py:77
msgid "OS version"
msgstr "系统版本"
#: assets/models/asset.py:70
#: assets/models/asset.py:78
msgid "OS arch"
msgstr "系统架构"
#: assets/models/asset.py:71
#: assets/models/asset.py:79
msgid "Hostname raw"
msgstr "主机名原始"
#: assets/models/asset.py:74 assets/models/cluster.py:28
#: assets/models/asset.py:82 assets/models/cluster.py:28
#: assets/models/group.py:21 assets/models/user.py:36
#: assets/templates/assets/admin_user_detail.html:68
#: assets/templates/assets/asset_detail.html:117
......@@ -268,7 +268,7 @@ msgstr "主机名原始"
msgid "Created by"
msgstr "创建者"
#: assets/models/asset.py:75 assets/models/cluster.py:26
#: assets/models/asset.py:83 assets/models/cluster.py:26
#: assets/models/group.py:22 assets/models/label.py:23
#: assets/templates/assets/admin_user_detail.html:64
#: assets/templates/assets/system_user_detail.html:92
......@@ -280,7 +280,7 @@ msgstr "创建者"
msgid "Date created"
msgstr "创建日期"
#: assets/models/asset.py:76 assets/models/cluster.py:29
#: assets/models/asset.py:84 assets/models/cluster.py:29
#: assets/models/group.py:23 assets/models/label.py:21 assets/models/user.py:33
#: assets/templates/assets/admin_user_detail.html:72
#: assets/templates/assets/admin_user_list.html:28
......@@ -288,7 +288,7 @@ msgstr "创建日期"
#: assets/templates/assets/system_user_detail.html:100
#: assets/templates/assets/system_user_list.html:30 common/models.py:30
#: ops/models.py:37 perms/models.py:24 perms/models.py:81
#: perms/templates/perms/asset_permission_detail.html:98 terminal/models.py:25
#: perms/templates/perms/asset_permission_detail.html:98 terminal/models.py:26
#: terminal/templates/terminal/terminal_detail.html:63 users/models/group.py:15
#: users/models/user.py:47 users/templates/users/user_detail.html:111
#: users/templates/users/user_group_detail.html:67
......@@ -331,7 +331,7 @@ msgid "Default"
msgstr "默认"
#: assets/models/cluster.py:36 assets/models/label.py:13
#: users/models/user.py:261
#: users/models/user.py:266
msgid "System"
msgstr "系统"
......@@ -352,13 +352,14 @@ msgid "Default asset group"
msgstr "默认资产组"
#: assets/models/label.py:14 perms/models.py:15
#: terminal/backends/command/models.py:10 terminal/models.py:115
#: terminal/backends/command/models.py:10 terminal/models.py:122
#: terminal/templates/terminal/command_list.html:32
#: terminal/templates/terminal/command_list.html:72
#: terminal/templates/terminal/session_list.html:33
#: terminal/templates/terminal/session_list.html:71 users/forms.py:190
#: users/models/user.py:30 users/templates/users/user_group_detail.html:78
#: users/templates/users/user_group_list.html:13 users/views/user.py:330
#: users/models/user.py:30 users/models/user.py:254
#: users/templates/users/user_group_detail.html:78
#: users/templates/users/user_group_list.html:13 users/views/user.py:333
msgid "User"
msgstr "用户"
......@@ -383,32 +384,32 @@ msgstr "ssh密钥"
msgid "SSH public key"
msgstr "ssh公钥"
#: assets/models/user.py:222
#: assets/models/user.py:219
msgid "Priority"
msgstr "优先级"
#: assets/models/user.py:223 assets/templates/assets/system_user_detail.html:66
#: assets/models/user.py:220 assets/templates/assets/system_user_detail.html:66
msgid "Protocol"
msgstr "协议"
#: assets/models/user.py:224 assets/templates/assets/_system_user.html:58
#: assets/models/user.py:221 assets/templates/assets/_system_user.html:58
#: assets/templates/assets/system_user_detail.html:118
#: assets/templates/assets/system_user_update.html:11
msgid "Auto push"
msgstr "自动推送"
#: assets/models/user.py:225 assets/templates/assets/system_user_detail.html:70
#: assets/models/user.py:222 assets/templates/assets/system_user_detail.html:70
msgid "Sudo"
msgstr "Sudo"
#: assets/models/user.py:226 assets/templates/assets/system_user_detail.html:75
#: assets/models/user.py:223 assets/templates/assets/system_user_detail.html:75
msgid "Shell"
msgstr "Shell"
#: assets/models/user.py:269 perms/forms.py:25 perms/models.py:19
#: assets/models/user.py:266 perms/forms.py:25 perms/models.py:19
#: perms/models.py:76 perms/templates/perms/asset_permission_detail.html:136
#: perms/templates/perms/asset_permission_list.html:69 templates/_nav.html:24
#: terminal/backends/command/models.py:12 terminal/models.py:117
#: perms/templates/perms/asset_permission_list.html:69 templates/_nav.html:25
#: terminal/backends/command/models.py:12 terminal/models.py:124
#: terminal/templates/terminal/command_list.html:48
#: terminal/templates/terminal/command_list.html:74
#: terminal/templates/terminal/session_list.html:49
......@@ -463,7 +464,7 @@ msgstr "推送系统用户到节点: {}"
#: assets/templates/assets/_asset_group_bulk_update_modal.html:5
msgid "Update asset group"
msgstr "编辑用户组"
msgstr "更新用户组"
#: assets/templates/assets/_asset_group_bulk_update_modal.html:8
msgid "Hint: only change the field you want to update."
......@@ -474,12 +475,11 @@ msgstr "仅修改你需要更新的字段"
#: assets/views/admin_user.py:29 assets/views/admin_user.py:47
#: assets/views/admin_user.py:63 assets/views/admin_user.py:78
#: assets/views/admin_user.py:102 assets/views/asset.py:48
#: assets/views/asset.py:61 assets/views/asset.py:95 assets/views/asset.py:155
#: assets/views/asset.py:172 assets/views/asset.py:196 assets/views/label.py:26
#: assets/views/label.py:42 assets/views/label.py:58
#: assets/views/system_user.py:28 assets/views/system_user.py:44
#: assets/views/system_user.py:60 assets/views/system_user.py:74
#: templates/_nav.html:19
#: assets/views/asset.py:94 assets/views/asset.py:154 assets/views/asset.py:171
#: assets/views/asset.py:195 assets/views/label.py:26 assets/views/label.py:42
#: assets/views/label.py:58 assets/views/system_user.py:28
#: assets/views/system_user.py:44 assets/views/system_user.py:60
#: assets/views/system_user.py:74 templates/_nav.html:20
msgid "Assets"
msgstr "资产管理"
......@@ -522,14 +522,14 @@ msgid "If set id, will use this id update asset existed"
msgstr "如果设置了id,则会使用该行信息更新该id的资产"
#: assets/templates/assets/_asset_list_modal.html:22
#: assets/templates/assets/asset_list.html:82
#: assets/templates/assets/asset_list.html:88
#: assets/templates/assets/user_asset_list.html:22
msgid "Hardware"
msgstr "硬件"
#: assets/templates/assets/_asset_list_modal.html:23
#: assets/templates/assets/asset_detail.html:143
#: assets/templates/assets/asset_list.html:83
#: assets/templates/assets/asset_list.html:89
#: assets/templates/assets/user_asset_list.html:23 perms/models.py:20
#: perms/models.py:77
#: perms/templates/perms/asset_permission_create_update.html:51
......@@ -548,7 +548,7 @@ msgstr "激活中"
#: assets/templates/assets/admin_user_assets.html:54
#: assets/templates/assets/admin_user_list.html:25
#: assets/templates/assets/asset_detail.html:357
#: assets/templates/assets/asset_list.html:84
#: assets/templates/assets/asset_list.html:90
#: assets/templates/assets/system_user_asset.html:52
#: assets/templates/assets/system_user_list.html:27
#: users/templates/users/user_granted_asset.html:47
......@@ -558,13 +558,13 @@ msgstr "可连接"
#: assets/templates/assets/_asset_list_modal.html:25
#: assets/templates/assets/admin_user_list.html:29
#: assets/templates/assets/asset_list.html:85
#: assets/templates/assets/asset_list.html:91
#: assets/templates/assets/label_list.html:17
#: assets/templates/assets/system_user_list.html:31
#: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:61
#: ops/templates/ops/task_history.html:62 ops/templates/ops/task_list.html:41
#: perms/templates/perms/asset_permission_list.html:72
#: terminal/templates/terminal/session_list.html:79
#: terminal/templates/terminal/session_list.html:80
#: terminal/templates/terminal/terminal_list.html:36
#: users/templates/users/user_group_list.html:15
#: users/templates/users/user_list.html:28
......@@ -572,25 +572,25 @@ msgid "Action"
msgstr "动作"
#: assets/templates/assets/_asset_list_modal.html:34
#: assets/templates/assets/asset_list.html:94
#: assets/templates/assets/asset_list.html:100
#: users/templates/users/user_list.html:37
msgid "Delete selected"
msgstr "批量删除"
#: assets/templates/assets/_asset_list_modal.html:35
#: assets/templates/assets/asset_list.html:95
#: assets/templates/assets/asset_list.html:101
#: users/templates/users/user_list.html:38
msgid "Update selected"
msgstr "批量更新"
#: assets/templates/assets/_asset_list_modal.html:36
#: assets/templates/assets/asset_list.html:97
#: assets/templates/assets/asset_list.html:103
#: users/templates/users/user_list.html:39
msgid "Deactive selected"
msgstr "禁用所选"
#: assets/templates/assets/_asset_list_modal.html:37
#: assets/templates/assets/asset_list.html:98
#: assets/templates/assets/asset_list.html:104
#: users/templates/users/user_list.html:40
msgid "Active selected"
msgstr "激活所选"
......@@ -599,16 +599,17 @@ msgstr "激活所选"
#: assets/templates/assets/_system_user.html:71
#: assets/templates/assets/admin_user_create_update.html:46
#: assets/templates/assets/asset_bulk_update.html:24
#: assets/templates/assets/asset_create.html:65
#: assets/templates/assets/asset_list.html:102
#: assets/templates/assets/asset_update.html:69
#: assets/templates/assets/asset_create.html:66
#: assets/templates/assets/asset_list.html:108
#: assets/templates/assets/asset_update.html:70
#: assets/templates/assets/label_create_update.html:17
#: common/templates/common/basic_setting.html:59
#: common/templates/common/email_setting.html:60
#: common/templates/common/ldap_setting.html:60
#: common/templates/common/terminal_setting.html:108
#: common/templates/common/terminal_setting.html:103
#: perms/templates/perms/asset_permission_create_update.html:72
#: terminal/templates/terminal/terminal_update.html:47
#: terminal/templates/terminal/session_list.html:120
#: terminal/templates/terminal/terminal_update.html:48
#: users/templates/users/_user.html:44
#: users/templates/users/first_login.html:62
#: users/templates/users/forgot_password.html:44
......@@ -624,7 +625,7 @@ msgstr "提交"
#: assets/templates/assets/admin_user_detail.html:24
#: assets/templates/assets/admin_user_list.html:84
#: assets/templates/assets/asset_detail.html:24
#: assets/templates/assets/asset_list.html:160
#: assets/templates/assets/asset_list.html:166
#: assets/templates/assets/label_list.html:38
#: assets/templates/assets/system_user_detail.html:26
#: assets/templates/assets/system_user_list.html:85
......@@ -643,7 +644,7 @@ msgstr "更新"
#: assets/templates/assets/admin_user_detail.html:28
#: assets/templates/assets/admin_user_list.html:85
#: assets/templates/assets/asset_detail.html:28
#: assets/templates/assets/asset_list.html:161
#: assets/templates/assets/asset_list.html:167
#: assets/templates/assets/label_list.html:39
#: assets/templates/assets/system_user_detail.html:30
#: assets/templates/assets/system_user_list.html:86
......@@ -673,8 +674,8 @@ msgid "Basic"
msgstr "基本"
#: assets/templates/assets/_system_user.html:44
#: assets/templates/assets/asset_create.html:23
#: assets/templates/assets/asset_update.html:28
#: assets/templates/assets/asset_create.html:24
#: assets/templates/assets/asset_update.html:29
#: assets/templates/assets/system_user_update.html:7
#: users/templates/users/user_create.html:9
#: users/templates/users/user_update.html:6
......@@ -683,28 +684,28 @@ msgstr "认证"
#: assets/templates/assets/_system_user.html:47
msgid "Auto generate key"
msgstr "自动生成钥"
msgstr "自动生成钥"
#: assets/templates/assets/_system_user.html:64
#: assets/templates/assets/asset_create.html:57
#: assets/templates/assets/asset_update.html:61
#: assets/templates/assets/asset_create.html:58
#: assets/templates/assets/asset_update.html:62
#: perms/templates/perms/asset_permission_create_update.html:49
#: terminal/templates/terminal/terminal_update.html:41
#: terminal/templates/terminal/terminal_update.html:42
msgid "Other"
msgstr "其它"
#: assets/templates/assets/_system_user.html:70
#: assets/templates/assets/admin_user_create_update.html:45
#: assets/templates/assets/asset_bulk_update.html:23
#: assets/templates/assets/asset_create.html:64
#: assets/templates/assets/asset_update.html:68
#: assets/templates/assets/asset_create.html:65
#: assets/templates/assets/asset_update.html:69
#: assets/templates/assets/label_create_update.html:16
#: common/templates/common/basic_setting.html:58
#: common/templates/common/email_setting.html:59
#: common/templates/common/ldap_setting.html:59
#: common/templates/common/terminal_setting.html:106
#: common/templates/common/terminal_setting.html:101
#: perms/templates/perms/asset_permission_create_update.html:71
#: terminal/templates/terminal/terminal_update.html:46
#: terminal/templates/terminal/terminal_update.html:47
#: users/templates/users/_user.html:43
#: users/templates/users/user_bulk_update.html:23
#: users/templates/users/user_password_update.html:58
......@@ -773,7 +774,7 @@ msgstr "替换资产的管理员"
#: assets/templates/assets/admin_user_detail.html:100
#: assets/templates/assets/asset_detail.html:198
#: assets/templates/assets/asset_list.html:482
#: assets/templates/assets/asset_list.html:541
#: assets/templates/assets/system_user_detail.html:181
#: assets/templates/assets/system_user_list.html:135 templates/_modal.html:16
#: terminal/templates/terminal/session_detail.html:108
......@@ -799,20 +800,20 @@ msgstr "不可达"
msgid "Ratio"
msgstr "比例"
#: assets/templates/assets/asset_create.html:27
#: assets/templates/assets/asset_update.html:32 perms/models.py:74
#: assets/templates/assets/asset_create.html:28
#: assets/templates/assets/asset_update.html:33 perms/models.py:74
#: perms/templates/perms/asset_permission_create_update.html:40
#: perms/templates/perms/asset_permission_list.html:67
msgid "Node"
msgstr "节点"
#: assets/templates/assets/asset_create.html:33
#: assets/templates/assets/asset_list.html:69
#: assets/templates/assets/asset_update.html:38
#: assets/templates/assets/asset_create.html:34
#: assets/templates/assets/asset_list.html:75
#: assets/templates/assets/asset_update.html:39
msgid "Label"
msgstr "标签"
#: assets/templates/assets/asset_detail.html:20 assets/views/asset.py:197
#: assets/templates/assets/asset_detail.html:20 assets/views/asset.py:196
msgid "Asset detail"
msgstr "资产详情"
......@@ -850,50 +851,50 @@ msgstr "刷新"
msgid "Update successfully!"
msgstr "更新成功"
#: assets/templates/assets/asset_list.html:57
#: assets/templates/assets/asset_list.html:114 assets/views/asset.py:96
#: assets/templates/assets/asset_list.html:63
#: assets/templates/assets/asset_list.html:120 assets/views/asset.py:95
msgid "Create asset"
msgstr "创建资产"
#: assets/templates/assets/asset_list.html:61
#: assets/templates/assets/asset_list.html:67
#: users/templates/users/user_list.html:7
msgid "Import"
msgstr "导入"
#: assets/templates/assets/asset_list.html:64
#: assets/templates/assets/asset_list.html:70
#: users/templates/users/user_list.html:10
msgid "Export"
msgstr "导出"
#: assets/templates/assets/asset_list.html:96
#: assets/templates/assets/asset_list.html:102
msgid "Remove from this node"
msgstr "从节点移除"
#: assets/templates/assets/asset_list.html:115
#: assets/templates/assets/asset_list.html:121
msgid "Add asset"
msgstr "添加资产到节点"
#: assets/templates/assets/asset_list.html:117
#: assets/templates/assets/asset_list.html:123
msgid "Add node"
msgstr "新建节点"
#: assets/templates/assets/asset_list.html:118
#: assets/templates/assets/asset_list.html:124
msgid "Rename node"
msgstr "重命名节点"
#: assets/templates/assets/asset_list.html:120
#: assets/templates/assets/asset_list.html:126
msgid "Delete node"
msgstr "删除节点"
#: assets/templates/assets/asset_list.html:195
#: assets/templates/assets/asset_list.html:201
msgid "Create node failed"
msgstr "创建节点失败"
#: assets/templates/assets/asset_list.html:208
#: assets/templates/assets/asset_list.html:214
msgid "Have child node, cancel"
msgstr "存在子节点,不能删除"
#: assets/templates/assets/asset_list.html:477
#: assets/templates/assets/asset_list.html:536
#: assets/templates/assets/system_user_list.html:130
#: users/templates/users/user_detail.html:334
#: users/templates/users/user_detail.html:359
......@@ -902,24 +903,24 @@ msgstr "存在子节点,不能删除"
msgid "Are you sure?"
msgstr "你确认吗?"
#: assets/templates/assets/asset_list.html:478
#: assets/templates/assets/asset_list.html:537
msgid "This will delete the selected assets !!!"
msgstr "删除选择资产"
#: assets/templates/assets/asset_list.html:486
#: assets/templates/assets/asset_list.html:545
msgid "Asset Deleted."
msgstr "已被删除"
#: assets/templates/assets/asset_list.html:487
#: assets/templates/assets/asset_list.html:492
#: assets/templates/assets/asset_list.html:546
#: assets/templates/assets/asset_list.html:551
msgid "Asset Delete"
msgstr "删除"
#: assets/templates/assets/asset_list.html:491
#: assets/templates/assets/asset_list.html:550
msgid "Asset Deleting failed."
msgstr "删除失败"
#: assets/templates/assets/asset_update.html:57
#: assets/templates/assets/asset_update.html:58
msgid "Configuration"
msgstr "配置"
......@@ -1011,17 +1012,21 @@ msgstr "更新管理用户"
msgid "Admin user detail"
msgstr "管理用户详情"
#: assets/views/asset.py:49 assets/views/asset.py:62 templates/_nav.html:22
#: assets/views/asset.py:49 templates/_nav.html:23
msgid "Asset list"
msgstr "资产列表"
#: assets/views/asset.py:156
#: assets/views/asset.py:61 templates/_nav_user.html:4
msgid "My assets"
msgstr "我的资产"
#: assets/views/asset.py:155
msgid "Bulk update asset"
msgstr "批量更新资产"
#: assets/views/asset.py:173
#: assets/views/asset.py:172
msgid "Update asset"
msgstr "编辑资产"
msgstr "更新资产"
#: assets/views/asset.py:296
msgid "already exists"
......@@ -1033,7 +1038,7 @@ msgstr "标签列表"
#: assets/views/label.py:59
msgid "Update label"
msgstr "编辑标签"
msgstr "更新标签"
#: assets/views/system_user.py:29
msgid "System user list"
......@@ -1192,10 +1197,10 @@ msgstr "密码认证"
#: common/forms.py:156
msgid "Public key auth"
msgstr "钥认证"
msgstr "钥认证"
#: common/forms.py:159 common/templates/common/terminal_setting.html:63
#: terminal/forms.py:21 terminal/models.py:19
#: terminal/forms.py:30 terminal/models.py:20
msgid "Command storage"
msgstr "命令存储"
......@@ -1205,8 +1210,8 @@ msgid ""
"other storage and some terminal using"
msgstr "设置终端命令存储,default是默认用的存储方式"
#: common/forms.py:165 common/templates/common/terminal_setting.html:84
#: terminal/models.py:20
#: common/forms.py:165 common/templates/common/terminal_setting.html:81
#: terminal/forms.py:34 terminal/models.py:21
msgid "Replay storage"
msgstr "录像存储"
......@@ -1263,19 +1268,13 @@ msgid "Test connection"
msgstr "测试连接"
#: common/templates/common/terminal_setting.html:68
#: common/templates/common/terminal_setting.html:89
#: common/templates/common/terminal_setting.html:86
#: users/templates/users/login_log_list.html:50
msgid "Type"
msgstr "类型"
#: common/templates/common/terminal_setting.html:90
#: users/templates/users/reset_password.html:57
#: users/templates/users/user_profile.html:20
msgid "Setting"
msgstr "设置"
#: common/views.py:20 common/views.py:46 common/views.py:72 common/views.py:102
#: templates/_nav.html:66
#: templates/_nav.html:72
msgid "Settings"
msgstr "系统设置"
......@@ -1430,7 +1429,7 @@ msgstr "执行历史"
#: ops/templates/ops/adhoc_history.html:52
#: ops/templates/ops/adhoc_history_detail.html:58
#: ops/templates/ops/task_history.html:55 terminal/models.py:124
#: ops/templates/ops/task_history.html:55 terminal/models.py:132
#: terminal/templates/terminal/session_list.html:77
msgid "Date start"
msgstr "开始日期"
......@@ -1542,7 +1541,7 @@ msgstr "任务开始: "
msgid "Ops"
msgstr "作业中心"
#: ops/views.py:37 templates/_nav.html:52
#: ops/views.py:37 templates/_nav.html:58
msgid "Task list"
msgstr "任务列表"
......@@ -1551,8 +1550,9 @@ msgid "Task run history"
msgstr "执行历史"
#: perms/forms.py:22 perms/models.py:16 perms/models.py:75
#: perms/templates/perms/asset_permission_list.html:68 templates/_nav.html:13
#: users/models/user.py:37 users/templates/users/_select_user_modal.html:16
#: perms/templates/perms/asset_permission_list.html:68 templates/_nav.html:14
#: users/models/group.py:25 users/models/user.py:37
#: users/templates/users/_select_user_modal.html:16
#: users/templates/users/user_detail.html:179
#: users/templates/users/user_list.html:26
msgid "User group"
......@@ -1566,7 +1566,7 @@ msgstr "用户组"
msgid "Date expired"
msgstr "失效日期"
#: perms/models.py:88 templates/_nav.html:32
#: perms/models.py:88 templates/_nav.html:33
msgid "Asset permission"
msgstr "资产授权"
......@@ -1660,7 +1660,7 @@ msgstr "添加用户组"
msgid "Select user groups"
msgstr "选择用户组"
#: perms/views.py:23 perms/views.py:47 perms/views.py:67 templates/_nav.html:29
#: perms/views.py:23 perms/views.py:47 perms/views.py:67 templates/_nav.html:30
msgid "Perms"
msgstr "权限管理"
......@@ -1677,37 +1677,41 @@ msgid "Update asset permission"
msgstr "更新资产授权"
#: templates/_header_bar.html:18
msgid "Help"
msgstr "帮助"
msgid "Supports"
msgstr "商业支持"
#: templates/_header_bar.html:23
msgid "Docs"
msgstr "文档"
#: templates/_header_bar.html:32 templates/_nav_user.html:9
#: templates/_header_bar.html:37 templates/_nav_user.html:9
#: users/templates/users/_user.html:36
#: users/templates/users/user_password_update.html:37
#: users/templates/users/user_profile.html:17
#: users/templates/users/user_profile_update.html:37
#: users/templates/users/user_profile_update.html:57
#: users/templates/users/user_pubkey_update.html:37 users/views/user.py:313
#: users/templates/users/user_pubkey_update.html:37 users/views/user.py:316
msgid "Profile"
msgstr "个人信息"
#: templates/_header_bar.html:36
#: templates/_header_bar.html:40
msgid "Admin page"
msgstr "管理页面"
#: templates/_header_bar.html:38
#: templates/_header_bar.html:42
msgid "User page"
msgstr "用户页面"
#: templates/_header_bar.html:41
#: templates/_header_bar.html:45
msgid "Logout"
msgstr "注销登录"
#: templates/_header_bar.html:45 users/templates/users/login.html:42
#: users/templates/users/login.html:61
#: templates/_header_bar.html:49 users/templates/users/login.html:44
#: users/templates/users/login.html:64
msgid "Login"
msgstr "登录"
#: templates/_header_bar.html:58 templates/_nav.html:4
#: templates/_header_bar.html:62 templates/_nav.html:4
msgid "Dashboard"
msgstr "仪表盘"
......@@ -1733,7 +1737,7 @@ msgid ""
" "
msgstr ""
"\n"
" 您的ssh钥没有设置或已失效,请点击 <a href="
" 您的ssh钥没有设置或已失效,请点击 <a href="
"\"%(user_pubkey_update)s\"> 链接 </a> 更新\n"
" "
......@@ -1741,39 +1745,43 @@ msgstr ""
msgid "Close"
msgstr "关闭"
#: templates/_nav.html:9 users/views/group.py:28 users/views/group.py:44
#: users/views/group.py:62 users/views/group.py:79 users/views/login.py:200
#: users/views/login.py:249 users/views/user.py:57 users/views/user.py:72
#: users/views/user.py:91 users/views/user.py:147 users/views/user.py:300
#: users/views/user.py:312 users/views/user.py:348 users/views/user.py:370
#: templates/_nav.html:10 users/views/group.py:28 users/views/group.py:44
#: users/views/group.py:62 users/views/group.py:79 users/views/group.py:95
#: users/views/login.py:209 users/views/login.py:258 users/views/user.py:59
#: users/views/user.py:74 users/views/user.py:93 users/views/user.py:149
#: users/views/user.py:304 users/views/user.py:351 users/views/user.py:373
msgid "Users"
msgstr "用户管理"
#: templates/_nav.html:12 users/views/user.py:58
#: templates/_nav.html:13 users/views/user.py:60
msgid "User list"
msgstr "用户列表"
#: templates/_nav.html:14
#: templates/_nav.html:15
msgid "Login logs"
msgstr "登录日志"
#: templates/_nav.html:38
#: templates/_nav.html:39
msgid "Sessions"
msgstr "会话管理"
#: templates/_nav.html:41
#: templates/_nav.html:42
msgid "Session online"
msgstr "在线会话"
#: templates/_nav.html:42
#: templates/_nav.html:43
msgid "Session offline"
msgstr "历史会话"
#: templates/_nav.html:43
#: templates/_nav.html:44
msgid "Commands"
msgstr "命令记录"
#: templates/_nav.html:44 terminal/templates/terminal/session_list.html:75
#: templates/_nav.html:47 templates/_nav_user.html:14
msgid "Web terminal"
msgstr "Web终端"
#: templates/_nav.html:50 terminal/templates/terminal/session_list.html:75
#: terminal/views/command.py:47 terminal/views/session.py:75
#: terminal/views/session.py:92 terminal/views/session.py:114
#: terminal/views/terminal.py:31 terminal/views/terminal.py:46
......@@ -1781,18 +1789,10 @@ msgstr "命令记录"
msgid "Terminal"
msgstr "终端管理"
#: templates/_nav.html:49
#: templates/_nav.html:55
msgid "Job Center"
msgstr "作业中心"
#: templates/_nav_user.html:4
msgid "My assets"
msgstr "我的资产"
#: templates/_nav_user.html:14
msgid "Web terminal"
msgstr "Web终端"
#: templates/captcha/image.html:3
msgid "Play CAPTCHA as audio file"
msgstr "语言播放验证码"
......@@ -1819,71 +1819,75 @@ msgstr "输出"
msgid "Session"
msgstr "会话"
#: terminal/forms.py:27
#: terminal/forms.py:44
msgid "Coco ssh listen port"
msgstr "SSH 监听端口"
#: terminal/forms.py:28
#: terminal/forms.py:45
msgid "Coco http/ws listen port"
msgstr "Http/Websocket 监听端口"
#: terminal/models.py:16
#: terminal/models.py:17
msgid "Remote Address"
msgstr "远端地址"
#: terminal/models.py:17
#: terminal/models.py:18
msgid "SSH Port"
msgstr "SSH端口"
#: terminal/models.py:18
#: terminal/models.py:19
msgid "HTTP Port"
msgstr "HTTP端口"
#: terminal/models.py:91
#: terminal/models.py:98
msgid "Session Online"
msgstr "在线会话"
#: terminal/models.py:92
#: terminal/models.py:99
msgid "CPU Usage"
msgstr "CPU使用"
#: terminal/models.py:93
#: terminal/models.py:100
msgid "Memory Used"
msgstr "内存使用"
#: terminal/models.py:94
#: terminal/models.py:101
msgid "Connections"
msgstr "连接数"
#: terminal/models.py:95
#: terminal/models.py:102
msgid "Threads"
msgstr "线程数"
#: terminal/models.py:96
#: terminal/models.py:103
msgid "Boot Time"
msgstr "运行时间"
#: terminal/models.py:119 terminal/templates/terminal/session_list.html:74
#: terminal/models.py:126 terminal/templates/terminal/session_list.html:74
#: terminal/templates/terminal/terminal_detail.html:47
msgid "Remote addr"
msgstr "远端地址"
#: terminal/models.py:121 terminal/templates/terminal/session_list.html:100
#: terminal/models.py:128 terminal/templates/terminal/session_list.html:102
msgid "Replay"
msgstr "回放"
#: terminal/models.py:122 terminal/templates/terminal/command_list.html:55
#: terminal/models.py:129 terminal/templates/terminal/command_list.html:55
#: terminal/templates/terminal/command_list.html:71
#: terminal/templates/terminal/session_detail.html:48
#: terminal/templates/terminal/session_list.html:76
msgid "Command"
msgstr "命令"
#: terminal/models.py:125
#: terminal/models.py:131
msgid "Date last active"
msgstr "最后活跃日期"
#: terminal/models.py:133
msgid "Date end"
msgstr "结束日期"
#: terminal/models.py:142
#: terminal/models.py:150
msgid "Args"
msgstr "参数"
......@@ -1922,19 +1926,25 @@ msgstr "监控"
msgid "Terminate session"
msgstr "终止会话"
#: terminal/templates/terminal/session_list.html:78
#: terminal/templates/terminal/session_list.html:79
msgid "Duration"
msgstr "时长"
#: terminal/templates/terminal/session_list.html:102
#: terminal/templates/terminal/session_list.html:104
msgid "Monitor"
msgstr "监控"
#: terminal/templates/terminal/session_list.html:103
#: terminal/templates/terminal/session_list.html:105
msgid "Terminate"
msgstr "终断"
#: terminal/templates/terminal/session_list.html:119
#: terminal/templates/terminal/session_list.html:116
#, fuzzy
#| msgid "Deactive selected"
msgid "Terminate selected"
msgstr "禁用所选"
#: terminal/templates/terminal/session_list.html:136
msgid "Terminate task send, waiting ..."
msgstr "终断任务已发送,请等待"
......@@ -2105,31 +2115,31 @@ msgstr "ssh密钥不合法"
msgid "Select users"
msgstr "选择用户"
#: users/models/authentication.py:35
#: users/models/authentication.py:36
msgid "Private Token"
msgstr "ssh密钥"
#: users/models/authentication.py:45
#: users/models/authentication.py:46
msgid "Login type"
msgstr "登录方式"
#: users/models/authentication.py:46
#: users/models/authentication.py:47
msgid "Login ip"
msgstr "登录IP"
#: users/models/authentication.py:47
#: users/models/authentication.py:48
msgid "Login city"
msgstr "登录城市"
#: users/models/authentication.py:48
#: users/models/authentication.py:49
msgid "User agent"
msgstr "Agent"
#: users/models/authentication.py:49
#: users/models/authentication.py:50
msgid "Date login"
msgstr "登录日期"
#: users/models/user.py:29 users/models/user.py:257
#: users/models/user.py:29 users/models/user.py:262
msgid "Administrator"
msgstr "管理员"
......@@ -2168,7 +2178,7 @@ msgstr "二次验证"
msgid "Public key"
msgstr "ssh公钥"
#: users/models/user.py:260
#: users/models/user.py:265
msgid "Administrator is the super user of system"
msgstr "Administrator是初始的超级管理员"
......@@ -2239,7 +2249,7 @@ msgid " for more information"
msgstr "获取更多信息"
#: users/templates/users/forgot_password.html:26
#: users/templates/users/login.html:64
#: users/templates/users/login.html:73
msgid "Forgot password"
msgstr "忘记密码"
......@@ -2247,7 +2257,7 @@ msgstr "忘记密码"
msgid "Input your email, that will send a mail to your"
msgstr "输入您的邮箱, 将会发一封重置邮件到您的邮箱中"
#: users/templates/users/login.html:47
#: users/templates/users/login.html:50
msgid "Captcha invalid"
msgstr "验证码错误"
......@@ -2269,8 +2279,13 @@ msgstr "重置密码"
msgid "Password again"
msgstr "再次输入密码"
#: users/templates/users/reset_password.html:57
#: users/templates/users/user_profile.html:20
msgid "Setting"
msgstr "设置"
#: users/templates/users/user_create.html:4
#: users/templates/users/user_list.html:16 users/views/user.py:72
#: users/templates/users/user_list.html:16 users/views/user.py:74
msgid "Create user"
msgstr "创建用户"
......@@ -2279,7 +2294,7 @@ msgid "Reset link will be generated and sent to the user. "
msgstr "生成重置密码连接,通过邮件发送给用户"
#: users/templates/users/user_detail.html:19
#: users/templates/users/user_granted_asset.html:18 users/views/user.py:148
#: users/templates/users/user_granted_asset.html:18 users/views/user.py:150
msgid "User detail"
msgstr "用户详情"
......@@ -2320,7 +2335,7 @@ msgstr "将失效用户当前密码,并发送重设密码邮件到用户邮箱
msgid ""
"The reset-ssh-public-key E-mail has been sent successfully. Please inform "
"the user to update his new ssh public key."
msgstr "重设钥邮件将会发送到用户邮箱"
msgstr "重设钥邮件将会发送到用户邮箱"
#: users/templates/users/user_detail.html:350
#: users/templates/users/user_profile.html:140
......@@ -2329,7 +2344,7 @@ msgstr "重置SSH密钥"
#: users/templates/users/user_detail.html:360
msgid "This will reset the user public key and send a reset mail"
msgstr "将会失效用户当前钥,并发送重置邮件到用户邮箱"
msgstr "将会失效用户当前钥,并发送重置邮件到用户邮箱"
#: users/templates/users/user_detail.html:377
#: users/templates/users/user_profile.html:166
......@@ -2351,7 +2366,7 @@ msgstr "取消"
#: users/templates/users/user_group_granted_asset.html:18
#: users/views/group.py:80
msgid "User group detail"
msgstr "资产组详情"
msgstr "用户组详情"
#: users/templates/users/user_group_detail.html:86
msgid "Add user"
......@@ -2399,8 +2414,8 @@ msgstr "用户删除失败"
msgid "OTP"
msgstr ""
#: users/templates/users/user_profile.html:100 users/views/user.py:177
#: users/views/user.py:229
#: users/templates/users/user_profile.html:100 users/views/user.py:179
#: users/views/user.py:233
msgid "User groups"
msgstr "用户组"
......@@ -2420,9 +2435,9 @@ msgstr "指纹"
msgid "Update public key"
msgstr "更新密钥"
#: users/templates/users/user_update.html:4 users/views/user.py:91
#: users/templates/users/user_update.html:4 users/views/user.py:93
msgid "Update user"
msgstr "编辑用户"
msgstr "更新用户"
#: users/utils.py:35
msgid "Create account successfully"
......@@ -2552,7 +2567,7 @@ msgstr "禁用或失效"
#: users/utils.py:154
msgid "Password or SSH public key invalid"
msgstr "密码或钥不合法"
msgstr "密码或钥不合法"
#: users/views/group.py:29
msgid "User group list"
......@@ -2560,78 +2575,81 @@ msgstr "用户组列表"
#: users/views/group.py:63
msgid "Update user group"
msgstr "编辑用户组"
msgstr "更新用户组"
#: users/views/group.py:96
msgid "User group granted asset"
msgstr "用户组授权资产"
#: users/views/login.py:56
#: users/views/login.py:57
msgid "Please enable cookies and try again."
msgstr "设置你的浏览器支持cookie"
#: users/views/login.py:90
#: users/views/login.py:99
msgid "Logout success"
msgstr "退出登录成功"
#: users/views/login.py:91
#: users/views/login.py:100
msgid "Logout success, return login page"
msgstr "退出登录成功,返回到登录页面"
#: users/views/login.py:107
#: users/views/login.py:116
msgid "Email address invalid, please input again"
msgstr "邮箱地址错误,重新输入"
#: users/views/login.py:120
#: users/views/login.py:129
msgid "Send reset password message"
msgstr "发送重置密码邮件"
#: users/views/login.py:121
#: users/views/login.py:130
msgid "Send reset password mail success, login your mail box and follow it "
msgstr ""
"发送重置邮件成功, 请登录邮箱查看, 按照提示操作 (如果没收到,请等待3-5分钟)"
#: users/views/login.py:135
#: users/views/login.py:144
msgid "Reset password success"
msgstr "重置密码成功"
#: users/views/login.py:136
#: users/views/login.py:145
msgid "Reset password success, return to login page"
msgstr "重置密码成功,返回到登录页面"
#: users/views/login.py:153 users/views/login.py:166
#: users/views/login.py:162 users/views/login.py:175
msgid "Token invalid or expired"
msgstr "Token错误或失效"
#: users/views/login.py:162
#: users/views/login.py:171
msgid "Password not same"
msgstr "密码不一致"
#: users/views/login.py:200
#: users/views/login.py:209
msgid "First login"
msgstr "首次登陆"
#: users/views/login.py:250
#: users/views/login.py:259
msgid "Login log list"
msgstr "登录日志"
#: users/views/user.py:101
#: users/views/user.py:103
msgid "Bulk update user success"
msgstr "批量更新用户成功"
#: users/views/user.py:206
#: users/views/user.py:208
msgid "Invalid file."
msgstr "文件不合法"
#: users/views/user.py:301
#: users/views/user.py:305
msgid "User granted assets"
msgstr "用户授权资产"
#: users/views/user.py:331
#: users/views/user.py:334
msgid "Profile setting"
msgstr "个人信息设置"
#: users/views/user.py:349
#: users/views/user.py:352
msgid "Password update"
msgstr "密码更新"
#: users/views/user.py:371
#: users/views/user.py:374
msgid "Public key update"
msgstr "秘钥更新"
msgstr "密钥更新"
......@@ -397,6 +397,6 @@ BOOTSTRAP3 = {
}
TOKEN_EXPIRATION = CONFIG.TOKEN_EXPIRATION or 3600
DISPLAY_PER_PAGE = CONFIG.DISPLAY_PER_PAGE
DISPLAY_PER_PAGE = CONFIG.DISPLAY_PER_PAGE or 25
DEFAULT_EXPIRED_YEARS = 70
USER_GUIDE_URL = ""
......@@ -4,16 +4,16 @@ from __future__ import unicode_literals
from django.conf.urls import url, include
from django.conf import settings
from django.conf.urls.static import static
from django.views.static import serve as static_serve
from rest_framework.schemas import get_schema_view
from rest_framework_swagger.renderers import SwaggerUIRenderer, OpenAPIRenderer
from .views import IndexView
from .views import IndexView, LunaView
schema_view = get_schema_view(title='Users API', renderer_classes=[OpenAPIRenderer, SwaggerUIRenderer])
urlpatterns = [
url(r'^$', IndexView.as_view(), name='index'),
url(r'^luna/$', LunaView.as_view(), name='luna-error'),
url(r'^users/', include('users.urls.views_urls', namespace='users')),
url(r'^assets/', include('assets.urls.views_urls', namespace='assets')),
url(r'^perms/', include('perms.urls.views_urls', namespace='perms')),
......
from django.views.generic import TemplateView
from django.http import HttpResponse
from django.views.generic import TemplateView, View
from django.utils import timezone
from django.db.models import Count
from django.contrib.auth.mixins import LoginRequiredMixin
......@@ -45,7 +46,8 @@ class IndexView(LoginRequiredMixin, TemplateView):
return self.session_week.values('user').distinct().count()
def get_week_login_asset_count(self):
return self.session_week.values('asset').distinct().count()
return self.session_week.count()
# return self.session_week.values('asset').distinct().count()
def get_month_day_metrics(self):
month_str = [d.strftime('%m-%d') for d in self.session_month_dates] or ['0']
......@@ -149,3 +151,12 @@ class IndexView(LoginRequiredMixin, TemplateView):
kwargs.update(context)
return super(IndexView, self).get_context_data(**kwargs)
class LunaView(View):
def get(self, request):
msg = """
Luna是单独部署的一个程序,你需要部署luna,coco,配置nginx做url分发,
如果你看到了这个页面,证明你访问的不是nginx监听的端口,祝你好运
"""
return HttpResponse(msg)
\ No newline at end of file
......@@ -54,7 +54,11 @@ class UserGrantedAssetsApi(ListAPIView):
user = self.request.user
for k, v in NodePermissionUtil.get_user_assets(user).items():
k.system_users_granted = v
if k.is_unixlike():
system_users_granted = [s for s in v if s.protocol == 'ssh']
else:
system_users_granted = [s for s in v if s.protocol == 'rdp']
k.system_users_granted = system_users_granted
queryset.append(k)
return queryset
......@@ -118,9 +122,16 @@ class UserGrantedNodesWithAssetsApi(ListAPIView):
user = get_object_or_404(User, id=user_id)
nodes = NodePermissionUtil.get_user_nodes_with_assets(user)
assets = {}
for k, v in NodePermissionUtil.get_user_assets(user).items():
if k.is_unixlike():
system_users_granted = [s for s in v if s.protocol == 'ssh']
else:
system_users_granted = [s for s in v if s.protocol == 'rdp']
assets[k] = system_users_granted
for node, v in nodes.items():
for asset in v['assets']:
asset.system_users_granted = v['system_users']
asset.system_users_granted = assets[asset]
node.assets_granted = v['assets']
queryset.append(node)
return queryset
......
......@@ -12,7 +12,7 @@ class AssetPermissionCreateUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = NodePermission
fields = [
'node', 'user_group', 'system_user',
'id', 'node', 'user_group', 'system_user',
'is_active', 'date_expired'
]
......
......@@ -14,7 +14,7 @@
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>{% trans 'Create asset permission ' %}</h5>
<h5>{{ action }}</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
......
......@@ -215,16 +215,6 @@ $(document).ready(function(){
initTable();
initTree();
})
.on('click', '.btn-create-asset', function () {
var url = "{% url 'assets:asset-create' %}";
var nodes = zTree.getSelectedNodes();
var current_node;
if (nodes && nodes.length ===1 ){
current_node = nodes[0];
url += "?node=" + current_node.id;
}
window.open(url);
})
.on('click', '.btn-del', function () {
var $this = $(this);
var uid = $this.data('uid');
......@@ -241,7 +231,7 @@ $(document).ready(function(){
current_node = nodes[0];
url += "?node_id=" + current_node.id;
}
window.open(url);
window.open(url, '_self');
})
</script>
......
......@@ -56,7 +56,7 @@ class NodePermissionUtil:
nodes_with_assets = dict()
for node, system_users in nodes.items():
nodes_with_assets[node] = {
'assets': node.get_assets(),
'assets': node.get_active_assets(),
'system_users': system_users
}
return nodes_with_assets
......@@ -87,7 +87,7 @@ class NodePermissionUtil:
nodes_with_assets = dict()
for node, system_users in nodes.items():
nodes_with_assets[node] = {
'assets': node.get_assets(),
'assets': node.get_active_assets(),
'system_users': system_users
}
return nodes_with_assets
......
......@@ -427,3 +427,9 @@ div.dataTables_wrapper div.dataTables_filter {
text-align: center;
padding: 5px 0;
}
.profile-dropdown li a {
font-size: 12px !important;
}
......@@ -3299,7 +3299,7 @@ body.tour-open .animated {
border-bottom: 1px solid #e7eaec;
}
body {
font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-family: "open sans", "Helvetica Neue", "微软雅黑", Helvetica, Arial, sans-serif;
background-color: #2f4050;
font-size: 13px;
color: #676a6c;
......
apps/static/img/logo-text.png

12.4 KB | W: | H:

apps/static/img/logo-text.png

17.7 KB | W: | H:

apps/static/img/logo-text.png
apps/static/img/logo-text.png
apps/static/img/logo-text.png
apps/static/img/logo-text.png
  • 2-up
  • Swipe
  • Onion skin
<strong>Copyright</strong> 北京堆栈科技有限公司 &copy; 2014-2018
\ No newline at end of file
......@@ -14,8 +14,13 @@
{# <span class="m-r-sm text-muted welcome-message">{% trans 'Welcome to use Jumpserver system' %}</span>#}
{# </li>#}
<li class="dropdown">
<a class="dropdown-toggle count-info" data-toggle="dropdown" href="#">
<span class="m-r-sm text-muted welcome-message">{% trans 'Help' %}</span>
<a class="dropdown-toggle count-info" data-toggle="dropdown" href="https://market.aliyun.com/products/53690006/cmgj026011.html?spm=5176.730005.0.0.cY2io1">
<span class="m-r-sm text-muted welcome-message">{% trans 'Supports' %}</span>
</a>
</li>
<li class="dropdown">
<a class="count-info" href="http://jumpserver.readthedocs.io/">
<span class="m-r-sm text-muted welcome-message">{% trans 'Docs' %}</span>
</a>
</li>
<li class="dropdown">
......@@ -28,9 +33,8 @@
</span>
</span>
</a>
<ul class="dropdown-menu animated fadeInRight m-t-xs">
<li><a href="{% url 'users:user-profile' %}"><i class="fa fa-cogs"> </i><span> {% trans 'Profile' %}</span></a></li>
<li class="divider"></li>
<ul class="dropdown-menu animated fadeInRight m-t-xs profile-dropdown">
<li><a href="{% url 'users:user-profile' %}"><i class="fa fa-cogs"> </i><span> {% trans 'Profile' %}</span></a></li>
{% if request.user.is_superuser %}
{% if request.COOKIES.IN_ADMIN_PAGE == 'No' %}
<li><a id="switch_admin"><i class="fa fa-exchange"></i><span> {% trans 'Admin page' %}</span></a></li>
......@@ -57,11 +61,11 @@
<li>
<a href="">{% trans 'Dashboard' %}</a>
</li>
<li>
{% if app %}
<li>
<a>{{ app }}</a>
{% endif %}
</li>
{% endif %}
{% if action %}
<li class="active">
<strong>{{ action }}</strong>
......
{% load i18n %}
<li id="index">
<a href="{% url 'index' %}">
<i class="fa fa-dashboard" style="font-size: 13px"></i> <span class="nav-label">{% trans 'Dashboard' %}</span><span class="label label-info pull-right"></span>
<i class="fa fa-dashboard" style="width: 14px"></i> <span class="nav-label">{% trans 'Dashboard' %}</span><span
class="label label-info pull-right"></span>
</a>
</li>
<li id="users">
<a href="#">
<i class="fa fa-group" style="font-size: 13px"></i> <span class="nav-label">{% trans 'Users' %}</span><span class="fa arrow"></span>
<i class="fa fa-group" style="width: 14px"></i> <span class="nav-label">{% trans 'Users' %}</span><span class="fa arrow"></span>
</a>
<ul class="nav nav-second-level active">
<li id="user"><a href="{% url 'users:user-list' %}">{% trans 'User list' %}</a></li>
......@@ -16,7 +17,7 @@
</li>
<li id="assets">
<a>
<i class="fa fa-inbox"></i> <span class="nav-label">{% trans 'Assets' %}</span><span class="fa arrow"></span>
<i class="fa fa-inbox" style="width: 14px"></i> <span class="nav-label">{% trans 'Assets' %}</span><span class="fa arrow"></span>
</a>
<ul class="nav nav-second-level">
<li id="asset"><a href="{% url 'assets:asset-list' %}">{% trans 'Asset list' %}</a></li>
......@@ -26,7 +27,7 @@
</ul>
</li>
<li id="perms">
<a href="#"><i class="fa fa-edit"></i> <span class="nav-label">{% trans 'Perms' %}</span><span class="fa arrow"></span></a>
<a href="#"><i class="fa fa-edit" style="width: 14px"></i> <span class="nav-label">{% trans 'Perms' %}</span><span class="fa arrow"></span></a>
<ul class="nav nav-second-level">
<li id="asset-permission">
<a href="{% url 'perms:asset-permission-list' %}">{% trans 'Asset permission' %}</a>
......@@ -35,18 +36,23 @@
</li>
<li id="terminal">
<a>
<i class="fa fa-rocket"></i> <span class="nav-label">{% trans 'Sessions' %}</span><span class="fa arrow"></span>
<i class="fa fa-rocket" style="width: 14px"></i> <span class="nav-label">{% trans 'Sessions' %}</span><span class="fa arrow"></span>
</a>
<ul class="nav nav-second-level">
<li id="session-online"><a href="{% url 'terminal:session-online-list' %}">{% trans 'Session online' %}</a></li>
<li id="session-offline"><a href="{% url 'terminal:session-offline-list' %}">{% trans 'Session offline' %}</a></li>
<li id="command"><a href="{% url 'terminal:command-list' %}">{% trans 'Commands' %}</a></li>
<li>
<a href="{% url 'terminal:web-terminal' %}" target="_blank">
<span class="nav-label">{% trans 'Web terminal' %}</span>
</a>
</li>
<li id="terminal"><a href="{% url 'terminal:terminal-list' %}">{% trans 'Terminal' %}</a></li>
</ul>
</li>
<li id="ops">
<a>
<i class="fa fa-coffee"></i> <span class="nav-label">{% trans 'Job Center' %}</span><span class="fa arrow"></span>
<i class="fa fa-coffee" style="width: 14px"></i> <span class="nav-label">{% trans 'Job Center' %}</span><span class="fa arrow"></span>
</a>
<ul class="nav nav-second-level">
<li id="task"><a href="{% url 'ops:task-list' %}">{% trans 'Task list' %}</a></li>
......
{% load i18n %}
<li id="assets">
<a href="{% url 'assets:user-asset-list' %}">
<i class="fa fa-files-o"></i><span class="nav-label">{% trans 'My assets' %}</span><span class="label label-info pull-right"></span>
<i class="fa fa-files-o" style="width: 14px"></i><span class="nav-label">{% trans 'My assets' %}</span><span class="label label-info pull-right"></span>
</a>
</li>
<li id="users">
<a href="{% url 'users:user-profile' %}">
<i class="fa fa-user" ></i> <span class="nav-label">{% trans 'Profile' %}</span><span class="label label-info pull-right"></span>
<i class="fa fa-user" style="width: 14px"></i> <span class="nav-label">{% trans 'Profile' %}</span><span class="label label-info pull-right"></span>
</a>
</li>
<li >
<a href="{% url 'terminal:web-terminal' %}" target="_blank"><i class="fa fa-window-maximize"></i>
<a href="{% url 'terminal:web-terminal' %}" target="_blank"><i class="fa fa-window-maximize" style="width: 14px"></i>
<span class="nav-label">{% trans 'Web terminal' %}</span>
</a>
</li>
\ No newline at end of file
......@@ -3,7 +3,7 @@
<li class="nav-header">
<div class="dropdown profile-element">
<div href="http://www.jumpserver.org" target="_blank">
<img alt="image" height="55" src="/static/img/logo-text.png" style="margin-left: 10px"/>
<img alt="logo" height="55" width="185" src="/static/img/logo-text.png" style="margin-left: 20px"/>
</div>
</div>
<div class="clearfix"></div>
......
......@@ -49,7 +49,7 @@
<hr/>
<div class="row">
<div class="col-md-6">
Copyright Jumpserver.org
{% include '_copyright.html' %}
</div>
<div class="col-md-6 text-right">
<small>2014-2018</small>
......
......@@ -11,7 +11,7 @@
</div>
<div class="ibox-content">
<h1 class="no-margins"><a href="{% url 'users:user-list' %}">{{ users_count }}</a></h1>
<small>All user</small>
<small>All users</small>
</div>
</div>
</div>
......@@ -23,7 +23,7 @@
</div>
<div class="ibox-content">
<h1 class="no-margins"><a href="{% url 'assets:asset-list' %}">{{ assets_count }}</a></h1>
<small>All host</small>
<small>All hosts</small>
</div>
</div>
</div>
......@@ -36,7 +36,7 @@
</div>
<div class="ibox-content">
<h1 class="no-margins"><a href="{% url 'terminal:session-online-list' %}"> <span id="online_users"></span>{{ online_user_count }}</a></h1>
<small>Online user</small>
<small>Online users</small>
</div>
</div>
</div>
......@@ -57,7 +57,7 @@
<div class="row">
<div class="col-sm-2 border-bottom white-bg dashboard-header" style="margin-left:15px;height: 346px">
<h2>活跃用户TOP5</h2>
<small>过去一周共有<span class="text-info">{{ user_visit_count_weekly }}</span>位用户登录<span class="text-success">{{ asset_visit_count_weekly }}</span>服务器.</small>
<small>过去一周共有<span class="text-info">{{ user_visit_count_weekly }}</span>位用户登录<span class="text-success">{{ asset_visit_count_weekly }}</span>资产.</small>
<ul class="list-group clear-list m-t">
{% for data in user_visit_count_top_five %}
<li class="list-group-item fist-item">
......
......@@ -25,18 +25,22 @@ def get_all_replay_storage():
class TerminalForm(forms.ModelForm):
command_storage = forms.ChoiceField(choices=get_all_command_storage(),
label=_("Command storage"))
replay_storage = forms.ChoiceField(choices=get_all_replay_storage(),
label=_("Replay storage"))
command_storage = forms.ChoiceField(
choices=get_all_command_storage(),
label=_("Command storage")
)
replay_storage = forms.ChoiceField(
choices=get_all_replay_storage(),
label=_("Replay storage")
)
class Meta:
model = Terminal
fields = ['name', 'remote_addr', 'ssh_port', 'http_port', 'comment', 'command_storage', 'replay_storage']
fields = [
'name', 'remote_addr', 'ssh_port', 'http_port', 'comment',
'command_storage', 'replay_storage',
]
help_texts = {
'ssh_port': _("Coco ssh listen port"),
'http_port': _("Coco http/ws listen port"),
}
widgets = {
'name': forms.TextInput(attrs={'readonly': 'readonly'})
}
......@@ -4,6 +4,7 @@ import uuid
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
from django.conf import settings
from users.models import User
......@@ -127,6 +128,7 @@ class Session(models.Model):
has_replay = models.BooleanField(default=False, verbose_name=_("Replay"))
has_command = models.BooleanField(default=False, verbose_name=_("Command"))
terminal = models.ForeignKey(Terminal, null=True, on_delete=models.CASCADE)
date_last_active = models.DateTimeField(verbose_name=_("Date last active"), default=timezone.now)
date_start = models.DateTimeField(verbose_name=_("Date start"))
date_end = models.DateTimeField(verbose_name=_("Date end"), null=True)
......
# -*- coding: utf-8 -*-
#
import datetime
from celery import shared_task
from django.utils import timezone
from common.celery import register_as_period_task, after_app_ready_start, \
after_app_shutdown_clean
from .models import Status, Session
CACHE_REFRESH_INTERVAL = 10
RUNNING = False
# Todo: 定期清理上报history
@shared_task
def clean_terminal_history():
pass
@register_as_period_task(interval=3600)
@after_app_ready_start
@after_app_shutdown_clean
def delete_terminal_status_period():
yesterday = timezone.now() - datetime.timedelta(days=3)
Status.objects.filter(date_created__lt=yesterday).delete()
@shared_task
@register_as_period_task(interval=3600)
@after_app_ready_start
@after_app_shutdown_clean
def clean_orphan_session():
active_sessions = Session.objects.filter(is_finished=False)
for session in active_sessions:
if not session.terminal.is_active:
session.is_finished = True
session.save()
......@@ -75,6 +75,7 @@
<th class="text-center">{% trans 'Terminal' %}</th>
<th class="text-center">{% trans 'Command' %}</th>
<th class="text-center">{% trans 'Date start' %}</th>
{# <th class="text-center">{% trans 'Date last active' %}</th>#}
<th class="text-center">{% trans 'Duration' %}</th>
<th class="text-center">{% trans 'Action' %}</th>
{% endblock %}
......@@ -94,6 +95,7 @@
<td class="text-center">{{ session.id | get_session_command_amount }}</td>
<td class="text-center">{{ session.date_start }}</td>
{# <td class="text-center">{{ session.date_last_active }}</td>#}
<td class="text-center">{{ session.date_start|time_util_with_seconds:session.date_end }}</td>
<td>
{% if session.is_finished %}
......@@ -107,6 +109,21 @@
{% endfor %}
{% endblock %}
{% block content_bottom_left %}
<div id="actions" >
<div class="input-group">
<select class="form-control m-b" style="width: auto" id="slct_bulk_update">
<option value="delete">{% trans 'Terminate selected' %}</option>
</select>
<div class="input-group-btn pull-left" style="padding-left: 5px;">
<button id='btn_bulk_update' style="height: 32px;" class="btn btn-sm btn-primary">
{% trans 'Submit' %}
</button>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"></script>
<script>
......
......@@ -6,7 +6,7 @@ from django.conf import settings
from django.utils import timezone
from django.utils.translation import ugettext as _
from common.mixins import DatetimeSearchMixin
from common.mixins import DatetimeSearchMixin, AdminUserRequiredMixin
from ..models import Command
from .. import utils
from ..backends import get_multi_command_store
......@@ -15,7 +15,7 @@ __all__ = ['CommandListView']
common_storage = get_multi_command_store()
class CommandListView(DatetimeSearchMixin, ListView):
class CommandListView(DatetimeSearchMixin, AdminUserRequiredMixin, ListView):
model = Command
template_name = "terminal/command_list.html"
context_object_name = 'command_list'
......
......@@ -97,7 +97,7 @@ class SessionOfflineListView(SessionListView):
return super().get_context_data(**kwargs)
class SessionDetailView(SingleObjectMixin, ListView):
class SessionDetailView(SingleObjectMixin, AdminUserRequiredMixin, ListView):
template_name = 'terminal/session_detail.html'
model = Session
object = None
......
......@@ -145,7 +145,8 @@ class UserAuthApi(APIView):
if not login_ip:
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR', '').split(',')
if x_forwarded_for:
if x_forwarded_for and x_forwarded_for[0]:
login_ip = x_forwarded_for[0]
else:
login_ip = request.META.get("REMOTE_ADDR")
......
......@@ -6,3 +6,6 @@ from django.apps import AppConfig
class UsersConfig(AppConfig):
name = 'users'
def ready(self):
from . import signals_handler
super().ready()
......@@ -16,7 +16,8 @@ class AccessKey(models.Model):
default=uuid.uuid4, editable=False)
secret = models.UUIDField(verbose_name='AccessKeySecret',
default=uuid.uuid4, editable=False)
user = models.ForeignKey(User, verbose_name='User', on_delete=models.CASCADE, related_name='access_key')
user = models.ForeignKey(User, verbose_name='User',
on_delete=models.CASCADE, related_name='access_key')
def get_id(self):
return str(self.id)
......
......@@ -22,6 +22,7 @@ class UserGroup(NoDeleteModelMixin):
class Meta:
ordering = ['name']
verbose_name = _("User group")
@classmethod
def initial(cls):
......
......@@ -151,6 +151,10 @@ class User(AbstractUser):
def save(self, *args, **kwargs):
if not self.name:
self.name = self.username
if self.username == 'admin':
self.role = 'Admin'
self.is_active = True
super().save(*args, **kwargs)
@property
......@@ -247,6 +251,7 @@ class User(AbstractUser):
class Meta:
ordering = ['username']
verbose_name = _("User")
#: Use this method initial user
@classmethod
......
# -*- coding: utf-8 -*-
#
from django.dispatch import Signal
from django.dispatch import Signal, receiver
from django.db.models.signals import post_save
from common.utils import get_logger
from .models import User
logger = get_logger(__file__)
@receiver(post_save, sender=User)
def on_user_created(sender, instance=None, created=False, **kwargs):
if created:
logger.debug("Receive user `{}` create signal".format(instance.name))
from .utils import send_user_created_mail
logger.info(" - Sending welcome mail ...".format(instance.name))
if instance.email:
send_user_created_mail(instance)
post_user_create = Signal(providing_args=('user',))
# -*- coding: utf-8 -*-
#
from django.dispatch import receiver
from django.db.models.signals import post_save
from common.utils import get_logger
from .models import User
logger = get_logger(__file__)
@receiver(post_save, sender=User)
def on_user_created(sender, instance=None, created=False, **kwargs):
if created:
logger.debug("Receive user `{}` create signal".format(instance.name))
from .utils import send_user_created_mail
logger.info(" - Sending welcome mail ...".format(instance.name))
if instance.email:
send_user_created_mail(instance)
\ No newline at end of file
......@@ -51,11 +51,8 @@
</div>
<hr/>
<div class="row">
<div class="col-md-6">
Copyright Jumpserver.org
</div>
<div class="col-md-6 text-right">
<small>© 2014-2018</small>
<div class="col-md-12">
{% include '_copyright.html' %}
</div>
</div>
</div>
......
......@@ -22,24 +22,27 @@
<div class="loginColumns animated fadeInDown">
<div class="row">
<div class="col-md-6">
<h2 class="font-bold">欢迎使用Jumpserver开源跳板</h2>
<h2 class="font-bold">欢迎使用Jumpserver开源堡垒</h2>
<p>
Jumpserver是一款使用Python, Django开发的开源跳板机系统, 助力互联网企业高效 用户、资产、权限、审计 管理
全球首款完全开源的堡垒机,使用GNU GPL v2.0开源协议,是符合 4A 的专业运维审计系统。
</p>
<p>
我们自五湖四海,我们对开源精神无比敬仰和崇拜,我们对完美、整洁、优雅 无止境的追求
使用Python / Django 进行开发,遵循 Web 2.0 规范,配备了业界领先的 Web Terminal 解决方案,交互界面美观、用户体验好。
</p>
<p>
专注自动化运维,努力打造 易用、稳定、安全、自动化 的跳板机, 这是我们的不懈的追求和动力
采纳分布式架构,支持多机房跨区域部署,中心节点提供 API,各机房部署登录节点,可横向扩展、无并发访问限制。
</p>
<p>
<small>永远年轻,永远热泪盈眶 stay foolish stay hungry</small>
改变世界,从一点点开始。
</p>
</div>
<div class="col-md-6">
<div class="ibox-content">
<div><img src="{% static 'img/logo.png' %}" width="82" height="82"> <span class="font-bold text-center" style="font-size: 32px; font-family: inherit">{% trans 'Login' %}</span></div>
<div>
<img src="{% static 'img/logo.png' %}" width="60" height="60">
<span class="font-bold text-center" style="font-size: 24px; font-family: inherit; margin-left: 20px">{% trans 'Login' %}</span>
</div>
<form class="m-t" role="form" method="post" action="">
{% csrf_token %}
{% if form.errors %}
......@@ -60,12 +63,16 @@
</div>
<button type="submit" class="btn btn-primary block full-width m-b">{% trans 'Login' %}</button>
{% if demo_mode %}
<p class="text-muted font-bold" style="color: red">
Demo账号: admin 密码: admin
</p>
{% endif %}
<a href="{% url 'users:forgot-password' %}">
<small>{% trans 'Forgot password' %}?</small>
</a>
<p class="text-muted text-center">
</p>
</form>
<p class="m-t">
</p>
......@@ -74,11 +81,8 @@
</div>
<hr/>
<div class="row">
<div class="col-md-6">
Copyright 北京堆栈科技有限公司
</div>
<div class="col-md-6 text-right">
<small>© 2014-2018</small>
<div class="col-md-12">
{% include '_copyright.html' %}
</div>
</div>
</div>
......
......@@ -70,11 +70,8 @@
</div>
<hr/>
<div class="row">
<div class="col-md-6">
Copyright Jumpserver.org
</div>
<div class="col-md-6 text-right">
<small>© 2014-2018</small>
<div class="col-md-12">
{% include '_copyright.html' %}
</div>
</div>
</div>
......
......@@ -92,8 +92,8 @@ class UserGroupGrantedAssetView(AdminUserRequiredMixin, DetailView):
def get_context_data(self, **kwargs):
context = {
'app': 'User',
'action': 'User group granted asset',
'app': _('Users'),
'action': _('User group granted asset'),
}
kwargs.update(context)
return super().get_context_data(**kwargs)
# ~*~ coding: utf-8 ~*~
from __future__ import unicode_literals
import os
from django import forms
from django.shortcuts import render
from django.contrib.auth import login as auth_login, logout as auth_logout
......@@ -56,6 +57,7 @@ class UserLoginView(FormView):
return HttpResponse(_("Please enable cookies and try again."))
auth_login(self.request, form.get_user())
x_forwarded_for = self.request.META.get('HTTP_X_FORWARDED_FOR', '').split(',')
if x_forwarded_for and x_forwarded_for[0]:
login_ip = x_forwarded_for[0]
else:
......@@ -75,6 +77,13 @@ class UserLoginView(FormView):
self.redirect_field_name,
self.request.GET.get(self.redirect_field_name, reverse('index')))
def get_context_data(self, **kwargs):
context = {
'demo_mode': os.environ.get("DEMO_MODE"),
}
kwargs.update(context)
return super().get_context_data(**kwargs)
@method_decorator(never_cache, name='dispatch')
class UserLogoutView(TemplateView):
......@@ -237,7 +246,7 @@ class LoginLogListView(DatetimeSearchMixin, ListView):
if self.user:
queryset = queryset.filter(username=self.user)
if self.keyword:
queryset = self.queryset.filter(
queryset = queryset.filter(
Q(ip__contains=self.keyword) |
Q(city__contains=self.keyword) |
Q(username__contains=self.keyword)
......
......@@ -6,6 +6,7 @@ import json
import uuid
import csv
import codecs
import chardet
from io import StringIO
from django.contrib import messages
......@@ -20,6 +21,7 @@ from django.utils.translation import ugettext as _
from django.utils.decorators import method_decorator
from django.views import View
from django.views.generic.base import TemplateView
from django.db import transaction
from django.views.generic.edit import (
CreateView, UpdateView, FormMixin, FormView
)
......@@ -33,7 +35,7 @@ from common.utils import get_logger, get_object_or_none, is_uuid
from .. import forms
from ..models import User, UserGroup
from ..utils import AdminUserRequiredMixin
from ..signals import on_user_created
from ..signals import post_user_create
__all__ = [
......@@ -212,8 +214,10 @@ class UserBulkImportView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
# todo: need be patch, method to long
def form_valid(self, form):
file = form.cleaned_data['file']
data = file.read().decode('utf-8').strip(codecs.BOM_UTF8.decode('utf-8'))
f = form.cleaned_data['file']
det_result = chardet.detect(f.read())
f.seek(0) # reset file seek index
data = f.read().decode(det_result['encoding']).strip(codecs.BOM_UTF8.decode())
csv_file = StringIO(data)
reader = csv.reader(csv_file)
csv_data = [row for row in reader]
......@@ -252,15 +256,15 @@ class UserBulkImportView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
else:
continue
user_dict[k] = v
user = get_object_or_none(User, id=id_) if is_uuid(id_) else None
user = get_object_or_none(User, id=id_) if id_ and is_uuid(id_) else None
if not user:
try:
groups = user_dict.pop('groups')
user = User.objects.create(**user_dict)
user.groups.set(groups)
created.append(user_dict['username'])
on_user_created.send(self.__class__, user=user)
with transaction.atomic():
groups = user_dict.pop('groups')
user = User.objects.create(**user_dict)
user.groups.set(groups)
created.append(user_dict['username'])
post_user_create.send(self.__class__, user=user)
except Exception as e:
failed.append('%s: %s' % (user_dict['username'], str(e)))
else:
......@@ -309,7 +313,6 @@ class UserProfileView(LoginRequiredMixin, TemplateView):
def get_context_data(self, **kwargs):
context = {
'app': _('Users'),
'action': _('Profile'),
}
kwargs.update(context)
......
......@@ -4,7 +4,7 @@
contain the root `toctree` directive.
Jumpserver 文档
====================
======================================
目录:
......
简介
============
Jumpserver是混合云下更好用的堡垒机, 分布式架构设计无限扩展,轻松对接混合云资产,支持使用云存储(AWS S3, ES等)存储录像、命令
Jumpserver颠覆传统堡垒机, 无主机和并发数量限制,支持水平扩容,FIT2CLOUD提供完备的商业服务支持,用户无后顾之忧
Jumpserver拥有极致的用户体验, 极致UI体验,容器化的部署方式,部署过程方便快捷,可持续升级
组件说明
++++++++++++++++++++++++
Jumpserver
```````````
现指Jumpserver管理后台,是核心组件(Core), 使用 Django Class Based View 风格开发,支持Restful API。
`Github <https://github.com/jumpserver/jumpserver.git>`_
Coco
````````
实现了SSH Server 和 Web Terminal Server的组件,提供ssh和websocket接口, 使用 Paramiko 和 Flask 开发。
`Github <https://github.com/jumpserver/coco.git>`__
Luna
````````
现在是Web Terminal前端,计划前端页面都由该项目提供,Jumpserver只提供API,不再负责后台渲染html等。
`Github <https://github.com/jumpserver/luna.git>`__
Guacamole
```````````
Apache 跳板机项目,Jumpserver使用其组件实现RDP功能,Jumpserver并没有修改其代码而是添加了额外的插件,支持Jumpserver调用
Jumpserver-python-sdk
```````````````````````
Jumpserver API Python SDK,Coco目前使用该SDK与Jumpserver API交互
`Github <https://github.com/jumpserver/jumpserver-python-sdk.git>`__
组件架构图
++++++++++++++++++++++++
.. image:: _static/img/structure.png
:alt: 组件架构图
用户使用文档
===============
=============
这部分给您介绍Jumpserver的用户使用方法。
这部分给您介绍Jumpserver的用户管理模块的使用方法。
.. toctree::
:maxdepth: 1
......
......@@ -56,8 +56,8 @@ uritemplate==3.0.0
urllib3==1.22
vine==1.1.4
gunicorn==19.7.1
https://github.com/celery/django-celery-beat/zipball/master#egg=django-celery-beat
#django_celery_beat==1.1.0
#https://github.com/celery/django-celery-beat/zipball/master#egg=django-celery-beat
django_celery_beat==1.1.1
ephem==3.7.6.0
python-gssapi==0.6.4
jms-es-sdk
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment