diff --git a/apps/assets/api/node.py b/apps/assets/api/node.py
index 471a096b6..515f1f13c 100644
--- a/apps/assets/api/node.py
+++ b/apps/assets/api/node.py
@@ -20,6 +20,7 @@ from rest_framework.response import Response
from rest_framework_bulk import BulkModelViewSet
from django.utils.translation import ugettext_lazy as _
from django.shortcuts import get_object_or_404
+from django.db.models import Count
from common.utils import get_logger, get_object_or_none
from ..hands import IsOrgAdmin
@@ -42,40 +43,16 @@ class NodeViewSet(viewsets.ModelViewSet):
permission_classes = (IsOrgAdmin,)
serializer_class = serializers.NodeSerializer
+ def get_queryset(self):
+ queryset = super().get_queryset().annotate(Count('assets'))
+ return queryset
+
def perform_create(self, serializer):
child_key = Node.root().get_next_child_key()
serializer.validated_data["key"] = child_key
serializer.save()
-# class NodeWithAssetsApi(generics.ListAPIView):
-# permission_classes = (IsOrgAdmin,)
-# serializers = serializers.NodeSerializer
-#
-# def get_node(self):
-# pk = self.kwargs.get('pk') or self.request.query_params.get('node')
-# if not pk:
-# node = Node.root()
-# else:
-# node = get_object_or_404(Node, pk)
-# return node
-#
-# def get_queryset(self):
-# queryset = []
-# node = self.get_node()
-# children = node.get_children()
-# assets = node.get_assets()
-# queryset.extend(list(children))
-#
-# for asset in assets:
-# node = Node()
-# node.id = asset.id
-# node.parent = node.id
-# node.value = asset.hostname
-# queryset.append(node)
-# return queryset
-
-
class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView):
queryset = Node.objects.all()
permission_classes = (IsOrgAdmin,)
@@ -124,22 +101,26 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView):
query_all = self.request.query_params.get("all")
query_assets = self.request.query_params.get('assets')
node = self.get_object()
+
if node is None:
node = Node.root()
+ node.assets__count = node.get_all_assets().count()
queryset.append(node)
- if query_all:
- children = node.get_all_children()
- else:
- children = node.get_children()
+ if query_all:
+ children = node.get_all_children().annotate(Count("assets"))
+ else:
+ children = node.get_children().annotate(Count("assets"))
queryset.extend(list(children))
+
if query_assets:
assets = node.get_assets()
for asset in assets:
node_fake = Node()
+ node_fake.assets__count = 0
node_fake.id = asset.id
node_fake.is_node = False
- node_fake.parent_id = node.id
+ node_fake.key = node.key + ':0'
node_fake.value = asset.hostname
queryset.append(node_fake)
queryset = sorted(queryset, key=lambda x: x.is_node, reverse=True)
diff --git a/apps/assets/models/node.py b/apps/assets/models/node.py
index 27a8e4519..8d006a40e 100644
--- a/apps/assets/models/node.py
+++ b/apps/assets/models/node.py
@@ -97,12 +97,10 @@ class Node(OrgModelMixin):
def get_assets(self):
from .asset import Asset
- if self.is_root():
- assets = Asset.objects.filter(
- Q(nodes__id=self.id) | Q(nodes__isnull=True)
- )
+ if self.is_default_node():
+ assets = Asset.objects.filter(nodes__isnull=True)
else:
- assets = self.assets.all()
+ assets = Asset.objects.filter(nodes__id=self.id)
return assets
def get_valid_assets(self):
@@ -132,13 +130,17 @@ class Node(OrgModelMixin):
else:
return False
+ @property
+ def parent_key(self):
+ parent_key = ":".join(self.key.split(":")[:-1])
+ return parent_key
+
@property
def parent(self):
if self.is_root():
return self
- parent_key = ":".join(self.key.split(":")[:-1])
try:
- parent = self.__class__.objects.get(key=parent_key)
+ parent = self.__class__.objects.get(key=self.parent_key)
return parent
except Node.DoesNotExist:
return self.__class__.root()
@@ -197,5 +199,12 @@ class Node(OrgModelMixin):
else:
return cls.create_root_node()
+ @classmethod
+ def generate_fake(cls, count=100):
+ import random
+ for i in range(count):
+ node = random.choice(cls.objects.all())
+ node.create_child('Node {}'.format(i))
+
diff --git a/apps/assets/serializers/node.py b/apps/assets/serializers/node.py
index 3eca3276f..4f7031065 100644
--- a/apps/assets/serializers/node.py
+++ b/apps/assets/serializers/node.py
@@ -43,14 +43,15 @@ class NodeGrantedSerializer(BulkSerializerMixin, serializers.ModelSerializer):
class NodeSerializer(serializers.ModelSerializer):
- parent = serializers.SerializerMethodField()
assets_amount = serializers.SerializerMethodField()
+ tree_id = serializers.SerializerMethodField()
+ tree_parent = serializers.SerializerMethodField()
class Meta:
model = Node
fields = [
- 'id', 'key', 'value', 'parent', 'assets_amount',
- 'is_node', 'org_id',
+ 'id', 'key', 'value', 'assets_amount',
+ 'is_node', 'org_id', 'tree_id', 'tree_parent',
]
list_serializer_class = BulkListSerializer
@@ -66,12 +67,16 @@ class NodeSerializer(serializers.ModelSerializer):
return data
@staticmethod
- def get_parent(obj):
- return obj.parent.id if obj.is_node else obj.parent_id
+ def get_assets_amount(obj):
+ return obj.assets__count if hasattr(obj, 'assets__count') else 0
@staticmethod
- def get_assets_amount(obj):
- return obj.get_all_assets().count() if obj.is_node else 0
+ def get_tree_id(obj):
+ return obj.key
+
+ @staticmethod
+ def get_tree_parent(obj):
+ return obj.parent_key
def get_fields(self):
fields = super().get_fields()
diff --git a/apps/assets/templates/assets/_asset_list_modal.html b/apps/assets/templates/assets/_asset_list_modal.html
index faf569137..ea8d59e49 100644
--- a/apps/assets/templates/assets/_asset_list_modal.html
+++ b/apps/assets/templates/assets/_asset_list_modal.html
@@ -71,7 +71,7 @@ function initTable2() {
function onSelected2(event, treeNode) {
var url = asset_table2.ajax.url();
- url = setUrlParam(url, "node_id", treeNode.id);
+ url = setUrlParam(url, "node_id", treeNode.node_id);
setCookie('node_selected', treeNode.id);
asset_table2.ajax.url(url);
asset_table2.ajax.reload();
@@ -97,17 +97,20 @@ function initTree2() {
var zNodes = [];
$.get("{% url 'api-assets:node-list' %}", function(data, status){
$.each(data, function (index, value) {
- value["pId"] = value["parent"];
+ value["node_id"] = value["id"];
+ value["id"] = value["tree_id"];
+ value["pId"] = value["tree_parent"];
{#value["open"] = true;#}
if (value["key"] === "0") {
value["open"] = true;
}
value["name"] = value["value"] + ' (' + value['assets_amount'] + ')';
- value['value'] = value['value'];
});
zNodes = data;
$.fn.zTree.init($("#assetTree2"), setting, zNodes);
zTree2 = $.fn.zTree.getZTreeObj("assetTree2");
+ var root = zTree2.getNodes()[0];
+ zTree2.expandNode(root);
});
}
diff --git a/apps/assets/templates/assets/asset_list.html b/apps/assets/templates/assets/asset_list.html
index 270cc4c4f..4986bb959 100644
--- a/apps/assets/templates/assets/asset_list.html
+++ b/apps/assets/templates/assets/asset_list.html
@@ -166,16 +166,6 @@ function initTable() {
}
}},
- {#{targets: 5, createdCell: function (td, cellData) {#}
- {# if (cellData === 'Unknown'){#}
- {# $(td).html('')#}
- {# } else if (!cellData) {#}
- {# $(td).html('')#}
- {# } else {#}
- {# $(td).html('')#}
- {# }#}
- {# }},#}
-
{targets: 5, createdCell: function (td, cellData, rowData) {
var update_btn = '{% trans "Update" %}'.replace("{{ DEFAULT_PK }}", cellData);
var del_btn = '{% trans "Delete" %}'.replace('{{ DEFAULT_PK }}', cellData);
@@ -183,13 +173,6 @@ function initTable() {
}}
],
ajax_url: '{% url "api-assets:asset-list" %}',
-
- {#columns: [#}
- {# {data: "id"}, {data: "hostname" }, {data: "ip" },#}
- {# {data: "cpu_cores"}, {data: "is_active", orderable: false },#}
- {# {data: "is_connective", orderable: false}, {data: "id", orderable: false }#}
- {#],#}
-
columns: [
{data: "id"}, {data: "hostname" }, {data: "ip" },
{data: "cpu_cores"}, {data: "is_active", orderable: false },
@@ -207,17 +190,17 @@ function addTreeNode() {
if (!parentNode){
return
}
- var url = "{% url 'api-assets:node-children' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", parentNode.id );
+ var url = "{% url 'api-assets:node-children' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", parentNode.node_id );
$.post(url, {}, function (data, status){
if (status === "success") {
var newNode = {
name: data["value"],
id: data["id"],
- pId: parentNode.id
+ pId: parentNode.node_id
};
newNode.checked = zTree.getSelectedNodes()[0].checked;
zTree.addNodes(parentNode, 0, newNode);
- var node = zTree.getNodeByParam('id', newNode.id, parentNode)
+ var node = zTree.getNodeByParam('id', newNode.node_id, parentNode);
zTree.editName(node);
} else {
alert("{% trans 'Create node failed' %}")
@@ -236,7 +219,7 @@ function removeTreeNode() {
} else if (current_node.assets_amount !== 0) {
toastr.error("{% trans 'Have assets, cancel' %}");
} else {
- var url = "{% url 'api-assets:node-detail' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node.id );
+ var url = "{% url 'api-assets:node-detail' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node.node_id );
$.ajax({
url: url,
method: "DELETE",
@@ -296,7 +279,7 @@ function onBodyMouseDown(event){
function onRename(event, treeId, treeNode, isCancel){
- var url = "{% url 'api-assets:node-detail' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", treeNode.id);
+ var url = "{% url 'api-assets:node-detail' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", treeNode.node_id);
var data = {"value": treeNode.name};
if (isCancel){
return
@@ -310,9 +293,9 @@ function onRename(event, treeId, treeNode, isCancel){
function onSelected(event, treeNode) {
var url = asset_table.ajax.url();
- url = setUrlParam(url, "node_id", treeNode.id);
+ url = setUrlParam(url, "node_id", treeNode.node_id);
url = setUrlParam(url, "show_current_asset", getCookie('show_current_asset'));
- setCookie('node_selected', treeNode.id);
+ setCookie('node_selected', treeNode.node_id);
asset_table.ajax.url(url);
asset_table.ajax.reload();
}
@@ -329,7 +312,7 @@ function selectQueryNode() {
node_id = cookie_node_id;
}
- node = zTree.getNodesByParam("id", node_id, null);
+ node = zTree.getNodesByParam("node_id", node_id, null);
if (node){
zTree.selectNode(node[0]);
}
@@ -346,11 +329,7 @@ function beforeDrop(treeId, treeNodes, targetNode, moveType) {
});
var msg = "你想移动节点: `" + treeNodesNames.join(",") + "` 到 `" + targetNode.value + "` 下吗?";
- if (confirm(msg)){
- return true
- } else {
- return false
- }
+ return confirm(msg);
}
function onDrag(event, treeId, treeNodes) {
@@ -359,10 +338,10 @@ function onDrag(event, treeId, treeNodes) {
function onDrop(event, treeId, treeNodes, targetNode, moveType) {
var treeNodesIds = [];
$.each(treeNodes, function (index, value) {
- treeNodesIds.push(value.id);
+ treeNodesIds.push(value.node_id);
});
- var the_url = "{% url 'api-assets:node-add-children' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", targetNode.id);
+ var the_url = "{% url 'api-assets:node-add-children' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", targetNode.node_id);
var body = {nodes: treeNodesIds};
APIUpdateAttr({
url: the_url,
@@ -406,8 +385,10 @@ function initTree() {
var zNodes = [];
$.get("{% url 'api-assets:node-list' %}", function(data, status){
$.each(data, function (index, value) {
- if (value["parent"] !== value["id"]){
- value["pId"] = value["parent"];
+ value["node_id"] = value["id"];
+ value["id"] = value["tree_id"];
+ if (value["tree_id"] !== value["tree_parent"]){
+ value["pId"] = value["tree_parent"];
} else {
value["isParent"] = true;
}
@@ -470,7 +451,7 @@ $(document).ready(function(){
$.ajax({
url: "{% url "assets:asset-export" %}",
method: 'POST',
- data: JSON.stringify({assets_id: assets, node_id: current_node.id}),
+ data: JSON.stringify({assets_id: assets, node_id: current_node.node_id}),
dataType: "json",
success: function (data, textStatus) {
window.open(data.redirect)
@@ -487,8 +468,8 @@ $(document).ready(function(){
var current_node;
if (nodes && nodes.length ===1 ){
current_node = nodes[0];
- action = setUrlParam(action, 'node_id', current_node.id);
- {#action += "?node_id=" + current_node.id;#}
+ action = setUrlParam(action, 'node_id', current_node.node_id);
+ {#action += "?node_id=" + current_node.node_id;#}
$form.attr("action", action)
}
$form.find('.help-block').remove();
@@ -514,7 +495,7 @@ $(document).ready(function(){
var current_node;
if (nodes && nodes.length ===1 ){
current_node = nodes[0];
- url += "?node_id=" + current_node.id;
+ url += "?node_id=" + current_node.node_id;
}
window.open(url, '_self');
})
@@ -528,7 +509,7 @@ $(document).ready(function(){
return null;
}
- var the_url = url.replace("{{ DEFAULT_PK }}", current_node.id);
+ var the_url = url.replace("{{ DEFAULT_PK }}", current_node.node_id);
function success(data) {
rMenu.css({"visibility" : "hidden"});
var task_id = data.task;
@@ -553,7 +534,7 @@ $(document).ready(function(){
return null;
}
- var the_url = url.replace("{{ DEFAULT_PK }}", current_node.id);
+ var the_url = url.replace("{{ DEFAULT_PK }}", current_node.node_id);
function success(data) {
rMenu.css({"visibility" : "hidden"});
var task_id = data.task;
@@ -690,7 +671,7 @@ $(document).ready(function(){
};
APIUpdateAttr({
- 'url': '/api/assets/v1/nodes/' + current_node.id + '/assets/remove/',
+ 'url': '/api/assets/v1/nodes/' + current_node.node_id + '/assets/remove/',
'method': 'PUT',
'body': JSON.stringify(data),
'success': success
@@ -735,9 +716,9 @@ $(document).ready(function(){
var url = '';
if (update_node_action === "move") {
- url = "{% url 'api-assets:node-replace-assets' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node.id);
+ url = "{% url 'api-assets:node-replace-assets' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node.node_id);
} else {
- url = "{% url 'api-assets:node-add-assets' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node.id);
+ url = "{% url 'api-assets:node-add-assets' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node.node_id);
}
APIUpdateAttr({
diff --git a/apps/jumpserver/settings.py b/apps/jumpserver/settings.py
index 49b2f7870..b1c4fb3bf 100644
--- a/apps/jumpserver/settings.py
+++ b/apps/jumpserver/settings.py
@@ -261,10 +261,10 @@ LOGGING = {
'handlers': ['console', 'file'],
'level': "INFO",
},
- # 'django.db': {
- # 'handlers': ['console', 'file'],
- # 'level': 'DEBUG'
- # }
+ 'django.db': {
+ 'handlers': ['console', 'file'],
+ 'level': 'DEBUG'
+ }
}
}
diff --git a/apps/orgs/mixins.py b/apps/orgs/mixins.py
index 4a47f2ee3..7557600cb 100644
--- a/apps/orgs/mixins.py
+++ b/apps/orgs/mixins.py
@@ -29,8 +29,7 @@ class OrgManager(models.Manager):
kwargs = {}
if not hasattr(tl, 'times'):
tl.times = 0
- print("[{}]>>>>>>>>>> Get query set".format(tl.times))
- print(current_org)
+ # logger.debug("[{}]>>>>>>>>>> Get query set".format(tl.times))
if not current_org:
kwargs['id'] = None
elif current_org.is_real():
diff --git a/apps/perms/templates/perms/asset_permission_list.html b/apps/perms/templates/perms/asset_permission_list.html
index 36504ef59..31ccce112 100644
--- a/apps/perms/templates/perms/asset_permission_list.html
+++ b/apps/perms/templates/perms/asset_permission_list.html
@@ -80,12 +80,12 @@ function onSelected(event, treeNode) {
var url = table.ajax.url();
if (treeNode.is_node) {
url = setUrlParam(url, 'asset', "");
- url = setUrlParam(url, 'node', treeNode.id)
+ url = setUrlParam(url, 'node', treeNode.node_id)
} else {
url = setUrlParam(url, 'node', "");
- url = setUrlParam(url, 'asset', treeNode.id)
+ url = setUrlParam(url, 'asset', treeNode.node_id)
}
- setCookie('node_selected', treeNode.id);
+ setCookie('node_selected', treeNode.node_id);
table.ajax.url(url);
table.ajax.reload();
}
@@ -111,10 +111,19 @@ function selectQueryNode() {
function filter(treeId, parentNode, childNodes) {
$.each(childNodes, function (index, value) {
- value["pId"] = value["parent"];
- value["name"] = value["value"];
- value["isParent"] = value["is_node"];
+ value["node_id"] = value["id"];
+ value["id"] = value["tree_id"];
+ if (value["tree_id"] !== value["tree_parent"]) {
+ value["pId"] = value["tree_parent"];
+ } else {
+ value["isParent"] = true;
+ }
+ value['name'] = value['value'];
value["iconSkin"] = value["is_node"] ? null : 'file';
+
+ {#value["pId"] = value["parent"];#}
+ {#value["name"] = value["value"];#}
+ value["isParent"] = value["is_node"];
});
return childNodes;
}
@@ -227,7 +236,7 @@ function initTree() {
async: {
enable: true,
url: "{% url 'api-assets:node-children-2' %}?assets=1&all=",
- autoParam:["id", "name=n", "level=lv"],
+ autoParam:["node_id=id", "name=n", "level=lv"],
dataFilter: filter,
type: 'get'
},
@@ -238,15 +247,15 @@ function initTree() {
};
var zNodes = [];
- $.get("{% url 'api-assets:node-children-2' %}?assets=1&all=", function(data, status){
+ $.get("{% url 'api-assets:node-children-2' %}?assets=1", function(data, status){
$.each(data, function (index, value) {
- if (value["parent"] !== value["id"]){
- value["pId"] = value["parent"];
- } else {
- value["isParent"] = true;
+ value["node_id"] = value["id"];
+ value["id"] = value["tree_id"];
+ if (value["tree_id"] !== value["tree_parent"]) {
+ value["pId"] = value["tree_parent"];
}
- value["name"] = value["value"];
value["isParent"] = value["is_node"];
+ value['name'] = value['value'];
value["iconSkin"] = value["is_node"] ? null : 'file';
});
zNodes = data;
@@ -291,9 +300,9 @@ $(document).ready(function(){
var _assets = [];
$.each(nodes, function (id, node) {
if (node.is_node) {
- _nodes.push(node.id)
+ _nodes.push(node.node_id)
} else {
- _assets.push(node.id)
+ _assets.push(node.node_id)
}
});
url += "?assets=" + _assets.join(",") + "&nodes=" + _nodes.join(",");
diff --git a/apps/perms/utils.py b/apps/perms/utils.py
index a76953aac..326a8cfcf 100644
--- a/apps/perms/utils.py
+++ b/apps/perms/utils.py
@@ -13,7 +13,7 @@ logger = get_logger(__file__)
class Tree:
def __init__(self):
- self.__all_nodes = list(Node.objects.all().prefetch_related('assets'))
+ self.__all_nodes = Node.objects.all().prefetch_related('assets')
self.__node_asset_map = defaultdict(set)
self.nodes = defaultdict(dict)
self.root = Node.root()
@@ -21,7 +21,7 @@ class Tree:
def init_node_asset_map(self):
for node in self.__all_nodes:
- assets = node.get_assets().values_list('id', flat=True)
+ assets = [a.id for a in node.assets.all()]
for asset in assets:
self.__node_asset_map[str(asset)].add(node)
diff --git a/apps/users/templates/users/user_granted_asset.html b/apps/users/templates/users/user_granted_asset.html
index 299c33e07..5b30c71b6 100644
--- a/apps/users/templates/users/user_granted_asset.html
+++ b/apps/users/templates/users/user_granted_asset.html
@@ -107,31 +107,14 @@ function initTable() {
function onSelected(event, treeNode) {
url = '{% url "api-perms:user-node-assets" pk=object.id node_id=DEFAULT_PK %}';
- url = url.replace("{{ DEFAULT_PK }}", treeNode.id);
- setCookie('node_selected', treeNode.id);
+ console.log(">>>>>>>>>>>>>>>>>>>>>>>", treeNode.node_id, treeNode.id, treeNode);
+ url = url.replace("{{ DEFAULT_PK }}", treeNode.node_id);
+ setCookie('node_selected', treeNode.node_id);
asset_table = initTable();
asset_table.ajax.url(url);
asset_table.ajax.reload();
}
-function selectQueryNode() {
- 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("id", node_id, null);
- if (node){
- zTree.selectNode(node[0]);
- }
-}
-
function initTree() {
var setting = {
view: {
@@ -149,19 +132,22 @@ function initTree() {
};
var zNodes = [];
- $.get("{% url 'api-perms:user-nodes' pk=object.id %}", function(data, status){
+ $.get("{% url 'api-perms:user-nodes' pk=object.id %}", function(data, status) {
$.each(data, function (index, value) {
- value["pId"] = value["parent"];
- if (value["key"] === "0") {
- value["open"] = true;
+ value["node_id"] = value["id"];
+ value["id"] = value["tree_id"];
+ if (value["tree_id"] !== value["tree_parent"]) {
+ value["pId"] = value["tree_parent"];
}
- value["name"] = value["value"]
+ value["isParent"] = value["is_node"];
+ value['name'] = value['value'];
+ value["iconSkin"] = value["is_node"] ? null : 'file';
});
zNodes = data;
$.fn.zTree.init($("#assetTree"), setting, zNodes);
zTree = $.fn.zTree.getZTreeObj("assetTree");
- rMenu = $("#rMenu");
- selectQueryNode();
+ var root = zTree.getNodes()[0];
+ zTree.expandNode(root);
});
}