Commit f450accb authored by BaiJiangjie's avatar BaiJiangjie

[Merge] with dev

parents 0bbfc743 48e87857
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
__version__ = "1.0.0" __version__ = "1.2.0"
...@@ -32,6 +32,7 @@ __all__ = [ ...@@ -32,6 +32,7 @@ __all__ = [
'NodeViewSet', 'NodeChildrenApi', 'NodeViewSet', 'NodeChildrenApi',
'NodeAssetsApi', 'NodeWithAssetsApi', 'NodeAssetsApi', 'NodeWithAssetsApi',
'NodeAddAssetsApi', 'NodeRemoveAssetsApi', 'NodeAddAssetsApi', 'NodeRemoveAssetsApi',
'NodeReplaceAssetsApi',
'NodeAddChildrenApi', 'RefreshNodeHardwareInfoApi', 'NodeAddChildrenApi', 'RefreshNodeHardwareInfoApi',
'TestNodeConnectiveApi' 'TestNodeConnectiveApi'
] ]
...@@ -191,6 +192,19 @@ class NodeRemoveAssetsApi(generics.UpdateAPIView): ...@@ -191,6 +192,19 @@ class NodeRemoveAssetsApi(generics.UpdateAPIView):
instance.assets.remove(*tuple(assets)) instance.assets.remove(*tuple(assets))
class NodeReplaceAssetsApi(generics.UpdateAPIView):
serializer_class = serializers.NodeAssetsSerializer
queryset = Node.objects.all()
permission_classes = (IsSuperUser,)
instance = None
def perform_update(self, serializer):
assets = serializer.validated_data.get('assets')
instance = self.get_object()
for asset in assets:
asset.nodes.set([instance])
class RefreshNodeHardwareInfoApi(APIView): class RefreshNodeHardwareInfoApi(APIView):
permission_classes = (IsSuperUser,) permission_classes = (IsSuperUser,)
model = Node model = Node
......
...@@ -49,6 +49,7 @@ class Asset(models.Model): ...@@ -49,6 +49,7 @@ class Asset(models.Model):
ip = models.GenericIPAddressField(max_length=32, verbose_name=_('IP'), db_index=True) ip = models.GenericIPAddressField(max_length=32, verbose_name=_('IP'), db_index=True)
hostname = models.CharField(max_length=128, unique=True, verbose_name=_('Hostname')) hostname = models.CharField(max_length=128, unique=True, verbose_name=_('Hostname'))
port = models.IntegerField(default=22, verbose_name=_('Port')) port = models.IntegerField(default=22, verbose_name=_('Port'))
platform = models.CharField(max_length=128, choices=PLATFORM_CHOICES, default='Linux', verbose_name=_('Platform'))
domain = models.ForeignKey("assets.Domain", null=True, blank=True, related_name='assets', verbose_name=_("Domain"), on_delete=models.SET_NULL) domain = models.ForeignKey("assets.Domain", null=True, blank=True, related_name='assets', verbose_name=_("Domain"), on_delete=models.SET_NULL)
nodes = models.ManyToManyField('assets.Node', default=default_node, related_name='assets', verbose_name=_("Nodes")) nodes = models.ManyToManyField('assets.Node', default=default_node, related_name='assets', verbose_name=_("Nodes"))
is_active = models.BooleanField(default=True, verbose_name=_('Is active')) is_active = models.BooleanField(default=True, verbose_name=_('Is active'))
...@@ -72,7 +73,6 @@ class Asset(models.Model): ...@@ -72,7 +73,6 @@ class Asset(models.Model):
disk_total = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('Disk total')) 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')) disk_info = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('Disk info'))
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 = 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_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')) os_arch = models.CharField(max_length=16, blank=True, null=True, verbose_name=_('OS arch'))
...@@ -84,7 +84,7 @@ class Asset(models.Model): ...@@ -84,7 +84,7 @@ class Asset(models.Model):
comment = models.TextField(max_length=128, default='', blank=True, verbose_name=_('Comment')) comment = models.TextField(max_length=128, default='', blank=True, verbose_name=_('Comment'))
def __str__(self): def __str__(self):
return self.hostname return '{0.hostname}({0.ip})'.format(self)
@property @property
def is_valid(self): def is_valid(self):
......
...@@ -19,7 +19,7 @@ class Node(models.Model): ...@@ -19,7 +19,7 @@ class Node(models.Model):
is_asset = False is_asset = False
def __str__(self): def __str__(self):
return self.value return self.full_value
@property @property
def name(self): def name(self):
...@@ -30,7 +30,7 @@ class Node(models.Model): ...@@ -30,7 +30,7 @@ class Node(models.Model):
if self == self.__class__.root(): if self == self.__class__.root():
return self.value return self.value
else: else:
return '{}/{}'.format(self.value, self.parent.full_value) return '{} / {}'.format(self.parent.full_value, self.value)
@property @property
def level(self): def level(self):
...@@ -72,7 +72,7 @@ class Node(models.Model): ...@@ -72,7 +72,7 @@ class Node(models.Model):
assets = Asset.objects.all() assets = Asset.objects.all()
else: else:
nodes = self.get_family() nodes = self.get_family()
assets = Asset.objects.filter(nodes__in=nodes) assets = Asset.objects.filter(nodes__in=nodes).distinct()
return assets return assets
def has_assets(self): def has_assets(self):
......
...@@ -109,7 +109,7 @@ class SystemUser(AssetUser): ...@@ -109,7 +109,7 @@ class SystemUser(AssetUser):
shell = models.CharField(max_length=64, default='/bin/bash', verbose_name=_('Shell')) shell = models.CharField(max_length=64, default='/bin/bash', verbose_name=_('Shell'))
def __str__(self): def __str__(self):
return self.name return '{0.name}({0.username})'.format(self)
def to_json(self): def to_json(self):
return { return {
......
...@@ -96,6 +96,9 @@ def update_assets_hardware_info_util(assets, task_name=None): ...@@ -96,6 +96,9 @@ def update_assets_hardware_info_util(assets, task_name=None):
task_name = _("更新资产硬件信息") task_name = _("更新资产硬件信息")
tasks = const.UPDATE_ASSETS_HARDWARE_TASKS tasks = const.UPDATE_ASSETS_HARDWARE_TASKS
hostname_list = [asset.hostname for asset in assets if asset.is_active and asset.is_unixlike()] hostname_list = [asset.hostname for asset in assets if asset.is_active and asset.is_unixlike()]
if not hostname_list:
logger.info("Not hosts get, may be asset is not active or not unixlike platform")
return {}
task, created = update_or_create_ansible_task( task, created = update_or_create_ansible_task(
task_name, hosts=hostname_list, tasks=tasks, pattern='all', task_name, hosts=hostname_list, tasks=tasks, pattern='all',
options=const.TASK_OPTIONS, run_as_admin=True, created_by='System', options=const.TASK_OPTIONS, run_as_admin=True, created_by='System',
......
{% extends '_modal.html' %} {% extends '_modal.html' %}
{% load i18n %} {% load i18n %}
{% load static %}
{% block modal_class %}modal-lg{% endblock %} {% block modal_class %}modal-lg{% endblock %}
{% block modal_id %}asset_list_modal{% endblock %} {% block modal_id %}asset_list_modal{% endblock %}
{#{% block modal_title%}{% trans "Please select assets" %}{% endblock %}#} {% block modal_title%}{% trans "Asset list" %}{% endblock %}
{% block modal_body %} {% block modal_body %}
{#<div class="btn-group" style="float: right">#} <link href="{% static 'css/plugins/ztree/awesomeStyle/awesome.css' %}" rel="stylesheet">
{# <button data-toggle="dropdown" class="btn btn-default btn-sm dropdown-toggle">{% trans 'Label' %} <span class="caret"></span></button>#} <script type="text/javascript" src="{% static 'js/plugins/ztree/jquery.ztree.all.min.js' %}"></script>
{# <ul class="dropdown-menu labels">#} <script src="{% static 'js/jquery.form.min.js' %}"></script>
{# {% for label in labels %}#} <style>
{# <li><a style="font-weight: bolder">{{ label.name }}:{{ label.value }}</a></li>#} .inmodal .modal-header {
{# {% endfor %}#} padding: 10px 10px;
{# </ul>#} text-align: center;
{#</div>#} }
<table class="table table-striped table-bordered table-hover " id="asset_modal_table" width="100%">
<thead> #assetTree2.ztree * {
<tr> background-color: #f8fafb;
<th class="text-center"><input type="checkbox" class="ipt_check_all"></th> }
<th class="text-center">{% trans 'Hostname' %}</th> #assetTree2.ztree {
<th class="text-center">{% trans 'IP' %}</th> background-color: #f8fafb;
<th class="text-center">{% trans 'Hardware' %}</th> }
<th class="text-center">{% trans 'Active' %}</th> </style>
<th class="text-center">{% trans 'Reachable' %}</th>
<th class="text-center">{% trans 'Action' %}</th> <div class="wrapper wrapper-content">
</tr> <div class="row">
</thead> <div class="col-lg-3" id="split-left" style="padding-left: 3px">
<tbody> <div class="ibox float-e-margins">
</tbody> <div class="ibox-content mailbox-content" style="padding-top: 0;padding-left: 1px">
</table> <div class="file-manager ">
<div id="actions" class="hide"> <div id="assetTree2" class="ztree">
<div class="input-group"> </div>
<select class="form-control m-b" style="width: auto" id="slct_bulk_update"> <div class="clearfix"></div>
<option value="delete">{% trans 'Delete selected' %}</option> </div>
<option value="update">{% trans 'Update selected' %}</option> </div>
<option value="deactive">{% trans 'Deactive selected' %}</option> </div>
<option value="active">{% trans 'Active selected' %}</option> </div>
</select> <div class="col-lg-9 animated fadeInRight" id="split-right">
<div class="input-group-btn pull-left" style="padding-left: 5px;"> <div class="mail-box-header">
<button id='btn_bulk_update' style="height: 32px;" class="btn btn-sm btn-primary"> <table class="table table-striped table-bordered table-hover " id="asset_list_modal_table" style="width: 100%">
{% trans 'Submit' %} <thead>
</button> <tr>
<th class="text-center"><input type="checkbox" class="ipt_check_all"></th>
<th class="text-center">{% trans 'Hostname' %}</th>
<th class="text-center">{% trans 'IP' %}</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div> </div>
</div> </div>
</div> </div>
<script>
var modal_table;
function initModalTable() { <script>
var zTree2, asset_table2 = 0;
function initTable2() {
var options = { var options = {
ele: $('#asset_modal_table'), ele: $('#asset_list_modal_table'),
columnDefs: [
{targets: 1, createdCell: function (td, cellData, rowData) {
{% url 'assets:asset-detail' pk=DEFAULT_PK as the_url %}
var detail_btn = '<a href="{{ the_url }}">' + cellData + '</a>';
$(td).html(detail_btn.replace('{{ DEFAULT_PK }}', rowData.id));
}},
{targets: 3, createdCell: function (td, cellData, rowData) {
$(td).html(rowData.hardware_info)
}},
{targets: 4, createdCell: function (td, cellData) {
if (!cellData) {
$(td).html('<i class="fa fa-times text-danger"></i>')
} else {
$(td).html('<i class="fa fa-check text-navy"></i>')
}
}},
{targets: 5, createdCell: function (td, cellData) {
if (cellData === 'Unknown'){
$(td).html('<i class="fa fa-circle text-warning"></i>')
} else if (!cellData) {
$(td).html('<i class="fa fa-circle text-danger"></i>')
} else {
$(td).html('<i class="fa fa-circle text-navy"></i>')
}
}},
{targets: 6, createdCell: function (td, cellData, rowData) {
var update_btn = '<a href="{% url "assets:asset-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace("{{ DEFAULT_PK }}", cellData);
var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_asset_delete" data-uid="{{ DEFAULT_PK }}">{% trans "Delete" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
$(td).html(update_btn + del_btn)
}}
],
ajax_url: '{% url "api-assets:asset-list" %}', ajax_url: '{% url "api-assets:asset-list" %}',
columns: [ columns: [
{data: "id"}, {data: "hostname" }, {data: "ip" }, {data: "id"}, {data: "hostname" }, {data: "ip" }
{data: "cpu_cores"}, {data: "is_active", orderable: false },
{data: "is_connective", orderable: false}, {data: "id", orderable: false }
], ],
op_html: $('#actions').html() pageLength: 10
}; };
modal_table = jumpserver.initServerSideDataTable(options); asset_table2 = jumpserver.initServerSideDataTable(options);
return modal_table; return asset_table2
} }
$(document).ready(function(){ function onSelected2(event, treeNode) {
initModalTable(); var url = asset_table2.ajax.url();
}).on('click', '#btn_select_assets', function () { url = setUrlParam(url, "node_id", treeNode.id);
var data_table = $('#asset_modal_table').DataTable(); setCookie('node_selected', treeNode.id);
var id_list = []; asset_table2.ajax.url(url);
data_table.rows({selected: true}).every(function(){ asset_table2.ajax.reload();
id_list.push(this.data().id); }
});
var current_node;
var nodes = zTree.getSelectedNodes();
if (nodes && nodes.length === 1) {
current_node = nodes[0]
} else {
return
}
var data = {
'assets': id_list
};
var success = function () { function initTree2() {
modal_table.ajax.reload() var setting = {
view: {
dblClickExpand: false,
showLine: true
},
data: {
simpleData: {
enable: true
}
},
callback: {
onSelected: onSelected2
}
}; };
APIUpdateAttr({ var zNodes = [];
'url': '/api/assets/v1/nodes/' + current_node.id + '/assets/add/', $.get("{% url 'api-assets:node-list' %}", function(data, status){
'method': 'PUT', $.each(data, function (index, value) {
'body': JSON.stringify(data), value["pId"] = value["parent"];
'success': success value["open"] = true;
}) value["name"] = value["value"] + ' (' + value['assets_amount'] + ')';
value['value'] = value['value'];
});
zNodes = data;
$.fn.zTree.init($("#assetTree2"), setting, zNodes);
zTree2 = $.fn.zTree.getZTreeObj("assetTree2");
});
}
$(document).ready(function(){
initTable2();
initTree2();
}) })
</script> </script>
{% endblock %}
{% block modal_button %}
{{ block.super }}
{% endblock %} {% endblock %}
{% block modal_confirm_id %}btn_select_assets{% endblock %} {% block modal_confirm_id %}btn_asset_modal_confirm{% endblock %}
...@@ -305,9 +305,9 @@ $(document).ready(function () { ...@@ -305,9 +305,9 @@ $(document).ready(function () {
success_message: success success_message: success
}); });
if (status === "False") { if (status === "False") {
$(".ibox-content > table > tbody > tr:nth-child(13) > td:last >b").html('True'); $(".ibox-content > table > tbody > tr:nth-child(13) > td:last >b").html('True');
}else{ }else{
$(".ibox-content > table > tbody > tr:nth-child(13) > td:last >b").html('False'); $(".ibox-content > table > tbody > tr:nth-child(13) > td:last >b").html('False');
} }
}).on('click', '#btn-update-nodes', function () { }).on('click', '#btn-update-nodes', function () {
if (Object.keys(jumpserver.nodes_selected).length === 0) { if (Object.keys(jumpserver.nodes_selected).length === 0) {
......
...@@ -59,57 +59,57 @@ ...@@ -59,57 +59,57 @@
<i class="fa fa-angle-left fa-x" id="toggle-icon"></i> <i class="fa fa-angle-left fa-x" id="toggle-icon"></i>
</div> </div>
</div> </div>
<div class="mail-box-header"> <div class="mail-box-header">
<div class="uc pull-left m-r-5"><a class="btn btn-sm btn-primary btn-create-asset"> {% trans "Create asset" %} </a></div> <div class="uc pull-left m-r-5"><a class="btn btn-sm btn-primary btn-create-asset"> {% trans "Create asset" %} </a></div>
<div class="html5buttons"> <div class="html5buttons">
<div class="dt-buttons btn-group"> <div class="dt-buttons btn-group">
<a class="btn btn-default btn_import" data-toggle="modal" data-target="#asset_import_modal" tabindex="0"> <a class="btn btn-default btn_import" data-toggle="modal" data-target="#asset_import_modal" tabindex="0">
<span>{% trans "Import" %}</span> <span>{% trans "Import" %}</span>
</a> </a>
<a class="btn btn-default btn_export" tabindex="0"> <a class="btn btn-default btn_export" tabindex="0">
<span>{% trans "Export" %}</span> <span>{% trans "Export" %}</span>
</a> </a>
</div>
</div>
<div class="btn-group" style="float: right">
<button data-toggle="dropdown" class="btn btn-default btn-sm dropdown-toggle">{% trans 'Label' %} <span class="caret"></span></button>
<ul class="dropdown-menu labels">
{% for label in labels %}
<li><a style="font-weight: bolder">{{ label.name }}:{{ label.value }}</a></li>
{% endfor %}
</ul>
</div> </div>
<table class="table table-striped table-bordered table-hover " id="asset_list_table" style="width: 100%"> </div>
<thead> <div class="btn-group" style="float: right">
<tr> <button data-toggle="dropdown" class="btn btn-default btn-sm dropdown-toggle">{% trans 'Label' %} <span class="caret"></span></button>
<th class="text-center"><input type="checkbox" class="ipt_check_all"></th> <ul class="dropdown-menu labels">
<th class="text-center">{% trans 'Hostname' %}</th> {% for label in labels %}
<th class="text-center">{% trans 'IP' %}</th> <li><a style="font-weight: bolder">{{ label.name }}:{{ label.value }}</a></li>
<th class="text-center">{% trans 'Hardware' %}</th> {% endfor %}
<th class="text-center">{% trans 'Active' %}</th> </ul>
<th class="text-center">{% trans 'Reachable' %}</th> </div>
<th class="text-center">{% trans 'Action' %}</th> <table class="table table-striped table-bordered table-hover " id="asset_list_table" style="width: 100%">
</tr> <thead>
</thead> <tr>
<tbody> <th class="text-center"><input type="checkbox" class="ipt_check_all"></th>
</tbody> <th class="text-center">{% trans 'Hostname' %}</th>
</table> <th class="text-center">{% trans 'IP' %}</th>
<div id="actions" class="hide"> <th class="text-center">{% trans 'Hardware' %}</th>
<div class="input-group"> <th class="text-center">{% trans 'Active' %}</th>
<select class="form-control m-b" style="width: auto" id="slct_bulk_update"> <th class="text-center">{% trans 'Reachable' %}</th>
<option value="delete">{% trans 'Delete selected' %}</option> <th class="text-center">{% trans 'Action' %}</th>
<option value="update">{% trans 'Update selected' %}</option> </tr>
<option value="remove">{% trans 'Remove from this node' %}</option> </thead>
<option value="deactive">{% trans 'Deactive selected' %}</option> <tbody>
<option value="active">{% trans 'Active selected' %}</option> </tbody>
</select> </table>
<div class="input-group-btn pull-left" style="padding-left: 5px;"> <div id="actions" class="hide">
<button id='btn_bulk_update' style="height: 32px;" class="btn btn-sm btn-primary"> <div class="input-group">
{% trans 'Submit' %} <select class="form-control m-b" style="width: auto" id="slct_bulk_update">
</button> <option value="delete">{% trans 'Delete selected' %}</option>
</div> <option value="update">{% trans 'Update selected' %}</option>
<option value="remove">{% trans 'Remove from this node' %}</option>
<option value="deactive">{% trans 'Deactive selected' %}</option>
<option value="active">{% trans 'Active 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> </div>
</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -117,15 +117,16 @@ ...@@ -117,15 +117,16 @@
<div id="rMenu"> <div id="rMenu">
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li id="menu_asset_create" class="btn-create-asset" tabindex="-1"><a>{% trans 'Create asset' %}</a></li>
<li id="menu_asset_add" class="btn-add-asset" data-toggle="modal" data-target="#asset_list_modal" tabindex="0"><a>{% trans 'Add asset' %}</a></li>
<li id="menu_refresh_hardware_info" class="btn-refresh-hardware" tabindex="-1"><a>{% trans 'Refresh node hardware info' %}</a></li>
<li id="menu_test_connective" class="btn-test-connective" tabindex="-1"><a>{% trans 'Test node connective' %}</a></li>
<li class="divider"></li> <li class="divider"></li>
<li id="m_create" tabindex="-1" onclick="addTreeNode();"><a>{% trans 'Add node' %}</a></li> <li id="m_create" tabindex="-1" onclick="addTreeNode();"><a><i class="fa fa-plus-square-o"></i> {% trans 'Add node' %}</a></li>
<li id="m_del" tabindex="-1" onclick="editTreeNode();"><a>{% trans 'Rename node' %}</a></li> <li id="m_del" tabindex="-1" onclick="editTreeNode();"><a><i class="fa fa-pencil-square-o"></i> {% trans 'Rename node' %}</a></li>
<li id="m_del" tabindex="-1" onclick="removeTreeNode();"><a><i class="fa fa-minus-square"></i> {% trans 'Delete node' %}</a></li>
<li class="divider"></li> <li class="divider"></li>
<li id="m_del" tabindex="-1" onclick="removeTreeNode();"><a>{% trans 'Delete node' %}</a></li> <li id="menu_asset_add" class="btn-add-asset" data-toggle="modal" data-target="#asset_list_modal" tabindex="0"><a><i class="fa fa-copy"></i> {% trans 'Add assets to node' %}</a></li>
<li id="menu_asset_move" class="btn-move-asset" data-toggle="modal" data-target="#asset_list_modal" tabindex="0"><a><i class="fa fa-cut"></i> {% trans 'Move assets to node' %}</a></li>
<li class="divider"></li>
<li id="menu_refresh_hardware_info" class="btn-refresh-hardware" tabindex="-1"><a><i class="fa fa-refresh"></i> {% trans 'Refresh node hardware info' %}</a></li>
<li id="menu_test_connective" class="btn-test-connective" tabindex="-1"><a><i class="fa fa-chain"></i> {% trans 'Test node connective' %}</a></li>
</ul> </ul>
</div> </div>
...@@ -136,6 +137,7 @@ ...@@ -136,6 +137,7 @@
{% block custom_foot_js %} {% block custom_foot_js %}
<script> <script>
var zTree, rMenu, asset_table, show = 0; var zTree, rMenu, asset_table, show = 0;
var update_node_action = "";
function initTable() { function initTable() {
var options = { var options = {
ele: $('#asset_list_table'), ele: $('#asset_list_table'),
...@@ -210,10 +212,11 @@ function removeTreeNode() { ...@@ -210,10 +212,11 @@ function removeTreeNode() {
if (!current_node){ if (!current_node){
return return
} }
if (current_node.children && current_node.children.length > 0) { if (current_node.children && current_node.children.length > 0) {
alert("{% trans 'Have child node, cancel' %}") toastr.error("{% trans 'Have child node, cancel' %}");
} else { } else if (current_node.assets_amount !== 0) {
toastr.error("{% trans 'Have assets, cancel' %}");
} else {
var url = "{% url 'api-assets:node-detail' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node.id ); var url = "{% url 'api-assets:node-detail' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node.id );
$.ajax({ $.ajax({
url: url, url: url,
...@@ -249,13 +252,6 @@ function OnRightClick(event, treeId, treeNode) { ...@@ -249,13 +252,6 @@ function OnRightClick(event, treeId, treeNode) {
function showRMenu(type, x, y) { function showRMenu(type, x, y) {
$("#rMenu ul").show(); $("#rMenu ul").show();
{#if (type === "root") {#}
{# return#}
{# } else {#}
{# $("#m_del").show();#}
{# $("#m_check").show();#}
{# $("#m_unCheck").show();#}
{# }#}
x -= 220; x -= 220;
rMenu.css({"top":y+"px", "left":x+"px", "visibility":"visible"}); rMenu.css({"top":y+"px", "left":x+"px", "visibility":"visible"});
...@@ -459,7 +455,8 @@ $(document).ready(function(){ ...@@ -459,7 +455,8 @@ $(document).ready(function(){
var current_node; var current_node;
if (nodes && nodes.length ===1 ){ if (nodes && nodes.length ===1 ){
current_node = nodes[0]; current_node = nodes[0];
action += "?node_id=" + current_node.id; action = setUrlParam(action, 'node_id', current_node.id);
{#action += "?node_id=" + current_node.id;#}
$form.attr("action", action) $form.attr("action", action)
} }
$form.find('.help-block').remove(); $form.find('.help-block').remove();
...@@ -673,7 +670,45 @@ $(document).ready(function(){ ...@@ -673,7 +670,45 @@ $(document).ready(function(){
break; break;
} }
$(".ipt_check_all").prop("checked", false) $(".ipt_check_all").prop("checked", false)
}); })
.on('click', '#btn_asset_modal_confirm', function () {
var assets_selected = asset_table2.selected;
var current_node;
var nodes = zTree.getSelectedNodes();
if (nodes && nodes.length === 1) {
current_node = nodes[0]
} else {
return
}
var data = {
'assets': assets_selected
};
var success = function () {
asset_table2.selected = [];
asset_table2.ajax.reload()
};
var url = '';
if (update_node_action === "move") {
url = "{% url 'api-assets:node-replace-assets' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node.id);
} else {
url = "{% url 'api-assets:node-add-assets' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node.id);
}
APIUpdateAttr({
'url': url,
'method': 'PUT',
'body': JSON.stringify(data),
'success': success
})
}).on('hidden.bs.modal', '#asset_list_modal', function () {
window.location.reload();
}).on('click', '#menu_asset_add', function () {
update_node_action = "add"
}).on('click', '#menu_asset_move', function () {
update_node_action = "move"
})
</script> </script>
{% endblock %} {% endblock %}
\ No newline at end of file
...@@ -18,14 +18,25 @@ ...@@ -18,14 +18,25 @@
</div> </div>
</div> </div>
</form> </form>
{% include 'assets/_asset_list_modal.html' %}
{% endblock %} {% endblock %}
{% block custom_foot_js %} {% block custom_foot_js %}
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function () { $(document).ready(function () {
$('.select2').select2({ console.log($.fn.select2.defaults);
closeOnSelect: false $('.select2').select2().off("select2:open");
}); }).on('click', '.select2-selection__rendered', function (e) {
e.preventDefault();
$("#asset_list_modal").modal();
})
.on('click', '#btn_asset_modal_confirm', function () {
var assets = asset_table2.selected;
$.each(assets, function (id, data) {
$('.select2').val(assets).trigger('change');
}); });
$("#asset_list_modal").modal('hide');
})
</script> </script>
{% endblock %} {% endblock %}
\ No newline at end of file
...@@ -81,11 +81,6 @@ function initTable() { ...@@ -81,11 +81,6 @@ function initTable() {
var options = { var options = {
ele: $('#domain_list_table'), ele: $('#domain_list_table'),
columnDefs: [ columnDefs: [
{targets: 1, createdCell: function (td, cellData, rowData) {
var detail_btn = '<a href="{% url "assets:domain-detail" pk=DEFAULT_PK %}">' + cellData + '</a>';
$(td).html(detail_btn.replace('{{ DEFAULT_PK }}', rowData.id));
}},
{targets: 7, createdCell: function (td, cellData, rowData) { {targets: 7, createdCell: function (td, cellData, rowData) {
var update_btn = '<a href="{% url "assets:domain-gateway-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('{{ DEFAULT_PK }}', cellData); var update_btn = '<a href="{% url "assets:domain-gateway-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn-delete" data-uid="{{ DEFAULT_PK }}">{% trans "Delete" %}</a>'.replace('{{ DEFAULT_PK }}', cellData); var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn-delete" data-uid="{{ DEFAULT_PK }}">{% trans "Delete" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
{% load bootstrap3 %} {% load bootstrap3 %}
{% load i18n %} {% load i18n %}
{% block form %} {% block form %}
<form id="groupForm" method="post" class="form-horizontal"> <form id="groupForm" method="post" class="form-horizontal">
{% csrf_token %} {% csrf_token %}
...@@ -18,14 +20,28 @@ ...@@ -18,14 +20,28 @@
</div> </div>
</div> </div>
</form> </form>
{% include 'assets/_asset_list_modal.html' %}
{% endblock %} {% endblock %}
{% block custom_foot_js %} {% block custom_foot_js %}
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function () { $(document).ready(function () {
$('.select2').select2({ $('.select2').select2({
closeOnSelect: false closeOnSelect: false
}); })
}).on('click', '.select2-selection__rendered', function (e) {
e.preventDefault();
$("#asset_list_modal").modal();
})
.on('click', '#btn_asset_modal_confirm', function () {
var assets = asset_table2.selected;
$('.select2 option:selected').each(function (i, data) {
assets.push($(data).attr('value'))
});
$.each(assets, function (id, data) {
$('.select2').val(assets).trigger('change');
}); });
$("#asset_list_modal").modal('hide');
})
</script> </script>
{% endblock %} {% endblock %}
\ No newline at end of file
...@@ -173,7 +173,7 @@ ...@@ -173,7 +173,7 @@
<td colspan="2" class="no-borders"> <td colspan="2" class="no-borders">
<select data-placeholder="{% trans 'Add to node' %}" id="node_selected" class="select2" style="width: 100%" multiple="" tabindex="4"> <select data-placeholder="{% trans 'Add to node' %}" id="node_selected" class="select2" style="width: 100%" multiple="" tabindex="4">
{% for node in nodes_remain %} {% for node in nodes_remain %}
<option value="{{ node.id }}" id="opt_{{ node.id }}" >{{ node.name }}</option> <option value="{{ node.id }}" id="opt_{{ node.id }}" >{{ node }}</option>
{% endfor %} {% endfor %}
</select> </select>
</td> </td>
...@@ -187,7 +187,7 @@ ...@@ -187,7 +187,7 @@
{% for node in system_user.nodes.all %} {% for node in system_user.nodes.all %}
<tr> <tr>
<td ><b class="bdg_node" data-gid={{ node.id }}>{{ node.name }}</b></td> <td ><b class="bdg_node" data-gid={{ node.id }}>{{ node }}</b></td>
<td> <td>
<button class="btn btn-danger pull-right btn-xs btn-remove-from-node" type="button"><i class="fa fa-minus"></i></button> <button class="btn btn-danger pull-right btn-xs btn-remove-from-node" type="button"><i class="fa fa-minus"></i></button>
</td> </td>
......
...@@ -40,6 +40,7 @@ urlpatterns = [ ...@@ -40,6 +40,7 @@ urlpatterns = [
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})/children/add/$', api.NodeAddChildrenApi.as_view(), name='node-add-children'),
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/$', api.NodeAssetsApi.as_view(), name='node-assets'), url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/$', api.NodeAssetsApi.as_view(), name='node-assets'),
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/add/$', api.NodeAddAssetsApi.as_view(), name='node-add-assets'),
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/replace/$', api.NodeReplaceAssetsApi.as_view(), name='node-replace-assets'),
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/remove/$', api.NodeRemoveAssetsApi.as_view(), name='node-remove-assets'), url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/assets/remove/$', api.NodeRemoveAssetsApi.as_view(), name='node-remove-assets'),
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/refresh-hardware-info/$', api.RefreshNodeHardwareInfoApi.as_view(), name='node-refresh-hardware-info'), url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/refresh-hardware-info/$', api.RefreshNodeHardwareInfoApi.as_view(), name='node-refresh-hardware-info'),
url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/test-connective/$', api.TestNodeConnectiveApi.as_view(), name='node-test-connective'), url(r'^v1/nodes/(?P<pk>[0-9a-zA-Z\-]{36})/test-connective/$', api.TestNodeConnectiveApi.as_view(), name='node-test-connective'),
......
...@@ -49,6 +49,7 @@ class AssetListView(AdminUserRequiredMixin, TemplateView): ...@@ -49,6 +49,7 @@ class AssetListView(AdminUserRequiredMixin, TemplateView):
'app': _('Assets'), 'app': _('Assets'),
'action': _('Asset list'), 'action': _('Asset list'),
'labels': Label.objects.all().order_by('name'), 'labels': Label.objects.all().order_by('name'),
'nodes': Node.objects.all().order_by('-key'),
} }
kwargs.update(context) kwargs.update(context)
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
...@@ -284,24 +285,26 @@ class BulkImportAssetView(AdminUserRequiredMixin, JSONResponseMixin, FormView): ...@@ -284,24 +285,26 @@ class BulkImportAssetView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
if set(row) == {''}: if set(row) == {''}:
continue continue
asset_dict = dict(zip(attr, row)) asset_dict_raw = dict(zip(attr, row))
id_ = asset_dict.pop('id', 0) asset_dict = dict()
for k, v in asset_dict.items(): for k, v in asset_dict_raw.items():
v = v.strip() v = v.strip()
if k == 'is_active': if k == 'is_active':
v = True if v in ['TRUE', 1, 'true'] else False v = False if v in ['False', 0, 'false'] else True
elif k == 'admin_user': elif k == 'admin_user':
v = get_object_or_none(AdminUser, name=v) v = get_object_or_none(AdminUser, name=v)
elif k in ['port', 'cpu_count', 'cpu_cores']: elif k in ['port', 'cpu_count', 'cpu_cores']:
try: try:
v = int(v) v = int(v)
except ValueError: except ValueError:
v = 0 v = ''
elif k == 'domain': elif k == 'domain':
v = get_object_or_none(Domain, name=v) v = get_object_or_none(Domain, name=v)
asset_dict[k] = v
asset = get_object_or_none(Asset, id=id_) if is_uuid(id_) else None if v != '':
asset_dict[k] = v
asset = get_object_or_none(Asset, id=asset_dict.pop('id', 0))
if not asset: if not asset:
try: try:
if len(Asset.objects.filter(hostname=asset_dict.get('hostname'))): if len(Asset.objects.filter(hostname=asset_dict.get('hostname'))):
...@@ -316,7 +319,7 @@ class BulkImportAssetView(AdminUserRequiredMixin, JSONResponseMixin, FormView): ...@@ -316,7 +319,7 @@ class BulkImportAssetView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
failed.append('%s: %s' % (asset_dict['hostname'], str(e))) failed.append('%s: %s' % (asset_dict['hostname'], str(e)))
else: else:
for k, v in asset_dict.items(): for k, v in asset_dict.items():
if v: if v != '':
setattr(asset, k, v) setattr(asset, k, v)
try: try:
asset.save() asset.save()
......
...@@ -2,11 +2,15 @@ ...@@ -2,11 +2,15 @@
# #
import json import json
from django.db import models
from django import forms from django import forms
from django.utils import six from django.utils import six
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from rest_framework import serializers from rest_framework import serializers
from .utils import get_signer
signer = get_signer()
class DictField(forms.Field): class DictField(forms.Field):
...@@ -46,4 +50,27 @@ class StringIDField(serializers.Field): ...@@ -46,4 +50,27 @@ class StringIDField(serializers.Field):
class StringManyToManyField(serializers.RelatedField): class StringManyToManyField(serializers.RelatedField):
def to_representation(self, value): def to_representation(self, value):
return value.__str__() return value.__str__()
\ No newline at end of file
class EncryptMixin:
def from_db_value(self, value, expression, connection, context):
if value is not None:
return signer.unsign(value)
return super().from_db_value(self, value, expression, connection, context)
def get_prep_value(self, value):
if value is None:
return value
return signer.sign(value).decode('utf-8')
class EncryptTextField(EncryptMixin, models.TextField):
description = _("Encrypt field using Secret Key")
class EncryptCharField(EncryptMixin, models.CharField):
def __init__(self, *args, **kwargs):
kwargs['max_length'] = 2048
super().__init__(*args, **kwargs)
...@@ -8,7 +8,7 @@ msgid "" ...@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Jumpserver 0.3.3\n" "Project-Id-Version: Jumpserver 0.3.3\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-04-06 10:24+0800\n" "POT-Creation-Date: 2018-04-13 17:27+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: ibuler <ibuler@qq.com>\n" "Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: Jumpserver team<ibuler@qq.com>\n" "Language-Team: Jumpserver team<ibuler@qq.com>\n"
...@@ -17,45 +17,57 @@ msgstr "" ...@@ -17,45 +17,57 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
#: assets/api/node.py:58 #: assets/api/node.py:88
msgid "New node {}" msgid "New node {}"
msgstr "新节点 {}" msgstr "新节点 {}"
#: assets/api/node.py:133 #: assets/api/node.py:216
msgid "更新节点资产硬件信息: {}" msgid "更新节点资产硬件信息: {}"
msgstr "" msgstr ""
#: assets/api/node.py:146 #: assets/api/node.py:229
msgid "测试节点下资产是否可连接: {}" msgid "测试节点下资产是否可连接: {}"
msgstr "" msgstr ""
#: assets/forms/asset.py:24 assets/forms/asset.py:60 assets/models/asset.py:53 #: assets/forms/asset.py:24 assets/models/asset.py:54 assets/models/user.py:103
#: assets/models/user.py:102 assets/templates/assets/asset_detail.html:183 #: assets/templates/assets/asset_detail.html:183
#: assets/templates/assets/asset_detail.html:191 #: assets/templates/assets/asset_detail.html:191
#: assets/templates/assets/system_user_detail.html:166 #: assets/templates/assets/system_user_detail.html:166 perms/models.py:23
msgid "Nodes" msgid "Nodes"
msgstr "节点管理" msgstr "节点管理"
#: assets/forms/asset.py:27 assets/forms/asset.py:63 assets/forms/asset.py:103 #: assets/forms/asset.py:27 assets/forms/asset.py:66 assets/forms/asset.py:109
#: assets/forms/asset.py:107 assets/models/asset.py:57 #: assets/forms/asset.py:113 assets/models/asset.py:58
#: assets/models/cluster.py:19 assets/models/user.py:71 #: assets/models/cluster.py:19 assets/models/user.py:72
#: assets/templates/assets/asset_detail.html:73 templates/_nav.html:25 #: assets/templates/assets/asset_detail.html:73 templates/_nav.html:25
msgid "Admin user" msgid "Admin user"
msgstr "管理用户" msgstr "管理用户"
#: assets/forms/asset.py:30 assets/forms/asset.py:66 assets/models/asset.py:81 #: assets/forms/asset.py:30 assets/forms/asset.py:69 assets/forms/asset.py:125
#: assets/templates/assets/asset_create.html:33 #: assets/templates/assets/asset_create.html:35
#: assets/templates/assets/asset_detail.html:220 #: assets/templates/assets/asset_create.html:37
#: assets/templates/assets/asset_update.html:38 templates/_nav.html:27 #: assets/templates/assets/asset_list.html:75
msgid "Labels" #: assets/templates/assets/asset_update.html:40
msgstr "标签管理" #: assets/templates/assets/asset_update.html:42
#: assets/templates/assets/user_asset_list.html:34
msgid "Label"
msgstr "标签"
#: assets/forms/asset.py:34 assets/forms/asset.py:70 assets/models/asset.py:52 #: assets/forms/asset.py:34 assets/forms/asset.py:73 assets/models/asset.py:53
#: assets/models/domain.py:46 #: assets/models/domain.py:46
msgid "Domain" msgid "Domain"
msgstr "网域" msgstr "网域"
#: assets/forms/asset.py:42 assets/forms/asset.py:79 #: assets/forms/asset.py:38 assets/forms/asset.py:63 assets/forms/asset.py:77
#: assets/forms/asset.py:128 assets/templates/assets/asset_create.html:29
#: assets/templates/assets/asset_update.html:34 perms/forms.py:40
#: perms/forms.py:47 perms/models.py:67
#: perms/templates/perms/asset_permission_list.html:57
#: perms/templates/perms/asset_permission_list.html:142
msgid "Node"
msgstr "节点"
#: assets/forms/asset.py:45 assets/forms/asset.py:85
msgid "" msgid ""
"root or other NOPASSWD sudo privilege user existed in asset,If asset is " "root or other NOPASSWD sudo privilege user existed in asset,If asset is "
"windows or other set any one, more see admin user left menu" "windows or other set any one, more see admin user left menu"
...@@ -63,46 +75,41 @@ msgstr "" ...@@ -63,46 +75,41 @@ msgstr ""
"root或其他拥有NOPASSWD: ALL权限的用户, 如果是windows或其它硬件可以随意设置一" "root或其他拥有NOPASSWD: ALL权限的用户, 如果是windows或其它硬件可以随意设置一"
"个, 更多信息查看左侧 `管理用户` 菜单" "个, 更多信息查看左侧 `管理用户` 菜单"
#: assets/forms/asset.py:45 assets/forms/asset.py:82 #: assets/forms/asset.py:48 assets/forms/asset.py:88
msgid "* required Must set exact system platform, Windows, Linux ..." msgid "* required Must set exact system platform, Windows, Linux ..."
msgstr "* required 必须准确设置操作系统平台,如Windows, Linux ..." msgstr "* required 必须准确设置操作系统平台,如Windows, Linux ..."
#: assets/forms/asset.py:46 assets/forms/asset.py:83 #: assets/forms/asset.py:49 assets/forms/asset.py:89
msgid "" msgid ""
"If your have some network not connect with each other, you can set domain" "If your have some network not connect with each other, you can set domain"
msgstr "如果有多个的互相隔离的网络,设置资产属于的网域,使用网域网关跳转登录" msgstr "如果有多个的互相隔离的网络,设置资产属于的网域,使用网域网关跳转登录"
#: assets/forms/asset.py:90 assets/forms/asset.py:94 assets/forms/domain.py:16 #: assets/forms/asset.py:96 assets/forms/asset.py:100 assets/forms/domain.py:16
#: assets/forms/label.py:15 #: assets/forms/label.py:15
#: perms/templates/perms/asset_permission_asset.html:88 users/forms.py:272 #: perms/templates/perms/asset_permission_asset.html:88
msgid "Select assets" msgid "Select assets"
msgstr "选择资产" msgstr "选择资产"
#: assets/forms/asset.py:99 assets/models/asset.py:51 #: assets/forms/asset.py:105 assets/models/asset.py:51
#: assets/models/domain.py:44 assets/templates/assets/admin_user_assets.html:53 #: assets/models/domain.py:44 assets/templates/assets/admin_user_assets.html:53
#: assets/templates/assets/asset_detail.html:69 #: assets/templates/assets/asset_detail.html:69
#: assets/templates/assets/domain_gateway_list.html:58 #: assets/templates/assets/domain_gateway_list.html:58
#: assets/templates/assets/system_user_asset.html:51 #: assets/templates/assets/system_user_asset.html:51
#: assets/templates/assets/user_asset_list.html:21
msgid "Port" msgid "Port"
msgstr "端口" msgstr "端口"
#: assets/forms/asset.py:119 assets/templates/assets/asset_create.html:37
msgid "Select labels"
msgstr "选择标签"
#: assets/forms/asset.py:122 assets/templates/assets/admin_user_detail.html:91
msgid "Select nodes"
msgstr "选择节点"
#: assets/forms/domain.py:14 assets/forms/label.py:13 #: assets/forms/domain.py:14 assets/forms/label.py:13
#: assets/models/asset.py:165 assets/templates/assets/admin_user_list.html:25 #: assets/models/asset.py:169 assets/templates/assets/admin_user_list.html:25
#: assets/templates/assets/domain_detail.html:60 #: assets/templates/assets/domain_detail.html:60
#: assets/templates/assets/domain_list.html:15 #: assets/templates/assets/domain_list.html:15
#: assets/templates/assets/label_list.html:16 #: assets/templates/assets/label_list.html:16
#: assets/templates/assets/system_user_list.html:29 audits/models.py:11 #: assets/templates/assets/system_user_list.html:29 audits/models.py:11
#: audits/templates/audits/ftp_log_list.html:41 #: audits/templates/audits/ftp_log_list.html:41
#: audits/templates/audits/ftp_log_list.html:72 perms/models.py:17 #: audits/templates/audits/ftp_log_list.html:72 perms/forms.py:37
#: perms/models.py:22
#: perms/templates/perms/asset_permission_create_update.html:40
#: perms/templates/perms/asset_permission_list.html:56
#: perms/templates/perms/asset_permission_list.html:139
#: terminal/backends/command/models.py:11 terminal/models.py:123 #: terminal/backends/command/models.py:11 terminal/models.py:123
#: terminal/templates/terminal/command_list.html:40 #: terminal/templates/terminal/command_list.html:40
#: terminal/templates/terminal/command_list.html:73 #: terminal/templates/terminal/command_list.html:73
...@@ -125,11 +132,12 @@ msgstr "资产" ...@@ -125,11 +132,12 @@ msgstr "资产"
#: common/templates/common/terminal_setting.html:67 #: common/templates/common/terminal_setting.html:67
#: common/templates/common/terminal_setting.html:85 ops/models/adhoc.py:36 #: common/templates/common/terminal_setting.html:85 ops/models/adhoc.py:36
#: ops/templates/ops/task_detail.html:59 ops/templates/ops/task_list.html:35 #: ops/templates/ops/task_detail.html:59 ops/templates/ops/task_list.html:35
#: perms/models.py:14 perms/templates/perms/asset_permission_detail.html:62 #: perms/models.py:19 perms/templates/perms/asset_permission_detail.html:62
#: perms/templates/perms/asset_permission_list.html:53
#: perms/templates/perms/asset_permission_user.html:54 terminal/models.py:16 #: perms/templates/perms/asset_permission_user.html:54 terminal/models.py:16
#: terminal/models.py:149 terminal/templates/terminal/terminal_detail.html:43 #: terminal/models.py:149 terminal/templates/terminal/terminal_detail.html:43
#: terminal/templates/terminal/terminal_list.html:29 users/models/group.py:14 #: 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/models/user.py:40 users/templates/users/_select_user_modal.html:13
#: users/templates/users/user_detail.html:63 #: users/templates/users/user_detail.html:63
#: users/templates/users/user_group_detail.html:55 #: users/templates/users/user_group_detail.html:55
#: users/templates/users/user_group_list.html:12 #: users/templates/users/user_group_list.html:12
...@@ -145,8 +153,8 @@ msgstr "名称" ...@@ -145,8 +153,8 @@ msgstr "名称"
#: assets/templates/assets/domain_gateway_list.html:60 #: assets/templates/assets/domain_gateway_list.html:60
#: assets/templates/assets/system_user_detail.html:62 #: assets/templates/assets/system_user_detail.html:62
#: assets/templates/assets/system_user_list.html:27 #: assets/templates/assets/system_user_list.html:27
#: perms/templates/perms/asset_permission_user.html:55 users/forms.py:14 #: perms/templates/perms/asset_permission_user.html:55 users/forms.py:13
#: users/models/authentication.py:45 users/models/user.py:34 #: users/models/authentication.py:45 users/models/user.py:39
#: users/templates/users/_select_user_modal.html:14 #: users/templates/users/_select_user_modal.html:14
#: users/templates/users/login.html:56 #: users/templates/users/login.html:56
#: users/templates/users/login_log_list.html:49 #: users/templates/users/login_log_list.html:49
...@@ -161,7 +169,7 @@ msgid "Password or private key passphrase" ...@@ -161,7 +169,7 @@ msgid "Password or private key passphrase"
msgstr "密码或密钥密码" msgstr "密码或密钥密码"
#: assets/forms/user.py:25 assets/models/base.py:22 common/forms.py:113 #: assets/forms/user.py:25 assets/models/base.py:22 common/forms.py:113
#: users/forms.py:16 users/forms.py:25 users/templates/users/login.html:59 #: users/forms.py:15 users/forms.py:24 users/templates/users/login.html:59
#: users/templates/users/reset_password.html:52 #: users/templates/users/reset_password.html:52
#: users/templates/users/user_create.html:11 #: users/templates/users/user_create.html:11
#: users/templates/users/user_password_update.html:40 #: users/templates/users/user_password_update.html:40
...@@ -170,7 +178,7 @@ msgstr "密码或密钥密码" ...@@ -170,7 +178,7 @@ msgstr "密码或密钥密码"
msgid "Password" msgid "Password"
msgstr "密码" msgstr "密码"
#: assets/forms/user.py:28 users/models/user.py:45 #: assets/forms/user.py:28 users/models/user.py:50
msgid "Private key" msgid "Private key"
msgstr "ssh私钥" msgstr "ssh私钥"
...@@ -193,13 +201,13 @@ msgid "" ...@@ -193,13 +201,13 @@ msgid ""
msgstr "高优先级的系统用户将会作为默认登录用户" msgstr "高优先级的系统用户将会作为默认登录用户"
#: assets/models/asset.py:49 assets/models/domain.py:43 #: assets/models/asset.py:49 assets/models/domain.py:43
#: assets/templates/assets/_asset_list_modal.html:21 #: assets/templates/assets/_asset_list_modal.html:46
#: assets/templates/assets/admin_user_assets.html:52 #: assets/templates/assets/admin_user_assets.html:52
#: assets/templates/assets/asset_detail.html:61 #: assets/templates/assets/asset_detail.html:61
#: assets/templates/assets/asset_list.html:87 #: assets/templates/assets/asset_list.html:87
#: assets/templates/assets/domain_gateway_list.html:57 #: assets/templates/assets/domain_gateway_list.html:57
#: assets/templates/assets/system_user_asset.html:50 #: assets/templates/assets/system_user_asset.html:50
#: assets/templates/assets/user_asset_list.html:20 common/forms.py:144 #: assets/templates/assets/user_asset_list.html:46 common/forms.py:144
#: perms/templates/perms/asset_permission_asset.html:55 #: perms/templates/perms/asset_permission_asset.html:55
#: users/templates/users/login_log_list.html:52 #: users/templates/users/login_log_list.html:52
#: users/templates/users/user_granted_asset.html:45 #: users/templates/users/user_granted_asset.html:45
...@@ -207,72 +215,71 @@ msgstr "高优先级的系统用户将会作为默认登录用户" ...@@ -207,72 +215,71 @@ msgstr "高优先级的系统用户将会作为默认登录用户"
msgid "IP" msgid "IP"
msgstr "IP" msgstr "IP"
#: assets/models/asset.py:50 assets/templates/assets/_asset_list_modal.html:20 #: assets/models/asset.py:50 assets/templates/assets/_asset_list_modal.html:45
#: assets/templates/assets/admin_user_assets.html:51 #: assets/templates/assets/admin_user_assets.html:51
#: assets/templates/assets/asset_detail.html:57 #: assets/templates/assets/asset_detail.html:57
#: assets/templates/assets/asset_list.html:86 #: assets/templates/assets/asset_list.html:86
#: assets/templates/assets/system_user_asset.html:49 #: assets/templates/assets/system_user_asset.html:49
#: assets/templates/assets/user_asset_list.html:19 common/forms.py:143 #: assets/templates/assets/user_asset_list.html:45 common/forms.py:143
#: perms/templates/perms/asset_permission_asset.html:54 #: perms/templates/perms/asset_permission_asset.html:54
#: users/templates/users/user_granted_asset.html:44 #: users/templates/users/user_granted_asset.html:44
#: users/templates/users/user_group_granted_asset.html:44 #: users/templates/users/user_group_granted_asset.html:44
msgid "Hostname" msgid "Hostname"
msgstr "主机名" msgstr "主机名"
#: assets/models/asset.py:54 assets/models/domain.py:48 #: assets/models/asset.py:52 assets/templates/assets/asset_detail.html:97
msgid "Platform"
msgstr "系统平台"
#: assets/models/asset.py:55 assets/models/domain.py:48
#: assets/models/label.py:20 assets/templates/assets/asset_detail.html:105 #: assets/models/label.py:20 assets/templates/assets/asset_detail.html:105
#: perms/templates/perms/asset_permission_list.html:70
msgid "Is active" msgid "Is active"
msgstr "激活" msgstr "激活"
#: assets/models/asset.py:60 assets/templates/assets/asset_detail.html:65 #: assets/models/asset.py:61 assets/templates/assets/asset_detail.html:65
msgid "Public IP" msgid "Public IP"
msgstr "公网IP" msgstr "公网IP"
#: assets/models/asset.py:61 assets/templates/assets/asset_detail.html:113 #: assets/models/asset.py:62 assets/templates/assets/asset_detail.html:113
msgid "Asset number" msgid "Asset number"
msgstr "资产编号" msgstr "资产编号"
#: assets/models/asset.py:64 assets/templates/assets/asset_detail.html:77 #: assets/models/asset.py:65 assets/templates/assets/asset_detail.html:77
msgid "Vendor" msgid "Vendor"
msgstr "制造商" msgstr "制造商"
#: assets/models/asset.py:65 assets/templates/assets/asset_detail.html:81 #: assets/models/asset.py:66 assets/templates/assets/asset_detail.html:81
msgid "Model" msgid "Model"
msgstr "型号" msgstr "型号"
#: assets/models/asset.py:66 assets/templates/assets/asset_detail.html:109 #: assets/models/asset.py:67 assets/templates/assets/asset_detail.html:109
msgid "Serial number" msgid "Serial number"
msgstr "序列号" msgstr "序列号"
#: assets/models/asset.py:68 #: assets/models/asset.py:69
msgid "CPU model" msgid "CPU model"
msgstr "CPU型号" msgstr "CPU型号"
#: assets/models/asset.py:69 #: assets/models/asset.py:70
msgid "CPU count" msgid "CPU count"
msgstr "CPU数量" msgstr "CPU数量"
#: assets/models/asset.py:70 #: assets/models/asset.py:71
msgid "CPU cores" msgid "CPU cores"
msgstr "CPU核数" msgstr "CPU核数"
#: assets/models/asset.py:71 assets/templates/assets/asset_detail.html:89 #: assets/models/asset.py:72 assets/templates/assets/asset_detail.html:89
msgid "Memory" msgid "Memory"
msgstr "内存" msgstr "内存"
#: assets/models/asset.py:72 #: assets/models/asset.py:73
msgid "Disk total" msgid "Disk total"
msgstr "硬盘大小" msgstr "硬盘大小"
#: assets/models/asset.py:73 #: assets/models/asset.py:74
msgid "Disk info" msgid "Disk info"
msgstr "硬盘信息" msgstr "硬盘信息"
#: assets/models/asset.py:75 assets/templates/assets/asset_detail.html:97
msgid "Platform"
msgstr "系统平台"
#: assets/models/asset.py:76 assets/templates/assets/asset_detail.html:101 #: assets/models/asset.py:76 assets/templates/assets/asset_detail.html:101
msgid "OS" msgid "OS"
msgstr "操作系统" msgstr "操作系统"
...@@ -289,15 +296,21 @@ msgstr "系统架构" ...@@ -289,15 +296,21 @@ msgstr "系统架构"
msgid "Hostname raw" msgid "Hostname raw"
msgstr "主机名原始" msgstr "主机名原始"
#: assets/models/asset.py:81 assets/templates/assets/asset_create.html:33
#: assets/templates/assets/asset_detail.html:220
#: assets/templates/assets/asset_update.html:38 templates/_nav.html:27
msgid "Labels"
msgstr "标签管理"
#: assets/models/asset.py:82 assets/models/base.py:28 #: assets/models/asset.py:82 assets/models/base.py:28
#: assets/models/cluster.py:28 assets/models/group.py:21 #: assets/models/cluster.py:28 assets/models/group.py:21
#: assets/templates/assets/admin_user_detail.html:68 #: assets/templates/assets/admin_user_detail.html:68
#: assets/templates/assets/asset_detail.html:117 #: assets/templates/assets/asset_detail.html:117
#: assets/templates/assets/domain_detail.html:72 #: assets/templates/assets/domain_detail.html:72
#: assets/templates/assets/system_user_detail.html:96 #: assets/templates/assets/system_user_detail.html:96
#: ops/templates/ops/adhoc_detail.html:86 perms/models.py:22 perms/models.py:79 #: ops/templates/ops/adhoc_detail.html:86 perms/models.py:28 perms/models.py:72
#: perms/templates/perms/asset_permission_detail.html:94 #: perms/templates/perms/asset_permission_detail.html:98
#: users/models/user.py:50 users/templates/users/user_detail.html:99 #: users/models/user.py:55 users/templates/users/user_detail.html:99
msgid "Created by" msgid "Created by"
msgstr "创建者" msgstr "创建者"
...@@ -307,8 +320,8 @@ msgstr "创建者" ...@@ -307,8 +320,8 @@ msgstr "创建者"
#: assets/templates/assets/domain_detail.html:68 #: assets/templates/assets/domain_detail.html:68
#: assets/templates/assets/system_user_detail.html:92 #: assets/templates/assets/system_user_detail.html:92
#: ops/templates/ops/adhoc_detail.html:90 ops/templates/ops/task_detail.html:63 #: ops/templates/ops/adhoc_detail.html:90 ops/templates/ops/task_detail.html:63
#: perms/models.py:23 perms/models.py:80 #: perms/models.py:29 perms/models.py:73
#: perms/templates/perms/asset_permission_detail.html:90 #: perms/templates/perms/asset_permission_detail.html:94
#: terminal/templates/terminal/terminal_detail.html:59 users/models/group.py:17 #: terminal/templates/terminal/terminal_detail.html:59 users/models/group.py:17
#: users/templates/users/user_group_detail.html:63 #: users/templates/users/user_group_detail.html:63
msgid "Date created" msgid "Date created"
...@@ -325,10 +338,10 @@ msgstr "创建日期" ...@@ -325,10 +338,10 @@ msgstr "创建日期"
#: assets/templates/assets/domain_list.html:17 #: assets/templates/assets/domain_list.html:17
#: assets/templates/assets/system_user_detail.html:100 #: assets/templates/assets/system_user_detail.html:100
#: assets/templates/assets/system_user_list.html:33 common/models.py:30 #: assets/templates/assets/system_user_list.html:33 common/models.py:30
#: ops/models/adhoc.py:42 perms/models.py:24 perms/models.py:81 #: ops/models/adhoc.py:42 perms/models.py:30 perms/models.py:74
#: perms/templates/perms/asset_permission_detail.html:98 terminal/models.py:26 #: perms/templates/perms/asset_permission_detail.html:102 terminal/models.py:26
#: terminal/templates/terminal/terminal_detail.html:63 users/models/group.py:15 #: 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/models/user.py:52 users/templates/users/user_detail.html:111
#: users/templates/users/user_group_detail.html:67 #: users/templates/users/user_group_detail.html:67
#: users/templates/users/user_group_list.html:14 #: users/templates/users/user_group_list.html:14
#: users/templates/users/user_profile.html:114 #: users/templates/users/user_profile.html:114
...@@ -351,7 +364,7 @@ msgstr "带宽" ...@@ -351,7 +364,7 @@ msgstr "带宽"
msgid "Contact" msgid "Contact"
msgstr "联系人" msgstr "联系人"
#: assets/models/cluster.py:22 users/models/user.py:41 #: assets/models/cluster.py:22 users/models/user.py:46
#: users/templates/users/user_detail.html:76 #: users/templates/users/user_detail.html:76
msgid "Phone" msgid "Phone"
msgstr "手机" msgstr "手机"
...@@ -377,7 +390,7 @@ msgid "Default" ...@@ -377,7 +390,7 @@ msgid "Default"
msgstr "默认" msgstr "默认"
#: assets/models/cluster.py:36 assets/models/label.py:13 #: assets/models/cluster.py:36 assets/models/label.py:13
#: users/models/user.py:266 #: users/models/user.py:285
msgid "System" msgid "System"
msgstr "系统" msgstr "系统"
...@@ -389,14 +402,14 @@ msgstr "默认Cluster" ...@@ -389,14 +402,14 @@ msgstr "默认Cluster"
msgid "Cluster" msgid "Cluster"
msgstr "集群" msgstr "集群"
#: assets/models/domain.py:45 assets/models/user.py:104 #: assets/models/domain.py:45 assets/models/user.py:106
#: assets/templates/assets/domain_gateway_list.html:59 #: assets/templates/assets/domain_gateway_list.html:59
#: assets/templates/assets/system_user_detail.html:66 #: assets/templates/assets/system_user_detail.html:66
#: assets/templates/assets/system_user_list.html:28 #: assets/templates/assets/system_user_list.html:28
msgid "Protocol" msgid "Protocol"
msgstr "协议" msgstr "协议"
#: assets/models/group.py:30 perms/models.py:18 #: assets/models/group.py:30
msgid "Asset group" msgid "Asset group"
msgstr "资产组" msgstr "资产组"
...@@ -406,15 +419,19 @@ msgstr "默认资产组" ...@@ -406,15 +419,19 @@ msgstr "默认资产组"
#: assets/models/label.py:14 audits/models.py:9 #: assets/models/label.py:14 audits/models.py:9
#: audits/templates/audits/ftp_log_list.html:33 #: audits/templates/audits/ftp_log_list.html:33
#: audits/templates/audits/ftp_log_list.html:71 perms/models.py:15 #: audits/templates/audits/ftp_log_list.html:71 perms/forms.py:14
#: perms/forms.py:31 perms/models.py:20
#: perms/templates/perms/asset_permission_create_update.html:36
#: perms/templates/perms/asset_permission_list.html:54
#: perms/templates/perms/asset_permission_list.html:133
#: terminal/backends/command/models.py:10 terminal/models.py:122 #: terminal/backends/command/models.py:10 terminal/models.py:122
#: terminal/templates/terminal/command_list.html:32 #: terminal/templates/terminal/command_list.html:32
#: terminal/templates/terminal/command_list.html:72 #: terminal/templates/terminal/command_list.html:72
#: terminal/templates/terminal/session_list.html:33 #: terminal/templates/terminal/session_list.html:33
#: terminal/templates/terminal/session_list.html:71 users/forms.py:220 #: terminal/templates/terminal/session_list.html:71 users/forms.py:219
#: users/models/user.py:30 users/models/user.py:254 #: users/models/user.py:30 users/models/user.py:273
#: users/templates/users/user_group_detail.html:78 #: users/templates/users/user_group_detail.html:78
#: users/templates/users/user_group_list.html:13 users/views/user.py:334 #: users/templates/users/user_group_list.html:13 users/views/user.py:335
msgid "User" msgid "User"
msgstr "用户" msgstr "用户"
...@@ -431,30 +448,49 @@ msgstr "分类" ...@@ -431,30 +448,49 @@ msgstr "分类"
msgid "Key" msgid "Key"
msgstr "" msgstr ""
#: assets/models/user.py:103 #: assets/models/user.py:104
#: assets/templates/assets/_asset_group_bulk_update_modal.html:11
#: assets/templates/assets/system_user_asset.html:21
#: 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:49
#: assets/views/asset.py:96 assets/views/asset.py:156 assets/views/asset.py:173
#: assets/views/asset.py:197 assets/views/domain.py:29
#: assets/views/domain.py:45 assets/views/domain.py:61
#: assets/views/domain.py:74 assets/views/domain.py:98
#: assets/views/domain.py:126 assets/views/domain.py:150
#: 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 "资产管理"
#: assets/models/user.py:105
msgid "Priority" msgid "Priority"
msgstr "优先级" msgstr "优先级"
#: assets/models/user.py:105 assets/templates/assets/_system_user.html:58 #: assets/models/user.py:107 assets/templates/assets/_system_user.html:58
#: assets/templates/assets/system_user_detail.html:118 #: assets/templates/assets/system_user_detail.html:118
#: assets/templates/assets/system_user_update.html:11 #: assets/templates/assets/system_user_update.html:11
msgid "Auto push" msgid "Auto push"
msgstr "自动推送" msgstr "自动推送"
#: assets/models/user.py:106 assets/templates/assets/system_user_detail.html:70 #: assets/models/user.py:108 assets/templates/assets/system_user_detail.html:70
msgid "Sudo" msgid "Sudo"
msgstr "Sudo" msgstr "Sudo"
#: assets/models/user.py:107 assets/templates/assets/system_user_detail.html:75 #: assets/models/user.py:109 assets/templates/assets/system_user_detail.html:75
msgid "Shell" msgid "Shell"
msgstr "Shell" msgstr "Shell"
#: assets/models/user.py:150 audits/models.py:12 #: assets/models/user.py:149 audits/models.py:12
#: audits/templates/audits/ftp_log_list.html:49 #: audits/templates/audits/ftp_log_list.html:49
#: audits/templates/audits/ftp_log_list.html:73 perms/forms.py:25 #: audits/templates/audits/ftp_log_list.html:73 perms/forms.py:43
#: perms/models.py:19 perms/models.py:76 #: perms/models.py:24 perms/models.py:69
#: perms/templates/perms/asset_permission_detail.html:136 #: perms/templates/perms/asset_permission_detail.html:140
#: perms/templates/perms/asset_permission_list.html:69 templates/_nav.html:26 #: perms/templates/perms/asset_permission_list.html:58
#: perms/templates/perms/asset_permission_list.html:145 templates/_nav.html:26
#: terminal/backends/command/models.py:12 terminal/models.py:124 #: terminal/backends/command/models.py:12 terminal/models.py:124
#: terminal/templates/terminal/command_list.html:48 #: terminal/templates/terminal/command_list.html:48
#: terminal/templates/terminal/command_list.html:74 #: terminal/templates/terminal/command_list.html:74
...@@ -468,41 +504,65 @@ msgstr "系统用户" ...@@ -468,41 +504,65 @@ msgstr "系统用户"
msgid "%(value)s is not an even number" msgid "%(value)s is not an even number"
msgstr "%(value)s is not an even number" msgstr "%(value)s is not an even number"
#: assets/tasks.py:96 assets/tasks.py:113 #: assets/tasks.py:96 assets/tasks.py:116
msgid "更新资产硬件信息" msgid "更新资产硬件信息"
msgstr "" msgstr ""
#: assets/tasks.py:132 #: assets/tasks.py:135
msgid "定期更新资产硬件信息" msgid "定期更新资产硬件信息"
msgstr "" msgstr ""
#: assets/tasks.py:210 #: assets/tasks.py:213
msgid "定期测试管理账号可连接性: {}" msgid "定期测试管理账号可连接性: {}"
msgstr "" msgstr ""
#: assets/tasks.py:217 #: assets/tasks.py:220
msgid "测试管理行号可连接性: {}" msgid "测试管理行号可连接性: {}"
msgstr "" msgstr ""
#: assets/tasks.py:227 #: assets/tasks.py:230
msgid "测试资产可连接性" msgid "测试资产可连接性"
msgstr "" msgstr ""
#: assets/tasks.py:297 #: assets/tasks.py:300
msgid "Test system user connectability: {}" msgid "Test system user connectability: {}"
msgstr "测试系统用户可连接性: {}" msgstr "测试系统用户可连接性: {}"
#: assets/tasks.py:313 #: assets/tasks.py:316
msgid "定期测试系统用户可连接性: {}" msgid "定期测试系统用户可连接性: {}"
msgstr "" msgstr ""
#: assets/tasks.py:392 #: assets/tasks.py:401
msgid "推送系统用户到节点资产: {} => {}" msgid "推送系统用户到入资产: {}"
msgstr "" msgstr ""
#: assets/tasks.py:433 #: assets/templates/assets/_admin_user_setting_modal.html:4
msgid "推送节点系统用户到新加入资产中: {}" #: users/templates/users/reset_password.html:57
msgstr "" #: users/templates/users/user_profile.html:20
msgid "Setting"
msgstr "设置"
#: assets/templates/assets/_admin_user_setting_modal.html:9
#: assets/templates/assets/_asset_import_modal.html:9
#: users/templates/users/_user_import_modal.html:10
msgid "Template"
msgstr "模板"
#: assets/templates/assets/_admin_user_setting_modal.html:10
#: assets/templates/assets/_asset_import_modal.html:10
#: users/templates/users/_user_import_modal.html:11
msgid "Download"
msgstr "下载"
#: assets/templates/assets/_admin_user_setting_modal.html:13
#: assets/templates/assets/_asset_import_modal.html:13
msgid "Asset csv file"
msgstr "资产csv文件"
#: assets/templates/assets/_admin_user_setting_modal.html:16
#: assets/templates/assets/_asset_import_modal.html:16
msgid "If set id, will use this id update asset existed"
msgstr "如果设置了id,则会使用该行信息更新该id的资产"
#: assets/templates/assets/_asset_group_bulk_update_modal.html:5 #: assets/templates/assets/_asset_group_bulk_update_modal.html:5
msgid "Update asset group" msgid "Update asset group"
...@@ -512,28 +572,13 @@ msgstr "更新用户组" ...@@ -512,28 +572,13 @@ msgstr "更新用户组"
msgid "Hint: only change the field you want to update." msgid "Hint: only change the field you want to update."
msgstr "仅修改你需要更新的字段" msgstr "仅修改你需要更新的字段"
#: assets/templates/assets/_asset_group_bulk_update_modal.html:11
#: assets/templates/assets/system_user_asset.html:21
#: 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:49
#: assets/views/asset.py:95 assets/views/asset.py:155 assets/views/asset.py:172
#: assets/views/asset.py:196 assets/views/domain.py:29
#: assets/views/domain.py:45 assets/views/domain.py:61
#: assets/views/domain.py:74 assets/views/domain.py:98
#: assets/views/domain.py:126 assets/views/domain.py:150
#: 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 "资产管理"
#: assets/templates/assets/_asset_group_bulk_update_modal.html:13 #: assets/templates/assets/_asset_group_bulk_update_modal.html:13
msgid "Select Asset" msgid "Select Asset"
msgstr "选择资产" msgstr "选择资产"
#: assets/templates/assets/_asset_group_bulk_update_modal.html:21 #: assets/templates/assets/_asset_group_bulk_update_modal.html:21
#: assets/templates/assets/user_asset_list.html:48
#: users/templates/users/user_granted_asset.html:47
msgid "System users" msgid "System users"
msgstr "系统用户" msgstr "系统用户"
...@@ -549,181 +594,16 @@ msgstr "二次验证" ...@@ -549,181 +594,16 @@ msgstr "二次验证"
msgid "Import asset" msgid "Import asset"
msgstr "导入资产" msgstr "导入资产"
#: assets/templates/assets/_asset_import_modal.html:9 #: assets/templates/assets/_asset_list_modal.html:7 assets/views/asset.py:50
#: users/templates/users/_user_import_modal.html:10 #: templates/_nav.html:23
msgid "Template" msgid "Asset list"
msgstr "模板" msgstr "资产列表"
#: assets/templates/assets/_asset_import_modal.html:10
#: users/templates/users/_user_import_modal.html:11
msgid "Download"
msgstr "下载"
#: assets/templates/assets/_asset_import_modal.html:13
msgid "Asset csv file"
msgstr "资产csv文件"
#: assets/templates/assets/_asset_import_modal.html:16
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: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: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
#: perms/templates/perms/asset_permission_detail.html:116
#: terminal/templates/terminal/terminal_list.html:34
#: users/templates/users/_select_user_modal.html:18
#: users/templates/users/user_detail.html:128
#: users/templates/users/user_granted_asset.html:46
#: users/templates/users/user_group_granted_asset.html:46
#: users/templates/users/user_list.html:27
#: users/templates/users/user_profile.html:63
msgid "Active"
msgstr "激活中"
#: assets/templates/assets/_asset_list_modal.html:24
#: assets/templates/assets/admin_user_assets.html:54
#: assets/templates/assets/admin_user_list.html:26
#: assets/templates/assets/asset_list.html:90
#: assets/templates/assets/system_user_asset.html:52
#: assets/templates/assets/system_user_list.html:30
#: users/templates/users/user_granted_asset.html:47
#: users/templates/users/user_group_granted_asset.html:47
msgid "Reachable"
msgstr "可连接"
#: assets/templates/assets/_asset_list_modal.html:25
#: assets/templates/assets/admin_user_list.html:30
#: assets/templates/assets/asset_list.html:91
#: assets/templates/assets/domain_gateway_list.html:62
#: assets/templates/assets/domain_list.html:18
#: assets/templates/assets/label_list.html:17
#: assets/templates/assets/system_user_list.html:34
#: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:64
#: ops/templates/ops/task_history.html:65 ops/templates/ops/task_list.html:42
#: perms/templates/perms/asset_permission_list.html:72
#: 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
msgid "Action"
msgstr "动作"
#: assets/templates/assets/_asset_list_modal.html:34
#: 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: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: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:104
#: users/templates/users/user_list.html:40
msgid "Active selected"
msgstr "激活所选"
#: assets/templates/assets/_asset_list_modal.html:41
#: 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:67
#: assets/templates/assets/asset_list.html:108
#: assets/templates/assets/asset_update.html:71
#: assets/templates/assets/domain_create_update.html:17
#: assets/templates/assets/gateway_create_update.html:59
#: 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:103
#: perms/templates/perms/asset_permission_create_update.html:72
#: 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
#: users/templates/users/user_bulk_update.html:24
#: users/templates/users/user_list.html:44
#: users/templates/users/user_password_update.html:59
#: users/templates/users/user_profile_update.html:64
#: users/templates/users/user_pubkey_update.html:77
msgid "Submit"
msgstr "提交"
#: assets/templates/assets/_asset_list_modal.html:79
#: assets/templates/assets/admin_user_detail.html:24
#: assets/templates/assets/admin_user_list.html:85
#: assets/templates/assets/asset_detail.html:24
#: assets/templates/assets/asset_list.html:168
#: assets/templates/assets/domain_detail.html:24
#: assets/templates/assets/domain_detail.html:103
#: assets/templates/assets/domain_gateway_list.html:90
#: assets/templates/assets/domain_list.html:42
#: assets/templates/assets/label_list.html:38
#: assets/templates/assets/system_user_detail.html:26
#: assets/templates/assets/system_user_list.html:88
#: perms/templates/perms/asset_permission_detail.html:30
#: perms/templates/perms/asset_permission_list.html:121
#: terminal/templates/terminal/terminal_detail.html:16
#: terminal/templates/terminal/terminal_list.html:71
#: users/templates/users/user_detail.html:25
#: users/templates/users/user_group_detail.html:28
#: users/templates/users/user_group_list.html:43
#: users/templates/users/user_list.html:76
#: users/templates/users/user_profile.html:135
#: users/templates/users/user_profile.html:143
msgid "Update"
msgstr "更新"
#: assets/templates/assets/_asset_list_modal.html:80
#: assets/templates/assets/admin_user_detail.html:28
#: assets/templates/assets/admin_user_list.html:86
#: assets/templates/assets/asset_detail.html:28
#: assets/templates/assets/asset_list.html:169
#: assets/templates/assets/domain_detail.html:28
#: assets/templates/assets/domain_detail.html:104
#: assets/templates/assets/domain_gateway_list.html:91
#: assets/templates/assets/domain_list.html:43
#: assets/templates/assets/label_list.html:39
#: assets/templates/assets/system_user_detail.html:30
#: assets/templates/assets/system_user_list.html:89
#: ops/templates/ops/task_list.html:72
#: perms/templates/perms/asset_permission_detail.html:34
#: perms/templates/perms/asset_permission_list.html:122
#: terminal/templates/terminal/terminal_list.html:73
#: users/templates/users/user_detail.html:30
#: users/templates/users/user_group_detail.html:32
#: users/templates/users/user_group_list.html:45
#: users/templates/users/user_list.html:80
#: users/templates/users/user_list.html:84
msgid "Delete"
msgstr "删除"
#: assets/templates/assets/_system_user.html:37 #: assets/templates/assets/_system_user.html:37
#: assets/templates/assets/asset_create.html:16 #: assets/templates/assets/asset_create.html:16
#: assets/templates/assets/asset_update.html:21 #: assets/templates/assets/asset_update.html:21
#: assets/templates/assets/gateway_create_update.html:37 #: assets/templates/assets/gateway_create_update.html:37
#: perms/templates/perms/asset_permission_create_update.html:38 #: perms/templates/perms/asset_permission_create_update.html:33
msgid "Basic" msgid "Basic"
msgstr "基本" msgstr "基本"
...@@ -745,7 +625,7 @@ msgstr "自动生成密钥" ...@@ -745,7 +625,7 @@ msgstr "自动生成密钥"
#: assets/templates/assets/asset_create.html:59 #: assets/templates/assets/asset_create.html:59
#: assets/templates/assets/asset_update.html:63 #: assets/templates/assets/asset_update.html:63
#: assets/templates/assets/gateway_create_update.html:53 #: assets/templates/assets/gateway_create_update.html:53
#: perms/templates/perms/asset_permission_create_update.html:49 #: perms/templates/perms/asset_permission_create_update.html:45
#: terminal/templates/terminal/terminal_update.html:42 #: terminal/templates/terminal/terminal_update.html:42
msgid "Other" msgid "Other"
msgstr "其它" msgstr "其它"
...@@ -762,7 +642,7 @@ msgstr "其它" ...@@ -762,7 +642,7 @@ msgstr "其它"
#: common/templates/common/email_setting.html:59 #: common/templates/common/email_setting.html:59
#: common/templates/common/ldap_setting.html:59 #: common/templates/common/ldap_setting.html:59
#: common/templates/common/terminal_setting.html:101 #: common/templates/common/terminal_setting.html:101
#: perms/templates/perms/asset_permission_create_update.html:71 #: perms/templates/perms/asset_permission_create_update.html:69
#: terminal/templates/terminal/terminal_update.html:47 #: terminal/templates/terminal/terminal_update.html:47
#: users/templates/users/_user.html:43 #: users/templates/users/_user.html:43
#: users/templates/users/user_bulk_update.html:23 #: users/templates/users/user_bulk_update.html:23
...@@ -774,6 +654,33 @@ msgstr "其它" ...@@ -774,6 +654,33 @@ msgstr "其它"
msgid "Reset" msgid "Reset"
msgstr "重置" 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:67
#: assets/templates/assets/asset_list.html:108
#: assets/templates/assets/asset_update.html:71
#: assets/templates/assets/domain_create_update.html:17
#: assets/templates/assets/gateway_create_update.html:59
#: 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:103
#: perms/templates/perms/asset_permission_create_update.html:70
#: 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
#: users/templates/users/user_bulk_update.html:24
#: users/templates/users/user_list.html:44
#: users/templates/users/user_password_update.html:59
#: users/templates/users/user_profile_update.html:64
#: users/templates/users/user_pubkey_update.html:77
msgid "Submit"
msgstr "提交"
#: assets/templates/assets/admin_user_assets.html:18 #: assets/templates/assets/admin_user_assets.html:18
#: assets/templates/assets/admin_user_detail.html:18 #: assets/templates/assets/admin_user_detail.html:18
#: assets/templates/assets/domain_detail.html:18 #: assets/templates/assets/domain_detail.html:18
...@@ -799,10 +706,19 @@ msgstr "资产列表" ...@@ -799,10 +706,19 @@ msgstr "资产列表"
msgid "Asset list of " msgid "Asset list of "
msgstr "资产列表" msgstr "资产列表"
#: assets/templates/assets/admin_user_assets.html:54
#: assets/templates/assets/admin_user_list.html:26
#: assets/templates/assets/asset_list.html:90
#: assets/templates/assets/system_user_asset.html:52
#: assets/templates/assets/system_user_list.html:30
#: users/templates/users/user_group_granted_asset.html:47
msgid "Reachable"
msgstr "可连接"
#: assets/templates/assets/admin_user_assets.html:66 #: assets/templates/assets/admin_user_assets.html:66
#: assets/templates/assets/system_user_asset.html:64 #: assets/templates/assets/system_user_asset.html:64
#: assets/templates/assets/system_user_detail.html:112 #: assets/templates/assets/system_user_detail.html:112
#: perms/templates/perms/asset_permission_detail.html:110 #: perms/templates/perms/asset_permission_detail.html:114
msgid "Quick update" msgid "Quick update"
msgstr "快速更新" msgstr "快速更新"
...@@ -818,15 +734,67 @@ msgstr "测试可连接性" ...@@ -818,15 +734,67 @@ msgstr "测试可连接性"
msgid "Test" msgid "Test"
msgstr "测试" msgstr "测试"
#: assets/templates/assets/admin_user_detail.html:24
#: assets/templates/assets/admin_user_list.html:85
#: assets/templates/assets/asset_detail.html:24
#: assets/templates/assets/asset_list.html:170
#: assets/templates/assets/domain_detail.html:24
#: assets/templates/assets/domain_detail.html:103
#: assets/templates/assets/domain_gateway_list.html:90
#: assets/templates/assets/domain_list.html:42
#: assets/templates/assets/label_list.html:38
#: assets/templates/assets/system_user_detail.html:26
#: assets/templates/assets/system_user_list.html:88
#: perms/templates/perms/asset_permission_detail.html:30
#: perms/templates/perms/asset_permission_list.html:191
#: terminal/templates/terminal/terminal_detail.html:16
#: terminal/templates/terminal/terminal_list.html:71
#: users/templates/users/user_detail.html:25
#: users/templates/users/user_group_detail.html:28
#: users/templates/users/user_group_list.html:43
#: users/templates/users/user_list.html:76
#: users/templates/users/user_profile.html:135
#: users/templates/users/user_profile.html:143
msgid "Update"
msgstr "更新"
#: assets/templates/assets/admin_user_detail.html:28
#: assets/templates/assets/admin_user_list.html:86
#: assets/templates/assets/asset_detail.html:28
#: assets/templates/assets/asset_list.html:171
#: assets/templates/assets/domain_detail.html:28
#: assets/templates/assets/domain_detail.html:104
#: assets/templates/assets/domain_gateway_list.html:91
#: assets/templates/assets/domain_list.html:43
#: assets/templates/assets/label_list.html:39
#: assets/templates/assets/system_user_detail.html:30
#: assets/templates/assets/system_user_list.html:89
#: ops/templates/ops/task_list.html:72
#: perms/templates/perms/asset_permission_detail.html:34
#: perms/templates/perms/asset_permission_list.html:192
#: terminal/templates/terminal/terminal_list.html:73
#: users/templates/users/user_detail.html:30
#: users/templates/users/user_group_detail.html:32
#: users/templates/users/user_group_list.html:45
#: users/templates/users/user_list.html:80
#: users/templates/users/user_list.html:84
msgid "Delete"
msgstr "删除"
#: assets/templates/assets/admin_user_detail.html:83 #: assets/templates/assets/admin_user_detail.html:83
msgid "Replace node assets admin user with this" msgid "Replace node assets admin user with this"
msgstr "替换资产的管理员" msgstr "替换资产的管理员"
#: assets/templates/assets/admin_user_detail.html:91
#: perms/templates/perms/asset_permission_asset.html:116
msgid "Select nodes"
msgstr "选择节点"
#: assets/templates/assets/admin_user_detail.html:100 #: assets/templates/assets/admin_user_detail.html:100
#: assets/templates/assets/asset_detail.html:200 #: assets/templates/assets/asset_detail.html:200
#: assets/templates/assets/asset_list.html:600 #: assets/templates/assets/asset_list.html:600
#: assets/templates/assets/system_user_detail.html:183 #: assets/templates/assets/system_user_detail.html:183
#: assets/templates/assets/system_user_list.html:138 templates/_modal.html:16 #: assets/templates/assets/system_user_list.html:138 templates/_modal.html:22
#: terminal/templates/terminal/session_detail.html:108 #: terminal/templates/terminal/session_detail.html:108
#: users/templates/users/user_detail.html:339 #: users/templates/users/user_detail.html:339
#: users/templates/users/user_detail.html:364 #: users/templates/users/user_detail.html:364
...@@ -855,20 +823,23 @@ msgstr "不可达" ...@@ -855,20 +823,23 @@ msgstr "不可达"
msgid "Ratio" msgid "Ratio"
msgstr "比例" msgstr "比例"
#: assets/templates/assets/asset_create.html:29 #: assets/templates/assets/admin_user_list.html:30
#: assets/templates/assets/asset_update.html:34 perms/models.py:74 #: assets/templates/assets/asset_list.html:91
#: perms/templates/perms/asset_permission_create_update.html:40 #: assets/templates/assets/domain_gateway_list.html:62
#: perms/templates/perms/asset_permission_list.html:67 #: assets/templates/assets/domain_list.html:18
msgid "Node" #: assets/templates/assets/label_list.html:17
msgstr "节点" #: assets/templates/assets/system_user_list.html:34
#: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:64
#: assets/templates/assets/asset_create.html:35 #: ops/templates/ops/task_history.html:65 ops/templates/ops/task_list.html:42
#: assets/templates/assets/asset_list.html:75 #: perms/templates/perms/asset_permission_list.html:60
#: assets/templates/assets/asset_update.html:40 #: terminal/templates/terminal/session_list.html:80
msgid "Label" #: terminal/templates/terminal/terminal_list.html:36
msgstr "标签" #: users/templates/users/user_group_list.html:15
#: users/templates/users/user_list.html:28
msgid "Action"
msgstr "动作"
#: assets/templates/assets/asset_detail.html:20 assets/views/asset.py:197 #: assets/templates/assets/asset_detail.html:20 assets/views/asset.py:198
msgid "Asset detail" msgid "Asset detail"
msgstr "资产详情" msgstr "资产详情"
...@@ -893,6 +864,23 @@ msgstr "创建日期" ...@@ -893,6 +864,23 @@ msgstr "创建日期"
msgid "Quick modify" msgid "Quick modify"
msgstr "快速修改" msgstr "快速修改"
#: assets/templates/assets/asset_detail.html:143
#: assets/templates/assets/asset_list.html:89
#: assets/templates/assets/user_asset_list.html:47 perms/models.py:25
#: perms/models.py:70
#: perms/templates/perms/asset_permission_create_update.html:47
#: perms/templates/perms/asset_permission_detail.html:120
#: perms/templates/perms/asset_permission_list.html:59
#: terminal/templates/terminal/terminal_list.html:34
#: users/templates/users/_select_user_modal.html:18
#: users/templates/users/user_detail.html:128
#: users/templates/users/user_granted_asset.html:46
#: users/templates/users/user_group_granted_asset.html:46
#: users/templates/users/user_list.html:27
#: users/templates/users/user_profile.html:63
msgid "Active"
msgstr "激活中"
#: assets/templates/assets/asset_detail.html:160 #: assets/templates/assets/asset_detail.html:160
msgid "Refresh hardware" msgid "Refresh hardware"
msgstr "更新硬件信息" msgstr "更新硬件信息"
...@@ -906,8 +894,7 @@ msgstr "刷新" ...@@ -906,8 +894,7 @@ msgstr "刷新"
msgid "Update successfully!" msgid "Update successfully!"
msgstr "更新成功" msgstr "更新成功"
#: assets/templates/assets/asset_list.html:63 #: assets/templates/assets/asset_list.html:63 assets/views/asset.py:97
#: assets/templates/assets/asset_list.html:120 assets/views/asset.py:96
msgid "Create asset" msgid "Create asset"
msgstr "创建资产" msgstr "创建资产"
...@@ -921,35 +908,63 @@ msgstr "导入" ...@@ -921,35 +908,63 @@ msgstr "导入"
msgid "Export" msgid "Export"
msgstr "导出" msgstr "导出"
#: assets/templates/assets/asset_list.html:88
msgid "Hardware"
msgstr "硬件"
#: assets/templates/assets/asset_list.html:100
#: users/templates/users/user_list.html:37
msgid "Delete selected"
msgstr "批量删除"
#: assets/templates/assets/asset_list.html:101
#: users/templates/users/user_list.html:38
msgid "Update selected"
msgstr "批量更新"
#: assets/templates/assets/asset_list.html:102 #: assets/templates/assets/asset_list.html:102
msgid "Remove from this node" msgid "Remove from this node"
msgstr "从节点移除" msgstr "从节点移除"
#: assets/templates/assets/asset_list.html:103
#: users/templates/users/user_list.html:39
msgid "Deactive selected"
msgstr "禁用所选"
#: assets/templates/assets/asset_list.html:104
#: users/templates/users/user_list.html:40
msgid "Active selected"
msgstr "激活所选"
#: assets/templates/assets/asset_list.html:121 #: assets/templates/assets/asset_list.html:121
msgid "Add asset" msgid "Add node"
msgstr "添加资产到节点" msgstr "新建节点"
#: assets/templates/assets/asset_list.html:122 #: assets/templates/assets/asset_list.html:122
msgid "Refresh node hardware info" msgid "Rename node"
msgstr "更新节点资产硬件信息" msgstr "重命名节点"
#: assets/templates/assets/asset_list.html:123 #: assets/templates/assets/asset_list.html:123
msgid "Test node connective" msgid "Delete node"
msgstr "测试节点资产可连接性" msgstr "删除节点"
#: assets/templates/assets/asset_list.html:125 #: assets/templates/assets/asset_list.html:125
msgid "Add node" msgid "Add assets to node"
msgstr "新建节点" msgstr "添加资产到节点"
#: assets/templates/assets/asset_list.html:126 #: assets/templates/assets/asset_list.html:126
msgid "Rename node" msgid "Move assets to node"
msgstr "重命名节点" msgstr "移动资产到节点"
#: assets/templates/assets/asset_list.html:128 #: assets/templates/assets/asset_list.html:128
msgid "Delete node" msgid "Refresh node hardware info"
msgstr "删除节点" msgstr "更新节点资产硬件信息"
#: assets/templates/assets/asset_list.html:203 #: assets/templates/assets/asset_list.html:129
msgid "Test node connective"
msgstr "测试节点资产可连接性"
#: assets/templates/assets/asset_list.html:204
msgid "Create node failed" msgid "Create node failed"
msgstr "创建节点失败" msgstr "创建节点失败"
...@@ -957,6 +972,10 @@ msgstr "创建节点失败" ...@@ -957,6 +972,10 @@ msgstr "创建节点失败"
msgid "Have child node, cancel" msgid "Have child node, cancel"
msgstr "存在子节点,不能删除" msgstr "存在子节点,不能删除"
#: assets/templates/assets/asset_list.html:218
msgid "Have assets, cancel"
msgstr "存在资产,不能删除"
#: assets/templates/assets/asset_list.html:595 #: assets/templates/assets/asset_list.html:595
#: assets/templates/assets/system_user_list.html:133 #: assets/templates/assets/system_user_list.html:133
#: users/templates/users/user_detail.html:334 #: users/templates/users/user_detail.html:334
...@@ -1088,10 +1107,6 @@ msgstr "删除系统用户" ...@@ -1088,10 +1107,6 @@ msgstr "删除系统用户"
msgid "System Users Deleting failed." msgid "System Users Deleting failed."
msgstr "系统用户删除失败" msgstr "系统用户删除失败"
#: assets/templates/assets/user_asset_list.html:24
msgid "Connective"
msgstr "连接性"
#: assets/views/admin_user.py:30 #: assets/views/admin_user.py:30
msgid "Admin user list" msgid "Admin user list"
msgstr "管理用户列表" msgstr "管理用户列表"
...@@ -1104,23 +1119,19 @@ msgstr "更新管理用户" ...@@ -1104,23 +1119,19 @@ msgstr "更新管理用户"
msgid "Admin user detail" msgid "Admin user detail"
msgstr "管理用户详情" msgstr "管理用户详情"
#: assets/views/asset.py:50 templates/_nav.html:23 #: assets/views/asset.py:63 templates/_nav_user.html:4
msgid "Asset list"
msgstr "资产列表"
#: assets/views/asset.py:62 templates/_nav_user.html:4
msgid "My assets" msgid "My assets"
msgstr "我的资产" msgstr "我的资产"
#: assets/views/asset.py:156 #: assets/views/asset.py:157
msgid "Bulk update asset" msgid "Bulk update asset"
msgstr "批量更新资产" msgstr "批量更新资产"
#: assets/views/asset.py:173 #: assets/views/asset.py:174
msgid "Update asset" msgid "Update asset"
msgstr "更新资产" msgstr "更新资产"
#: assets/views/asset.py:300 #: assets/views/asset.py:311
msgid "already exists" msgid "already exists"
msgstr "已经存在" msgstr "已经存在"
...@@ -1182,18 +1193,33 @@ msgstr "远端地址" ...@@ -1182,18 +1193,33 @@ msgstr "远端地址"
msgid "Operate" msgid "Operate"
msgstr "操作" msgstr "操作"
#: audits/models.py:14 audits/templates/audits/ftp_log_list.html:76 #: audits/models.py:14 audits/templates/audits/ftp_log_list.html:56
#: audits/templates/audits/ftp_log_list.html:76
msgid "Filename" msgid "Filename"
msgstr "文件名" msgstr "文件名"
#: audits/templates/audits/ftp_log_list.html:77 #: audits/models.py:15 audits/templates/audits/ftp_log_list.html:77
#: ops/templates/ops/task_list.html:39
msgid "Success"
msgstr "成功"
#: audits/templates/audits/ftp_log_list.html:78
#: ops/templates/ops/adhoc_history.html:52 #: ops/templates/ops/adhoc_history.html:52
#: ops/templates/ops/adhoc_history_detail.html:61 #: ops/templates/ops/adhoc_history_detail.html:61
#: ops/templates/ops/task_history.html:58 terminal/models.py:132 #: ops/templates/ops/task_history.html:58 perms/models.py:26
#: perms/templates/perms/asset_permission_detail.html:86 terminal/models.py:132
#: terminal/templates/terminal/session_list.html:77 #: terminal/templates/terminal/session_list.html:77
msgid "Date start" msgid "Date start"
msgstr "开始日期" msgstr "开始日期"
#: audits/views.py:50 templates/_nav.html:64
msgid "Audits"
msgstr "日志审计"
#: audits/views.py:51 templates/_nav.html:67
msgid "FTP log"
msgstr "FTP日志"
#: common/api.py:18 #: common/api.py:18
msgid "Test mail sent to {}, please check" msgid "Test mail sent to {}, please check"
msgstr "邮件已经发送{}, 请检查" msgstr "邮件已经发送{}, 请检查"
...@@ -1655,10 +1681,6 @@ msgstr "搜索" ...@@ -1655,10 +1681,6 @@ msgstr "搜索"
msgid "Versions" msgid "Versions"
msgstr "版本" msgstr "版本"
#: ops/templates/ops/task_list.html:39
msgid "Success"
msgstr "成功"
#: ops/templates/ops/task_list.html:40 #: ops/templates/ops/task_list.html:40
#: users/templates/users/login_log_list.html:54 #: users/templates/users/login_log_list.html:54
msgid "Date" msgid "Date"
...@@ -1685,24 +1707,37 @@ msgstr "任务列表" ...@@ -1685,24 +1707,37 @@ msgstr "任务列表"
msgid "Task run history" msgid "Task run history"
msgstr "执行历史" msgstr "执行历史"
#: perms/forms.py:22 perms/models.py:16 perms/models.py:75 #: perms/forms.py:18 users/forms.py:176 users/forms.py:181 users/forms.py:193
#: perms/templates/perms/asset_permission_list.html:68 templates/_nav.html:14 #: users/forms.py:223
#: users/models/group.py:25 users/models/user.py:37 msgid "Select users"
msgstr "选择用户"
#: perms/forms.py:34 perms/models.py:21 perms/models.py:68
#: perms/templates/perms/asset_permission_list.html:55
#: perms/templates/perms/asset_permission_list.html:136 templates/_nav.html:14
#: users/models/group.py:25 users/models/user.py:42
#: users/templates/users/_select_user_modal.html:16 #: users/templates/users/_select_user_modal.html:16
#: users/templates/users/user_detail.html:179 #: users/templates/users/user_detail.html:179
#: users/templates/users/user_list.html:26 #: users/templates/users/user_list.html:26
msgid "User group" msgid "User group"
msgstr "用户组" msgstr "用户组"
#: perms/models.py:21 perms/models.py:78 #: perms/forms.py:56
#: perms/templates/perms/asset_permission_detail.html:86 msgid "User or group at least one required"
#: perms/templates/perms/asset_permission_list.html:71 users/models/user.py:49 msgstr ""
#: users/templates/users/user_detail.html:95
#: perms/forms.py:65
msgid "Asset or group at least one required"
msgstr ""
#: perms/models.py:27 perms/models.py:71
#: perms/templates/perms/asset_permission_detail.html:90
#: users/models/user.py:54 users/templates/users/user_detail.html:95
#: users/templates/users/user_profile.html:96 #: users/templates/users/user_profile.html:96
msgid "Date expired" msgid "Date expired"
msgstr "失效日期" msgstr "失效日期"
#: perms/models.py:88 templates/_nav.html:34 #: perms/models.py:81 templates/_nav.html:34
msgid "Asset permission" msgid "Asset permission"
msgstr "资产授权" msgstr "资产授权"
...@@ -1723,7 +1758,7 @@ msgid "Add asset to this permission" ...@@ -1723,7 +1758,7 @@ msgid "Add asset to this permission"
msgstr "添加资产" msgstr "添加资产"
#: perms/templates/perms/asset_permission_asset.html:97 #: perms/templates/perms/asset_permission_asset.html:97
#: perms/templates/perms/asset_permission_detail.html:153 #: perms/templates/perms/asset_permission_detail.html:157
#: perms/templates/perms/asset_permission_user.html:97 #: perms/templates/perms/asset_permission_user.html:97
#: perms/templates/perms/asset_permission_user.html:125 #: perms/templates/perms/asset_permission_user.html:125
#: users/templates/users/user_group_detail.html:95 #: users/templates/users/user_group_detail.html:95
...@@ -1731,12 +1766,8 @@ msgid "Add" ...@@ -1731,12 +1766,8 @@ msgid "Add"
msgstr "添加" msgstr "添加"
#: perms/templates/perms/asset_permission_asset.html:108 #: perms/templates/perms/asset_permission_asset.html:108
msgid "Add asset group to this permission" msgid "Add node to this permission"
msgstr "添加资产组" msgstr "添加节点"
#: perms/templates/perms/asset_permission_asset.html:116 users/forms.py:275
msgid "Select asset groups"
msgstr "选择资产组"
#: perms/templates/perms/asset_permission_asset.html:125 #: perms/templates/perms/asset_permission_asset.html:125
#: users/templates/users/user_detail.html:196 #: users/templates/users/user_detail.html:196
...@@ -1756,18 +1787,18 @@ msgid "Asset count" ...@@ -1756,18 +1787,18 @@ msgid "Asset count"
msgstr "资产数量" msgstr "资产数量"
#: perms/templates/perms/asset_permission_detail.html:78 #: perms/templates/perms/asset_permission_detail.html:78
msgid "Asset group count" msgid "Node count"
msgstr "资产组数量" msgstr "节点数量"
#: perms/templates/perms/asset_permission_detail.html:82 #: perms/templates/perms/asset_permission_detail.html:82
msgid "System user count" msgid "System user count"
msgstr "系统用户数量" msgstr "系统用户数量"
#: perms/templates/perms/asset_permission_detail.html:144 users/forms.py:278 #: perms/templates/perms/asset_permission_detail.html:148
msgid "Select system users" msgid "Select system users"
msgstr "选择系统用户" msgstr "选择系统用户"
#: perms/templates/perms/asset_permission_list.html:58 #: perms/templates/perms/asset_permission_list.html:46
msgid "Create permission" msgid "Create permission"
msgstr "创建授权规则" msgstr "创建授权规则"
...@@ -1792,22 +1823,31 @@ msgstr "添加用户组" ...@@ -1792,22 +1823,31 @@ msgstr "添加用户组"
msgid "Select user groups" msgid "Select user groups"
msgstr "选择用户组" msgstr "选择用户组"
#: perms/views.py:23 perms/views.py:47 perms/views.py:67 templates/_nav.html:31 #: perms/views.py:25 perms/views.py:55 perms/views.py:70 perms/views.py:85
#: perms/views.py:120 perms/views.py:151 templates/_nav.html:31
msgid "Perms" msgid "Perms"
msgstr "权限管理" msgstr "权限管理"
#: perms/views.py:24 #: perms/views.py:26
msgid "Asset permission list" msgid "Asset permission list"
msgstr "资产授权列表" msgstr "资产授权列表"
#: perms/views.py:48 #: perms/views.py:56
msgid "Create asset permission" msgid "Create asset permission"
msgstr "创建权限规则" msgstr "创建权限规则"
#: perms/views.py:68 #: perms/views.py:71 perms/views.py:86
msgid "Update asset permission" msgid "Update asset permission"
msgstr "更新资产授权" msgstr "更新资产授权"
#: perms/views.py:121
msgid "Asset permission user list"
msgstr "资产授权用户列表"
#: perms/views.py:152
msgid "Asset permission asset list"
msgstr "资产授权资产列表"
#: templates/_header_bar.html:18 #: templates/_header_bar.html:18
msgid "Supports" msgid "Supports"
msgstr "商业支持" msgstr "商业支持"
...@@ -1816,13 +1856,13 @@ msgstr "商业支持" ...@@ -1816,13 +1856,13 @@ msgstr "商业支持"
msgid "Docs" msgid "Docs"
msgstr "文档" msgstr "文档"
#: templates/_header_bar.html:37 templates/_nav_user.html:9 users/forms.py:94 #: templates/_header_bar.html:37 templates/_nav_user.html:9 users/forms.py:93
#: users/templates/users/_user.html:36 #: users/templates/users/_user.html:36
#: users/templates/users/user_password_update.html:37 #: users/templates/users/user_password_update.html:37
#: users/templates/users/user_profile.html:17 #: users/templates/users/user_profile.html:17
#: users/templates/users/user_profile_update.html:37 #: users/templates/users/user_profile_update.html:37
#: users/templates/users/user_profile_update.html:57 #: users/templates/users/user_profile_update.html:57
#: users/templates/users/user_pubkey_update.html:37 users/views/user.py:317 #: users/templates/users/user_pubkey_update.html:37 users/views/user.py:318
msgid "Profile" msgid "Profile"
msgstr "个人信息" msgstr "个人信息"
...@@ -1873,15 +1913,15 @@ msgstr "" ...@@ -1873,15 +1913,15 @@ msgstr ""
"\"%(user_pubkey_update)s\"> 链接 </a> 更新\n" "\"%(user_pubkey_update)s\"> 链接 </a> 更新\n"
" " " "
#: templates/_modal.html:15 #: templates/_modal.html:21
msgid "Close" msgid "Close"
msgstr "关闭" msgstr "关闭"
#: templates/_nav.html:10 users/views/group.py:28 users/views/group.py:44 #: 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/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:60 #: users/views/login.py:205 users/views/login.py:254 users/views/user.py:60
#: users/views/user.py:75 users/views/user.py:94 users/views/user.py:150 #: users/views/user.py:75 users/views/user.py:95 users/views/user.py:151
#: users/views/user.py:305 users/views/user.py:352 users/views/user.py:374 #: users/views/user.py:306 users/views/user.py:353 users/views/user.py:375
msgid "Users" msgid "Users"
msgstr "用户管理" msgstr "用户管理"
...@@ -1925,14 +1965,6 @@ msgstr "终端管理" ...@@ -1925,14 +1965,6 @@ msgstr "终端管理"
msgid "Job Center" msgid "Job Center"
msgstr "作业中心" msgstr "作业中心"
#: templates/_nav.html:64
msgid "Audits"
msgstr "日志审计"
#: templates/_nav.html:67
msgid "FTP log"
msgstr "FTP日志"
#: templates/captcha/image.html:3 #: templates/captcha/image.html:3
msgid "Play CAPTCHA as audio file" msgid "Play CAPTCHA as audio file"
msgstr "语言播放验证码" msgstr "语言播放验证码"
...@@ -2199,7 +2231,7 @@ msgstr "" ...@@ -2199,7 +2231,7 @@ msgstr ""
msgid "Invalid token or cache refreshed." msgid "Invalid token or cache refreshed."
msgstr "" msgstr ""
#: users/forms.py:28 users/models/user.py:38 #: users/forms.py:27 users/models/user.py:43
#: users/templates/users/_select_user_modal.html:15 #: users/templates/users/_select_user_modal.html:15
#: users/templates/users/user_detail.html:87 #: users/templates/users/user_detail.html:87
#: users/templates/users/user_list.html:25 #: users/templates/users/user_list.html:25
...@@ -2207,55 +2239,55 @@ msgstr "" ...@@ -2207,55 +2239,55 @@ msgstr ""
msgid "Role" msgid "Role"
msgstr "角色" msgstr "角色"
#: users/forms.py:30 users/forms.py:140 #: users/forms.py:29 users/forms.py:139
msgid "ssh public key" msgid "ssh public key"
msgstr "ssh公钥" msgstr "ssh公钥"
#: users/forms.py:31 users/forms.py:141 #: users/forms.py:30 users/forms.py:140
msgid "ssh-rsa AAAA..." msgid "ssh-rsa AAAA..."
msgstr "" msgstr ""
#: users/forms.py:32 #: users/forms.py:31
msgid "Paste user id_rsa.pub here." msgid "Paste user id_rsa.pub here."
msgstr "复制用户公钥到这里" msgstr "复制用户公钥到这里"
#: users/forms.py:50 users/templates/users/user_detail.html:187 #: users/forms.py:49 users/templates/users/user_detail.html:187
msgid "Join user groups" msgid "Join user groups"
msgstr "添加到用户组" msgstr "添加到用户组"
#: users/forms.py:60 users/forms.py:155 #: users/forms.py:59 users/forms.py:154
msgid "Public key should not be the same as your old one." msgid "Public key should not be the same as your old one."
msgstr "不能和原来的密钥相同" msgstr "不能和原来的密钥相同"
#: users/forms.py:64 users/forms.py:159 users/serializers.py:42 #: users/forms.py:63 users/forms.py:158 users/serializers.py:42
msgid "Not a valid ssh public key" msgid "Not a valid ssh public key"
msgstr "ssh密钥不合法" msgstr "ssh密钥不合法"
#: users/forms.py:100 #: users/forms.py:99
msgid "Old password" msgid "Old password"
msgstr "原来密码" msgstr "原来密码"
#: users/forms.py:105 #: users/forms.py:104
msgid "New password" msgid "New password"
msgstr "新密码" msgstr "新密码"
#: users/forms.py:110 #: users/forms.py:109
msgid "Confirm password" msgid "Confirm password"
msgstr "确认密码" msgstr "确认密码"
#: users/forms.py:120 #: users/forms.py:119
msgid "Old password error" msgid "Old password error"
msgstr "原来密码错误" msgstr "原来密码错误"
#: users/forms.py:128 #: users/forms.py:127
msgid "Password does not match" msgid "Password does not match"
msgstr "密码不一致" msgstr "密码不一致"
#: users/forms.py:142 #: users/forms.py:141
msgid "Paste your id_rsa.pub here." msgid "Paste your id_rsa.pub here."
msgstr "复制你的公钥到这里" msgstr "复制你的公钥到这里"
#: users/forms.py:170 users/models/user.py:46 #: users/forms.py:169 users/models/user.py:51
#: users/templates/users/user_password_update.html:43 #: users/templates/users/user_password_update.html:43
#: users/templates/users/user_profile.html:71 #: users/templates/users/user_profile.html:71
#: users/templates/users/user_profile_update.html:43 #: users/templates/users/user_profile_update.html:43
...@@ -2263,10 +2295,6 @@ msgstr "复制你的公钥到这里" ...@@ -2263,10 +2295,6 @@ msgstr "复制你的公钥到这里"
msgid "Public key" msgid "Public key"
msgstr "ssh公钥" msgstr "ssh公钥"
#: users/forms.py:177 users/forms.py:182 users/forms.py:194 users/forms.py:224
msgid "Select users"
msgstr "选择用户"
#: users/models/authentication.py:36 #: users/models/authentication.py:36
msgid "Private Token" msgid "Private Token"
msgstr "ssh密钥" msgstr "ssh密钥"
...@@ -2291,7 +2319,7 @@ msgstr "Agent" ...@@ -2291,7 +2319,7 @@ msgstr "Agent"
msgid "Date login" msgid "Date login"
msgstr "登录日期" msgstr "登录日期"
#: users/models/user.py:29 users/models/user.py:262 #: users/models/user.py:29 users/models/user.py:281
msgid "Administrator" msgid "Administrator"
msgstr "管理员" msgstr "管理员"
...@@ -2299,24 +2327,36 @@ msgstr "管理员" ...@@ -2299,24 +2327,36 @@ msgstr "管理员"
msgid "Application" msgid "Application"
msgstr "应用程序" msgstr "应用程序"
#: users/models/user.py:36 users/templates/users/user_detail.html:71 #: users/models/user.py:34
msgid "Disable"
msgstr "禁用"
#: users/models/user.py:35
msgid "Enable"
msgstr "启用"
#: users/models/user.py:36
msgid "Force enable"
msgstr "强制启用"
#: users/models/user.py:41 users/templates/users/user_detail.html:71
#: users/templates/users/user_profile.html:59 #: users/templates/users/user_profile.html:59
msgid "Email" msgid "Email"
msgstr "邮件" msgstr "邮件"
#: users/models/user.py:39 #: users/models/user.py:44
msgid "Avatar" msgid "Avatar"
msgstr "头像" msgstr "头像"
#: users/models/user.py:40 users/templates/users/user_detail.html:82 #: users/models/user.py:45 users/templates/users/user_detail.html:82
msgid "Wechat" msgid "Wechat"
msgstr "微信" msgstr "微信"
#: users/models/user.py:42 #: users/models/user.py:47
msgid "Enable OTP" msgid "Enable OTP"
msgstr "二次验证" msgstr "二次验证"
#: users/models/user.py:265 #: users/models/user.py:284
msgid "Administrator is the super user of system" msgid "Administrator is the super user of system"
msgstr "Administrator是初始的超级管理员" msgstr "Administrator是初始的超级管理员"
...@@ -2416,11 +2456,6 @@ msgstr "重置密码" ...@@ -2416,11 +2456,6 @@ msgstr "重置密码"
msgid "Password again" msgid "Password again"
msgstr "再次输入密码" 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_create.html:4
#: users/templates/users/user_list.html:16 users/views/user.py:75 #: users/templates/users/user_list.html:16 users/views/user.py:75
msgid "Create user" msgid "Create user"
...@@ -2431,7 +2466,7 @@ msgid "Reset link will be generated and sent to the user. " ...@@ -2431,7 +2466,7 @@ msgid "Reset link will be generated and sent to the user. "
msgstr "生成重置密码连接,通过邮件发送给用户" msgstr "生成重置密码连接,通过邮件发送给用户"
#: users/templates/users/user_detail.html:19 #: users/templates/users/user_detail.html:19
#: users/templates/users/user_granted_asset.html:18 users/views/user.py:151 #: users/templates/users/user_granted_asset.html:18 users/views/user.py:152
msgid "User detail" msgid "User detail"
msgstr "用户详情" msgstr "用户详情"
...@@ -2550,8 +2585,8 @@ msgstr "用户删除失败" ...@@ -2550,8 +2585,8 @@ msgstr "用户删除失败"
msgid "OTP" msgid "OTP"
msgstr "" msgstr ""
#: users/templates/users/user_profile.html:100 users/views/user.py:180 #: users/templates/users/user_profile.html:100 users/views/user.py:181
#: users/views/user.py:234 #: users/views/user.py:235
msgid "User groups" msgid "User groups"
msgstr "用户组" msgstr "用户组"
...@@ -2587,7 +2622,7 @@ msgstr "更新密钥" ...@@ -2587,7 +2622,7 @@ msgstr "更新密钥"
msgid "Or reset by server" msgid "Or reset by server"
msgstr "或者重置并下载密钥" msgstr "或者重置并下载密钥"
#: users/templates/users/user_update.html:4 users/views/user.py:94 #: users/templates/users/user_update.html:4 users/views/user.py:95
msgid "Update user" msgid "Update user"
msgstr "更新用户" msgstr "更新用户"
...@@ -2733,78 +2768,78 @@ msgstr "更新用户组" ...@@ -2733,78 +2768,78 @@ msgstr "更新用户组"
msgid "User group granted asset" msgid "User group granted asset"
msgstr "用户组授权资产" msgstr "用户组授权资产"
#: users/views/login.py:57 #: users/views/login.py:55
msgid "Please enable cookies and try again." msgid "Please enable cookies and try again."
msgstr "设置你的浏览器支持cookie" msgstr "设置你的浏览器支持cookie"
#: users/views/login.py:99 #: users/views/login.py:97
msgid "Logout success" msgid "Logout success"
msgstr "退出登录成功" msgstr "退出登录成功"
#: users/views/login.py:100 #: users/views/login.py:98
msgid "Logout success, return login page" msgid "Logout success, return login page"
msgstr "退出登录成功,返回到登录页面" msgstr "退出登录成功,返回到登录页面"
#: users/views/login.py:116 #: users/views/login.py:114
msgid "Email address invalid, please input again" msgid "Email address invalid, please input again"
msgstr "邮箱地址错误,重新输入" msgstr "邮箱地址错误,重新输入"
#: users/views/login.py:129 #: users/views/login.py:127
msgid "Send reset password message" msgid "Send reset password message"
msgstr "发送重置密码邮件" msgstr "发送重置密码邮件"
#: users/views/login.py:130 #: users/views/login.py:128
msgid "Send reset password mail success, login your mail box and follow it " msgid "Send reset password mail success, login your mail box and follow it "
msgstr "" msgstr ""
"发送重置邮件成功, 请登录邮箱查看, 按照提示操作 (如果没收到,请等待3-5分钟)" "发送重置邮件成功, 请登录邮箱查看, 按照提示操作 (如果没收到,请等待3-5分钟)"
#: users/views/login.py:144 #: users/views/login.py:142
msgid "Reset password success" msgid "Reset password success"
msgstr "重置密码成功" msgstr "重置密码成功"
#: users/views/login.py:145 #: users/views/login.py:143
msgid "Reset password success, return to login page" msgid "Reset password success, return to login page"
msgstr "重置密码成功,返回到登录页面" msgstr "重置密码成功,返回到登录页面"
#: users/views/login.py:162 users/views/login.py:175 #: users/views/login.py:160 users/views/login.py:173
msgid "Token invalid or expired" msgid "Token invalid or expired"
msgstr "Token错误或失效" msgstr "Token错误或失效"
#: users/views/login.py:171 #: users/views/login.py:169
msgid "Password not same" msgid "Password not same"
msgstr "密码不一致" msgstr "密码不一致"
#: users/views/login.py:209 #: users/views/login.py:205
msgid "First login" msgid "First login"
msgstr "首次登陆" msgstr "首次登陆"
#: users/views/login.py:259 #: users/views/login.py:255
msgid "Login log list" msgid "Login log list"
msgstr "登录日志" msgstr "登录日志"
#: users/views/user.py:104 #: users/views/user.py:105
msgid "Bulk update user success" msgid "Bulk update user success"
msgstr "批量更新用户成功" msgstr "批量更新用户成功"
#: users/views/user.py:209 #: users/views/user.py:210
msgid "Invalid file." msgid "Invalid file."
msgstr "文件不合法" msgstr "文件不合法"
#: users/views/user.py:306 #: users/views/user.py:307
msgid "User granted assets" msgid "User granted assets"
msgstr "用户授权资产" msgstr "用户授权资产"
#: users/views/user.py:335 #: users/views/user.py:336
msgid "Profile setting" msgid "Profile setting"
msgstr "个人信息设置" msgstr "个人信息设置"
#: users/views/user.py:353 #: users/views/user.py:354
msgid "Password update" msgid "Password update"
msgstr "密码更新" msgstr "密码更新"
#: users/views/user.py:375 #: users/views/user.py:376
msgid "Public key update" msgid "Public key update"
msgstr "密钥更新" msgstr "密钥更新"
#~ msgid "Task has been send, seen left asset status" #~ msgid "Add asset"
#~ msgstr "任务已下发,查看左侧资产状态" #~ msgstr "添加资产到节点"
...@@ -36,9 +36,10 @@ urlpatterns = [ ...@@ -36,9 +36,10 @@ urlpatterns = [
url(r'^captcha/', include('captcha.urls')), url(r'^captcha/', include('captcha.urls')),
] ]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) \
+ static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
if settings.DEBUG: if settings.DEBUG:
urlpatterns += [ urlpatterns += [
url(r'^docs/', schema_view, name="docs"), url(r'^docs/', schema_view, name="docs"),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) \ ]
+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from rest_framework.views import APIView, Response from rest_framework.views import APIView, Response
from rest_framework.generics import ListAPIView, get_object_or_404 from rest_framework.generics import ListAPIView, get_object_or_404, RetrieveUpdateAPIView
from rest_framework import viewsets from rest_framework import viewsets
from common.utils import set_or_append_attr_bulk from common.utils import set_or_append_attr_bulk
...@@ -98,6 +98,11 @@ class UserGrantedNodesApi(ListAPIView): ...@@ -98,6 +98,11 @@ class UserGrantedNodesApi(ListAPIView):
nodes = AssetPermissionUtil.get_user_nodes_with_assets(user) nodes = AssetPermissionUtil.get_user_nodes_with_assets(user)
return nodes.keys() return nodes.keys()
def get_permissions(self):
if self.kwargs.get('pk') is None:
self.permission_classes = (IsValidUser,)
return super().get_permissions()
class UserGrantedNodesWithAssetsApi(ListAPIView): class UserGrantedNodesWithAssetsApi(ListAPIView):
permission_classes = (IsSuperUserOrAppUser,) permission_classes = (IsSuperUserOrAppUser,)
...@@ -246,3 +251,77 @@ class ValidateUserAssetPermissionView(APIView): ...@@ -246,3 +251,77 @@ class ValidateUserAssetPermissionView(APIView):
return Response({'msg': True}, status=200) return Response({'msg': True}, status=200)
else: else:
return Response({'msg': False}, status=403) return Response({'msg': False}, status=403)
class AssetPermissionRemoveUserApi(RetrieveUpdateAPIView):
"""
将用户从授权中移除,Detail页面会调用
"""
permission_classes = (IsSuperUser,)
serializer_class = serializers.AssetPermissionUpdateUserSerializer
queryset = AssetPermission.objects.all()
def update(self, request, *args, **kwargs):
perm = self.get_object()
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
users = serializer.validated_data.get('users')
if users:
perm.users.remove(*tuple(users))
return Response({"msg": "ok"})
else:
return Response({"error": serializer.errors})
class AssetPermissionAddUserApi(RetrieveUpdateAPIView):
permission_classes = (IsSuperUser,)
serializer_class = serializers.AssetPermissionUpdateUserSerializer
queryset = AssetPermission.objects.all()
def update(self, request, *args, **kwargs):
perm = self.get_object()
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
users = serializer.validated_data.get('users')
if users:
perm.users.add(*tuple(users))
return Response({"msg": "ok"})
else:
return Response({"error": serializer.errors})
class AssetPermissionRemoveAssetApi(RetrieveUpdateAPIView):
"""
将用户从授权中移除,Detail页面会调用
"""
permission_classes = (IsSuperUser,)
serializer_class = serializers.AssetPermissionUpdateAssetSerializer
queryset = AssetPermission.objects.all()
def update(self, request, *args, **kwargs):
perm = self.get_object()
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
assets = serializer.validated_data.get('assets')
if assets:
perm.assets.remove(*tuple(assets))
return Response({"msg": "ok"})
else:
return Response({"error": serializer.errors})
class AssetPermissionAddAssetApi(RetrieveUpdateAPIView):
permission_classes = (IsSuperUser,)
serializer_class = serializers.AssetPermissionUpdateAssetSerializer
queryset = AssetPermission.objects.all()
def update(self, request, *args, **kwargs):
perm = self.get_object()
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
assets = serializer.validated_data.get('assets')
if assets:
perm.assets.add(*tuple(assets))
return Response({"msg": "ok"})
else:
return Response({"error": serializer.errors})
...@@ -4,10 +4,23 @@ from __future__ import absolute_import, unicode_literals ...@@ -4,10 +4,23 @@ from __future__ import absolute_import, unicode_literals
from django import forms from django import forms
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from .hands import User
from .models import AssetPermission from .models import AssetPermission
class AssetPermissionForm(forms.ModelForm): class AssetPermissionForm(forms.ModelForm):
users = forms.ModelMultipleChoiceField(
queryset=User.objects.exclude(role=User.ROLE_APP),
label=_("User"),
widget=forms.SelectMultiple(
attrs={
'class': 'select2',
'data-placeholder': _('Select users')
}
),
required=False,
)
class Meta: class Meta:
model = AssetPermission model = AssetPermission
exclude = ( exclude = (
......
...@@ -4,7 +4,7 @@ from django.db import models ...@@ -4,7 +4,7 @@ from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils import timezone from django.utils import timezone
from common.utils import date_expired_default from common.utils import date_expired_default, set_or_append_attr_bulk
class ValidManager(models.Manager): class ValidManager(models.Manager):
...@@ -45,6 +45,22 @@ class AssetPermission(models.Model): ...@@ -45,6 +45,22 @@ class AssetPermission(models.Model):
return True return True
return False return False
def get_all_users(self):
users = set(self.users.all())
for group in self.user_groups.all():
_users = group.users.all()
set_or_append_attr_bulk(_users, 'inherit', group.name)
users.update(set(_users))
return users
def get_all_assets(self):
assets = set(self.assets.all())
for node in self.nodes.all():
_assets = node.get_all_assets()
set_or_append_attr_bulk(_assets, 'inherit', node.value)
assets.update(set(_assets))
return assets
class NodePermission(models.Model): class NodePermission(models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True) id = models.UUIDField(default=uuid.uuid4, primary_key=True)
......
...@@ -57,12 +57,12 @@ ...@@ -57,12 +57,12 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for asset in page_obj %} {% for asset in object_list %}
<tr> <tr>
<td>{{ asset.hostname }}</td> <td>{{ asset.hostname }}</td>
<td>{{ asset.ip }}</td> <td>{{ asset.ip }}</td>
<td> <td>
<button title="{{ asset.inherit_from_asset_groups }}" data-gid="{{ asset.id }}" class="btn btn-danger btn-xs btn-remove-asset {% if asset.is_inherit_from_asset_groups %} disabled {% endif %}" type="button" style="float: right;"><i class="fa fa-minus"></i></button> <button title="{{ asset.inherit }}" data-gid="{{ asset.id }}" class="btn btn-danger btn-xs btn-remove-asset {% if asset.inherit %} disabled {% endif %}" type="button" style="float: right;"><i class="fa fa-minus"></i></button>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
...@@ -85,9 +85,9 @@ ...@@ -85,9 +85,9 @@
<form> <form>
<tr class="no-borders-tr"> <tr class="no-borders-tr">
<td colspan="2"> <td colspan="2">
<select data-placeholder="{% trans 'Select assets' %}" class="select2 asset" style="width: 100%" multiple="" tabindex="4"> <select data-placeholder="{% trans 'Select assets' %}" class="select2" id="asset_select2" style="width: 100%" multiple="" tabindex="4">
{% for asset in assets_remain %} {% for asset in assets_remain %}
<option value="{{ asset.id }}">{{ asset.hostname }}</option> <option value="{{ asset.id }}">{{ asset }}</option>
{% endfor %} {% endfor %}
</select> </select>
</td> </td>
...@@ -105,7 +105,7 @@ ...@@ -105,7 +105,7 @@
<div class="panel panel-info"> <div class="panel panel-info">
<div class="panel-heading"> <div class="panel-heading">
<i class="fa fa-info-circle"></i> {% trans 'Add asset group to this permission' %} <i class="fa fa-info-circle"></i> {% trans 'Add node to this permission' %}
</div> </div>
<div class="panel-body"> <div class="panel-body">
<table class="table group_edit"> <table class="table group_edit">
...@@ -113,25 +113,25 @@ ...@@ -113,25 +113,25 @@
<form> <form>
<tr> <tr>
<td colspan="2" class="no-borders"> <td colspan="2" class="no-borders">
<select data-placeholder="{% trans 'Select asset groups' %}" class="select2 group" style="width: 100%" multiple="" tabindex="4"> <select data-placeholder="{% trans 'Select nodes' %}" class="select2" id="node_select2" style="width: 100%" multiple="" tabindex="4">
{% for asset_group in asset_groups_remain %} {% for node in nodes_remain %}
<option value="{{ asset_group.id }}" id="opt_{{ asset_group.id }}">{{ asset_group.name }}</option> <option value="{{ node.id }}" id="opt_{{ node.id }}">{{ node }}</option>
{% endfor %} {% endfor %}
</select> </select>
</td> </td>
</tr> </tr>
<tr> <tr>
<td colspan="2" class="no-borders"> <td colspan="2" class="no-borders">
<button type="button" class="btn btn-info btn-sm" id="btn-add-group">{% trans 'Join' %}</button> <button type="button" class="btn btn-info btn-sm" id="btn-add-node">{% trans 'Join' %}</button>
</td> </td>
</tr> </tr>
</form> </form>
{% for asset_group in asset_groups %} {% for node in asset_permission.nodes.all %}
<tr> <tr>
<td ><b class="bdg_user_group" data-gid={{ asset_group.id }}>{{ asset_group.name }}</b></td> <td ><b class="bdg_group" data-gid={{ node.id }}>{{ node }}</b></td>
<td> <td>
<button class="btn btn-danger btn-xs btn-remove-group" type="button" style="float: right;"><i class="fa fa-minus"></i></button> <button class="btn btn-danger btn-xs btn-remove-node" type="button" data-gid="{{ node.id }}" style="float: right;"><i class="fa fa-minus"></i></button>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
...@@ -179,49 +179,30 @@ function removeAssets(assets) { ...@@ -179,49 +179,30 @@ function removeAssets(assets) {
}); });
} }
function updateGroup(groups) { function updateNodes(nodes, success) {
var the_url = "{% url 'api-perms:asset-permission-detail' pk=asset_permission.id %}"; var the_url = "{% url 'api-perms:asset-permission-detail' pk=asset_permission.id %}";
var body = { var body = {
asset_groups: groups nodes: nodes
}; };
APIUpdateAttr({ APIUpdateAttr({
url: the_url, url: the_url,
body: JSON.stringify(body) body: JSON.stringify(body),
success: success
}); });
} }
jumpserver.assets_selected = {};
jumpserver.nodes_selected = {};
$(document).ready(function () { $(document).ready(function () {
$('.select2.asset').select2() $('.select2').select2();
.on('select2:select', function(evt) {
var data = evt.params.data;
jumpserver.assets_selected[data.id] = data.text;
})
.on('select2:unselect', function(evt) {
var data = evt.params.data;
delete jumpserver.assets_selected[data.id]
});
$('.select2.group').select2()
.on('select2:select', function(evt) {
var data = evt.params.data;
jumpserver.nodes_selected[data.id] = data.text;
})
.on('select2:unselect', function(evt) {
var data = evt.params.data;
delete jumpserver.nodes_selected[data.id]
})
}) })
.on('click', '.btn-add-assets', function () { .on('click', '.btn-add-assets', function () {
if (Object.keys(jumpserver.assets_selected).length === 0) { var assets_selected = $("#asset_select2 option:selected").map(function () {
return $(this).attr('value');
}).get();
if (assets_selected.length === 0) {
return false; return false;
} }
var assets = []; addAssets(assets_selected);
$.map(jumpserver.assets_selected, function(value, index) {
assets.push(index);
});
addAssets(assets);
}) })
.on('click', '.btn-remove-asset', function () { .on('click', '.btn-remove-asset', function () {
var asset_id = $(this).data("gid"); var asset_id = $(this).data("gid");
...@@ -231,38 +212,44 @@ $(document).ready(function () { ...@@ -231,38 +212,44 @@ $(document).ready(function () {
var assets = [asset_id]; var assets = [asset_id];
removeAssets(assets) removeAssets(assets)
}) })
.on('click', '#btn-add-group', function () { .on('click', '#btn-add-node', function () {
if (Object.keys(jumpserver.nodes_selected).length === 0) { var nodes_selected = {};
$("#node_select2 option:selected").each(function (i, data) {
nodes_selected[$(data).attr('value')] = $(data).text();
});
if (Object.keys(nodes_selected).length === 0) {
return false; return false;
} }
var nodes_origin = $('.bdg_group').map(function() {
var groups = $('.bdg_group').map(function() {
return $(this).data('gid'); return $(this).data('gid');
}).get(); }).get();
$.map(jumpserver.nodes_selected, function(group_name, index) { var nodes = nodes_origin.concat(Object.keys(nodes_selected));
groups.push(index); var success = function () {
$('#opt_' + index).remove(); $.map(nodes_selected, function(name, id) {
$('.group_edit tbody').append( $('#opt_' + id).remove();
'<tr>' + $('.group_edit tbody').append(
'<td><b class="bdg_group" data-gid="' + index + '">' + group_name + '</b></td>' + '<tr>' +
'<td><button class="btn btn-danger btn-xs pull-right btn-leave-group" type="button"><i class="fa fa-minus"></i></button></td>' + '<td><b class="bdg_group" data-gid="' + id + '">' + name + '</b></td>' +
'</tr>' '<td><button class="btn btn-danger btn-xs pull-right btn-leave-group" type="button"><i class="fa fa-minus"></i></button></td>' +
) '</tr>'
}); )
});
updateGroup(groups); };
updateNodes(nodes, success);
}) })
.on('click', '.btn-remove-group', function () { .on('click', '.btn-remove-node', function () {
var $this = $(this); var $this = $(this);
var $tr = $this.closest('tr'); var $tr = $this.closest('tr');
var groups = $('.bdg_group').map(function() { var nodes = $('.bdg_group').map(function() {
if ($(this).data('gid') !== $this.data('gid')){ if ($(this).data('gid') !== $this.data('gid')){
return $(this).data('gid'); return $(this).data('gid');
} }
}).get(); }).get();
updateGroup(groups); var success = function () {
$tr.remove() $tr.remove()
};
updateNodes(nodes, success);
}) })
</script> </script>
{% endblock %} {% endblock %}
...@@ -76,20 +76,37 @@ ...@@ -76,20 +76,37 @@
</div> </div>
</div> </div>
</div> </div>
{% include 'assets/_asset_list_modal.html' %}
{% endblock %} {% endblock %}
{% block custom_foot_js %} {% block custom_foot_js %}
<script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"></script> <script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"></script>
<script> <script>
$(document).ready(function () { $(document).ready(function () {
$('.select2').select2(); $('.select2').select2({
$('#datepicker').datepicker({ closeOnSelect: false
format: "yyyy-mm-dd", });
todayBtn: "linked", $('#datepicker').datepicker({
keyboardNavigation: false, format: "yyyy-mm-dd",
forceParse: false, todayBtn: "linked",
calendarWeeks: true, keyboardNavigation: false,
autoclose: true forceParse: false,
}); calendarWeeks: true,
}) autoclose: true
</script> });
$("#id_assets").parent().find(".select2-selection").on('click', function (e) {
e.preventDefault();
$("#asset_list_modal").modal();
})
})
.on('click', '#btn_asset_modal_confirm', function () {
var assets = asset_table2.selected;
$('.select2 option:selected').each(function (i, data) {
assets.push($(data).attr('value'))
});
$.each(assets, function (id, data) {
$('.select2').val(assets).trigger('change');
});
$("#asset_list_modal").modal('hide');
})
</script>
{% endblock %} {% endblock %}
\ No newline at end of file
...@@ -15,19 +15,19 @@ ...@@ -15,19 +15,19 @@
<div class="panel-options"> <div class="panel-options">
<ul class="nav nav-tabs"> <ul class="nav nav-tabs">
<li class="active"> <li class="active">
<a href="{% url 'perms:asset-permission-detail' pk=asset_permission.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Detail' %} </a> <a href="{% url 'perms:asset-permission-detail' pk=object.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Detail' %} </a>
</li> </li>
<li> <li>
<a href="{% url 'perms:asset-permission-user-list' pk=asset_permission.id %}" class="text-center"> <a href="{% url 'perms:asset-permission-user-list' pk=object.id %}" class="text-center">
<i class="fa fa-bar-chart-o"></i> {% trans 'Users and user groups' %} <i class="fa fa-bar-chart-o"></i> {% trans 'Users and user groups' %}
</a> </a>
</li> </li>
<li> <li>
<a href="{% url 'perms:asset-permission-asset-list' pk=asset_permission.id %}" class="text-center"> <a href="{% url 'perms:asset-permission-asset-list' pk=object.id %}" class="text-center">
<i class="fa fa-bar-chart-o"></i> {% trans 'Assets and asset groups' %}</a> <i class="fa fa-bar-chart-o"></i> {% trans 'Assets and asset groups' %}</a>
</li> </li>
<li class="pull-right"> <li class="pull-right">
<a class="btn btn-outline btn-default" href="{% url 'perms:asset-permission-update' pk=asset_permission.id %}"><i class="fa fa-edit"></i>{% trans 'Update' %}</a> <a class="btn btn-outline btn-default" href="{% url 'perms:asset-permission-update' pk=object.id %}"><i class="fa fa-edit"></i>{% trans 'Update' %}</a>
</li> </li>
<li class="pull-right"> <li class="pull-right">
<a class="btn btn-outline btn-danger btn-delete-perm"> <a class="btn btn-outline btn-danger btn-delete-perm">
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
<div class="col-sm-7" style="padding-left: 0;"> <div class="col-sm-7" style="padding-left: 0;">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<span class="label"><b>{{ asset_permission.name }}</b></span> <span class="label"><b>{{ object.name }}</b></span>
<div class="ibox-tools"> <div class="ibox-tools">
<a class="collapse-link"> <a class="collapse-link">
<i class="fa fa-chevron-up"></i> <i class="fa fa-chevron-up"></i>
...@@ -60,43 +60,47 @@ ...@@ -60,43 +60,47 @@
<tbody> <tbody>
<tr class="no-borders-tr"> <tr class="no-borders-tr">
<td>{% trans 'Name' %}:</td> <td>{% trans 'Name' %}:</td>
<td><b>{{ asset_permission.name }}</b></td> <td><b>{{ object.name }}</b></td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'User count' %}:</td> <td>{% trans 'User count' %}:</td>
<td><b>{{ asset_permission.users.count }}</b></td> <td><b>{{ object.users.count }}</b></td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'User group count' %}:</td> <td>{% trans 'User group count' %}:</td>
<td><b>{{ asset_permission.users.count }}</b></td> <td><b>{{ object.users.count }}</b></td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'Asset count' %}:</td> <td>{% trans 'Asset count' %}:</td>
<td><b>{{ asset_permission.assets.count }}</b></td> <td><b>{{ object.assets.count }}</b></td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'Asset group count' %}:</td> <td>{% trans 'Node count' %}:</td>
<td><b>{{ asset_permission.asset_groups.count }}</b></td> <td><b>{{ object.nodes.count }}</b></td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'System user count' %}:</td> <td>{% trans 'System user count' %}:</td>
<td><b>{{ asset_permission.system_users.count }}</b></td> <td><b>{{ object.system_users.count }}</b></td>
</tr>
<tr>
<td>{% trans 'Date start' %}:</td>
<td><b>{{ object.date_start }}</b></td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'Date expired' %}:</td> <td>{% trans 'Date expired' %}:</td>
<td><b>{{ asset_permission.date_expired }}</b></td> <td><b>{{ object.date_expired }}</b></td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'Date created' %}:</td> <td>{% trans 'Date created' %}:</td>
<td><b>{{ asset_permission.date_created }}</b></td> <td><b>{{ object.date_created }}</b></td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'Created by' %}:</td> <td>{% trans 'Created by' %}:</td>
<td><b>{{ asset_permission.created_by }}</b></td> <td><b>{{ object.created_by }}</b></td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'Comment' %}:</td> <td>{% trans 'Comment' %}:</td>
<td><b>{{ asset_permission.comment }}</b></td> <td><b>{{ object.comment }}</b></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
...@@ -117,7 +121,7 @@ ...@@ -117,7 +121,7 @@
<td><span style="float: right"> <td><span style="float: right">
<div class="switch"> <div class="switch">
<div class="onoffswitch"> <div class="onoffswitch">
<input type="checkbox" {% if asset_permission.is_active %} checked {% endif %} class="onoffswitch-checkbox" id="is_active"> <input type="checkbox" {% if object.is_active %} checked {% endif %} class="onoffswitch-checkbox" id="is_active">
<label class="onoffswitch-label" for="is_active"> <label class="onoffswitch-label" for="is_active">
<span class="onoffswitch-inner"></span> <span class="onoffswitch-inner"></span>
<span class="onoffswitch-switch"></span> <span class="onoffswitch-switch"></span>
...@@ -143,7 +147,7 @@ ...@@ -143,7 +147,7 @@
<td colspan="2"> <td colspan="2">
<select data-placeholder="{% trans 'Select system users' %}" class="select2" style="width: 100%" multiple="" tabindex="4"> <select data-placeholder="{% trans 'Select system users' %}" class="select2" style="width: 100%" multiple="" tabindex="4">
{% for system_user in system_users_remain %} {% for system_user in system_users_remain %}
<option value="{{ system_user.id }}" id="opt_{{ system_user.id }}">{{ system_user.name }}</option> <option value="{{ system_user.id }}" id="opt_{{ system_user.id }}">{{ system_user }}</option>
{% endfor %} {% endfor %}
</select> </select>
</td> </td>
...@@ -155,9 +159,9 @@ ...@@ -155,9 +159,9 @@
</tr> </tr>
</form> </form>
{% for system_user in system_users %} {% for system_user in object.system_users.all %}
<tr {% if forloop.counter == 1 %} class="no-borders-tr" {% endif %} > <tr {% if forloop.counter == 1 %} class="no-borders-tr" {% endif %} >
<td ><b class="bdg-system-user" data-uid={{ system_user.id }}>{{ system_user.name }}</b></td> <td ><b class="bdg-system-user" data-uid={{ system_user.id }}>{{ system_user }}</b></td>
<td> <td>
<button class="btn btn-danger btn-xs btn-remove-user" data-uid="{{ system_user.id }}" type="button" style="float: right;"><i class="fa fa-minus"></i></button> <button class="btn btn-danger btn-xs btn-remove-user" data-uid="{{ system_user.id }}" type="button" style="float: right;"><i class="fa fa-minus"></i></button>
</td> </td>
...@@ -179,7 +183,7 @@ ...@@ -179,7 +183,7 @@
jumpserver.system_users_selected = {}; jumpserver.system_users_selected = {};
function updateSystemUser(system_users) { function updateSystemUser(system_users) {
var the_url = "{% url 'api-perms:asset-permission-detail' pk=asset_permission.id %}"; var the_url = "{% url 'api-perms:asset-permission-detail' pk=object.id %}";
var body = { var body = {
system_users: Object.assign([], system_users) system_users: Object.assign([], system_users)
}; };
...@@ -203,7 +207,7 @@ $(document).ready(function () { ...@@ -203,7 +207,7 @@ $(document).ready(function () {
.on('click', '.btn-delete-perm', function () { .on('click', '.btn-delete-perm', function () {
var $this = $(this); var $this = $(this);
var name = "{{ asset_permission.name }}"; var name = "{{ asset_permission.name }}";
var uid = "{{ asset_permission.id }}"; var uid = "{{ object.id }}";
var the_url = '{% url "api-perms:asset-permission-detail" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', uid); var the_url = '{% url "api-perms:asset-permission-detail" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', uid);
var redirect_url = "{% url 'perms:asset-permission-list' %}"; var redirect_url = "{% url 'perms:asset-permission-list' %}";
objectDelete($this, name, the_url, redirect_url); objectDelete($this, name, the_url, redirect_url);
...@@ -238,7 +242,7 @@ $(document).ready(function () { ...@@ -238,7 +242,7 @@ $(document).ready(function () {
updateSystemUser(system_users); updateSystemUser(system_users);
$tr.remove() $tr.remove()
}).on('click', '#is_active', function () { }).on('click', '#is_active', function () {
var the_url = '{% url "api-perms:asset-permission-detail" pk=asset_permission.id %}'; var the_url = '{% url "api-perms:asset-permission-detail" pk=object.id %}';
var checked = $(this).prop('checked'); var checked = $(this).prop('checked');
var body = { var body = {
'is_active': checked 'is_active': checked
......
...@@ -57,12 +57,12 @@ ...@@ -57,12 +57,12 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for user in page_obj %} {% for user in object_list %}
<tr> <tr>
<td>{{ user.name }}</td> <td>{{ user.name }}</td>
<td>{{ user.username }}</td> <td>{{ user.username }}</td>
<td> <td>
<button class="btn btn-danger btn-xs btn-remove-user {% if user.is_inherit_from_user_groups %} disabled {% endif %}" data-gid="{{ user.id }}" type="button" style="float: right;"><i class="fa fa-minus"></i></button> <button class="btn btn-danger btn-xs btn-remove-user {% if user.inherit %} disabled {% endif %}" data-gid="{{ user.id }}" type="button" style="float: right;"><i class="fa fa-minus"></i></button>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
<td colspan="2"> <td colspan="2">
<select data-placeholder="{% trans 'Select user' %}" class="select2 user" style="width: 100%" multiple="" tabindex="4"> <select data-placeholder="{% trans 'Select user' %}" class="select2 user" style="width: 100%" multiple="" tabindex="4">
{% for user in users_remain %} {% for user in users_remain %}
<option value="{{ user.id }}">{{ user.name }}</option> <option value="{{ user.id }}">{{ user }}</option>
{% endfor %} {% endfor %}
</select> </select>
</td> </td>
...@@ -115,7 +115,7 @@ ...@@ -115,7 +115,7 @@
<td colspan="2" class="no-borders"> <td colspan="2" class="no-borders">
<select data-placeholder="{% trans 'Select user groups' %}" class="select2 user-group" style="width: 100%" multiple="" tabindex="4"> <select data-placeholder="{% trans 'Select user groups' %}" class="select2 user-group" style="width: 100%" multiple="" tabindex="4">
{% for user_group in user_groups_remain %} {% for user_group in user_groups_remain %}
<option value="{{ user_group.id }}" id="opt_{{ user_group.id }}">{{ user_group.name }}</option> <option value="{{ user_group.id }}" id="opt_{{ user_group.id }}">{{ user_group }}</option>
{% endfor %} {% endfor %}
</select> </select>
</td> </td>
...@@ -127,9 +127,9 @@ ...@@ -127,9 +127,9 @@
</tr> </tr>
</form> </form>
{% for user_group in user_groups %} {% for user_group in asset_permission.user_groups.all %}
<tr> <tr>
<td ><b class="bdg_group" data-gid={{ user_group.id }}>{{ user_group.name }}</b></td> <td ><b class="bdg_group" data-gid={{ user_group.id }}>{{ user_group }}</b></td>
<td> <td>
<button class="btn btn-danger btn-xs btn-remove-group" type="button" data-gid="{{ user_group.id }}" style="float: right;"><i class="fa fa-minus"></i></button> <button class="btn btn-danger btn-xs btn-remove-group" type="button" data-gid="{{ user_group.id }}" style="float: right;"><i class="fa fa-minus"></i></button>
</td> </td>
......
...@@ -11,20 +11,50 @@ router.register('v1/asset-permissions', api.AssetPermissionViewSet, 'asset-permi ...@@ -11,20 +11,50 @@ router.register('v1/asset-permissions', api.AssetPermissionViewSet, 'asset-permi
urlpatterns = [ urlpatterns = [
# 查询某个用户授权的资产和资产组 # 查询某个用户授权的资产和资产组
url(r'^v1/user/(?P<pk>[0-9a-zA-Z\-]{36})/assets/$', api.UserGrantedAssetsApi.as_view(), name='user-assets'), url(r'^v1/user/(?P<pk>[0-9a-zA-Z\-]{36})/assets/$',
url(r'^v1/user/assets/$', api.UserGrantedAssetsApi.as_view(), name='my-assets'), api.UserGrantedAssetsApi.as_view(), name='user-assets'),
url(r'^v1/user/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/$', api.UserGrantedNodesApi.as_view(), name='user-nodes'), url(r'^v1/user/assets/$', api.UserGrantedAssetsApi.as_view(),
url(r'^v1/user/nodes/$', api.UserGrantedNodesApi.as_view(), name='my-nodes'), name='my-assets'),
url(r'^v1/user/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/(?P<node_id>[0-9a-zA-Z\-]{36})/assets/$', api.UserGrantedNodeAssetsApi.as_view(), name='user-node-assets'), url(r'^v1/user/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/$',
url(r'^v1/user/nodes/(?P<node_id>[0-9a-zA-Z\-]{36})/assets/$', api.UserGrantedNodeAssetsApi.as_view(), name='my-node-assets'), api.UserGrantedNodesApi.as_view(), name='user-nodes'),
url(r'^v1/user/(?P<pk>[0-9a-zA-Z\-]{36})/nodes-assets/$', api.UserGrantedNodesWithAssetsApi.as_view(), name='user-nodes-assets'), url(r'^v1/user/nodes/$', api.UserGrantedNodesApi.as_view(),
url(r'^v1/user/nodes-assets/$', api.UserGrantedNodesWithAssetsApi.as_view(), name='my-nodes-assets'), name='my-nodes'),
url(
r'^v1/user/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/(?P<node_id>[0-9a-zA-Z\-]{36})/assets/$',
api.UserGrantedNodeAssetsApi.as_view(), name='user-node-assets'),
url(r'^v1/user/nodes/(?P<node_id>[0-9a-zA-Z\-]{36})/assets/$',
api.UserGrantedNodeAssetsApi.as_view(), name='my-node-assets'),
url(r'^v1/user/(?P<pk>[0-9a-zA-Z\-]{36})/nodes-assets/$',
api.UserGrantedNodesWithAssetsApi.as_view(), name='user-nodes-assets'),
url(r'^v1/user/nodes-assets/$', api.UserGrantedNodesWithAssetsApi.as_view(),
name='my-nodes-assets'),
# 查询某个用户组授权的资产和资产组 # 查询某个用户组授权的资产和资产组
url(r'^v1/user-group/(?P<pk>[0-9a-zA-Z\-]{36})/assets/$', api.UserGroupGrantedAssetsApi.as_view(), name='user-group-assets'), url(r'^v1/user-group/(?P<pk>[0-9a-zA-Z\-]{36})/assets/$',
url(r'^v1/user-group/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/$', api.UserGroupGrantedNodesApi.as_view(), name='user-group-nodes'), api.UserGroupGrantedAssetsApi.as_view(), name='user-group-assets'),
url(r'^v1/user-group/(?P<pk>[0-9a-zA-Z\-]{36})/nodes-assets/$', api.UserGroupGrantedNodesWithAssetsApi.as_view(), name='user-group-nodes-assets'), url(r'^v1/user-group/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/$',
url(r'^v1/user-group/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/(?P<node_id>[0-9a-zA-Z\-]{36})/assets/$', api.UserGroupGrantedNodeAssetsApi.as_view(), name='user-group-node-assets'), api.UserGroupGrantedNodesApi.as_view(), name='user-group-nodes'),
url(r'^v1/user-group/(?P<pk>[0-9a-zA-Z\-]{36})/nodes-assets/$',
api.UserGroupGrantedNodesWithAssetsApi.as_view(),
name='user-group-nodes-assets'),
url(
r'^v1/user-group/(?P<pk>[0-9a-zA-Z\-]{36})/nodes/(?P<node_id>[0-9a-zA-Z\-]{36})/assets/$',
api.UserGroupGrantedNodeAssetsApi.as_view(),
name='user-group-node-assets'),
# 用户和资产授权变更
url(r'^v1/asset-permissions/(?P<pk>[0-9a-zA-Z\-]{36})/user/remove/$',
api.AssetPermissionRemoveUserApi.as_view(),
name='asset-permission-remove-user'),
url(r'^v1/asset-permissions/(?P<pk>[0-9a-zA-Z\-]{36})/user/add/$',
api.AssetPermissionAddUserApi.as_view(),
name='asset-permission-add-user'),
url(r'^v1/asset-permissions/(?P<pk>[0-9a-zA-Z\-]{36})/asset/remove/$',
api.AssetPermissionRemoveAssetApi.as_view(),
name='asset-permission-remove-asset'),
url(r'^v1/asset-permissions/(?P<pk>[0-9a-zA-Z\-]{36})/asset/add/$',
api.AssetPermissionAddAssetApi.as_view(),
name='asset-permission-add-asset'),
# 验证用户是否有某个资产和系统用户的权限 # 验证用户是否有某个资产和系统用户的权限
url(r'v1/asset-permission/user/validate/$', api.ValidateUserAssetPermissionView.as_view(), name='validate-user-asset-permission'), url(r'v1/asset-permission/user/validate/$', api.ValidateUserAssetPermissionView.as_view(), name='validate-user-asset-permission'),
......
...@@ -11,8 +11,8 @@ urlpatterns = [ ...@@ -11,8 +11,8 @@ urlpatterns = [
url(r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/update$', views.AssetPermissionUpdateView.as_view(), name='asset-permission-update'), url(r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/update$', views.AssetPermissionUpdateView.as_view(), name='asset-permission-update'),
url(r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})$', views.AssetPermissionDetailView.as_view(),name='asset-permission-detail'), url(r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})$', views.AssetPermissionDetailView.as_view(),name='asset-permission-detail'),
url(r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/delete$', views.AssetPermissionDeleteView.as_view(), name='asset-permission-delete'), url(r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/delete$', views.AssetPermissionDeleteView.as_view(), name='asset-permission-delete'),
# url(r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/user$', views.AssetPermissionUserView.as_view(), name='asset-permission-user-list'), url(r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/user$', views.AssetPermissionUserView.as_view(), name='asset-permission-user-list'),
# url(r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/asset$', views.AssetPermissionAssetView.as_view(), name='asset-permission-asset-list'), url(r'^asset-permission/(?P<pk>[0-9a-zA-Z\-]{36})/asset$', views.AssetPermissionAssetView.as_view(), name='asset-permission-asset-list'),
] ]
...@@ -4,12 +4,12 @@ from __future__ import unicode_literals, absolute_import ...@@ -4,12 +4,12 @@ from __future__ import unicode_literals, absolute_import
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.views.generic import ListView, CreateView, UpdateView, DetailView from django.views.generic import ListView, CreateView, UpdateView, DetailView
from django.views.generic.edit import DeleteView from django.views.generic.edit import DeleteView, SingleObjectMixin
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.conf import settings from django.conf import settings
from common.utils import is_uuid from common.mixins import AdminUserRequiredMixin
from .hands import AdminUserRequiredMixin, Node, Asset from .hands import Node, Asset, SystemUser, User, UserGroup
from .models import AssetPermission from .models import AssetPermission
from .forms import AssetPermissionForm from .forms import AssetPermissionForm
...@@ -83,7 +83,11 @@ class AssetPermissionDetailView(AdminUserRequiredMixin, DetailView): ...@@ -83,7 +83,11 @@ class AssetPermissionDetailView(AdminUserRequiredMixin, DetailView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = { context = {
'app': _('Perms'), 'app': _('Perms'),
'action': _('Update asset permission') 'action': _('Update asset permission'),
'system_users_remain': SystemUser.objects.exclude(
granted_by_permissions=self.object
),
} }
kwargs.update(context) kwargs.update(context)
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
...@@ -95,3 +99,59 @@ class AssetPermissionDeleteView(AdminUserRequiredMixin, DeleteView): ...@@ -95,3 +99,59 @@ class AssetPermissionDeleteView(AdminUserRequiredMixin, DeleteView):
success_url = reverse_lazy('perms:asset-permission-list') success_url = reverse_lazy('perms:asset-permission-list')
class AssetPermissionUserView(AdminUserRequiredMixin,
SingleObjectMixin,
ListView):
template_name = 'perms/asset_permission_user.html'
context_object_name = 'asset_permission'
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
object = None
def get(self, request, *args, **kwargs):
self.object = self.get_object(queryset=AssetPermission.objects.all())
return super().get(request, *args, **kwargs)
def get_queryset(self):
queryset = self.object.get_all_users()
return queryset
def get_context_data(self, **kwargs):
context = {
'app': _('Perms'),
'action': _('Asset permission user list'),
'users_remain': User.objects.exclude(asset_permissions=self.object)
.exclude(role=User.ROLE_APP),
'user_groups_remain': UserGroup.objects.exclude(
asset_permissions=self.object
)
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class AssetPermissionAssetView(AdminUserRequiredMixin,
SingleObjectMixin,
ListView):
template_name = 'perms/asset_permission_asset.html'
context_object_name = 'asset_permission'
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
object = None
def get(self, request, *args, **kwargs):
self.object = self.get_object(queryset=AssetPermission.objects.all())
return super().get(request, *args, **kwargs)
def get_queryset(self):
queryset = self.object.get_all_assets()
return queryset
def get_context_data(self, **kwargs):
assets_granted = self.get_queryset()
context = {
'app': _('Perms'),
'action': _('Asset permission asset list'),
'assets_remain': Asset.objects.exclude(id__in=[a.id for a in assets_granted]),
'nodes_remain': Node.objects.exclude(granted_by_permissions=self.object),
}
kwargs.update(context)
return super().get_context_data(**kwargs)
\ No newline at end of file
...@@ -307,7 +307,7 @@ jumpserver.initDataTable = function (options) { ...@@ -307,7 +307,7 @@ jumpserver.initDataTable = function (options) {
last: "»" last: "»"
} }
}, },
lengthMenu: [[15, 25, 50, -1], [15, 25, 50, "All"]] lengthMenu: [[10, 15, 25, 50, -1], [10, 15, 25, 50, "All"]]
}); });
table.on('select', function(e, dt, type, indexes) { table.on('select', function(e, dt, type, indexes) {
var $node = table[ type ]( indexes ).nodes().to$(); var $node = table[ type ]( indexes ).nodes().to$();
...@@ -446,22 +446,56 @@ jumpserver.initServerSideDataTable = function (options) { ...@@ -446,22 +446,56 @@ jumpserver.initServerSideDataTable = function (options) {
last: "»" last: "»"
} }
}, },
lengthMenu: [[15, 25, 50], [15, 25, 50]] lengthMenu: [[10, 15, 25, 50], [10, 15, 25, 50]]
}); });
table.selected = [];
table.on('select', function(e, dt, type, indexes) { table.on('select', function(e, dt, type, indexes) {
var $node = table[ type ]( indexes ).nodes().to$(); var $node = table[ type ]( indexes ).nodes().to$();
$node.find('input.ipt_check').prop('checked', true); $node.find('input.ipt_check').prop('checked', true);
jumpserver.selected[$node.find('input.ipt_check').prop('id')] = true jumpserver.selected[$node.find('input.ipt_check').prop('id')] = true;
if (type === 'row') {
var rows = table.rows(indexes).data();
$.each(rows, function (id, row) {
if (row.id){
table.selected.push(row.id)
}
})
}
}).on('deselect', function(e, dt, type, indexes) { }).on('deselect', function(e, dt, type, indexes) {
var $node = table[ type ]( indexes ).nodes().to$(); var $node = table[ type ]( indexes ).nodes().to$();
$node.find('input.ipt_check').prop('checked', false); $node.find('input.ipt_check').prop('checked', false);
jumpserver.selected[$node.find('input.ipt_check').prop('id')] = false jumpserver.selected[$node.find('input.ipt_check').prop('id')] = false;
if (type === 'row') {
var rows = table.rows(indexes).data();
$.each(rows, function (id, row) {
if (row.id){
var index = table.selected.indexOf(row.id);
if (index > -1){
table.selected.splice(index, 1)
}
}
})
}
}). }).
on('draw', function(){ on('draw', function(){
$('#op').html(options.op_html || ''); $('#op').html(options.op_html || '');
$('#uc').html(options.uc_html || ''); $('#uc').html(options.uc_html || '');
var table_data = [];
$.each(table.rows().data(), function (id, row) {
if (row.id) {
table_data.push(row.id)
}
});
$.each(table.selected, function (id, data) {
var index = table_data.indexOf(data);
if (index > -1){
table.rows(index).select()
}
});
}); });
$('.ipt_check_all').on('click', function() { var table_id = table.settings()[0].sTableId;
$('#' + table_id + ' .ipt_check_all').on('click', function() {
if ($(this).prop("checked")) { if ($(this).prop("checked")) {
$(this).closest('table').find('.ipt_check').prop('checked', true); $(this).closest('table').find('.ipt_check').prop('checked', true);
table.rows({search:'applied', page:'current'}).select(); table.rows({search:'applied', page:'current'}).select();
......
<div class="footer fixed"> <div class="footer fixed">
<div class="pull-right"> <div class="pull-right">
Version <strong>1.0.0-{% include '_build.html' %}</strong> GPLv2. Version <strong>1.2.0-{% include '_build.html' %}</strong> GPLv2.
<img style="display: none" src="http://www.jumpserver.org/img/evaluate_avatar1.jpg"> <img style="display: none" src="http://www.jumpserver.org/img/evaluate_avatar1.jpg">
</div> </div>
<div> <div>
......
{% load i18n %} {% load i18n %}
<style>
.modal-body {
padding: 0px 20px 0px 20px;
}
</style>
<div aria-hidden="true" role="dialog" id="{% block modal_id %}{% endblock %}" class="modal inmodal"> <div aria-hidden="true" role="dialog" id="{% block modal_id %}{% endblock %}" class="modal inmodal">
<div class="modal-dialog {% block modal_class %}{% endblock %}"> <div class="modal-dialog {% block modal_class %}{% endblock %}">
<div class="modal-content animated fadeIn"> <div class="modal-content animated fadeIn">
...@@ -12,8 +17,10 @@ ...@@ -12,8 +17,10 @@
{% endblock %} {% endblock %}
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
{% block modal_button %}
<button data-dismiss="modal" class="btn btn-white" type="button">{% trans "Close" %}</button> <button data-dismiss="modal" class="btn btn-white" type="button">{% trans "Close" %}</button>
<button class="btn btn-primary" type="button" id="{% block modal_confirm_id %}{% endblock %}">{% trans 'Confirm' %}</button> <button class="btn btn-primary" type="button" id="{% block modal_confirm_id %}{% endblock %}">{% trans 'Confirm' %}</button>
{% endblock %}
</div> </div>
</div> </div>
</div> </div>
......
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
</li> </li>
<li id="audits"> <li id="audits">
<a> <a>
<i class="fa fa-coffee" style="width: 14px"></i> <span class="nav-label">{% trans 'Audits' %}</span><span class="fa arrow"></span> <i class="fa fa-history" style="width: 14px"></i> <span class="nav-label">{% trans 'Audits' %}</span><span class="fa arrow"></span>
</a> </a>
<ul class="nav nav-second-level"> <ul class="nav nav-second-level">
<li id="ftp-log"><a href="{% url 'audits:ftp-log-list' %}">{% trans 'FTP log' %}</a></li> <li id="ftp-log"><a href="{% url 'audits:ftp-log-list' %}">{% trans 'FTP log' %}</a></li>
......
...@@ -248,7 +248,7 @@ class CommandViewSet(viewsets.ViewSet): ...@@ -248,7 +248,7 @@ class CommandViewSet(viewsets.ViewSet):
class SessionReplayViewSet(viewsets.ViewSet): class SessionReplayViewSet(viewsets.ViewSet):
serializer_class = ReplaySerializer serializer_class = ReplaySerializer
permission_classes = () permission_classes = (IsSuperUserOrAppUser,)
session = None session = None
def gen_session_path(self): def gen_session_path(self):
......
...@@ -45,7 +45,7 @@ class User(AbstractUser): ...@@ -45,7 +45,7 @@ class User(AbstractUser):
wechat = models.CharField(max_length=128, blank=True, verbose_name=_('Wechat')) wechat = models.CharField(max_length=128, blank=True, verbose_name=_('Wechat'))
phone = models.CharField(max_length=20, blank=True, null=True, verbose_name=_('Phone')) phone = models.CharField(max_length=20, blank=True, null=True, verbose_name=_('Phone'))
otp_level = models.SmallIntegerField(default=0, choices=OTP_LEVEL_CHOICES, verbose_name=_('Enable OTP')) otp_level = models.SmallIntegerField(default=0, choices=OTP_LEVEL_CHOICES, verbose_name=_('Enable OTP'))
otp_secret_key = models.CharField(max_length=16, blank=True, null=True) _otp_secret_key = models.CharField(max_length=128, blank=True, null=True)
# Todo: Auto generate key, let user download # Todo: Auto generate key, let user download
_private_key = models.CharField(max_length=5000, blank=True, verbose_name=_('Private key')) _private_key = models.CharField(max_length=5000, blank=True, verbose_name=_('Private key'))
_public_key = models.CharField(max_length=5000, blank=True, verbose_name=_('Public key')) _public_key = models.CharField(max_length=5000, blank=True, verbose_name=_('Public key'))
...@@ -55,7 +55,7 @@ class User(AbstractUser): ...@@ -55,7 +55,7 @@ class User(AbstractUser):
created_by = models.CharField(max_length=30, default='', verbose_name=_('Created by')) created_by = models.CharField(max_length=30, default='', verbose_name=_('Created by'))
def __str__(self): def __str__(self):
return self.username return '{0.name}({0.username})'.format(self)
@property @property
def password_raw(self): def password_raw(self):
...@@ -70,6 +70,14 @@ class User(AbstractUser): ...@@ -70,6 +70,14 @@ class User(AbstractUser):
def password_raw(self, password_raw_): def password_raw(self, password_raw_):
self.set_password(password_raw_) self.set_password(password_raw_)
@property
def otp_secret_key(self):
return signer.unsign(self._otp_secret_key)
@otp_secret_key.setter
def otp_secret_key(self, item):
self._otp_secret_key = signer.sign(item).decode('utf-8')
def get_absolute_url(self): def get_absolute_url(self):
return reverse('users:user-detail', args=(self.id,)) return reverse('users:user-detail', args=(self.id,))
......
...@@ -13,7 +13,7 @@ Docker 安装见: `Docker官方安装文档 <https://docs.docker.com/install/>`_ ...@@ -13,7 +13,7 @@ Docker 安装见: `Docker官方安装文档 <https://docs.docker.com/install/>`_
``````````````` ```````````````
使用 root 命令行输入:: 使用 root 命令行输入::
$ docker run -d -p 8080:80 -p 2222:2222 registry.jumpserver.org/public/jumpserver:latest $ docker run -d -p 8080:80 -p 2222:2222 registry.jumpserver.org/public/jumpserver:1.0.0
访问 访问
``````````````` ```````````````
...@@ -42,10 +42,13 @@ XShell等工具请添加connection连接 ...@@ -42,10 +42,13 @@ XShell等工具请添加connection连接
:: ::
docker run -d -p 8080:80 -p 2222:2222 -e DB_ENGINE=mysql -e DB_HOST=192.168.1.1 -e DB_PORT=3306 -e DB_USER=root -e DB_PASSWORD=xxx -e DB_NAME=jumpserver registry.jumpserver.org/public/jumpserver:latest docker run -d -p 8080:80 -p 2222:2222 -e DB_ENGINE=mysql -e DB_HOST=192.168.1.1 -e DB_PORT=3306 -e DB_USER=root -e DB_PASSWORD=xxx -e DB_NAME=jumpserver registry.jumpserver.org/public/jumpserver:1.0.0
仓库地址 仓库地址
``````````````` ```````````````
https://github.com/jumpserver/Dockerfile https://github.com/jumpserver/Dockerfile
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
# 看到下面的提示符代表成功,以后运行 Jumpserver 都要先运行以上 source 命令,以下所有命令均在该虚拟环境中运行 # 看到下面的提示符代表成功,以后运行 Jumpserver 都要先运行以上 source 命令,以下所有命令均在该虚拟环境中运行
(py3) [root@localhost py3] (py3) [root@localhost py3]
二. 安装 Jumpserver 0.5.0 二. 安装 Jumpserver 1.0.0
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**2.1 下载或 Clone 项目** **2.1 下载或 Clone 项目**
...@@ -201,7 +201,7 @@ ...@@ -201,7 +201,7 @@
Luna 已改为纯前端,需要 Nginx 来运行访问 Luna 已改为纯前端,需要 Nginx 来运行访问
访问(https://github.com/jumpserver/luna/releases)下载对应 release 包,直接解压,不需要编译 访问(https://github.com/jumpserver/luna/releases)下载对应版本的 release 包,直接解压,不需要编译
4.1 解压 Luna 4.1 解压 Luna
...@@ -228,7 +228,7 @@ Luna 已改为纯前端,需要 Nginx 来运行访问 ...@@ -228,7 +228,7 @@ Luna 已改为纯前端,需要 Nginx 来运行访问
-p 8081:8080 -v /opt/guacamole/key:/config/guacamole/key \ -p 8081:8080 -v /opt/guacamole/key:/config/guacamole/key \
-e JUMPSERVER_KEY_DIR=/config/guacamole/key \ -e JUMPSERVER_KEY_DIR=/config/guacamole/key \
-e JUMPSERVER_SERVER=http://<填写本机的IP地址>:8080 \ -e JUMPSERVER_SERVER=http://<填写本机的IP地址>:8080 \
registry.jumpserver.org/public/guacamole:latest registry.jumpserver.org/public/guacamole:1.0.0
这里所需要注意的是 guacamole 暴露出来的端口是 8081,若与主机上其他端口冲突请自定义一下。 这里所需要注意的是 guacamole 暴露出来的端口是 8081,若与主机上其他端口冲突请自定义一下。
......
...@@ -3,9 +3,10 @@ ...@@ -3,9 +3,10 @@
python ../apps/manage.py shell << EOF python ../apps/manage.py shell << EOF
from perms.models import * from perms.models import *
from assets.models import SystemUser
for old in NodePermission.objects.all(): for old in NodePermission.objects.all():
perm = asset_perm_model.objects.using(db_alias).create( perm = AssetPermission.objects.create(
name="{}-{}-{}".format( name="{}-{}-{}".format(
old.node.value, old.node.value,
old.user_group.name, old.user_group.name,
...@@ -20,5 +21,10 @@ for old in NodePermission.objects.all(): ...@@ -20,5 +21,10 @@ for old in NodePermission.objects.all():
perm.user_groups.add(old.user_group) perm.user_groups.add(old.user_group)
perm.nodes.add(old.node) perm.nodes.add(old.node)
perm.system_users.add(old.system_user) perm.system_users.add(old.system_user)
for s in SystemUser.objects.all():
nodes = list(s.nodes.all())
s.nodes.set([])
s.nodes.set(nodes)
EOF EOF
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