Commit 8e9b3f13 authored by ibuler's avatar ibuler

[Update] 修改permission actions

parents 48ba1993 320b17c8
...@@ -112,12 +112,16 @@ class NodeChildrenAsTreeApi(generics.ListAPIView): ...@@ -112,12 +112,16 @@ class NodeChildrenAsTreeApi(generics.ListAPIView):
is_root = False is_root = False
def get_queryset(self): def get_queryset(self):
self.check_need_refresh_nodes()
node_key = self.request.query_params.get('key') node_key = self.request.query_params.get('key')
util = NodeUtil() util = NodeUtil()
# 是否包含自己
with_self = False
if not node_key: if not node_key:
node_key = Node.root().key node_key = Node.root().key
with_self = True
self.node = util.get_node_by_key(node_key) self.node = util.get_node_by_key(node_key)
queryset = self.node.get_children(with_self=True) queryset = self.node.get_children(with_self=with_self)
queryset = [node.as_tree_node() for node in queryset] queryset = [node.as_tree_node() for node in queryset]
queryset = sorted(queryset) queryset = sorted(queryset)
return queryset return queryset
...@@ -133,14 +137,11 @@ class NodeChildrenAsTreeApi(generics.ListAPIView): ...@@ -133,14 +137,11 @@ class NodeChildrenAsTreeApi(generics.ListAPIView):
def filter_queryset(self, queryset): def filter_queryset(self, queryset):
queryset = self.filter_assets(queryset) queryset = self.filter_assets(queryset)
queryset = self.filter_refresh_nodes(queryset)
return queryset return queryset
def filter_refresh_nodes(self, queryset): def check_need_refresh_nodes(self):
if self.request.query_params.get('refresh', '0') == '1': if self.request.query_params.get('refresh', '0') == '1':
Node.expire_nodes_assets_amount() Node.refresh_nodes()
Node.expire_nodes_full_value()
return queryset
class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView): class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView):
......
...@@ -6,7 +6,7 @@ from django.utils.translation import gettext_lazy as _ ...@@ -6,7 +6,7 @@ from django.utils.translation import gettext_lazy as _
from common.utils import get_logger from common.utils import get_logger
from orgs.mixins import OrgModelForm from orgs.mixins import OrgModelForm
from ..models import Asset, Protocol from ..models import Asset, Protocol, Node
logger = get_logger(__file__) logger = get_logger(__file__)
...@@ -33,6 +33,12 @@ class ProtocolForm(forms.ModelForm): ...@@ -33,6 +33,12 @@ class ProtocolForm(forms.ModelForm):
class AssetCreateForm(OrgModelForm): class AssetCreateForm(OrgModelForm):
PROTOCOL_CHOICES = Protocol.PROTOCOL_CHOICES PROTOCOL_CHOICES = Protocol.PROTOCOL_CHOICES
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if not self.data:
nodes_field = self.fields['nodes']
nodes_field._queryset = Node.get_queryset()
class Meta: class Meta:
model = Asset model = Asset
fields = [ fields = [
......
...@@ -186,9 +186,6 @@ class FullValueMixin: ...@@ -186,9 +186,6 @@ class FullValueMixin:
def expire_nodes_full_value(cls, nodes=None): def expire_nodes_full_value(cls, nodes=None):
key = cls._full_value_cache_key.format('*') key = cls._full_value_cache_key.format('*')
cache.delete_pattern(key+'*') cache.delete_pattern(key+'*')
from ..utils import NodeUtil
util = NodeUtil()
util.set_full_value()
class AssetsAmountMixin: class AssetsAmountMixin:
...@@ -216,7 +213,7 @@ class AssetsAmountMixin: ...@@ -216,7 +213,7 @@ class AssetsAmountMixin:
def assets_amount(self, value): def assets_amount(self, value):
self._assets_amount = value self._assets_amount = value
cache_key = self._assets_amount_cache_key.format(self.key) cache_key = self._assets_amount_cache_key.format(self.key)
cache.set(cache_key, value, 3600 * 24) cache.set(cache_key, value)
def expire_assets_amount(self): def expire_assets_amount(self):
ancestor_keys = self.get_ancestor_keys(with_self=True) ancestor_keys = self.get_ancestor_keys(with_self=True)
...@@ -226,11 +223,15 @@ class AssetsAmountMixin: ...@@ -226,11 +223,15 @@ class AssetsAmountMixin:
@classmethod @classmethod
def expire_nodes_assets_amount(cls, nodes=None): def expire_nodes_assets_amount(cls, nodes=None):
from ..utils import NodeUtil
key = cls._assets_amount_cache_key.format('*') key = cls._assets_amount_cache_key.format('*')
cache.delete_pattern(key) cache.delete_pattern(key)
@classmethod
def refresh_nodes(cls):
from ..utils import NodeUtil
util = NodeUtil(with_assets_amount=True) util = NodeUtil(with_assets_amount=True)
util.set_assets_amount() util.set_assets_amount()
util.set_full_value()
class Node(OrgModelMixin, FamilyMixin, FullValueMixin, AssetsAmountMixin): class Node(OrgModelMixin, FamilyMixin, FullValueMixin, AssetsAmountMixin):
...@@ -375,9 +376,7 @@ class Node(OrgModelMixin, FamilyMixin, FullValueMixin, AssetsAmountMixin): ...@@ -375,9 +376,7 @@ class Node(OrgModelMixin, FamilyMixin, FullValueMixin, AssetsAmountMixin):
def as_tree_node(self): def as_tree_node(self):
from common.tree import TreeNode from common.tree import TreeNode
from ..serializers import NodeSerializer
name = '{} ({})'.format(self.value, self.assets_amount) name = '{} ({})'.format(self.value, self.assets_amount)
node_serializer = NodeSerializer(instance=self)
data = { data = {
'id': self.key, 'id': self.key,
'name': name, 'name': name,
...@@ -386,7 +385,12 @@ class Node(OrgModelMixin, FamilyMixin, FullValueMixin, AssetsAmountMixin): ...@@ -386,7 +385,12 @@ class Node(OrgModelMixin, FamilyMixin, FullValueMixin, AssetsAmountMixin):
'isParent': True, 'isParent': True,
'open': self.is_root(), 'open': self.is_root(),
'meta': { 'meta': {
'node': node_serializer.data, 'node': {
"id": self.id,
"name": self.name,
"value": self.value,
"key": self.key,
},
'type': 'node' 'type': 'node'
} }
} }
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from rest_framework import serializers from rest_framework import serializers
from django.utils.translation import ugettext as _
from orgs.mixins import BulkOrgResourceModelSerializer from orgs.mixins import BulkOrgResourceModelSerializer
from ..models import Asset, Node from ..models import Asset, Node
...@@ -25,11 +26,11 @@ class NodeSerializer(BulkOrgResourceModelSerializer): ...@@ -25,11 +26,11 @@ class NodeSerializer(BulkOrgResourceModelSerializer):
def validate_value(self, data): def validate_value(self, data):
instance = self.instance if self.instance else Node.root() instance = self.instance if self.instance else Node.root()
children = instance.parent.get_children().exclude(key=instance.key) children = instance.parent.get_children()
values = [child.value for child in children] children_values = [node.value for node in children if node != instance]
if data in values: if data in children_values:
raise serializers.ValidationError( raise serializers.ValidationError(
'The same level node name cannot be the same' _('The same level node name cannot be the same')
) )
return data return data
......
...@@ -67,6 +67,7 @@ function initTable2() { ...@@ -67,6 +67,7 @@ function initTable2() {
columns: [ columns: [
{data: "id"}, {data: "hostname" }, {data: "ip" } {data: "id"}, {data: "hostname" }, {data: "ip" }
], ],
lengthMenu: [[10, 25, 50], [10, 25, 50]],
pageLength: 10 pageLength: 10
}; };
asset_table2 = jumpserver.initServerSideDataTable(options); asset_table2 = jumpserver.initServerSideDataTable(options);
......
{% load static %}
{% load i18n %}
<link href="{% static 'css/plugins/ztree/awesomeStyle/awesome.css' %}" rel="stylesheet">
{# <link href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css" rel="stylesheet">#}
<script type="text/javascript" src="{% static 'js/plugins/ztree/jquery.ztree.all.min.js' %}"></script>
<style type="text/css">
div#rMenu {
position: absolute;
visibility: hidden;
text-align: left;
{#top: 100%;#}
top: 0;
left: 0;
z-index: 999;
{#float: left;#}
padding: 0 0;
margin: 2px 0 0;
list-style: none;
background-clip: padding-box;
}
.dataTables_wrapper .dataTables_processing {
opacity: .9;
border: none;
}
div#rMenu li{
margin: 1px 0;
cursor: pointer;
list-style: none outside none;
}
.dropdown a:hover {
background-color: #f1f1f1
}
</style>
<div class="ibox float-e-margins">
<div class="ibox-content mailbox-content" style="padding-top: 0;padding-left: 1px">
<div class="file-manager" id="tree-node-id">
<div id="{% block treeID %}nodeTree{% endblock %}" class="ztree">
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
<div id="rMenu">
<ul class="dropdown-menu menu-actions">
<li class="divider"></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><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>
</ul>
</div>
<script>
var zTree, rMenu = null;
var current_node_id = null;
var current_node = null;
var showMenu = false;
var treeUrl = '{% url 'api-assets:node-children-tree' %}?assets=0';
// options:
// {
// "onSelected": func,
// "showAssets": false,
// "beforeAsync": func()
// "showMenu": false,
// "otherMenu": "",
// "showAssets": false,
// }
function initNodeTree(options) {
var setting = {
view: {
dblClickExpand: false,
showLine: true
},
data: {
simpleData: {
enable: true
}
},
async: {
enable: true,
url: treeUrl,
autoParam: ["id=key", "name=n", "level=lv"],
type: 'get'
},
edit: {
enable: true,
showRemoveBtn: false,
showRenameBtn: false,
drag: {
isCopy: true,
isMove: true
}
},
callback: {
onRightClick: OnRightClick,
beforeClick: beforeClick,
onRename: onRename,
onSelected: options.onSelected || defaultCallback("On selected"),
beforeDrag: beforeDrag,
onDrag: onDrag,
beforeDrop: beforeDrop,
onDrop: onDrop,
beforeAsync: options.beforeAsync || defaultCallback("Before async")
}
};
if (options.showAssets) {
treeUrl = setUrlParam(treeUrl, 'assets', '1')
}
$.get(treeUrl, function(data, status){
zNodes = data;
zTree = $.fn.zTree.init($("#nodeTree"), setting, zNodes);
rootNodeAddDom(zTree, function () {
treeUrl = setUrlParam(treeUrl, 'refresh', '1');
initTree();
treeUrl = setUrlParam(treeUrl, 'refresh', '0')
});
});
if (options.showMenu) {
showMenu = true;
rMenu = $("#rMenu");
}
if (options.otherMenu) {
$(".menu-actions").append(options.otherMenu)
}
return zTree
}
function addTreeNode() {
hideRMenu();
var parentNode = zTree.getSelectedNodes()[0];
if (!parentNode){
return
}
var url = "{% url 'api-assets:node-children' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", parentNode.meta.node.id);
$.post(url, {}, function (data, status){
if (status === "success") {
var newNode = {
id: data["key"],
name: data["value"],
pId: parentNode.id,
meta: {
"node": data
}
};
newNode.checked = zTree.getSelectedNodes()[0].checked;
zTree.addNodes(parentNode, 0, newNode);
var node = zTree.getNodeByParam('id', newNode.id, parentNode);
zTree.editName(node);
} else {
alert("{% trans 'Create node failed' %}")
}
});
}
function removeTreeNode() {
hideRMenu();
var current_node = zTree.getSelectedNodes()[0];
if (!current_node){
return
}
if (current_node.children && current_node.children.length > 0) {
toastr.error("{% trans 'Have child node, cancel' %}");
} else if (current_node.meta.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);
$.ajax({
url: url,
method: "DELETE",
success: function () {
zTree.removeNode(current_node);
}
});
}
}
function editTreeNode() {
hideRMenu();
var current_node = zTree.getSelectedNodes()[0];
if (!current_node){
return
}
if (current_node) {
current_node.name = current_node.meta.node.value;
}
zTree.editName(current_node);
}
function OnRightClick(event, treeId, treeNode) {
if (!showMenu) {
return
}
if (!treeNode && event.target.tagName.toLowerCase() !== "button" && $(event.target).parents("a").length === 0) {
zTree.cancelSelectedNode();
showRMenu("root", event.clientX, event.clientY);
} else if (treeNode && !treeNode.noR) {
zTree.selectNode(treeNode);
showRMenu("node", event.clientX, event.clientY);
}
}
function showRMenu(type, x, y) {
var offset = $("#tree-node-id").offset();
x -= offset.left;
y -= offset.top;
x += document.body.scrollLeft;
y += document.body.scrollTop + document.documentElement.scrollTop;
rMenu.css({"top":y+"px", "left":x+"px", "visibility":"visible"});
$("#rMenu ul").show();
$("body").bind("mousedown", onBodyMouseDown);
}
function beforeClick(treeId, treeNode, clickFlag) {
return true;
}
function hideRMenu() {
if (rMenu) rMenu.css({"visibility": "hidden"});
$("body").unbind("mousedown", onBodyMouseDown);
}
function onBodyMouseDown(event){
if (!(event.target.id === "rMenu" || $(event.target).parents("#rMenu").length>0)) {
rMenu.css({"visibility" : "hidden"});
}
}
function onRename(event, treeId, treeNode, isCancel){
var url = "{% url 'api-assets:node-detail' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node_id);
var data = {"value": treeNode.name};
if (isCancel){
return
}
APIUpdateAttr({
url: url,
body: JSON.stringify(data),
method: "PATCH",
success_message: "{% trans 'Rename success' %}",
success: function () {
treeNode.name = treeNode.name + ' (' + treeNode.meta.node.assets_amount + ')';
zTree.updateNode(treeNode);
console.log("Success: " + treeNode.name)
}
})
}
function beforeDrag() {
return true
}
function beforeDrop(treeId, treeNodes, targetNode, moveType) {
var treeNodesNames = [];
$.each(treeNodes, function (index, value) {
treeNodesNames.push(value.name);
});
var msg = "你想移动节点: `" + treeNodesNames.join(",") + "` 到 `" + targetNode.name + "` 下吗?";
return confirm(msg);
}
function onDrag(event, treeId, treeNodes) {
}
function onDrop(event, treeId, treeNodes, targetNode, moveType) {
var treeNodesIds = [];
$.each(treeNodes, function (index, value) {
treeNodesIds.push(value.meta.node.id);
});
var the_url = "{% url 'api-assets:node-add-children' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", targetNode.meta.node.id);
var body = {nodes: treeNodesIds};
APIUpdateAttr({
url: the_url,
method: "PUT",
body: JSON.stringify(body)
})
}
function defaultCallback(action) {
function logging() {
console.log(action)
}
return logging
}
$(document).ready(function () {
})
.on('click', '.btn-refresh-hardware', function () {
var url = "{% url 'api-assets:node-refresh-hardware-info' pk=DEFAULT_PK %}";
var the_url = url.replace("{{ DEFAULT_PK }}", current_node_id);
function success(data) {
rMenu.css({"visibility" : "hidden"});
var task_id = data.task;
var url = '{% url "ops:celery-task-log" pk=DEFAULT_PK %}'.replace("{{ DEFAULT_PK }}", task_id);
window.open(url, '', 'width=800,height=600')
}
APIUpdateAttr({
url: the_url,
method: "GET",
success: success,
flash_message: false
});
})
.on('click', '.btn-test-connective', function () {
var url = "{% url 'api-assets:node-test-connective' pk=DEFAULT_PK %}";
if (!current_node_id) {
return null;
}
var the_url = url.replace("{{ DEFAULT_PK }}", current_node_id);
function success(data) {
rMenu.css({"visibility" : "hidden"});
var task_id = data.task;
var url = '{% url "ops:celery-task-log" pk=DEFAULT_PK %}'.replace("{{ DEFAULT_PK }}", task_id);
window.open(url, '', 'width=800,height=600')
}
APIUpdateAttr({
url: the_url,
method: "GET",
success: success,
flash_message: false
});
})
.on('click', '.btn-show-current-asset', function(){
hideRMenu();
$(this).css('display', 'none');
$('#show_all_asset').css('display', 'inline-block');
setCookie('show_current_asset', '1');
location.reload()
})
.on('click', '.btn-show-all-asset', function(){
hideRMenu();
$(this).css('display', 'none');
$('#show_current_asset').css('display', 'inline-block');
setCookie('show_current_asset', '');
location.reload();
})
.on('click', '.btn-test-connective', function () {
hideRMenu();
})
.on('click', '#menu_refresh_assets_amount', function () {
hideRMenu();
var url = "{% url 'api-assets:refresh-assets-amount' %}";
APIUpdateAttr({
'url': url,
'method': 'GET'
});
window.location.reload();
})
</script>
\ No newline at end of file
...@@ -49,15 +49,7 @@ ...@@ -49,15 +49,7 @@
<div class="wrapper wrapper-content"> <div class="wrapper wrapper-content">
<div class="row"> <div class="row">
<div class="col-lg-3" id="split-left" style="padding-left: 3px"> <div class="col-lg-3" id="split-left" style="padding-left: 3px">
<div class="ibox float-e-margins"> {% include 'assets/_node_tree.html' %}
<div class="ibox-content mailbox-content" style="padding-top: 0;padding-left: 1px">
<div class="file-manager ">
<div id="assetTree" class="ztree">
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
</div> </div>
<div class="col-lg-9 animated fadeInRight" id="split-right"> <div class="col-lg-9 animated fadeInRight" id="split-right">
<div class="tree-toggle"> <div class="tree-toggle">
...@@ -132,26 +124,7 @@ ...@@ -132,26 +124,7 @@
</div> </div>
</div> </div>
<div id="rMenu"> {% include 'assets/_node_tree.html' %}
<ul class="dropdown-menu">
<li class="divider"></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><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 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>
<li class="divider"></li>
<li id="menu_refresh_assets_amount" class="btn-refresh-assets-amount" tabindex="-1"><a><i class="fa fa-refresh"></i> {% trans 'Refresh all node assets amount' %}</a></li>
<li class="divider"></li>
<li id="show_current_asset" class="btn-show-current-asset" style="display: none;" tabindex="-1"><a><i class="fa fa-hand-o-up"></i> {% trans 'Display only current node assets' %}</a></li>
<li id="show_all_asset" class="btn-show-all-asset" style="display: none;" tabindex="-1"><a><i class="fa fa-th"></i> {% trans 'Displays all child node assets' %}</a></li>
{# <li id="fresh_tree" class="btn-refresh-tree" tabindex="-1"><a><i class="fa fa-refresh"></i> {% trans 'Refresh' %}</a></li>#}
</ul>
</div>
{% include 'assets/_asset_update_modal.html' %} {% include 'assets/_asset_update_modal.html' %}
{% include 'assets/_asset_import_modal.html' %} {% include 'assets/_asset_import_modal.html' %}
{% include 'assets/_asset_list_modal.html' %} {% include 'assets/_asset_list_modal.html' %}
...@@ -159,11 +132,11 @@ ...@@ -159,11 +132,11 @@
{% block custom_foot_js %} {% block custom_foot_js %}
<script> <script>
var zTree, rMenu, asset_table, show = 0; var asset_table, show = 0;
var update_node_action = ""; var update_node_action = "";
var current_node_id = null; var current_node_id = null;
var current_node = null;
var testDatetime = "{% trans 'Test datetime: ' %}"; var testDatetime = "{% trans 'Test datetime: ' %}";
function initTable() { function initTable() {
var options = { var options = {
ele: $('#asset_list_table'), ele: $('#asset_list_table'),
...@@ -209,239 +182,24 @@ function initTable() { ...@@ -209,239 +182,24 @@ function initTable() {
asset_table = jumpserver.initServerSideDataTable(options); asset_table = jumpserver.initServerSideDataTable(options);
return asset_table return asset_table
} }
function initTree() {
function addTreeNode() { initNodeTree({
hideRMenu(); onSelected: onNodeSelected,
var parentNode = zTree.getSelectedNodes()[0]; showMenu: true,
if (!parentNode){ otherMenu: `
return <li class="divider"></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>
var url = "{% url 'api-assets:node-children' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", parentNode.meta.node.id); <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>
$.post(url, {}, function (data, status){ <li class="divider"></li>
if (status === "success") { <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>
var newNode = { <li id="menu_test_connective" class="btn-test-connective" tabindex="-1"><a><i class="fa fa-chain"></i> {% trans 'Test node connective' %}</a></li>
id: data["key"], <li class="divider"></li>
name: data["value"], <li id="show_current_asset" class="btn-show-current-asset" style="display: none;" tabindex="-1"><a><i class="fa fa-hand-o-up"></i> {% trans 'Display only current node assets' %}</a></li>
pId: parentNode.id, <li id="show_all_asset" class="btn-show-all-asset" style="display: none;" tabindex="-1"><a><i class="fa fa-th"></i> {% trans 'Displays all child node assets' %}</a></li>
meta: { `
"node": data
}
};
newNode.checked = zTree.getSelectedNodes()[0].checked;
zTree.addNodes(parentNode, 0, newNode);
var node = zTree.getNodeByParam('id', newNode.id, parentNode);
zTree.editName(node);
} else {
alert("{% trans 'Create node failed' %}")
}
});
}
function removeTreeNode() {
hideRMenu();
var current_node = zTree.getSelectedNodes()[0];
if (!current_node){
return
}
if (current_node.children && current_node.children.length > 0) {
toastr.error("{% trans 'Have child node, cancel' %}");
} else if (current_node.meta.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);
$.ajax({
url: url,
method: "DELETE",
success: function () {
zTree.removeNode(current_node);
}
});
}
}
function editTreeNode() {
hideRMenu();
var current_node = zTree.getSelectedNodes()[0];
if (!current_node){
return
}
if (current_node) {
current_node.name = current_node.meta.node.value;
}
zTree.editName(current_node);
}
function OnRightClick(event, treeId, treeNode) {
if (!treeNode && event.target.tagName.toLowerCase() !== "button" && $(event.target).parents("a").length === 0) {
zTree.cancelSelectedNode();
showRMenu("root", event.clientX, event.clientY);
} else if (treeNode && !treeNode.noR) {
zTree.selectNode(treeNode);
showRMenu("node", event.clientX, event.clientY);
}
}
function showRMenu(type, x, y) {
$("#rMenu ul").show();
x -= 220;
x += document.body.scrollLeft;
y += document.body.scrollTop+document.documentElement.scrollTop;
rMenu.css({"top":y+"px", "left":x+"px", "visibility":"visible"});
$("body").bind("mousedown", onBodyMouseDown);
}
function beforeClick(treeId, treeNode, clickFlag) {
return true;
}
function hideRMenu() {
if (rMenu) rMenu.css({"visibility": "hidden"});
$("body").unbind("mousedown", onBodyMouseDown);
}
function onBodyMouseDown(event){
if (!(event.target.id === "rMenu" || $(event.target).parents("#rMenu").length>0)) {
rMenu.css({"visibility" : "hidden"});
}
}
function onRename(event, treeId, treeNode, isCancel){
var url = "{% url 'api-assets:node-detail' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node_id);
var data = {"value": treeNode.name};
if (isCancel){
return
}
APIUpdateAttr({
url: url,
body: JSON.stringify(data),
method: "PATCH",
success_message: "{% trans 'Rename success' %}",
fail_message: "{% trans 'Rename failed, do not change the root node name' %}",
success: function () {
treeNode.name = treeNode.name + ' (' + treeNode.meta.node.assets_amount + ')'
zTree.updateNode(treeNode);
console.log("Success: " + treeNode.name)
}
})
}
function onSelected(event, treeNode) {
current_node = treeNode;
current_node_id = treeNode.meta.node.id;
zTree.expandNode(current_node, true);
var url = asset_table.ajax.url();
url = setUrlParam(url, "node_id", current_node_id);
url = setUrlParam(url, "show_current_asset", getCookie('show_current_asset'));
setCookie('node_selected', treeNode.node_id);
asset_table.ajax.url(url);
asset_table.ajax.reload();
}
function selectQueryNode() {
// TODO: 是否应该添加
// 暂时忽略之前选中的内容
return
var query_node_id = $.getUrlParam("node");
var cookie_node_id = getCookie('node_selected');
var node;
var node_id;
if (query_node_id !== null) {
node_id = query_node_id
} else if (cookie_node_id !== null) {
node_id = cookie_node_id;
}
node = zTree.getNodesByParam("node_id", node_id, null);
if (node){
zTree.selectNode(node[0]);
}
}
function beforeDrag() {
return true
}
function beforeDrop(treeId, treeNodes, targetNode, moveType) {
var treeNodesNames = [];
$.each(treeNodes, function (index, value) {
treeNodesNames.push(value.name);
});
var msg = "你想移动节点: `" + treeNodesNames.join(",") + "` 到 `" + targetNode.name + "` 下吗?";
return confirm(msg);
}
function onDrag(event, treeId, treeNodes) {
}
function onDrop(event, treeId, treeNodes, targetNode, moveType) {
var treeNodesIds = [];
$.each(treeNodes, function (index, value) {
treeNodesIds.push(value.meta.node.id);
});
var the_url = "{% url 'api-assets:node-add-children' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", targetNode.meta.node.id);
var body = {nodes: treeNodesIds};
APIUpdateAttr({
url: the_url,
method: "PUT",
body: JSON.stringify(body)
}) })
} }
function initTree() {
if (zTree) {
return
}
var url = '{% url 'api-assets:node-children-tree' %}?assets=0&all=';
var showCurrentAsset = getCookie('show_current_asset');
if (!showCurrentAsset) {
url += '1'
}
var setting = {
view: {
dblClickExpand: false,
showLine: true
},
data: {
simpleData: {
enable: true
}
},
async: {
enable: true,
url: url,
autoParam: ["id=key", "name=n", "level=lv"],
type: 'get'
},
edit: {
enable: true,
showRemoveBtn: false,
showRenameBtn: false,
drag: {
isCopy: true,
isMove: true
}
},
callback: {
onRightClick: OnRightClick,
beforeClick: beforeClick,
onRename: onRename,
onSelected: onSelected,
beforeDrag: beforeDrag,
onDrag: onDrag,
beforeDrop: beforeDrop,
onDrop: onDrop
}
};
var zNodes = [];
zTree = $.fn.zTree.init($("#assetTree"), setting, zNodes);
rMenu = $("#rMenu");
}
function toggle() { function toggle() {
if (show === 0) { if (show === 0) {
...@@ -458,6 +216,18 @@ function toggle() { ...@@ -458,6 +216,18 @@ function toggle() {
} }
} }
function onNodeSelected(event, treeNode) {
current_node = treeNode;
current_node_id = treeNode.meta.node.id;
zTree.expandNode(current_node, true);
var url = asset_table.ajax.url();
url = setUrlParam(url, "node_id", current_node_id);
url = setUrlParam(url, "show_current_asset", getCookie('show_current_asset'));
setCookie('node_selected', treeNode.node_id);
asset_table.ajax.url(url);
asset_table.ajax.reload();
}
$(document).ready(function(){ $(document).ready(function(){
initTable(); initTable();
initTree(); initTree();
...@@ -555,69 +325,7 @@ $(document).ready(function(){ ...@@ -555,69 +325,7 @@ $(document).ready(function(){
} }
window.open(url, '_self'); window.open(url, '_self');
}) })
.on('click', '.btn-refresh-hardware', function () {
var url = "{% url 'api-assets:node-refresh-hardware-info' pk=DEFAULT_PK %}";
var the_url = url.replace("{{ DEFAULT_PK }}", current_node_id);
function success(data) {
rMenu.css({"visibility" : "hidden"});
var task_id = data.task;
var url = '{% url "ops:celery-task-log" pk=DEFAULT_PK %}'.replace("{{ DEFAULT_PK }}", task_id);
window.open(url, '', 'width=800,height=600')
}
APIUpdateAttr({
url: the_url,
method: "GET",
success: success,
flash_message: false
});
})
.on('click', '.btn-test-connective', function () {
var url = "{% url 'api-assets:node-test-connective' pk=DEFAULT_PK %}";
if (!current_node_id) {
return null;
}
var the_url = url.replace("{{ DEFAULT_PK }}", current_node_id);
function success(data) {
rMenu.css({"visibility" : "hidden"});
var task_id = data.task;
var url = '{% url "ops:celery-task-log" pk=DEFAULT_PK %}'.replace("{{ DEFAULT_PK }}", task_id);
window.open(url, '', 'width=800,height=600')
}
APIUpdateAttr({
url: the_url,
method: "GET",
success: success,
flash_message: false
});
})
.on('click', '.btn-show-current-asset', function(){
hideRMenu();
$(this).css('display', 'none');
$('#show_all_asset').css('display', 'inline-block');
setCookie('show_current_asset', '1');
location.reload();
})
.on('click', '.btn-show-all-asset', function(){
hideRMenu();
$(this).css('display', 'none');
$('#show_current_asset').css('display', 'inline-block');
setCookie('show_current_asset', '');
location.reload();
})
.on('click', '.btn-test-connective', function () {
hideRMenu();
})
.on('click', '#menu_refresh_assets_amount', function () {
hideRMenu();
var url = "{% url 'api-assets:refresh-assets-amount' %}";
APIUpdateAttr({
'url': url,
'method': 'GET'
});
window.location.reload();
})
.on('click', '.btn_asset_delete', function () { .on('click', '.btn_asset_delete', function () {
var $this = $(this); var $this = $(this);
var $data_table = $("#asset_list_table").DataTable(); var $data_table = $("#asset_list_table").DataTable();
......
# ~*~ coding: utf-8 ~*~ # ~*~ coding: utf-8 ~*~
# #
import time
from django.db.models import Prefetch from django.db.models import Prefetch
from common.utils import get_object_or_none, get_logger from common.utils import get_object_or_none, get_logger
...@@ -56,9 +57,11 @@ class NodeUtil: ...@@ -56,9 +57,11 @@ class NodeUtil:
def get_all_nodes(self): def get_all_nodes(self):
all_nodes = Node.objects.all() all_nodes = Node.objects.all()
if self.with_assets_amount: if self.with_assets_amount:
now = time.time()
all_nodes = all_nodes.prefetch_related( all_nodes = all_nodes.prefetch_related(
Prefetch('assets', queryset=Asset.objects.all().only('id')) Prefetch('assets', queryset=Asset.objects.all().only('id'))
) )
all_nodes = list(all_nodes)
for node in all_nodes: for node in all_nodes:
node._assets = set(node.assets.all()) node._assets = set(node.assets.all())
all_nodes = sorted(all_nodes, key=self.sorted_by) all_nodes = sorted(all_nodes, key=self.sorted_by)
......
...@@ -130,16 +130,13 @@ def get_short_uuid_str(): ...@@ -130,16 +130,13 @@ def get_short_uuid_str():
def is_uuid(seq): def is_uuid(seq):
if isinstance(seq, str): if isinstance(seq, uuid.UUID):
if UUID_PATTERN.match(seq):
return True return True
else: elif isinstance(seq, str) and UUID_PATTERN.match(seq):
return False
else:
for s in seq:
if not is_uuid(s):
return False
return True return True
elif isinstance(seq, (list, tuple)):
all([is_uuid(x) for x in seq])
return False
def get_request_ip(request): def get_request_ip(request):
......
...@@ -399,7 +399,7 @@ REST_FRAMEWORK = { ...@@ -399,7 +399,7 @@ REST_FRAMEWORK = {
'ORDERING_PARAM': "order", 'ORDERING_PARAM': "order",
'SEARCH_PARAM': "search", 'SEARCH_PARAM': "search",
'DATETIME_FORMAT': '%Y-%m-%d %H:%M:%S %z', 'DATETIME_FORMAT': '%Y-%m-%d %H:%M:%S %z',
'DATETIME_INPUT_FORMATS': ['%Y-%m-%d %H:%M:%S %z'], 'DATETIME_INPUT_FORMATS': ['iso-8601', '%Y-%m-%d %H:%M:%S %z'],
# 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', # 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
# 'PAGE_SIZE': 15 # 'PAGE_SIZE': 15
} }
......
...@@ -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: 2019-06-24 21:38+0800\n" "POT-Creation-Date: 2019-06-28 20:08+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"
...@@ -76,8 +76,8 @@ msgstr "运行参数" ...@@ -76,8 +76,8 @@ msgstr "运行参数"
#: applications/templates/applications/remote_app_list.html:22 #: applications/templates/applications/remote_app_list.html:22
#: applications/templates/applications/user_remote_app_list.html:18 #: applications/templates/applications/user_remote_app_list.html:18
#: assets/forms/domain.py:15 assets/forms/label.py:13 #: assets/forms/domain.py:15 assets/forms/label.py:13
#: assets/models/asset.py:298 assets/models/authbook.py:24 #: assets/models/asset.py:292 assets/models/authbook.py:24
#: assets/serializers/admin_user.py:35 assets/serializers/asset_user.py:106 #: assets/serializers/admin_user.py:35 assets/serializers/asset_user.py:89
#: assets/serializers/system_user.py:29 #: assets/serializers/system_user.py:29
#: assets/templates/assets/admin_user_list.html:49 #: assets/templates/assets/admin_user_list.html:49
#: assets/templates/assets/domain_detail.html:60 #: assets/templates/assets/domain_detail.html:60
...@@ -86,10 +86,10 @@ msgstr "运行参数" ...@@ -86,10 +86,10 @@ msgstr "运行参数"
#: assets/templates/assets/system_user_list.html:55 audits/models.py:19 #: assets/templates/assets/system_user_list.html:55 audits/models.py:19
#: audits/templates/audits/ftp_log_list.html:41 #: audits/templates/audits/ftp_log_list.html:41
#: audits/templates/audits/ftp_log_list.html:71 #: audits/templates/audits/ftp_log_list.html:71
#: perms/forms/asset_permission.py:46 perms/models/asset_permission.py:37 #: perms/forms/asset_permission.py:47 perms/models/asset_permission.py:53
#: perms/templates/perms/asset_permission_create_update.html:45 #: perms/templates/perms/asset_permission_create_update.html:45
#: perms/templates/perms/asset_permission_list.html:56 #: perms/templates/perms/asset_permission_list.html:48
#: perms/templates/perms/asset_permission_list.html:125 #: perms/templates/perms/asset_permission_list.html:117
#: terminal/backends/command/models.py:13 terminal/models.py:155 #: terminal/backends/command/models.py:13 terminal/models.py:155
#: 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
...@@ -115,12 +115,12 @@ msgstr "资产" ...@@ -115,12 +115,12 @@ msgstr "资产"
#: assets/models/user.py:160 assets/templates/assets/user_asset_list.html:172 #: assets/models/user.py:160 assets/templates/assets/user_asset_list.html:172
#: audits/models.py:20 audits/templates/audits/ftp_log_list.html:49 #: audits/models.py:20 audits/templates/audits/ftp_log_list.html:49
#: audits/templates/audits/ftp_log_list.html:72 #: audits/templates/audits/ftp_log_list.html:72
#: perms/forms/asset_permission.py:52 perms/models/asset_permission.py:39 #: perms/forms/asset_permission.py:53 perms/models/asset_permission.py:55
#: perms/models/asset_permission.py:59 #: perms/models/asset_permission.py:76
#: perms/templates/perms/asset_permission_detail.html:140 #: perms/templates/perms/asset_permission_detail.html:140
#: perms/templates/perms/asset_permission_list.html:58 #: perms/templates/perms/asset_permission_list.html:50
#: perms/templates/perms/asset_permission_list.html:79 #: perms/templates/perms/asset_permission_list.html:71
#: perms/templates/perms/asset_permission_list.html:131 templates/_nav.html:25 #: perms/templates/perms/asset_permission_list.html:123 templates/_nav.html:25
#: terminal/backends/command/models.py:14 terminal/models.py:156 #: terminal/backends/command/models.py:14 terminal/models.py:156
#: 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
...@@ -135,7 +135,7 @@ msgstr "系统用户" ...@@ -135,7 +135,7 @@ msgstr "系统用户"
#: applications/templates/applications/remote_app_list.html:20 #: applications/templates/applications/remote_app_list.html:20
#: applications/templates/applications/user_remote_app_list.html:16 #: applications/templates/applications/user_remote_app_list.html:16
#: assets/forms/domain.py:73 assets/forms/user.py:84 assets/forms/user.py:148 #: assets/forms/domain.py:73 assets/forms/user.py:84 assets/forms/user.py:148
#: assets/models/asset.py:70 assets/models/base.py:27 #: assets/models/asset.py:64 assets/models/base.py:27
#: assets/models/cluster.py:18 assets/models/cmd_filter.py:20 #: assets/models/cluster.py:18 assets/models/cmd_filter.py:20
#: assets/models/domain.py:20 assets/models/group.py:20 #: assets/models/domain.py:20 assets/models/group.py:20
#: assets/models/label.py:18 assets/templates/assets/admin_user_detail.html:56 #: assets/models/label.py:18 assets/templates/assets/admin_user_detail.html:56
...@@ -149,11 +149,11 @@ msgstr "系统用户" ...@@ -149,11 +149,11 @@ msgstr "系统用户"
#: assets/templates/assets/system_user_detail.html:58 #: assets/templates/assets/system_user_detail.html:58
#: assets/templates/assets/system_user_list.html:51 ops/models/adhoc.py:37 #: assets/templates/assets/system_user_list.html:51 ops/models/adhoc.py:37
#: ops/templates/ops/task_detail.html:60 ops/templates/ops/task_list.html:27 #: ops/templates/ops/task_detail.html:60 ops/templates/ops/task_list.html:27
#: orgs/models.py:12 perms/models/asset_permission.py:22 #: orgs/models.py:11 perms/models/asset_permission.py:22
#: perms/models/base.py:35 #: perms/models/base.py:35
#: perms/templates/perms/asset_permission_detail.html:62 #: perms/templates/perms/asset_permission_detail.html:62
#: perms/templates/perms/asset_permission_list.html:53 #: perms/templates/perms/asset_permission_list.html:45
#: perms/templates/perms/asset_permission_list.html:72 #: perms/templates/perms/asset_permission_list.html:64
#: perms/templates/perms/asset_permission_user.html:54 #: perms/templates/perms/asset_permission_user.html:54
#: perms/templates/perms/remote_app_permission_detail.html:62 #: perms/templates/perms/remote_app_permission_detail.html:62
#: perms/templates/perms/remote_app_permission_list.html:14 #: perms/templates/perms/remote_app_permission_list.html:14
...@@ -167,7 +167,7 @@ msgstr "系统用户" ...@@ -167,7 +167,7 @@ msgstr "系统用户"
#: settings/templates/settings/terminal_setting.html:105 terminal/models.py:22 #: settings/templates/settings/terminal_setting.html:105 terminal/models.py:22
#: terminal/models.py:258 terminal/templates/terminal/terminal_detail.html:43 #: terminal/models.py:258 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:63 users/templates/users/_select_user_modal.html:13 #: users/models/user.py:64 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:35 #: users/templates/users/user_group_list.html:35
...@@ -206,7 +206,7 @@ msgstr "参数" ...@@ -206,7 +206,7 @@ msgstr "参数"
#: applications/models/remote_app.py:43 #: applications/models/remote_app.py:43
#: applications/templates/applications/remote_app_detail.html:77 #: applications/templates/applications/remote_app_detail.html:77
#: assets/models/asset.py:130 assets/models/base.py:35 #: assets/models/asset.py:124 assets/models/base.py:35
#: assets/models/cluster.py:28 assets/models/cmd_filter.py:25 #: assets/models/cluster.py:28 assets/models/cmd_filter.py:25
#: assets/models/cmd_filter.py:58 assets/models/group.py:21 #: assets/models/cmd_filter.py:58 assets/models/group.py:21
#: assets/templates/assets/admin_user_detail.html:68 #: assets/templates/assets/admin_user_detail.html:68
...@@ -214,11 +214,11 @@ msgstr "参数" ...@@ -214,11 +214,11 @@ msgstr "参数"
#: assets/templates/assets/cmd_filter_detail.html:77 #: assets/templates/assets/cmd_filter_detail.html:77
#: assets/templates/assets/domain_detail.html:72 #: assets/templates/assets/domain_detail.html:72
#: assets/templates/assets/system_user_detail.html:100 #: assets/templates/assets/system_user_detail.html:100
#: ops/templates/ops/adhoc_detail.html:86 orgs/models.py:15 #: ops/templates/ops/adhoc_detail.html:86 orgs/models.py:14
#: perms/models/asset_permission.py:62 perms/models/base.py:41 #: perms/models/asset_permission.py:79 perms/models/base.py:41
#: perms/templates/perms/asset_permission_detail.html:98 #: perms/templates/perms/asset_permission_detail.html:98
#: perms/templates/perms/remote_app_permission_detail.html:90 #: perms/templates/perms/remote_app_permission_detail.html:90
#: users/models/user.py:104 users/serializers/v1.py:73 #: users/models/user.py:105 users/serializers/v1.py:99
#: users/templates/users/user_detail.html:111 #: users/templates/users/user_detail.html:111
#: xpack/plugins/change_auth_plan/models.py:106 #: xpack/plugins/change_auth_plan/models.py:106
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:113 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:113
...@@ -230,7 +230,7 @@ msgstr "创建者" ...@@ -230,7 +230,7 @@ msgstr "创建者"
# msgstr "创建者" # msgstr "创建者"
#: applications/models/remote_app.py:46 #: applications/models/remote_app.py:46
#: applications/templates/applications/remote_app_detail.html:73 #: applications/templates/applications/remote_app_detail.html:73
#: assets/models/asset.py:131 assets/models/base.py:33 #: assets/models/asset.py:125 assets/models/base.py:33
#: assets/models/cluster.py:26 assets/models/domain.py:23 #: assets/models/cluster.py:26 assets/models/domain.py:23
#: assets/models/group.py:22 assets/models/label.py:25 #: assets/models/group.py:22 assets/models/label.py:25
#: assets/templates/assets/admin_user_detail.html:64 #: assets/templates/assets/admin_user_detail.html:64
...@@ -238,7 +238,7 @@ msgstr "创建者" ...@@ -238,7 +238,7 @@ msgstr "创建者"
#: assets/templates/assets/domain_detail.html:68 #: assets/templates/assets/domain_detail.html:68
#: assets/templates/assets/system_user_detail.html:96 #: assets/templates/assets/system_user_detail.html:96
#: ops/templates/ops/adhoc_detail.html:90 ops/templates/ops/task_detail.html:64 #: ops/templates/ops/adhoc_detail.html:90 ops/templates/ops/task_detail.html:64
#: orgs/models.py:16 perms/models/asset_permission.py:63 #: orgs/models.py:15 perms/models/asset_permission.py:80
#: perms/models/base.py:42 #: perms/models/base.py:42
#: perms/templates/perms/asset_permission_detail.html:94 #: perms/templates/perms/asset_permission_detail.html:94
#: perms/templates/perms/remote_app_permission_detail.html:86 #: perms/templates/perms/remote_app_permission_detail.html:86
...@@ -258,7 +258,7 @@ msgstr "创建日期" ...@@ -258,7 +258,7 @@ msgstr "创建日期"
#: applications/templates/applications/remote_app_detail.html:81 #: applications/templates/applications/remote_app_detail.html:81
#: applications/templates/applications/remote_app_list.html:24 #: applications/templates/applications/remote_app_list.html:24
#: applications/templates/applications/user_remote_app_list.html:20 #: applications/templates/applications/user_remote_app_list.html:20
#: assets/models/asset.py:132 assets/models/base.py:32 #: assets/models/asset.py:126 assets/models/base.py:32
#: assets/models/cluster.py:29 assets/models/cmd_filter.py:22 #: assets/models/cluster.py:29 assets/models/cmd_filter.py:22
#: assets/models/cmd_filter.py:55 assets/models/domain.py:21 #: assets/models/cmd_filter.py:55 assets/models/domain.py:21
#: assets/models/domain.py:53 assets/models/group.py:23 #: assets/models/domain.py:53 assets/models/group.py:23
...@@ -274,13 +274,13 @@ msgstr "创建日期" ...@@ -274,13 +274,13 @@ msgstr "创建日期"
#: assets/templates/assets/system_user_detail.html:104 #: assets/templates/assets/system_user_detail.html:104
#: assets/templates/assets/system_user_list.html:59 #: assets/templates/assets/system_user_list.html:59
#: assets/templates/assets/user_asset_list.html:175 ops/models/adhoc.py:43 #: assets/templates/assets/user_asset_list.html:175 ops/models/adhoc.py:43
#: orgs/models.py:17 perms/models/asset_permission.py:64 #: orgs/models.py:16 perms/models/asset_permission.py:81
#: perms/models/base.py:43 #: perms/models/base.py:43
#: perms/templates/perms/asset_permission_detail.html:102 #: perms/templates/perms/asset_permission_detail.html:102
#: perms/templates/perms/remote_app_permission_detail.html:94 #: perms/templates/perms/remote_app_permission_detail.html:94
#: settings/models.py:34 terminal/models.py:32 #: settings/models.py:34 terminal/models.py:32
#: 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:96 users/templates/users/user_detail.html:127 #: users/models/user.py:97 users/templates/users/user_detail.html:127
#: users/templates/users/user_group_detail.html:67 #: users/templates/users/user_group_detail.html:67
#: users/templates/users/user_group_list.html:37 #: users/templates/users/user_group_list.html:37
#: users/templates/users/user_profile.html:134 #: users/templates/users/user_profile.html:134
...@@ -350,7 +350,7 @@ msgstr "重置" ...@@ -350,7 +350,7 @@ msgstr "重置"
#: assets/templates/assets/admin_user_create_update.html:46 #: assets/templates/assets/admin_user_create_update.html:46
#: assets/templates/assets/asset_bulk_update.html:24 #: assets/templates/assets/asset_bulk_update.html:24
#: assets/templates/assets/asset_create.html:82 #: assets/templates/assets/asset_create.html:82
#: assets/templates/assets/asset_list.html:125 #: assets/templates/assets/asset_list.html:117
#: assets/templates/assets/cmd_filter_create_update.html:16 #: assets/templates/assets/cmd_filter_create_update.html:16
#: assets/templates/assets/cmd_filter_rule_create_update.html:41 #: assets/templates/assets/cmd_filter_rule_create_update.html:41
#: assets/templates/assets/domain_create_update.html:17 #: assets/templates/assets/domain_create_update.html:17
...@@ -416,8 +416,8 @@ msgstr "详情" ...@@ -416,8 +416,8 @@ msgstr "详情"
#: assets/templates/assets/admin_user_list.html:29 #: assets/templates/assets/admin_user_list.html:29
#: assets/templates/assets/admin_user_list.html:114 #: assets/templates/assets/admin_user_list.html:114
#: assets/templates/assets/asset_detail.html:27 #: assets/templates/assets/asset_detail.html:27
#: assets/templates/assets/asset_list.html:86 #: assets/templates/assets/asset_list.html:78
#: assets/templates/assets/asset_list.html:196 #: assets/templates/assets/asset_list.html:169
#: assets/templates/assets/cmd_filter_detail.html:29 #: assets/templates/assets/cmd_filter_detail.html:29
#: assets/templates/assets/cmd_filter_list.html:58 #: assets/templates/assets/cmd_filter_list.html:58
#: assets/templates/assets/cmd_filter_rule_list.html:86 #: assets/templates/assets/cmd_filter_rule_list.html:86
...@@ -430,7 +430,7 @@ msgstr "详情" ...@@ -430,7 +430,7 @@ msgstr "详情"
#: assets/templates/assets/system_user_list.html:33 #: assets/templates/assets/system_user_list.html:33
#: assets/templates/assets/system_user_list.html:119 audits/models.py:33 #: assets/templates/assets/system_user_list.html:119 audits/models.py:33
#: perms/templates/perms/asset_permission_detail.html:30 #: perms/templates/perms/asset_permission_detail.html:30
#: perms/templates/perms/asset_permission_list.html:181 #: perms/templates/perms/asset_permission_list.html:173
#: perms/templates/perms/remote_app_permission_detail.html:30 #: perms/templates/perms/remote_app_permission_detail.html:30
#: perms/templates/perms/remote_app_permission_list.html:59 #: perms/templates/perms/remote_app_permission_list.html:59
#: terminal/templates/terminal/terminal_detail.html:16 #: terminal/templates/terminal/terminal_detail.html:16
...@@ -459,7 +459,7 @@ msgstr "更新" ...@@ -459,7 +459,7 @@ msgstr "更新"
#: assets/templates/assets/admin_user_detail.html:28 #: assets/templates/assets/admin_user_detail.html:28
#: assets/templates/assets/admin_user_list.html:115 #: assets/templates/assets/admin_user_list.html:115
#: assets/templates/assets/asset_detail.html:31 #: assets/templates/assets/asset_detail.html:31
#: assets/templates/assets/asset_list.html:197 #: assets/templates/assets/asset_list.html:170
#: assets/templates/assets/cmd_filter_detail.html:33 #: assets/templates/assets/cmd_filter_detail.html:33
#: assets/templates/assets/cmd_filter_list.html:59 #: assets/templates/assets/cmd_filter_list.html:59
#: assets/templates/assets/cmd_filter_rule_list.html:87 #: assets/templates/assets/cmd_filter_rule_list.html:87
...@@ -472,7 +472,7 @@ msgstr "更新" ...@@ -472,7 +472,7 @@ msgstr "更新"
#: assets/templates/assets/system_user_list.html:120 audits/models.py:34 #: assets/templates/assets/system_user_list.html:120 audits/models.py:34
#: ops/templates/ops/task_list.html:64 #: ops/templates/ops/task_list.html:64
#: perms/templates/perms/asset_permission_detail.html:34 #: perms/templates/perms/asset_permission_detail.html:34
#: perms/templates/perms/asset_permission_list.html:182 #: perms/templates/perms/asset_permission_list.html:174
#: perms/templates/perms/remote_app_permission_detail.html:34 #: perms/templates/perms/remote_app_permission_detail.html:34
#: perms/templates/perms/remote_app_permission_list.html:60 #: perms/templates/perms/remote_app_permission_list.html:60
#: settings/templates/settings/terminal_setting.html:93 #: settings/templates/settings/terminal_setting.html:93
...@@ -517,7 +517,7 @@ msgstr "创建远程应用" ...@@ -517,7 +517,7 @@ msgstr "创建远程应用"
#: assets/models/cmd_filter.py:54 #: assets/models/cmd_filter.py:54
#: assets/templates/assets/_asset_user_list.html:20 #: assets/templates/assets/_asset_user_list.html:20
#: assets/templates/assets/admin_user_list.html:54 #: assets/templates/assets/admin_user_list.html:54
#: assets/templates/assets/asset_list.html:108 #: assets/templates/assets/asset_list.html:100
#: assets/templates/assets/cmd_filter_list.html:28 #: assets/templates/assets/cmd_filter_list.html:28
#: assets/templates/assets/cmd_filter_rule_list.html:63 #: assets/templates/assets/cmd_filter_rule_list.html:63
#: assets/templates/assets/domain_gateway_list.html:73 #: assets/templates/assets/domain_gateway_list.html:73
...@@ -529,11 +529,11 @@ msgstr "创建远程应用" ...@@ -529,11 +529,11 @@ msgstr "创建远程应用"
#: audits/templates/audits/operate_log_list.html:67 #: audits/templates/audits/operate_log_list.html:67
#: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:64 #: 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:34 #: ops/templates/ops/task_history.html:65 ops/templates/ops/task_list.html:34
#: perms/forms/asset_permission.py:55 perms/models/asset_permission.py:26 #: perms/forms/asset_permission.py:56 perms/models/asset_permission.py:26
#: perms/models/asset_permission.py:40 #: perms/models/asset_permission.py:57
#: perms/templates/perms/asset_permission_create_update.html:50 #: perms/templates/perms/asset_permission_create_update.html:50
#: perms/templates/perms/asset_permission_list.html:60 #: perms/templates/perms/asset_permission_list.html:52
#: perms/templates/perms/asset_permission_list.html:134 #: perms/templates/perms/asset_permission_list.html:126
#: perms/templates/perms/remote_app_permission_list.html:19 #: perms/templates/perms/remote_app_permission_list.html:19
#: settings/templates/settings/terminal_setting.html:85 #: settings/templates/settings/terminal_setting.html:85
#: settings/templates/settings/terminal_setting.html:107 #: settings/templates/settings/terminal_setting.html:107
...@@ -552,6 +552,7 @@ msgstr "动作" ...@@ -552,6 +552,7 @@ msgstr "动作"
#: applications/templates/applications/user_remote_app_list.html:57 #: applications/templates/applications/user_remote_app_list.html:57
#: assets/templates/assets/user_asset_list.html:100 perms/const.py:19 #: assets/templates/assets/user_asset_list.html:100 perms/const.py:19
#: perms/models/asset_permission.py:45
msgid "Connect" msgid "Connect"
msgstr "连接" msgstr "连接"
...@@ -586,15 +587,15 @@ msgstr "%(hostname)s %(action)s成功" ...@@ -586,15 +587,15 @@ msgstr "%(hostname)s %(action)s成功"
msgid "Please select assets that need to be updated" msgid "Please select assets that need to be updated"
msgstr "请选择需要更新的资产" msgstr "请选择需要更新的资产"
#: assets/api/node.py:60 #: assets/api/node.py:61
msgid "You can't update the root node name" msgid "You can't update the root node name"
msgstr "不能修改根节点名称" msgstr "不能修改根节点名称"
#: assets/api/node.py:285 #: assets/api/node.py:281
msgid "Update node asset hardware information: {}" msgid "Update node asset hardware information: {}"
msgstr "更新节点资产硬件信息: {}" msgstr "更新节点资产硬件信息: {}"
#: assets/api/node.py:299 #: assets/api/node.py:295
msgid "Test if the assets under the node are connectable: {}" msgid "Test if the assets under the node are connectable: {}"
msgstr "测试节点下资产是否可连接: {}" msgstr "测试节点下资产是否可连接: {}"
...@@ -606,7 +607,7 @@ msgstr "不可达" ...@@ -606,7 +607,7 @@ msgstr "不可达"
#: assets/const.py:78 assets/models/utils.py:44 #: assets/const.py:78 assets/models/utils.py:44
#: assets/templates/assets/admin_user_list.html:50 #: assets/templates/assets/admin_user_list.html:50
#: assets/templates/assets/asset_list.html:107 #: assets/templates/assets/asset_list.html:99
#: assets/templates/assets/system_user_list.html:56 #: assets/templates/assets/system_user_list.html:56
#: users/templates/users/user_group_granted_asset.html:47 #: users/templates/users/user_group_granted_asset.html:47
msgid "Reachable" msgid "Reachable"
...@@ -617,16 +618,16 @@ msgstr "可连接" ...@@ -617,16 +618,16 @@ msgstr "可连接"
msgid "Unknown" msgid "Unknown"
msgstr "未知" msgstr "未知"
#: assets/forms/asset.py:45 assets/models/asset.py:101 #: assets/forms/asset.py:51 assets/models/asset.py:95 assets/models/user.py:107
#: assets/models/user.py:107 assets/templates/assets/asset_detail.html:194 #: assets/templates/assets/asset_detail.html:194
#: assets/templates/assets/asset_detail.html:202 #: assets/templates/assets/asset_detail.html:202
#: assets/templates/assets/system_user_assets.html:83 #: assets/templates/assets/system_user_assets.html:83
#: perms/models/asset_permission.py:38 #: perms/models/asset_permission.py:54
#: xpack/plugins/change_auth_plan/models.py:72 #: xpack/plugins/change_auth_plan/models.py:72
msgid "Nodes" msgid "Nodes"
msgstr "节点" msgstr "节点"
#: assets/forms/asset.py:48 assets/forms/asset.py:83 assets/models/asset.py:105 #: assets/forms/asset.py:54 assets/forms/asset.py:89 assets/models/asset.py:99
#: assets/models/cluster.py:19 assets/models/user.py:65 #: assets/models/cluster.py:19 assets/models/user.py:65
#: assets/templates/assets/asset_detail.html:80 templates/_nav.html:24 #: assets/templates/assets/asset_detail.html:80 templates/_nav.html:24
#: xpack/plugins/cloud/models.py:124 #: xpack/plugins/cloud/models.py:124
...@@ -635,16 +636,16 @@ msgstr "节点" ...@@ -635,16 +636,16 @@ msgstr "节点"
msgid "Admin user" msgid "Admin user"
msgstr "管理用户" msgstr "管理用户"
#: assets/forms/asset.py:51 assets/forms/asset.py:86 assets/forms/asset.py:125 #: assets/forms/asset.py:57 assets/forms/asset.py:92 assets/forms/asset.py:131
#: assets/templates/assets/asset_create.html:48 #: assets/templates/assets/asset_create.html:48
#: assets/templates/assets/asset_create.html:50 #: assets/templates/assets/asset_create.html:50
#: assets/templates/assets/asset_list.html:93 #: assets/templates/assets/asset_list.html:85
#: assets/templates/assets/user_asset_list.html:33 #: assets/templates/assets/user_asset_list.html:33
#: xpack/plugins/orgs/templates/orgs/org_list.html:20 #: xpack/plugins/orgs/templates/orgs/org_list.html:20
msgid "Label" msgid "Label"
msgstr "标签" msgstr "标签"
#: assets/forms/asset.py:54 assets/forms/asset.py:89 assets/models/asset.py:100 #: assets/forms/asset.py:60 assets/forms/asset.py:95 assets/models/asset.py:94
#: assets/models/domain.py:26 assets/models/domain.py:52 #: assets/models/domain.py:26 assets/models/domain.py:52
#: assets/templates/assets/asset_detail.html:84 #: assets/templates/assets/asset_detail.html:84
#: assets/templates/assets/user_asset_list.html:173 #: assets/templates/assets/user_asset_list.html:173
...@@ -652,14 +653,14 @@ msgstr "标签" ...@@ -652,14 +653,14 @@ msgstr "标签"
msgid "Domain" msgid "Domain"
msgstr "网域" msgstr "网域"
#: assets/forms/asset.py:58 assets/forms/asset.py:80 assets/forms/asset.py:93 #: assets/forms/asset.py:64 assets/forms/asset.py:86 assets/forms/asset.py:99
#: assets/forms/asset.py:128 assets/models/node.py:31 #: assets/forms/asset.py:134 assets/models/node.py:248
#: assets/templates/assets/asset_create.html:42 #: assets/templates/assets/asset_create.html:42
#: perms/forms/asset_permission.py:49 perms/forms/asset_permission.py:59 #: perms/forms/asset_permission.py:50 perms/forms/asset_permission.py:60
#: perms/models/asset_permission.py:57 #: perms/models/asset_permission.py:74
#: perms/templates/perms/asset_permission_list.html:57 #: perms/templates/perms/asset_permission_list.html:49
#: perms/templates/perms/asset_permission_list.html:78 #: perms/templates/perms/asset_permission_list.html:70
#: perms/templates/perms/asset_permission_list.html:128 #: perms/templates/perms/asset_permission_list.html:120
#: xpack/plugins/change_auth_plan/forms.py:115 #: xpack/plugins/change_auth_plan/forms.py:115
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:55 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:55
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:15 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:15
...@@ -669,7 +670,7 @@ msgstr "网域" ...@@ -669,7 +670,7 @@ msgstr "网域"
msgid "Node" msgid "Node"
msgstr "节点" msgstr "节点"
#: assets/forms/asset.py:62 assets/forms/asset.py:97 #: assets/forms/asset.py:68 assets/forms/asset.py:103
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"
...@@ -677,16 +678,16 @@ msgstr "" ...@@ -677,16 +678,16 @@ msgstr ""
"root或其他拥有NOPASSWD: ALL权限的用户, 如果是windows或其它硬件可以随意设置一" "root或其他拥有NOPASSWD: ALL权限的用户, 如果是windows或其它硬件可以随意设置一"
"个, 更多信息查看左侧 `管理用户` 菜单" "个, 更多信息查看左侧 `管理用户` 菜单"
#: assets/forms/asset.py:65 assets/forms/asset.py:100 #: assets/forms/asset.py:71 assets/forms/asset.py:106
msgid "Windows 2016 RDP protocol is different, If is window 2016, set it" msgid "Windows 2016 RDP protocol is different, If is window 2016, set it"
msgstr "Windows 2016的RDP协议与之前不同,如果是请设置" msgstr "Windows 2016的RDP协议与之前不同,如果是请设置"
#: assets/forms/asset.py:66 assets/forms/asset.py:101 #: assets/forms/asset.py:72 assets/forms/asset.py:107
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:108 assets/forms/asset.py:112 #: assets/forms/asset.py:114 assets/forms/asset.py:118
#: assets/forms/domain.py:17 assets/forms/label.py:15 #: assets/forms/domain.py:17 assets/forms/label.py:15
#: perms/templates/perms/asset_permission_asset.html:88 #: perms/templates/perms/asset_permission_asset.html:88
#: xpack/plugins/change_auth_plan/forms.py:105 #: xpack/plugins/change_auth_plan/forms.py:105
...@@ -715,11 +716,11 @@ msgstr "SSH网关,支持代理SSH,RDP和VNC" ...@@ -715,11 +716,11 @@ msgstr "SSH网关,支持代理SSH,RDP和VNC"
#: audits/templates/audits/login_log_list.html:51 authentication/forms.py:11 #: audits/templates/audits/login_log_list.html:51 authentication/forms.py:11
#: authentication/templates/authentication/login.html:64 #: authentication/templates/authentication/login.html:64
#: authentication/templates/authentication/new_login.html:90 #: authentication/templates/authentication/new_login.html:90
#: ops/models/adhoc.py:164 perms/templates/perms/asset_permission_list.html:74 #: ops/models/adhoc.py:164 perms/templates/perms/asset_permission_list.html:66
#: perms/templates/perms/asset_permission_user.html:55 #: perms/templates/perms/asset_permission_user.html:55
#: perms/templates/perms/remote_app_permission_user.html:54 #: perms/templates/perms/remote_app_permission_user.html:54
#: settings/templates/settings/_ldap_list_users_modal.html:37 users/forms.py:13 #: settings/templates/settings/_ldap_list_users_modal.html:37 users/forms.py:13
#: users/models/user.py:61 users/templates/users/_select_user_modal.html:14 #: users/models/user.py:62 users/templates/users/_select_user_modal.html:14
#: users/templates/users/user_detail.html:67 #: users/templates/users/user_detail.html:67
#: users/templates/users/user_list.html:36 #: users/templates/users/user_list.html:36
#: users/templates/users/user_profile.html:47 #: users/templates/users/user_profile.html:47
...@@ -738,8 +739,7 @@ msgid "Password or private key passphrase" ...@@ -738,8 +739,7 @@ msgid "Password or private key passphrase"
msgstr "密码或密钥密码" msgstr "密码或密钥密码"
#: assets/forms/user.py:26 assets/models/base.py:29 #: assets/forms/user.py:26 assets/models/base.py:29
#: assets/serializers/admin_user.py:19 assets/serializers/asset_user.py:34 #: assets/serializers/asset_user.py:70
#: assets/serializers/asset_user.py:87 assets/serializers/system_user.py:16
#: assets/templates/assets/_asset_user_auth_update_modal.html:21 #: assets/templates/assets/_asset_user_auth_update_modal.html:21
#: assets/templates/assets/_asset_user_auth_view_modal.html:27 #: assets/templates/assets/_asset_user_auth_view_modal.html:27
#: authentication/forms.py:13 #: authentication/forms.py:13
...@@ -757,10 +757,9 @@ msgstr "密码或密钥密码" ...@@ -757,10 +757,9 @@ msgstr "密码或密钥密码"
msgid "Password" msgid "Password"
msgstr "密码" msgstr "密码"
#: assets/forms/user.py:29 assets/serializers/asset_user.py:42 #: assets/forms/user.py:29 assets/serializers/asset_user.py:78
#: assets/serializers/asset_user.py:95
#: assets/templates/assets/_asset_user_auth_update_modal.html:27 #: assets/templates/assets/_asset_user_auth_update_modal.html:27
#: users/models/user.py:90 #: users/models/user.py:91
msgid "Private key" msgid "Private key"
msgstr "ssh私钥" msgstr "ssh私钥"
...@@ -804,7 +803,7 @@ msgstr "如果选择手动登录模式,用户名和密码可以不填写" ...@@ -804,7 +803,7 @@ msgstr "如果选择手动登录模式,用户名和密码可以不填写"
msgid "Use comma split multi command, ex: /bin/whoami,/bin/ifconfig" msgid "Use comma split multi command, ex: /bin/whoami,/bin/ifconfig"
msgstr "使用逗号分隔多个命令,如: /bin/whoami,/sbin/ifconfig" msgstr "使用逗号分隔多个命令,如: /bin/whoami,/sbin/ifconfig"
#: assets/models/asset.py:71 assets/models/asset.py:96 #: assets/models/asset.py:65 assets/models/asset.py:90
#: assets/models/domain.py:50 #: assets/models/domain.py:50
#: assets/templates/assets/domain_gateway_list.html:69 #: assets/templates/assets/domain_gateway_list.html:69
#: assets/templates/assets/user_asset_list.html:168 #: assets/templates/assets/user_asset_list.html:168
...@@ -812,12 +811,12 @@ msgstr "使用逗号分隔多个命令,如: /bin/whoami,/sbin/ifconfig" ...@@ -812,12 +811,12 @@ msgstr "使用逗号分隔多个命令,如: /bin/whoami,/sbin/ifconfig"
msgid "Port" msgid "Port"
msgstr "端口" msgstr "端口"
#: assets/models/asset.py:91 assets/models/domain.py:49 #: assets/models/asset.py:85 assets/models/domain.py:49
#: assets/serializers/asset_user.py:29 #: assets/serializers/asset_user.py:29
#: assets/templates/assets/_asset_list_modal.html:46 #: assets/templates/assets/_asset_list_modal.html:46
#: assets/templates/assets/_asset_user_list.html:15 #: assets/templates/assets/_asset_user_list.html:15
#: assets/templates/assets/asset_detail.html:64 #: assets/templates/assets/asset_detail.html:64
#: assets/templates/assets/asset_list.html:105 #: assets/templates/assets/asset_list.html:97
#: assets/templates/assets/domain_gateway_list.html:68 #: assets/templates/assets/domain_gateway_list.html:68
#: assets/templates/assets/user_asset_list.html:45 #: assets/templates/assets/user_asset_list.html:45
#: assets/templates/assets/user_asset_list.html:167 #: assets/templates/assets/user_asset_list.html:167
...@@ -829,24 +828,24 @@ msgstr "端口" ...@@ -829,24 +828,24 @@ msgstr "端口"
msgid "IP" msgid "IP"
msgstr "IP" msgstr "IP"
#: assets/models/asset.py:92 assets/serializers/asset_user.py:28 #: assets/models/asset.py:86 assets/serializers/asset_user.py:28
#: assets/templates/assets/_asset_list_modal.html:45 #: assets/templates/assets/_asset_list_modal.html:45
#: assets/templates/assets/_asset_user_auth_update_modal.html:9 #: assets/templates/assets/_asset_user_auth_update_modal.html:9
#: assets/templates/assets/_asset_user_auth_view_modal.html:15 #: assets/templates/assets/_asset_user_auth_view_modal.html:15
#: assets/templates/assets/_asset_user_list.html:14 #: assets/templates/assets/_asset_user_list.html:14
#: assets/templates/assets/asset_detail.html:60 #: assets/templates/assets/asset_detail.html:60
#: assets/templates/assets/asset_list.html:104 #: assets/templates/assets/asset_list.html:96
#: assets/templates/assets/user_asset_list.html:44 #: assets/templates/assets/user_asset_list.html:44
#: assets/templates/assets/user_asset_list.html:166 #: assets/templates/assets/user_asset_list.html:166
#: perms/templates/perms/asset_permission_asset.html:54 #: perms/templates/perms/asset_permission_asset.html:54
#: perms/templates/perms/asset_permission_list.html:77 settings/forms.py:139 #: perms/templates/perms/asset_permission_list.html:69 settings/forms.py:139
#: 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
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:50 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:50
msgid "Hostname" msgid "Hostname"
msgstr "主机名" msgstr "主机名"
#: assets/models/asset.py:95 assets/models/asset.py:98 #: assets/models/asset.py:89 assets/models/asset.py:92
#: assets/models/domain.py:51 assets/models/user.py:110 #: assets/models/domain.py:51 assets/models/user.py:110
#: assets/templates/assets/asset_detail.html:72 #: assets/templates/assets/asset_detail.html:72
#: assets/templates/assets/domain_gateway_list.html:70 #: assets/templates/assets/domain_gateway_list.html:70
...@@ -857,85 +856,85 @@ msgstr "主机名" ...@@ -857,85 +856,85 @@ msgstr "主机名"
msgid "Protocol" msgid "Protocol"
msgstr "协议" msgstr "协议"
#: assets/models/asset.py:99 assets/templates/assets/asset_detail.html:108 #: assets/models/asset.py:93 assets/templates/assets/asset_detail.html:108
#: assets/templates/assets/user_asset_list.html:170 #: assets/templates/assets/user_asset_list.html:170
msgid "Platform" msgid "Platform"
msgstr "系统平台" msgstr "系统平台"
#: assets/models/asset.py:102 assets/models/cmd_filter.py:21 #: assets/models/asset.py:96 assets/models/cmd_filter.py:21
#: assets/models/domain.py:54 assets/models/label.py:22 #: assets/models/domain.py:54 assets/models/label.py:22
#: assets/templates/assets/asset_detail.html:116 #: assets/templates/assets/asset_detail.html:116
#: assets/templates/assets/user_asset_list.html:174 #: assets/templates/assets/user_asset_list.html:174
msgid "Is active" msgid "Is active"
msgstr "激活" msgstr "激活"
#: assets/models/asset.py:108 assets/templates/assets/asset_detail.html:68 #: assets/models/asset.py:102 assets/templates/assets/asset_detail.html:68
msgid "Public IP" msgid "Public IP"
msgstr "公网IP" msgstr "公网IP"
#: assets/models/asset.py:109 assets/templates/assets/asset_detail.html:124 #: assets/models/asset.py:103 assets/templates/assets/asset_detail.html:124
msgid "Asset number" msgid "Asset number"
msgstr "资产编号" msgstr "资产编号"
#: assets/models/asset.py:112 assets/templates/assets/asset_detail.html:88 #: assets/models/asset.py:106 assets/templates/assets/asset_detail.html:88
msgid "Vendor" msgid "Vendor"
msgstr "制造商" msgstr "制造商"
#: assets/models/asset.py:113 assets/templates/assets/asset_detail.html:92 #: assets/models/asset.py:107 assets/templates/assets/asset_detail.html:92
msgid "Model" msgid "Model"
msgstr "型号" msgstr "型号"
#: assets/models/asset.py:114 assets/templates/assets/asset_detail.html:120 #: assets/models/asset.py:108 assets/templates/assets/asset_detail.html:120
msgid "Serial number" msgid "Serial number"
msgstr "序列号" msgstr "序列号"
#: assets/models/asset.py:116 #: assets/models/asset.py:110
msgid "CPU model" msgid "CPU model"
msgstr "CPU型号" msgstr "CPU型号"
#: assets/models/asset.py:117 #: assets/models/asset.py:111
#: xpack/plugins/license/templates/license/license_detail.html:80 #: xpack/plugins/license/templates/license/license_detail.html:80
msgid "CPU count" msgid "CPU count"
msgstr "CPU数量" msgstr "CPU数量"
#: assets/models/asset.py:118 #: assets/models/asset.py:112
msgid "CPU cores" msgid "CPU cores"
msgstr "CPU核数" msgstr "CPU核数"
#: assets/models/asset.py:119 #: assets/models/asset.py:113
msgid "CPU vcpus" msgid "CPU vcpus"
msgstr "CPU总数" msgstr "CPU总数"
#: assets/models/asset.py:120 assets/templates/assets/asset_detail.html:100 #: assets/models/asset.py:114 assets/templates/assets/asset_detail.html:100
msgid "Memory" msgid "Memory"
msgstr "内存" msgstr "内存"
#: assets/models/asset.py:121 #: assets/models/asset.py:115
msgid "Disk total" msgid "Disk total"
msgstr "硬盘大小" msgstr "硬盘大小"
#: assets/models/asset.py:122 #: assets/models/asset.py:116
msgid "Disk info" msgid "Disk info"
msgstr "硬盘信息" msgstr "硬盘信息"
#: assets/models/asset.py:124 assets/templates/assets/asset_detail.html:112 #: assets/models/asset.py:118 assets/templates/assets/asset_detail.html:112
#: assets/templates/assets/user_asset_list.html:171 #: assets/templates/assets/user_asset_list.html:171
msgid "OS" msgid "OS"
msgstr "操作系统" msgstr "操作系统"
#: assets/models/asset.py:125 #: assets/models/asset.py:119
msgid "OS version" msgid "OS version"
msgstr "系统版本" msgstr "系统版本"
#: assets/models/asset.py:126 #: assets/models/asset.py:120
msgid "OS arch" msgid "OS arch"
msgstr "系统架构" msgstr "系统架构"
#: assets/models/asset.py:127 #: assets/models/asset.py:121
msgid "Hostname raw" msgid "Hostname raw"
msgstr "主机名原始" msgstr "主机名原始"
#: assets/models/asset.py:129 assets/templates/assets/asset_create.html:46 #: assets/models/asset.py:123 assets/templates/assets/asset_create.html:46
#: assets/templates/assets/asset_detail.html:231 templates/_nav.html:26 #: assets/templates/assets/asset_detail.html:231 templates/_nav.html:26
msgid "Labels" msgid "Labels"
msgstr "标签管理" msgstr "标签管理"
...@@ -979,7 +978,7 @@ msgstr "带宽" ...@@ -979,7 +978,7 @@ msgstr "带宽"
msgid "Contact" msgid "Contact"
msgstr "联系人" msgstr "联系人"
#: assets/models/cluster.py:22 users/models/user.py:82 #: assets/models/cluster.py:22 users/models/user.py:83
#: users/templates/users/user_detail.html:76 #: users/templates/users/user_detail.html:76
msgid "Phone" msgid "Phone"
msgstr "手机" msgstr "手机"
...@@ -1001,12 +1000,12 @@ msgid "Operator" ...@@ -1001,12 +1000,12 @@ msgid "Operator"
msgstr "运营商" msgstr "运营商"
#: assets/models/cluster.py:36 assets/models/group.py:34 #: assets/models/cluster.py:36 assets/models/group.py:34
#: perms/utils/asset_permission.py:64 #: perms/utils/asset_permission.py:67
msgid "Default" msgid "Default"
msgstr "默认" msgstr "默认"
#: assets/models/cluster.py:36 assets/models/label.py:14 #: assets/models/cluster.py:36 assets/models/label.py:14
#: users/models/user.py:485 #: users/models/user.py:443
msgid "System" msgid "System"
msgstr "系统" msgstr "系统"
...@@ -1113,11 +1112,11 @@ msgstr "默认资产组" ...@@ -1113,11 +1112,11 @@ msgstr "默认资产组"
#: audits/templates/audits/password_change_log_list.html:50 #: audits/templates/audits/password_change_log_list.html:50
#: ops/templates/ops/command_execution_list.html:35 #: ops/templates/ops/command_execution_list.html:35
#: ops/templates/ops/command_execution_list.html:60 #: ops/templates/ops/command_execution_list.html:60
#: perms/forms/asset_permission.py:40 perms/forms/remote_app_permission.py:31 #: perms/forms/asset_permission.py:41 perms/forms/remote_app_permission.py:31
#: perms/models/base.py:36 #: perms/models/base.py:36
#: perms/templates/perms/asset_permission_create_update.html:41 #: perms/templates/perms/asset_permission_create_update.html:41
#: perms/templates/perms/asset_permission_list.html:54 #: perms/templates/perms/asset_permission_list.html:46
#: perms/templates/perms/asset_permission_list.html:119 #: perms/templates/perms/asset_permission_list.html:111
#: perms/templates/perms/remote_app_permission_create_update.html:43 #: perms/templates/perms/remote_app_permission_create_update.html:43
#: perms/templates/perms/remote_app_permission_list.html:15 #: perms/templates/perms/remote_app_permission_list.html:15
#: templates/index.html:87 terminal/backends/command/models.py:12 #: templates/index.html:87 terminal/backends/command/models.py:12
...@@ -1125,7 +1124,7 @@ msgstr "默认资产组" ...@@ -1125,7 +1124,7 @@ msgstr "默认资产组"
#: 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:301 #: terminal/templates/terminal/session_list.html:71 users/forms.py:301
#: users/models/user.py:37 users/models/user.py:473 users/serializers/v1.py:62 #: users/models/user.py:38 users/models/user.py:431 users/serializers/v1.py:88
#: users/templates/users/user_group_detail.html:78 #: users/templates/users/user_group_detail.html:78
#: users/templates/users/user_group_list.html:36 users/views/user.py:407 #: users/templates/users/user_group_list.html:36 users/views/user.py:407
#: xpack/plugins/orgs/forms.py:26 #: xpack/plugins/orgs/forms.py:26
...@@ -1134,7 +1133,7 @@ msgstr "默认资产组" ...@@ -1134,7 +1133,7 @@ msgstr "默认资产组"
msgid "User" msgid "User"
msgstr "用户" msgstr "用户"
#: assets/models/label.py:19 assets/models/node.py:21 #: assets/models/label.py:19 assets/models/node.py:240
#: assets/templates/assets/label_list.html:15 settings/models.py:30 #: assets/templates/assets/label_list.html:15 settings/models.py:30
msgid "Value" msgid "Value"
msgstr "值" msgstr "值"
...@@ -1143,11 +1142,11 @@ msgstr "值" ...@@ -1143,11 +1142,11 @@ msgstr "值"
msgid "Category" msgid "Category"
msgstr "分类" msgstr "分类"
#: assets/models/node.py:20 #: assets/models/node.py:239
msgid "Key" msgid "Key"
msgstr "键" msgstr "键"
#: assets/models/node.py:139 #: assets/models/node.py:296
msgid "New node" msgid "New node"
msgstr "新节点" msgstr "新节点"
...@@ -1221,7 +1220,7 @@ msgstr "协议组" ...@@ -1221,7 +1220,7 @@ msgstr "协议组"
msgid "Hardware info" msgid "Hardware info"
msgstr "硬件信息" msgstr "硬件信息"
#: assets/serializers/asset.py:74 orgs/mixins.py:220 #: assets/serializers/asset.py:74 orgs/mixins.py:192
msgid "Org name" msgid "Org name"
msgstr "组织名称" msgstr "组织名称"
...@@ -1229,9 +1228,16 @@ msgstr "组织名称" ...@@ -1229,9 +1228,16 @@ msgstr "组织名称"
msgid "Protocol duplicate: {}" msgid "Protocol duplicate: {}"
msgstr "协议重复: {}" msgstr "协议重复: {}"
#: assets/serializers/asset_user.py:38 assets/serializers/asset_user.py:91 #: assets/serializers/asset_user.py:32
#: users/forms.py:248 users/models/user.py:93 msgid "Backend"
#: users/templates/users/first_login.html:42 msgstr "后端"
#: assets/serializers/asset_user.py:57
msgid "private key invalid"
msgstr "密钥不合法"
#: assets/serializers/asset_user.py:74 users/forms.py:248
#: users/models/user.py:94 users/templates/users/first_login.html:42
#: users/templates/users/user_password_update.html:46 #: users/templates/users/user_password_update.html:46
#: users/templates/users/user_profile.html:68 #: users/templates/users/user_profile.html:68
#: users/templates/users/user_profile_update.html:43 #: users/templates/users/user_profile_update.html:43
...@@ -1239,13 +1245,9 @@ msgstr "协议重复: {}" ...@@ -1239,13 +1245,9 @@ msgstr "协议重复: {}"
msgid "Public key" msgid "Public key"
msgstr "ssh公钥" msgstr "ssh公钥"
#: assets/serializers/asset_user.py:44 #: assets/serializers/node.py:33
msgid "Backend" msgid "The same level node name cannot be the same"
msgstr "后端" msgstr "同级别节点名字不能重复"
#: assets/serializers/asset_user.py:66
msgid "private key invalid"
msgstr "密钥不合法"
#: assets/serializers/system_user.py:31 #: assets/serializers/system_user.py:31
msgid "Login mode display" msgid "Login mode display"
...@@ -1431,7 +1433,7 @@ msgid "Datetime" ...@@ -1431,7 +1433,7 @@ msgid "Datetime"
msgstr "日期" msgstr "日期"
#: assets/templates/assets/_asset_user_list.html:36 #: assets/templates/assets/_asset_user_list.html:36
#: assets/templates/assets/asset_list.html:166 #: assets/templates/assets/asset_list.html:138
msgid "Test datetime: " msgid "Test datetime: "
msgstr "测试日期: " msgstr "测试日期: "
...@@ -1466,6 +1468,34 @@ msgstr "SSH端口" ...@@ -1466,6 +1468,34 @@ msgstr "SSH端口"
msgid "If use nat, set the ssh real port" msgid "If use nat, set the ssh real port"
msgstr "如果使用了nat端口映射,请设置为ssh真实监听的端口" msgstr "如果使用了nat端口映射,请设置为ssh真实监听的端口"
#: assets/templates/assets/_node_tree.html:49
msgid "Add node"
msgstr "新建节点"
#: assets/templates/assets/_node_tree.html:50
msgid "Rename node"
msgstr "重命名节点"
#: assets/templates/assets/_node_tree.html:51
msgid "Delete node"
msgstr "删除节点"
#: assets/templates/assets/_node_tree.html:155
msgid "Create node failed"
msgstr "创建节点失败"
#: assets/templates/assets/_node_tree.html:167
msgid "Have child node, cancel"
msgstr "存在子节点,不能删除"
#: assets/templates/assets/_node_tree.html:169
msgid "Have assets, cancel"
msgstr "存在资产,不能删除"
#: assets/templates/assets/_node_tree.html:243
msgid "Rename success"
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/gateway_create_update.html:37 #: assets/templates/assets/gateway_create_update.html:37
...@@ -1549,7 +1579,7 @@ msgstr "选择节点" ...@@ -1549,7 +1579,7 @@ msgstr "选择节点"
#: assets/templates/assets/admin_user_detail.html:100 #: assets/templates/assets/admin_user_detail.html:100
#: assets/templates/assets/asset_detail.html:211 #: assets/templates/assets/asset_detail.html:211
#: assets/templates/assets/asset_list.html:688 #: assets/templates/assets/asset_list.html:396
#: assets/templates/assets/cmd_filter_detail.html:106 #: assets/templates/assets/cmd_filter_detail.html:106
#: assets/templates/assets/system_user_assets.html:100 #: assets/templates/assets/system_user_assets.html:100
#: assets/templates/assets/system_user_detail.html:182 #: assets/templates/assets/system_user_detail.html:182
...@@ -1564,7 +1594,6 @@ msgstr "选择节点" ...@@ -1564,7 +1594,6 @@ msgstr "选择节点"
#: users/templates/users/user_group_create_update.html:32 #: users/templates/users/user_group_create_update.html:32
#: users/templates/users/user_group_list.html:119 #: users/templates/users/user_group_list.html:119
#: users/templates/users/user_list.html:257 #: users/templates/users/user_list.html:257
#: users/templates/users/user_profile.html:238
#: xpack/plugins/cloud/templates/cloud/account_create_update.html:34 #: xpack/plugins/cloud/templates/cloud/account_create_update.html:34
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create.html:36 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_create.html:36
#: xpack/plugins/interface/templates/interface/interface.html:103 #: xpack/plugins/interface/templates/interface/interface.html:103
...@@ -1590,7 +1619,7 @@ msgid "You can set any one for Windows or other hardware." ...@@ -1590,7 +1619,7 @@ msgid "You can set any one for Windows or other hardware."
msgstr "Windows或其它硬件可以随意设置一个" msgstr "Windows或其它硬件可以随意设置一个"
#: assets/templates/assets/admin_user_list.html:19 #: assets/templates/assets/admin_user_list.html:19
#: assets/templates/assets/asset_list.html:76 #: assets/templates/assets/asset_list.html:68
#: assets/templates/assets/system_user_list.html:23 #: assets/templates/assets/system_user_list.html:23
#: audits/templates/audits/login_log_list.html:85 #: audits/templates/audits/login_log_list.html:85
#: users/templates/users/user_group_list.html:10 #: users/templates/users/user_group_list.html:10
...@@ -1600,7 +1629,7 @@ msgid "Export" ...@@ -1600,7 +1629,7 @@ msgid "Export"
msgstr "导出" msgstr "导出"
#: assets/templates/assets/admin_user_list.html:24 #: assets/templates/assets/admin_user_list.html:24
#: assets/templates/assets/asset_list.html:81 #: assets/templates/assets/asset_list.html:73
#: assets/templates/assets/system_user_list.html:28 #: assets/templates/assets/system_user_list.html:28
#: settings/templates/settings/_ldap_list_users_modal.html:100 #: settings/templates/settings/_ldap_list_users_modal.html:100
#: users/templates/users/user_group_list.html:15 #: users/templates/users/user_group_list.html:15
...@@ -1624,8 +1653,8 @@ msgstr "比例" ...@@ -1624,8 +1653,8 @@ msgstr "比例"
#: assets/templates/assets/admin_user_list.html:165 #: assets/templates/assets/admin_user_list.html:165
#: assets/templates/assets/admin_user_list.html:196 #: assets/templates/assets/admin_user_list.html:196
#: assets/templates/assets/asset_list.html:498 #: assets/templates/assets/asset_list.html:268
#: assets/templates/assets/asset_list.html:535 #: assets/templates/assets/asset_list.html:305
#: assets/templates/assets/system_user_list.html:224 #: assets/templates/assets/system_user_list.html:224
#: assets/templates/assets/system_user_list.html:255 #: assets/templates/assets/system_user_list.html:255
#: users/templates/users/user_group_list.html:163 #: users/templates/users/user_group_list.html:163
...@@ -1681,7 +1710,7 @@ msgstr "创建日期" ...@@ -1681,7 +1710,7 @@ msgstr "创建日期"
#: assets/templates/assets/asset_detail.html:154 #: assets/templates/assets/asset_detail.html:154
#: assets/templates/assets/user_asset_list.html:46 #: assets/templates/assets/user_asset_list.html:46
#: perms/models/asset_permission.py:60 perms/models/base.py:38 #: perms/models/asset_permission.py:77 perms/models/base.py:38
#: perms/templates/perms/asset_permission_create_update.html:55 #: perms/templates/perms/asset_permission_create_update.html:55
#: perms/templates/perms/asset_permission_detail.html:120 #: perms/templates/perms/asset_permission_detail.html:120
#: perms/templates/perms/remote_app_permission_create_update.html:54 #: perms/templates/perms/remote_app_permission_create_update.html:54
...@@ -1712,99 +1741,63 @@ msgstr "" ...@@ -1712,99 +1741,63 @@ msgstr ""
"左侧是资产树,右击可以新建、删除、更改树节点,授权资产也是以节点方式组织的," "左侧是资产树,右击可以新建、删除、更改树节点,授权资产也是以节点方式组织的,"
"右侧是属于该节点下的资产" "右侧是属于该节点下的资产"
#: assets/templates/assets/asset_list.html:69 assets/views/asset.py:129 #: assets/templates/assets/asset_list.html:61 assets/views/asset.py:129
msgid "Create asset" msgid "Create asset"
msgstr "创建资产" msgstr "创建资产"
#: assets/templates/assets/asset_list.html:106 #: assets/templates/assets/asset_list.html:98
msgid "Hardware" msgid "Hardware"
msgstr "硬件" msgstr "硬件"
#: assets/templates/assets/asset_list.html:117 #: assets/templates/assets/asset_list.html:109
#: users/templates/users/user_list.html:50 #: users/templates/users/user_list.html:50
msgid "Delete selected" msgid "Delete selected"
msgstr "批量删除" msgstr "批量删除"
#: assets/templates/assets/asset_list.html:118 #: assets/templates/assets/asset_list.html:110
#: users/templates/users/user_list.html:51 #: users/templates/users/user_list.html:51
msgid "Update selected" msgid "Update selected"
msgstr "批量更新" msgstr "批量更新"
#: assets/templates/assets/asset_list.html:119 #: assets/templates/assets/asset_list.html:111
msgid "Remove from this node" msgid "Remove from this node"
msgstr "从节点移除" msgstr "从节点移除"
#: assets/templates/assets/asset_list.html:120 #: assets/templates/assets/asset_list.html:112
#: users/templates/users/user_list.html:52 #: users/templates/users/user_list.html:52
msgid "Deactive selected" msgid "Deactive selected"
msgstr "禁用所选" msgstr "禁用所选"
#: assets/templates/assets/asset_list.html:121 #: assets/templates/assets/asset_list.html:113
#: users/templates/users/user_list.html:53 #: users/templates/users/user_list.html:53
msgid "Active selected" msgid "Active selected"
msgstr "激活所选" msgstr "激活所选"
#: assets/templates/assets/asset_list.html:138 #: assets/templates/assets/asset_list.html:191
msgid "Add node"
msgstr "新建节点"
#: assets/templates/assets/asset_list.html:139
msgid "Rename node"
msgstr "重命名节点"
#: assets/templates/assets/asset_list.html:140
msgid "Delete node"
msgstr "删除节点"
#: assets/templates/assets/asset_list.html:142
msgid "Add assets to node" msgid "Add assets to node"
msgstr "添加资产到节点" msgstr "添加资产到节点"
#: assets/templates/assets/asset_list.html:143 #: assets/templates/assets/asset_list.html:192
msgid "Move assets to node" msgid "Move assets to node"
msgstr "移动资产到节点" msgstr "移动资产到节点"
#: assets/templates/assets/asset_list.html:145 #: assets/templates/assets/asset_list.html:194
msgid "Refresh node hardware info" msgid "Refresh node hardware info"
msgstr "更新节点资产硬件信息" msgstr "更新节点资产硬件信息"
#: assets/templates/assets/asset_list.html:146 #: assets/templates/assets/asset_list.html:195
msgid "Test node connective" msgid "Test node connective"
msgstr "测试节点资产可连接性" msgstr "测试节点资产可连接性"
#: assets/templates/assets/asset_list.html:148 #: assets/templates/assets/asset_list.html:197
msgid "Refresh all node assets amount"
msgstr "刷新所有节点资产数量"
#: assets/templates/assets/asset_list.html:150
msgid "Display only current node assets" msgid "Display only current node assets"
msgstr "仅显示当前节点资产" msgstr "仅显示当前节点资产"
#: assets/templates/assets/asset_list.html:151 #: assets/templates/assets/asset_list.html:198
msgid "Displays all child node assets" msgid "Displays all child node assets"
msgstr "显示所有子节点资产" msgstr "显示所有子节点资产"
#: assets/templates/assets/asset_list.html:235 #: assets/templates/assets/asset_list.html:390
msgid "Create node failed"
msgstr "创建节点失败"
#: assets/templates/assets/asset_list.html:247
msgid "Have child node, cancel"
msgstr "存在子节点,不能删除"
#: assets/templates/assets/asset_list.html:249
msgid "Have assets, cancel"
msgstr "存在资产,不能删除"
#: assets/templates/assets/asset_list.html:320
msgid "Rename success"
msgstr "重命名成功"
#: assets/templates/assets/asset_list.html:321
msgid "Rename failed, do not change the root node name"
msgstr "重命名失败,不能更改root节点的名称"
#: assets/templates/assets/asset_list.html:682
#: assets/templates/assets/system_user_list.html:165 #: assets/templates/assets/system_user_list.html:165
#: users/templates/users/user_detail.html:382 #: users/templates/users/user_detail.html:382
#: users/templates/users/user_detail.html:408 #: users/templates/users/user_detail.html:408
...@@ -1815,11 +1808,11 @@ msgstr "重命名失败,不能更改root节点的名称" ...@@ -1815,11 +1808,11 @@ msgstr "重命名失败,不能更改root节点的名称"
msgid "Are you sure?" msgid "Are you sure?"
msgstr "你确认吗?" msgstr "你确认吗?"
#: assets/templates/assets/asset_list.html:683 #: assets/templates/assets/asset_list.html:391
msgid "This will delete the selected assets !!!" msgid "This will delete the selected assets !!!"
msgstr "删除选择资产" msgstr "删除选择资产"
#: assets/templates/assets/asset_list.html:686 #: assets/templates/assets/asset_list.html:394
#: assets/templates/assets/system_user_list.html:169 #: assets/templates/assets/system_user_list.html:169
#: settings/templates/settings/terminal_setting.html:166 #: settings/templates/settings/terminal_setting.html:166
#: users/templates/users/user_detail.html:386 #: users/templates/users/user_detail.html:386
...@@ -1833,16 +1826,16 @@ msgstr "删除选择资产" ...@@ -1833,16 +1826,16 @@ msgstr "删除选择资产"
msgid "Cancel" msgid "Cancel"
msgstr "取消" msgstr "取消"
#: assets/templates/assets/asset_list.html:699 #: assets/templates/assets/asset_list.html:407
msgid "Asset Deleted." msgid "Asset Deleted."
msgstr "已被删除" msgstr "已被删除"
#: assets/templates/assets/asset_list.html:700 #: assets/templates/assets/asset_list.html:408
#: assets/templates/assets/asset_list.html:704 #: assets/templates/assets/asset_list.html:412
msgid "Asset Delete" msgid "Asset Delete"
msgstr "删除" msgstr "删除"
#: assets/templates/assets/asset_list.html:703 #: assets/templates/assets/asset_list.html:411
msgid "Asset Deleting failed." msgid "Asset Deleting failed."
msgstr "删除失败" msgstr "删除失败"
...@@ -2232,7 +2225,7 @@ msgstr "Agent" ...@@ -2232,7 +2225,7 @@ msgstr "Agent"
#: audits/models.py:99 audits/templates/audits/login_log_list.html:56 #: audits/models.py:99 audits/templates/audits/login_log_list.html:56
#: authentication/templates/authentication/_mfa_confirm_modal.html:14 #: authentication/templates/authentication/_mfa_confirm_modal.html:14
#: users/forms.py:160 users/models/user.py:85 #: users/forms.py:160 users/models/user.py:86
#: users/templates/users/first_login.html:45 #: users/templates/users/first_login.html:45
msgid "MFA" msgid "MFA"
msgstr "MFA" msgstr "MFA"
...@@ -2652,7 +2645,7 @@ msgstr "不能包含特殊字符" ...@@ -2652,7 +2645,7 @@ msgstr "不能包含特殊字符"
msgid "This field must be unique." msgid "This field must be unique."
msgstr "字段必须唯一" msgstr "字段必须唯一"
#: jumpserver/views.py:188 #: jumpserver/views.py:190
msgid "" msgid ""
"<div>Luna is a separately deployed program, you need to deploy Luna, coco, " "<div>Luna is a separately deployed program, you need to deploy Luna, coco, "
"configure nginx for url distribution,</div> </div>If you see this page, " "configure nginx for url distribution,</div> </div>If you see this page, "
...@@ -3003,59 +2996,63 @@ msgstr "命令执行列表" ...@@ -3003,59 +2996,63 @@ msgstr "命令执行列表"
msgid "Command execution" msgid "Command execution"
msgstr "命令执行" msgstr "命令执行"
#: orgs/mixins.py:82 orgs/mixins.py:219 orgs/models.py:24 #: orgs/mixins.py:71 orgs/mixins.py:191 orgs/models.py:26
msgid "Organization" msgid "Organization"
msgstr "组织" msgstr "组织"
#: perms/const.py:18 settings/forms.py:143 #: perms/const.py:18 perms/models/asset_permission.py:44 settings/forms.py:143
msgid "All" msgid "All"
msgstr "全部" msgstr "全部"
#: perms/const.py:20 #: perms/const.py:20 perms/models/asset_permission.py:46
msgid "Upload file" msgid "Upload file"
msgstr "上传文件" msgstr "上传文件"
#: perms/const.py:21 #: perms/const.py:21 perms/models/asset_permission.py:48
msgid "Download file" msgid "Download file"
msgstr "下载文件" msgstr "下载文件"
#: perms/forms/asset_permission.py:43 perms/forms/remote_app_permission.py:34 #: perms/forms/asset_permission.py:44 perms/forms/remote_app_permission.py:34
#: perms/models/asset_permission.py:58 perms/models/base.py:37 #: perms/models/asset_permission.py:75 perms/models/base.py:37
#: perms/templates/perms/asset_permission_list.html:55 #: perms/templates/perms/asset_permission_list.html:47
#: perms/templates/perms/asset_permission_list.html:75 #: perms/templates/perms/asset_permission_list.html:67
#: perms/templates/perms/asset_permission_list.html:122 #: perms/templates/perms/asset_permission_list.html:114
#: perms/templates/perms/remote_app_permission_list.html:16 #: perms/templates/perms/remote_app_permission_list.html:16
#: templates/_nav.html:14 users/forms.py:271 users/models/group.py:26 #: templates/_nav.html:14 users/forms.py:271 users/models/group.py:26
#: users/models/user.py:69 users/templates/users/_select_user_modal.html:16 #: users/models/user.py:70 users/templates/users/_select_user_modal.html:16
#: users/templates/users/user_detail.html:213 #: users/templates/users/user_detail.html:213
#: users/templates/users/user_list.html:38 #: users/templates/users/user_list.html:38
#: xpack/plugins/orgs/templates/orgs/org_list.html:15 #: xpack/plugins/orgs/templates/orgs/org_list.html:15
msgid "User group" msgid "User group"
msgstr "用户组" msgstr "用户组"
#: perms/forms/asset_permission.py:62 #: perms/forms/asset_permission.py:63
msgid "" msgid ""
"Tips: The RDP protocol does not support separate controls for uploading or " "Tips: The RDP protocol does not support separate controls for uploading or "
"downloading files" "downloading files"
msgstr "提示:RDP 协议不支持单独控制上传或下载文件" msgstr "提示:RDP 协议不支持单独控制上传或下载文件"
#: perms/forms/asset_permission.py:72 perms/forms/remote_app_permission.py:47 #: perms/forms/asset_permission.py:73 perms/forms/remote_app_permission.py:47
msgid "User or group at least one required" msgid "User or group at least one required"
msgstr "用户和用户组至少选一个" msgstr "用户和用户组至少选一个"
#: perms/forms/asset_permission.py:81 #: perms/forms/asset_permission.py:82
msgid "Asset or group at least one required" msgid "Asset or group at least one required"
msgstr "资产和节点至少选一个" msgstr "资产和节点至少选一个"
#: perms/models/asset_permission.py:44 perms/models/asset_permission.py:70 #: perms/models/asset_permission.py:47
msgid "Upload download"
msgstr "上传下载"
#: perms/models/asset_permission.py:61 perms/models/asset_permission.py:87
#: templates/_nav.html:44 #: templates/_nav.html:44
msgid "Asset permission" msgid "Asset permission"
msgstr "资产授权" msgstr "资产授权"
#: perms/models/asset_permission.py:61 perms/models/base.py:40 #: perms/models/asset_permission.py:78 perms/models/base.py:40
#: perms/templates/perms/asset_permission_detail.html:90 #: perms/templates/perms/asset_permission_detail.html:90
#: perms/templates/perms/remote_app_permission_detail.html:82 #: perms/templates/perms/remote_app_permission_detail.html:82
#: users/models/user.py:101 users/templates/users/user_detail.html:107 #: users/models/user.py:102 users/templates/users/user_detail.html:107
#: users/templates/users/user_profile.html:116 #: users/templates/users/user_profile.html:116
msgid "Date expired" msgid "Date expired"
msgstr "失效日期" msgstr "失效日期"
...@@ -3145,13 +3142,13 @@ msgstr "系统用户数量" ...@@ -3145,13 +3142,13 @@ msgstr "系统用户数量"
msgid "Select system users" msgid "Select system users"
msgstr "选择系统用户" msgstr "选择系统用户"
#: perms/templates/perms/asset_permission_list.html:46 #: perms/templates/perms/asset_permission_list.html:38
#: perms/templates/perms/remote_app_permission_list.html:6 #: perms/templates/perms/remote_app_permission_list.html:6
msgid "Create permission" msgid "Create permission"
msgstr "创建授权规则" msgstr "创建授权规则"
#: perms/templates/perms/asset_permission_list.html:59 #: perms/templates/perms/asset_permission_list.html:51
#: perms/templates/perms/asset_permission_list.html:73 #: perms/templates/perms/asset_permission_list.html:65
#: perms/templates/perms/remote_app_permission_list.html:18 #: perms/templates/perms/remote_app_permission_list.html:18
#: users/templates/users/user_list.html:40 xpack/plugins/cloud/models.py:53 #: users/templates/users/user_list.html:40 xpack/plugins/cloud/models.py:53
#: xpack/plugins/cloud/templates/cloud/account_detail.html:58 #: xpack/plugins/cloud/templates/cloud/account_detail.html:58
...@@ -3201,9 +3198,9 @@ msgstr "添加用户" ...@@ -3201,9 +3198,9 @@ msgstr "添加用户"
msgid "Add user group to this permission" msgid "Add user group to this permission"
msgstr "添加用户组" msgstr "添加用户组"
#: perms/views/asset_permission.py:34 perms/views/asset_permission.py:67 #: perms/views/asset_permission.py:34 perms/views/asset_permission.py:65
#: perms/views/asset_permission.py:83 perms/views/asset_permission.py:99 #: perms/views/asset_permission.py:81 perms/views/asset_permission.py:97
#: perms/views/asset_permission.py:136 perms/views/asset_permission.py:169 #: perms/views/asset_permission.py:134 perms/views/asset_permission.py:167
#: perms/views/remote_app_permission.py:33 #: perms/views/remote_app_permission.py:33
#: perms/views/remote_app_permission.py:49 #: perms/views/remote_app_permission.py:49
#: perms/views/remote_app_permission.py:65 #: perms/views/remote_app_permission.py:65
...@@ -3218,23 +3215,23 @@ msgstr "权限管理" ...@@ -3218,23 +3215,23 @@ msgstr "权限管理"
msgid "Asset permission list" msgid "Asset permission list"
msgstr "资产授权列表" msgstr "资产授权列表"
#: perms/views/asset_permission.py:68 #: perms/views/asset_permission.py:66
msgid "Create asset permission" msgid "Create asset permission"
msgstr "创建权限规则" msgstr "创建权限规则"
#: perms/views/asset_permission.py:84 #: perms/views/asset_permission.py:82
msgid "Update asset permission" msgid "Update asset permission"
msgstr "更新资产授权" msgstr "更新资产授权"
#: perms/views/asset_permission.py:100 #: perms/views/asset_permission.py:98
msgid "Asset permission detail" msgid "Asset permission detail"
msgstr "资产授权详情" msgstr "资产授权详情"
#: perms/views/asset_permission.py:137 #: perms/views/asset_permission.py:135
msgid "Asset permission user list" msgid "Asset permission user list"
msgstr "资产授权用户列表" msgstr "资产授权用户列表"
#: perms/views/asset_permission.py:170 #: perms/views/asset_permission.py:168
msgid "Asset permission asset list" msgid "Asset permission asset list"
msgstr "资产授权资产列表" msgstr "资产授权资产列表"
...@@ -3591,7 +3588,7 @@ msgid "Please submit the LDAP configuration before import" ...@@ -3591,7 +3588,7 @@ msgid "Please submit the LDAP configuration before import"
msgstr "请先提交LDAP配置再进行导入" msgstr "请先提交LDAP配置再进行导入"
#: settings/templates/settings/_ldap_list_users_modal.html:39 #: settings/templates/settings/_ldap_list_users_modal.html:39
#: users/models/user.py:65 users/templates/users/user_detail.html:71 #: users/models/user.py:66 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 "邮件"
...@@ -4372,15 +4369,15 @@ msgid "" ...@@ -4372,15 +4369,15 @@ msgid ""
"You should use your ssh client tools connect terminal: {} <br /> <br />{}" "You should use your ssh client tools connect terminal: {} <br /> <br />{}"
msgstr "你可以使用ssh客户端工具连接终端" msgstr "你可以使用ssh客户端工具连接终端"
#: users/api/user.py:78 users/api/user.py:89 users/api/user.py:115 #: users/api/user.py:79 users/api/user.py:90 users/api/user.py:116
msgid "You do not have permission." msgid "You do not have permission."
msgstr "你没有权限" msgstr "你没有权限"
#: users/api/user.py:219 #: users/api/user.py:221
msgid "Could not reset self otp, use profile reset instead" msgid "Could not reset self otp, use profile reset instead"
msgstr "不能再该页面重置MFA, 请去个人信息页面重置" msgstr "不能再该页面重置MFA, 请去个人信息页面重置"
#: users/forms.py:32 users/models/user.py:73 #: users/forms.py:32 users/models/user.py:74
#: 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:37 #: users/templates/users/user_list.html:37
...@@ -4408,7 +4405,7 @@ msgstr "添加到用户组" ...@@ -4408,7 +4405,7 @@ msgstr "添加到用户组"
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:90 users/forms.py:237 users/serializers/v1.py:48 #: users/forms.py:90 users/forms.py:237 users/serializers/v1.py:74
msgid "Not a valid ssh public key" msgid "Not a valid ssh public key"
msgstr "ssh密钥不合法" msgstr "ssh密钥不合法"
...@@ -4489,88 +4486,94 @@ msgstr "复制你的公钥到这里" ...@@ -4489,88 +4486,94 @@ msgstr "复制你的公钥到这里"
msgid "Select users" msgid "Select users"
msgstr "选择用户" msgstr "选择用户"
#: users/models/user.py:36 users/models/user.py:481 #: users/models/user.py:37 users/models/user.py:439
msgid "Administrator" msgid "Administrator"
msgstr "管理员" msgstr "管理员"
#: users/models/user.py:38 #: users/models/user.py:39
msgid "Application" msgid "Application"
msgstr "应用程序" msgstr "应用程序"
#: users/models/user.py:39 #: users/models/user.py:40
msgid "Auditor" msgid "Auditor"
msgstr "审计员" msgstr "审计员"
#: users/models/user.py:42 users/templates/users/user_profile.html:92 #: users/models/user.py:43 users/templates/users/user_profile.html:92
#: users/templates/users/user_profile.html:159 #: users/templates/users/user_profile.html:159
#: users/templates/users/user_profile.html:162 #: users/templates/users/user_profile.html:162
msgid "Disable" msgid "Disable"
msgstr "禁用" msgstr "禁用"
#: users/models/user.py:43 users/templates/users/user_profile.html:90 #: users/models/user.py:44 users/templates/users/user_profile.html:90
#: users/templates/users/user_profile.html:166 #: users/templates/users/user_profile.html:166
msgid "Enable" msgid "Enable"
msgstr "启用" msgstr "启用"
#: users/models/user.py:44 users/templates/users/user_profile.html:88 #: users/models/user.py:45 users/templates/users/user_profile.html:88
msgid "Force enable" msgid "Force enable"
msgstr "强制启用" msgstr "强制启用"
#: users/models/user.py:76 #: users/models/user.py:77
msgid "Avatar" msgid "Avatar"
msgstr "头像" msgstr "头像"
#: users/models/user.py:79 users/templates/users/user_detail.html:82 #: users/models/user.py:80 users/templates/users/user_detail.html:82
msgid "Wechat" msgid "Wechat"
msgstr "微信" msgstr "微信"
#: users/models/user.py:108 users/templates/users/user_detail.html:103 #: users/models/user.py:109 users/templates/users/user_detail.html:103
#: users/templates/users/user_list.html:39 #: users/templates/users/user_list.html:39
#: users/templates/users/user_profile.html:100 #: users/templates/users/user_profile.html:100
msgid "Source" msgid "Source"
msgstr "用户来源" msgstr "用户来源"
#: users/models/user.py:112 #: users/models/user.py:113
msgid "Date password last updated" msgid "Date password last updated"
msgstr "最后更新密码日期" msgstr "最后更新密码日期"
#: users/models/user.py:138 users/templates/users/user_update.html:22 #: users/models/user.py:139 users/templates/users/user_update.html:22
#: users/views/login.py:46 users/views/login.py:107 users/views/user.py:439 #: users/views/login.py:46 users/views/login.py:107 users/views/user.py:439
msgid "User auth from {}, go there change password" msgid "User auth from {}, go there change password"
msgstr "用户认证源来自 {}, 请去相应系统修改密码" msgstr "用户认证源来自 {}, 请去相应系统修改密码"
#: users/models/user.py:484 #: users/models/user.py:442
msgid "Administrator is the super user of system" msgid "Administrator is the super user of system"
msgstr "Administrator是初始的超级管理员" msgstr "Administrator是初始的超级管理员"
#: users/serializers/v1.py:29 #: users/serializers/v1.py:32
msgid "Groups name" msgid "Groups name"
msgstr "用户组名" msgstr "用户组名"
#: users/serializers/v1.py:30 #: users/serializers/v1.py:33
msgid "Source name" msgid "Source name"
msgstr "用户来源名" msgstr "用户来源名"
#: users/serializers/v1.py:31 #: users/serializers/v1.py:34
msgid "Is first login" msgid "Is first login"
msgstr "首次登录" msgstr "首次登录"
#: users/serializers/v1.py:32 #: users/serializers/v1.py:35
msgid "Role name" msgid "Role name"
msgstr "角色名" msgstr "角色名"
#: users/serializers/v1.py:33 #: users/serializers/v1.py:36
msgid "Is valid" msgid "Is valid"
msgstr "账户是否有效" msgstr "账户是否有效"
#: users/serializers/v1.py:34 #: users/serializers/v1.py:37
msgid "Is expired" msgid "Is expired"
msgstr " 是否过期" msgstr " 是否过期"
#: users/serializers/v1.py:35 #: users/serializers/v1.py:38
msgid "Avatar url" msgid "Avatar url"
msgstr "头像路径" msgstr "头像路径"
#: users/serializers/v1.py:46
#, fuzzy
#| msgid "Password does not match"
msgid "Password does not match security rules"
msgstr "密码不一致"
#: users/serializers_v2/user.py:36 #: users/serializers_v2/user.py:36
msgid "name not unique" msgid "name not unique"
msgstr "名称重复" msgstr "名称重复"
...@@ -4846,14 +4849,11 @@ msgid "This will reset the user public key and send a reset mail" ...@@ -4846,14 +4849,11 @@ msgid "This will reset the user public key and send a reset mail"
msgstr "将会失效用户当前密钥,并发送重置邮件到用户邮箱" msgstr "将会失效用户当前密钥,并发送重置邮件到用户邮箱"
#: users/templates/users/user_detail.html:427 #: users/templates/users/user_detail.html:427
#: users/templates/users/user_profile.html:227
msgid "Successfully updated the SSH public key." msgid "Successfully updated the SSH public key."
msgstr "更新ssh密钥成功" msgstr "更新ssh密钥成功"
#: users/templates/users/user_detail.html:428 #: users/templates/users/user_detail.html:428
#: users/templates/users/user_detail.html:432 #: users/templates/users/user_detail.html:432
#: users/templates/users/user_profile.html:228
#: users/templates/users/user_profile.html:233
msgid "User SSH public key update" msgid "User SSH public key update"
msgstr "ssh密钥" msgstr "ssh密钥"
...@@ -4992,10 +4992,6 @@ msgstr "更改SSH密钥" ...@@ -4992,10 +4992,6 @@ msgstr "更改SSH密钥"
msgid "Reset public key and download" msgid "Reset public key and download"
msgstr "重置并下载SSH密钥" msgstr "重置并下载SSH密钥"
#: users/templates/users/user_profile.html:231
msgid "Failed to update SSH public key."
msgstr "更新密钥失败"
#: users/templates/users/user_pubkey_update.html:51 #: users/templates/users/user_pubkey_update.html:51
msgid "Old public key" msgid "Old public key"
msgstr "原来ssh密钥" msgstr "原来ssh密钥"
...@@ -5950,6 +5946,15 @@ msgstr "密码匣子" ...@@ -5950,6 +5946,15 @@ msgstr "密码匣子"
msgid "vault create" msgid "vault create"
msgstr "创建" msgstr "创建"
#~ msgid "Refresh all node assets amount"
#~ msgstr "刷新所有节点资产数量"
#~ msgid "Rename failed, do not change the root node name"
#~ msgstr "重命名失败,不能更改root节点的名称"
#~ msgid "Failed to update SSH public key."
#~ msgstr "更新密钥失败"
#~ msgid "Unreachable assets" #~ msgid "Unreachable assets"
#~ msgstr "不可达资产" #~ msgstr "不可达资产"
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from assets.models import Node from assets.models import Node
from orgs.utils import set_current_org, current_org from orgs.utils import set_current_org, current_org, get_current_org
...@@ -4,7 +4,8 @@ import traceback ...@@ -4,7 +4,8 @@ import traceback
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.shortcuts import redirect, get_object_or_404 from django.shortcuts import redirect, get_object_or_404
from django.forms import ModelForm from django import forms
from django.core.exceptions import ValidationError
from django.http.response import HttpResponseForbidden from django.http.response import HttpResponseForbidden
from rest_framework import serializers from rest_framework import serializers
from rest_framework.validators import UniqueTogetherValidator from rest_framework.validators import UniqueTogetherValidator
...@@ -101,6 +102,26 @@ class OrgModelMixin(models.Model): ...@@ -101,6 +102,26 @@ class OrgModelMixin(models.Model):
else: else:
return name return name
def validate_unique(self, exclude=None):
"""
Check unique constraints on the model and raise ValidationError if any
failed.
Form 提交时会使用这个检验
"""
self.org_id = current_org.id if current_org.is_real() else ''
if exclude and 'org_id' in exclude:
exclude.remove('org_id')
unique_checks, date_checks = self._get_unique_checks(exclude=exclude)
errors = self._perform_unique_checks(unique_checks)
date_errors = self._perform_date_checks(date_checks)
for k, v in date_errors.items():
errors.setdefault(k, []).extend(v)
if errors:
raise ValidationError(errors)
class Meta: class Meta:
abstract = True abstract = True
...@@ -123,11 +144,9 @@ class RootOrgViewMixin: ...@@ -123,11 +144,9 @@ class RootOrgViewMixin:
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
class OrgModelForm(ModelForm): class OrgModelForm(forms.ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
# if 'initial' not in kwargs:
# return
for name, field in self.fields.items(): for name, field in self.fields.items():
if not hasattr(field, 'queryset'): if not hasattr(field, 'queryset'):
continue continue
......
...@@ -6,7 +6,7 @@ from django.db.models.signals import post_save ...@@ -6,7 +6,7 @@ from django.db.models.signals import post_save
from django.dispatch import receiver from django.dispatch import receiver
from .models import Organization from .models import Organization
from .hands import set_current_org, current_org, Node from .hands import set_current_org, current_org, Node, get_current_org
from perms.models import AssetPermission from perms.models import AssetPermission
from users.models import UserGroup from users.models import UserGroup
...@@ -14,7 +14,7 @@ from users.models import UserGroup ...@@ -14,7 +14,7 @@ from users.models import UserGroup
@receiver(post_save, sender=Organization) @receiver(post_save, sender=Organization)
def on_org_create_or_update(sender, instance=None, created=False, **kwargs): def on_org_create_or_update(sender, instance=None, created=False, **kwargs):
if instance: if instance:
old_org = current_org old_org = get_current_org()
set_current_org(instance) set_current_org(instance)
node_root = Node.root() node_root = Node.root()
if node_root.value != instance.name: if node_root.value != instance.name:
......
...@@ -20,16 +20,10 @@ from .. import serializers ...@@ -20,16 +20,10 @@ from .. import serializers
__all__ = [ __all__ = [
'AssetPermissionViewSet', 'AssetPermissionRemoveUserApi', 'AssetPermissionViewSet', 'AssetPermissionRemoveUserApi',
'AssetPermissionAddUserApi', 'AssetPermissionRemoveAssetApi', 'AssetPermissionAddUserApi', 'AssetPermissionRemoveAssetApi',
'AssetPermissionAddAssetApi', 'ActionViewSet', 'AssetPermissionAddAssetApi',
] ]
class ActionViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Action.objects.all()
serializer_class = serializers.ActionSerializer
permission_classes = (IsOrgAdmin,)
class AssetPermissionViewSet(viewsets.ModelViewSet): class AssetPermissionViewSet(viewsets.ModelViewSet):
""" """
资产授权列表的增删改查api 资产授权列表的增删改查api
......
...@@ -14,7 +14,6 @@ from rest_framework.pagination import LimitOffsetPagination ...@@ -14,7 +14,6 @@ from rest_framework.pagination import LimitOffsetPagination
from common.permissions import IsValidUser, IsOrgAdminOrAppUser from common.permissions import IsValidUser, IsOrgAdminOrAppUser
from common.tree import TreeNodeSerializer from common.tree import TreeNodeSerializer
from common.utils import get_logger from common.utils import get_logger
from orgs.utils import set_to_root_org
from ..utils import ( from ..utils import (
AssetPermissionUtil, parse_asset_to_tree_node, parse_node_to_tree_node, AssetPermissionUtil, parse_asset_to_tree_node, parse_node_to_tree_node,
check_system_user_action, RemoteAppPermissionUtil, check_system_user_action, RemoteAppPermissionUtil,
...@@ -515,6 +514,7 @@ class ValidateUserRemoteAppPermissionApi(APIView): ...@@ -515,6 +514,7 @@ class ValidateUserRemoteAppPermissionApi(APIView):
permission_classes = (IsOrgAdminOrAppUser,) permission_classes = (IsOrgAdminOrAppUser,)
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
self.change_org_if_need(request, kwargs)
user_id = request.query_params.get('user_id', '') user_id = request.query_params.get('user_id', '')
remote_app_id = request.query_params.get('remote_app_id', '') remote_app_id = request.query_params.get('remote_app_id', '')
user = get_object_or_404(User, id=user_id) user = get_object_or_404(User, id=user_id)
......
# ~*~ coding: utf-8 ~*~ # ~*~ coding: utf-8 ~*~
from __future__ import absolute_import, unicode_literals from __future__ import absolute_import, unicode_literals
from functools import reduce
from django import forms from django import forms
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
...@@ -18,17 +19,22 @@ class AssetPermissionForm(OrgModelForm): ...@@ -18,17 +19,22 @@ class AssetPermissionForm(OrgModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
users_field = self.fields.get('users') users_field = self.fields.get('users')
if hasattr(users_field, 'queryset'):
users_field.queryset = current_org.get_org_users() users_field.queryset = current_org.get_org_users()
assets_field = self.fields.get('assets')
# 前端渲染优化, 防止过多资产 # 前端渲染优化, 防止过多资产
if not self.data: if not self.data:
instance = kwargs.get('instance') instance = kwargs.get('instance')
assets_field = self.fields['assets']
if instance: if instance:
assets_field.queryset = instance.assets.all() assets_field.queryset = instance.assets.all()
else: else:
assets_field.queryset = Asset.objects.none() assets_field.queryset = Asset.objects.none()
nodes_field = self.fields['nodes']
nodes_field._queryset = Node.get_queryset()
def clean_action(self):
actions = self.cleaned_data.get("action")
return reduce(lambda x, y: x | y, actions)
class Meta: class Meta:
model = AssetPermission model = AssetPermission
...@@ -51,15 +57,13 @@ class AssetPermissionForm(OrgModelForm): ...@@ -51,15 +57,13 @@ class AssetPermissionForm(OrgModelForm):
'system_users': forms.SelectMultiple( 'system_users': forms.SelectMultiple(
attrs={'class': 'select2', 'data-placeholder': _('System user')} attrs={'class': 'select2', 'data-placeholder': _('System user')}
), ),
'actions': forms.SelectMultiple( 'action': forms.CheckboxSelectMultiple()
attrs={'class': 'select2', 'data-placeholder': _('Action')}
)
} }
labels = { labels = {
'nodes': _("Node"), 'nodes': _("Node"),
} }
help_texts = { help_texts = {
'actions': _('Tips: The RDP protocol does not support separate ' 'action': _('Tips: The RDP protocol does not support separate '
'controls for uploading or downloading files') 'controls for uploading or downloading files')
} }
......
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2018-02-25 10:15
from __future__ import unicode_literals
import common.utils
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
('users', '0004_auto_20180125_1218'),
('assets', '0007_auto_20180225_1815'),
('perms', '0002_auto_20171228_0025'),
]
operations = [
migrations.CreateModel(
name='NodePermission',
fields=[
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('is_active', models.BooleanField(default=True, verbose_name='Active')),
('date_expired', models.DateTimeField(default=common.utils.date_expired_default, verbose_name='Date expired')),
('created_by', models.CharField(blank=True, max_length=128, verbose_name='Created by')),
('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')),
('comment', models.TextField(blank=True, verbose_name='Comment')),
('node', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.Node', verbose_name='Node')),
('system_user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.SystemUser', verbose_name='System user')),
('user_group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.UserGroup', verbose_name='User group')),
],
options={
'verbose_name': 'Asset permission',
},
),
migrations.AlterUniqueTogether(
name='nodepermission',
unique_together=set([('node', 'user_group', 'system_user')]),
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2018-04-11 03:35
from __future__ import unicode_literals
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('assets', '0013_auto_20180411_1135'),
('perms', '0003_auto_20180225_1815'),
]
operations = [
migrations.RemoveField(
model_name='assetpermission',
name='asset_groups',
),
migrations.AddField(
model_name='assetpermission',
name='date_start',
field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='Date start'),
),
migrations.AddField(
model_name='assetpermission',
name='nodes',
field=models.ManyToManyField(blank=True, related_name='granted_by_permissions', to='assets.Node', verbose_name='Nodes'),
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2018-04-11 03:35
from __future__ import unicode_literals
from django.db import migrations, models
import django.utils.timezone
def migrate_node_permissions(apps, schema_editor):
node_perm_model = apps.get_model("perms", "NodePermission")
asset_perm_model = apps.get_model("perms", "AssetPermission")
db_alias = schema_editor.connection.alias
for old in node_perm_model.objects.using(db_alias).all():
perm = asset_perm_model.objects.using(db_alias).create(
name="{}-{}-{}".format(
old.node.value,
old.user_group.name,
old.system_user.name
),
is_active=old.is_active,
date_expired=old.date_expired,
created_by=old.date_expired,
date_created=old.date_created,
comment=old.comment,
)
perm.user_groups.add(old.user_group)
perm.nodes.add(old.node)
perm.system_users.add(old.system_user)
def migrate_system_assets_relation(apps, schema_editor):
system_user_model = apps.get_model("assets", "SystemUser")
db_alias = schema_editor.connection.alias
for s in system_user_model.objects.using(db_alias).all():
nodes = list(s.nodes.all())
s.nodes.set([])
s.nodes.set(nodes)
class Migration(migrations.Migration):
dependencies = [
('perms', '0004_auto_20180411_1135'),
]
operations = [
migrations.RunPython(migrate_node_permissions),
migrations.RunPython(migrate_system_assets_relation),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2018-06-06 07:05
from __future__ import unicode_literals
import common.utils
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('perms', '0005_migrate_data_20180411_1144'),
]
operations = [
migrations.AlterField(
model_name='assetpermission',
name='date_expired',
field=models.DateTimeField(db_index=True, default=common.utils.date_expired_default, verbose_name='Date expired'),
),
migrations.AlterField(
model_name='assetpermission',
name='date_start',
field=models.DateTimeField(db_index=True, default=django.utils.timezone.now, verbose_name='Date start'),
),
]
# Generated by Django 2.1.7 on 2019-06-28 11:47
from django.db import migrations, models
from functools import reduce
def migrate_old_actions(apps, schema_editor):
from orgs.utils import set_to_root_org
from ..models import ActionFlag
set_to_root_org()
perm_model = apps.get_model('perms', 'AssetPermission')
db_alias = schema_editor.connection.alias
perms = perm_model.objects.using(db_alias).all()
actions_map = {
"all": ActionFlag.ALL,
"connect": ActionFlag.CONNECT,
"upload_file": ActionFlag.UPLOAD,
"download_file": ActionFlag.DOWNLOAD,
}
for perm in perms:
actions = perm.actions.all()
new_actions = [actions_map.get(action.name, ActionFlag.ALL) for action in actions]
new_action = reduce(lambda x, y: x | y, new_actions)
perm.action = new_action
perm.save()
class Migration(migrations.Migration):
dependencies = [
('perms', '0005_auto_20190521_1619'),
]
operations = [
migrations.AddField(
model_name='assetpermission',
name='action',
field=models.IntegerField(
choices=[(255, 'All'), (1, 'Connect'), (2, 'Upload file'),
(6, 'Upload download'), (4, 'Download file')],
default=255, verbose_name='Action'),
),
migrations.RunPython(migrate_old_actions),
]
# Generated by Django 2.0.7 on 2018-08-07 03:16
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('perms', '0006_auto_20180606_1505'),
]
operations = [
migrations.AddField(
model_name='assetpermission',
name='org_id',
field=models.CharField(blank=True, default=None, max_length=36, null=True),
),
migrations.AddField(
model_name='nodepermission',
name='org_id',
field=models.CharField(blank=True, default=None, max_length=36, null=True),
),
migrations.AlterField(
model_name='assetpermission',
name='name',
field=models.CharField(max_length=128, verbose_name='Name'),
),
migrations.AlterUniqueTogether(
name='assetpermission',
unique_together={('org_id', 'name')},
),
migrations.AlterUniqueTogether(
name='nodepermission',
unique_together=set(),
),
]
# Generated by Django 2.1 on 2018-09-03 03:32 # Generated by Django 2.1.7 on 2019-06-28 12:02
from django.db import migrations from django.db import migrations
...@@ -6,12 +6,12 @@ from django.db import migrations ...@@ -6,12 +6,12 @@ from django.db import migrations
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('perms', '0008_auto_20180816_1652'), ('perms', '0006_auto_20190628_1921'),
] ]
operations = [ operations = [
migrations.AlterModelOptions( migrations.RemoveField(
name='assetpermission', model_name='assetpermission',
options={'verbose_name': 'Asset permission'}, name='actions',
), ),
] ]
# Generated by Django 2.0.7 on 2018-08-16 08:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('perms', '0007_auto_20180807_1116'),
]
operations = [
migrations.AlterField(
model_name='assetpermission',
name='org_id',
field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'),
),
migrations.AlterField(
model_name='nodepermission',
name='org_id',
field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'),
),
]
...@@ -11,7 +11,7 @@ from .base import BasePermission ...@@ -11,7 +11,7 @@ from .base import BasePermission
__all__ = [ __all__ = [
'Action', 'AssetPermission', 'NodePermission', 'Action', 'AssetPermission', 'NodePermission', 'ActionFlag'
] ]
...@@ -33,11 +33,28 @@ class Action(models.Model): ...@@ -33,11 +33,28 @@ class Action(models.Model):
return cls.objects.get(name=PERMS_ACTION_NAME_ALL) return cls.objects.get(name=PERMS_ACTION_NAME_ALL)
class ActionFlag:
CONNECT = 0b00000001
UPLOAD = 0b00000010
DOWNLOAD = 0b00000100
UPDOWNLOAD = CONNECT | DOWNLOAD
ALL = 0b11111111
CHOICES = (
(ALL, _('All')),
(CONNECT, _('Connect')),
(UPLOAD, _('Upload file')),
(UPDOWNLOAD, _("Upload download")),
(DOWNLOAD, _('Download file')),
)
class AssetPermission(BasePermission): class AssetPermission(BasePermission):
assets = models.ManyToManyField('assets.Asset', related_name='granted_by_permissions', blank=True, verbose_name=_("Asset")) assets = models.ManyToManyField('assets.Asset', related_name='granted_by_permissions', blank=True, verbose_name=_("Asset"))
nodes = models.ManyToManyField('assets.Node', related_name='granted_by_permissions', blank=True, verbose_name=_("Nodes")) nodes = models.ManyToManyField('assets.Node', related_name='granted_by_permissions', blank=True, verbose_name=_("Nodes"))
system_users = models.ManyToManyField('assets.SystemUser', related_name='granted_by_permissions', verbose_name=_("System user")) system_users = models.ManyToManyField('assets.SystemUser', related_name='granted_by_permissions', verbose_name=_("System user"))
actions = models.ManyToManyField('Action', related_name='permissions', blank=True, verbose_name=_('Action')) # actions = models.ManyToManyField(Action, related_name='permissions', blank=True, verbose_name=_('Action'))
action = models.IntegerField(choices=ActionFlag.CHOICES, default=ActionFlag.ALL, verbose_name=_("Action"))
class Meta: class Meta:
unique_together = [('org_id', 'name')] unique_together = [('org_id', 'name')]
......
...@@ -13,16 +13,10 @@ __all__ = [ ...@@ -13,16 +13,10 @@ __all__ = [
'AssetPermissionCreateUpdateSerializer', 'AssetPermissionListSerializer', 'AssetPermissionCreateUpdateSerializer', 'AssetPermissionListSerializer',
'AssetPermissionUpdateUserSerializer', 'AssetPermissionUpdateAssetSerializer', 'AssetPermissionUpdateUserSerializer', 'AssetPermissionUpdateAssetSerializer',
'AssetPermissionNodeSerializer', 'GrantedNodeSerializer', 'AssetPermissionNodeSerializer', 'GrantedNodeSerializer',
'ActionSerializer', 'NodeGrantedSerializer', 'NodeGrantedSerializer',
] ]
class ActionSerializer(serializers.ModelSerializer):
class Meta:
model = Action
fields = '__all__'
class AssetPermissionCreateUpdateSerializer(BulkOrgResourceModelSerializer): class AssetPermissionCreateUpdateSerializer(BulkOrgResourceModelSerializer):
class Meta: class Meta:
model = AssetPermission model = AssetPermission
...@@ -35,7 +29,7 @@ class AssetPermissionListSerializer(BulkOrgResourceModelSerializer): ...@@ -35,7 +29,7 @@ class AssetPermissionListSerializer(BulkOrgResourceModelSerializer):
assets = StringManyToManyField(many=True, read_only=True) assets = StringManyToManyField(many=True, read_only=True)
nodes = StringManyToManyField(many=True, read_only=True) nodes = StringManyToManyField(many=True, read_only=True)
system_users = StringManyToManyField(many=True, read_only=True) system_users = StringManyToManyField(many=True, read_only=True)
actions = StringManyToManyField(many=True, read_only=True) action = serializers.IntegerField(read_only=True)
is_valid = serializers.BooleanField() is_valid = serializers.BooleanField()
is_expired = serializers.BooleanField() is_expired = serializers.BooleanField()
......
...@@ -25,13 +25,6 @@ def on_transaction_commit(func): ...@@ -25,13 +25,6 @@ def on_transaction_commit(func):
@on_transaction_commit @on_transaction_commit
def on_permission_created(sender, instance=None, created=False, **kwargs): def on_permission_created(sender, instance=None, created=False, **kwargs):
AssetPermissionUtil.expire_all_cache() AssetPermissionUtil.expire_all_cache()
actions = instance.actions.all()
if created and not actions:
default_action = Action.get_action_all()
instance.actions.add(default_action)
logger.debug(
"Set default action to perms: {}".format(default_action, instance)
)
@receiver(post_save, sender=AssetPermission) @receiver(post_save, sender=AssetPermission)
......
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
{% bootstrap_field form.system_users layout="horizontal" %} {% bootstrap_field form.system_users layout="horizontal" %}
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<h3>{% trans 'Action' %}</h3> <h3>{% trans 'Action' %}</h3>
{% bootstrap_field form.actions layout="horizontal" %} {% bootstrap_field form.action layout="horizontal" %}
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<h3>{% trans 'Other' %}</h3> <h3>{% trans 'Other' %}</h3>
<div class="form-group"> <div class="form-group">
...@@ -143,6 +143,34 @@ $(document).ready(function () { ...@@ -143,6 +143,34 @@ $(document).ready(function () {
$('#id_assets').val(assets).trigger('change'); $('#id_assets').val(assets).trigger('change');
$("#asset_list_modal").modal('hide'); $("#asset_list_modal").modal('hide');
}); })
.on("submit", "form", function (evt) {
evt.preventDefault();
var the_url = '{% url 'api-perms:asset-permission-list' %}';
var redirect_to = '{% url "perms:asset-permission-list" %}';
var method = "POST";
var form = $("form");
var data = form.serializeObject();
console.log(data)
var actions = data.action;
var action = 0;
for (i=0;i<actions.length;i++) {
console.log(actions[i])
action |= actions[i];
}
data.action = action;
objectAttrsIsList(data, ['users', 'user_groups', 'system_users', 'nodes', 'assets']);
objectAttrsIsDatetime(data, ['date_start', 'date_expired']);
objectAttrsIsBool(data, ['is_active'])
console.log(data)
var props = {
url: the_url,
data: data,
method: method,
form: form,
redirect_to: redirect_to
};
formSubmit(props);
})
</script> </script>
{% endblock %} {% endblock %}
\ No newline at end of file
...@@ -24,15 +24,7 @@ ...@@ -24,15 +24,7 @@
<div class="wrapper wrapper-content"> <div class="wrapper wrapper-content">
<div class="row"> <div class="row">
<div class="col-lg-3" id="split-left" style="padding-left: 3px"> <div class="col-lg-3" id="split-left" style="padding-left: 3px">
<div class="ibox float-e-margins"> {% include 'assets/_node_tree.html' %}
<div class="ibox-content mailbox-content" style="padding-top: 0;padding-left: 1px">
<div class="file-manager ">
<div id="assetTree" class="ztree">
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
</div> </div>
<div class="col-lg-9 animated fadeInRight" id="split-right"> <div class="col-lg-9 animated fadeInRight" id="split-right">
<div class="tree-toggle"> <div class="tree-toggle">
...@@ -86,7 +78,7 @@ ...@@ -86,7 +78,7 @@
<script> <script>
var zTree, table, show = 0; var zTree, table, show = 0;
function onSelected(event, treeNode) { function onNodeSelected(event, treeNode) {
setCookie('node_selected', treeNode.id); setCookie('node_selected', treeNode.id);
var url = table.ajax.url(); var url = table.ajax.url();
if (treeNode.meta.type === 'node') { if (treeNode.meta.type === 'node') {
...@@ -102,7 +94,7 @@ function onSelected(event, treeNode) { ...@@ -102,7 +94,7 @@ function onSelected(event, treeNode) {
} }
function beforeAsync(treeId, treeNode) { function beforeNodeAsync(treeId, treeNode) {
if (treeNode) { if (treeNode) {
return treeNode.meta.type === 'node' return treeNode.meta.type === 'node'
} }
...@@ -204,28 +196,12 @@ function initTable() { ...@@ -204,28 +196,12 @@ function initTable() {
function initTree() { function initTree() {
var setting = { initNodeTree({
view: { onSelected: onNodeSelected,
dblClickExpand: false, beforeAsync: beforeNodeAsync,
showLine: true showMenu: false,
}, showAssets: true,
data: { })
simpleData: {
enable: true
}
},
async: {
enable: true,
url: "{% url 'api-assets:node-children-tree' %}?assets=1",
autoParam:["id=key", "name=n", "level=lv"],
type: 'get'
},
callback: {
onSelected: onSelected,
beforeAsync: beforeAsync
}
};
zTree = $.fn.zTree.init($("#assetTree"), setting);
} }
function toggle() { function toggle() {
......
...@@ -7,7 +7,6 @@ from .. import api ...@@ -7,7 +7,6 @@ from .. import api
app_name = 'perms' app_name = 'perms'
router = routers.DefaultRouter() router = routers.DefaultRouter()
router.register('actions', api.ActionViewSet, 'action')
router.register('asset-permissions', api.AssetPermissionViewSet, 'asset-permission') router.register('asset-permissions', api.AssetPermissionViewSet, 'asset-permission')
router.register('remote-app-permissions', api.RemoteAppPermissionViewSet, 'remote-app-permission') router.register('remote-app-permissions', api.RemoteAppPermissionViewSet, 'remote-app-permission')
......
...@@ -5,6 +5,7 @@ from collections import defaultdict ...@@ -5,6 +5,7 @@ from collections import defaultdict
import json import json
from hashlib import md5 from hashlib import md5
import time import time
import itertools
from django.utils import timezone from django.utils import timezone
from django.db.models import Q from django.db.models import Q
...@@ -102,11 +103,11 @@ def get_user_permissions(user, include_group=True): ...@@ -102,11 +103,11 @@ def get_user_permissions(user, include_group=True):
arg = Q(users=user) | Q(user_groups__in=groups) arg = Q(users=user) | Q(user_groups__in=groups)
else: else:
arg = Q(users=user) arg = Q(users=user)
return AssetPermission.objects.all().valid().filter(arg) return AssetPermission.objects.valid().filter(arg)
def get_user_group_permissions(user_group): def get_user_group_permissions(user_group):
return AssetPermission.objects.all().valid().filter( return AssetPermission.objects.valid().filter(
user_groups=user_group user_groups=user_group
) )
...@@ -117,15 +118,15 @@ def get_asset_permissions(asset, include_node=True): ...@@ -117,15 +118,15 @@ def get_asset_permissions(asset, include_node=True):
arg = Q(assets=asset) | Q(nodes__in=nodes) arg = Q(assets=asset) | Q(nodes__in=nodes)
else: else:
arg = Q(assets=asset) arg = Q(assets=asset)
return AssetPermission.objects.all().valid().filter(arg) return AssetPermission.objects.valid().filter(arg)
def get_node_permissions(node): def get_node_permissions(node):
return AssetPermission.objects.all().valid().filter(nodes=node) return AssetPermission.objects.valid().filter(nodes=node)
def get_system_user_permissions(system_user): def get_system_user_permissions(system_user):
return AssetPermission.objects.valid().all().filter( return AssetPermission.objects.valid().filter(
system_users=system_user system_users=system_user
) )
...@@ -141,11 +142,6 @@ def timeit(func): ...@@ -141,11 +142,6 @@ def timeit(func):
return wrapper return wrapper
class AssetGranted:
def __init__(self):
self.system_users = {}
class AssetPermissionCacheMixin: class AssetPermissionCacheMixin:
CACHE_KEY_PREFIX = '_ASSET_PERM_CACHE_' CACHE_KEY_PREFIX = '_ASSET_PERM_CACHE_'
CACHE_META_KEY_PREFIX = '_ASSET_PERM_META_KEY_' CACHE_META_KEY_PREFIX = '_ASSET_PERM_META_KEY_'
...@@ -286,6 +282,38 @@ class AssetPermissionCacheMixin: ...@@ -286,6 +282,38 @@ class AssetPermissionCacheMixin:
cache.delete_pattern(key) cache.delete_pattern(key)
class FlatPermissionQueryset:
def __init__(self):
self.queryset = defaultdict(list)
def add(self, permission):
self.queryset[permission.id].append(permission)
def add_many(self, assets_or_nodes, system_users, actions):
if any([assets_or_nodes, system_users, actions]):
return
iterable = itertools.product(assets_or_nodes, system_users, actions)
for source, sysuser, action in iterable:
permission = FlatPermission(source, sysuser, action)
self.add(permission)
def clean(self):
pass
class FlatPermission:
def __init__(self, asset_or_node, system_user, action):
self.id = asset_or_node.id
self.source = asset_or_node
self.system_user = system_user
self.action = action
def __eq__(self, other):
pass
class AssetPermissionUtil(AssetPermissionCacheMixin): class AssetPermissionUtil(AssetPermissionCacheMixin):
get_permissions_map = { get_permissions_map = {
"User": get_user_permissions, "User": get_user_permissions,
...@@ -344,19 +372,15 @@ class AssetPermissionUtil(AssetPermissionCacheMixin): ...@@ -344,19 +372,15 @@ class AssetPermissionUtil(AssetPermissionCacheMixin):
def get_nodes_direct(self): def get_nodes_direct(self):
""" """
返回用户/组授权规则直接关联的节点 返回用户/组授权规则直接关联的节点
:return: {asset1: {system_user1: {'actions': set()},}} :return: {node1: {system_user1: {'actions': set()},}}
""" """
nodes = defaultdict(dict) nodes = FlatPermissionQueryset()
permissions = self.permissions.prefetch_related('nodes', 'system_users', 'actions') permissions = self.permissions
for perm in permissions: for perm in permissions:
actions = perm.actions.all() actions = perm.actions.all()
for node in perm.nodes.all():
system_users = perm.system_users.all() system_users = perm.system_users.all()
system_users = self._structured_system_user(system_users, actions) _nodes = perm.nodes.all()
nodes[node].update(system_users) nodes.add_many(_nodes, system_users, actions)
self.tree.add_nodes(nodes.keys())
# 替换成优化过的node
nodes = {self.tree.node_util.get_node_by_key(k.key): v for k, v in nodes.items()}
return nodes return nodes
@timeit @timeit
...@@ -385,24 +409,18 @@ class AssetPermissionUtil(AssetPermissionCacheMixin): ...@@ -385,24 +409,18 @@ class AssetPermissionUtil(AssetPermissionCacheMixin):
assets = self.get_assets_direct() assets = self.get_assets_direct()
nodes = self.get_nodes_direct() nodes = self.get_nodes_direct()
# for node, system_users in nodes.items(): # for node, system_users in nodes.items():
# print(9999, node) # print(">>>>> Node<<<<<<<<<<<<: ", node.value)
# _assets = node.get_all_valid_assets() # _assets = list(node.get_all_valid_assets())
# print(".......... end .......")
# for asset in _assets: # for asset in _assets:
# print(">>asset")
# for system_user, attr_dict in system_users.items(): # for system_user, attr_dict in system_users.items():
# print(">>>system user")
# if not asset.has_protocol(system_user.protocol): # if not asset.has_protocol(system_user.protocol):
# continue # continue
# if system_user in assets[asset]: # if system_user in assets[asset]:
# actions = assets[asset][system_user]['actions'] # actions = assets[asset][system_user]['actions']
# attr_dict['actions'].update(actions) # attr_dict['actions'].update(actions)
# system_users.update({system_user: attr_dict}) # system_users.update({system_user: attr_dict})
# print("<<<system user")
# print("<<<asset")
# assets[asset].update(system_users) # assets[asset].update(system_users)
# print(">>>>>>")
#
__assets = defaultdict(set) __assets = defaultdict(set)
for asset, system_users in assets.items(): for asset, system_users in assets.items():
for system_user, attr_dict in system_users.items(): for system_user, attr_dict in system_users.items():
...@@ -507,8 +525,7 @@ def parse_asset_to_tree_node(node, asset, system_users): ...@@ -507,8 +525,7 @@ def parse_asset_to_tree_node(node, asset, system_users):
'id': asset.id, 'id': asset.id,
'hostname': asset.hostname, 'hostname': asset.hostname,
'ip': asset.ip, 'ip': asset.ip,
'protocols': [{"name": p.name, "port": p.port} 'protocols': [str(p) for p in asset.protocols.all()],
for p in asset.protocols.all()],
'platform': asset.platform, 'platform': asset.platform,
'domain': None if not asset.domain else asset.domain.id, 'domain': None if not asset.domain else asset.domain.id,
'is_active': asset.is_active, 'is_active': asset.is_active,
......
...@@ -58,8 +58,6 @@ class AssetPermissionCreateView(PermissionsMixin, CreateView): ...@@ -58,8 +58,6 @@ class AssetPermissionCreateView(PermissionsMixin, CreateView):
assets_id = assets_id.split(",") assets_id = assets_id.split(",")
assets = Asset.objects.filter(id__in=assets_id) assets = Asset.objects.filter(id__in=assets_id)
form['assets'].initial = assets form['assets'].initial = assets
form['actions'].initial = Action.objects.get(name=PERMS_ACTION_NAME_ALL)
return form return form
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
......
...@@ -277,7 +277,7 @@ function APIUpdateAttr(props) { ...@@ -277,7 +277,7 @@ function APIUpdateAttr(props) {
}).done(function(data, textStatue, jqXHR) { }).done(function(data, textStatue, jqXHR) {
if (flash_message) { if (flash_message) {
var msg = ""; var msg = "";
if (user_fail_message) { if (user_success_message) {
msg = user_success_message; msg = user_success_message;
} else { } else {
msg = default_success_message; msg = default_success_message;
...@@ -635,7 +635,7 @@ jumpserver.initServerSideDataTable = function (options) { ...@@ -635,7 +635,7 @@ jumpserver.initServerSideDataTable = function (options) {
columns: options.columns || [], columns: options.columns || [],
select: options.select || select, select: options.select || select,
language: jumpserver.language, language: jumpserver.language,
lengthMenu: [[15, 25, 50, 9999], [15, 25, 50, 'All']] lengthMenu: options.lengthMenu || [[15, 25, 50, 9999], [15, 25, 50, 'All']]
}); });
table.selected = []; table.selected = [];
table.selected_rows = []; table.selected_rows = [];
...@@ -1072,3 +1072,27 @@ function htmlEscape ( d ) { ...@@ -1072,3 +1072,27 @@ function htmlEscape ( d ) {
d.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;') : d.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;') :
d; d;
} }
function objectAttrsIsList(obj, attrs) {
attrs.forEach(function (attr) {
if (obj[attr] && !(obj[attr] instanceof Array)){
obj[attr] = [obj[attr]]
}
})
}
function objectAttrsIsDatetime(obj, attrs) {
attrs.forEach(function (attr) {
obj[attr] = new Date(obj[attr]).toISOString();
})
}
function objectAttrsIsBool(obj, attrs) {
attrs.forEach(function (attr) {
if (!obj[attr]) {
obj[attr] = false
} else if (['on', '1'].includes(obj[attr])) {
obj[attr] = true
}
})
}
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