From 7c814080b264e73e1c2cc07e1f71d8039a2cd50d Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 6 Aug 2018 17:16:52 +0800 Subject: [PATCH] =?UTF-8?q?[Update]=20=E4=BC=98=E5=8C=96=E4=B8=80=E4=BA=9B?= =?UTF-8?q?api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/node.py | 47 ++++--------- apps/assets/models/node.py | 23 +++++-- apps/assets/serializers/node.py | 19 ++++-- .../templates/assets/_asset_list_modal.html | 9 ++- apps/assets/templates/assets/asset_list.html | 67 +++++++------------ apps/jumpserver/settings.py | 8 +-- apps/orgs/mixins.py | 3 +- .../perms/asset_permission_list.html | 39 ++++++----- apps/perms/utils.py | 4 +- .../templates/users/user_granted_asset.html | 40 ++++------- 10 files changed, 116 insertions(+), 143 deletions(-) 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); }); }