diff --git a/apps/assets/api/asset.py b/apps/assets/api/asset.py index 140981263..bc7aa0409 100644 --- a/apps/assets/api/asset.py +++ b/apps/assets/api/asset.py @@ -62,7 +62,7 @@ class AssetViewSet(IDInFilterMixin, LabelFilter, BulkModelViewSet): queryset = queryset.filter(cluster__in=clusters) if node_id: node = get_object_or_404(Node, id=node_id) - queryset = queryset.filter(nodes__key__startswith=node.key) + queryset = queryset.filter(nodes__key__startswith=node.key).distinct() return queryset diff --git a/apps/assets/api/tree.py b/apps/assets/api/tree.py index 02bb555f3..a5f9fff8a 100644 --- a/apps/assets/api/tree.py +++ b/apps/assets/api/tree.py @@ -14,6 +14,7 @@ # limitations under the License. from rest_framework import generics, mixins +from rest_framework.views import APIView from rest_framework.response import Response from rest_framework_bulk import BulkModelViewSet from django.utils.translation import ugettext_lazy as _ @@ -25,7 +26,10 @@ from .. import serializers logger = get_logger(__file__) -__all__ = ['NodeViewSet', 'NodeChildrenApi'] +__all__ = [ + 'NodeViewSet', 'NodeChildrenApi', + 'NodeAddAssetsApi', 'NodeRemoveAssetsApi', +] class NodeViewSet(BulkModelViewSet): @@ -70,3 +74,26 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView): response = [{"id": node.id, "key": node.key, "value": node.value} for node in children] return Response(response, status=200) + +class NodeAddAssetsApi(generics.UpdateAPIView): + serializer_class = serializers.NodeAssetsSerializer + queryset = Node.objects.all() + permission_classes = (IsSuperUser,) + instance = None + + def perform_update(self, serializer): + assets = serializer.validated_data.get('assets') + instance = self.get_object() + instance.assets.add(*tuple(assets)) + + +class NodeRemoveAssetsApi(generics.UpdateAPIView): + serializer_class = serializers.NodeAssetsSerializer + queryset = Node.objects.all() + permission_classes = (IsSuperUser,) + instance = None + + def perform_update(self, serializer): + assets = serializer.validated_data.get('assets') + instance = self.get_object() + instance.assets.remove(*tuple(assets)) diff --git a/apps/assets/serializers.py b/apps/assets/serializers.py index 4eb05b187..b7cc0ee9a 100644 --- a/apps/assets/serializers.py +++ b/apps/assets/serializers.py @@ -335,3 +335,11 @@ class NodeSerializer(serializers.ModelSerializer): field = fields["key"] field.required = False return fields + + +class NodeAssetsSerializer(serializers.ModelSerializer): + assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) + + class Meta: + model = Node + fields = ['assets'] diff --git a/apps/assets/templates/assets/_asset_list_modal.html b/apps/assets/templates/assets/_asset_list_modal.html index 3b9f8d136..b68ab0378 100644 --- a/apps/assets/templates/assets/_asset_list_modal.html +++ b/apps/assets/templates/assets/_asset_list_modal.html @@ -109,7 +109,20 @@ $(document).ready(function(){ return } + var data = { + 'assets': id_list + }; + var success = function () { + modal_table.ajax.reload() + }; + + APIUpdateAttr({ + 'url': '/api/assets/v1/nodes/' + current_node.id + '/assets/add/', + 'method': 'PUT', + 'body': JSON.stringify(data), + 'success': success + }) }) diff --git a/apps/assets/templates/assets/tree.html b/apps/assets/templates/assets/tree.html index dcbb6bec9..b6c33965a 100644 --- a/apps/assets/templates/assets/tree.html +++ b/apps/assets/templates/assets/tree.html @@ -88,6 +88,7 @@ @@ -169,8 +170,6 @@ function initTable() { } - - function addTreeNode() { hideRMenu(); var parentNode = zTree.getSelectedNodes()[0]; @@ -281,17 +280,26 @@ function onRename(event, treeId, treeNode, isCancel){ function onSelected(event, treeNode) { var url = asset_table.ajax.url(); url = setUrlParam(url, "node_id", treeNode.id); + setCookie('node_selected', treeNode.id); asset_table.ajax.url(url); asset_table.ajax.reload(); } function selectQueryNode() { - var node_id = $.getUrlParam("node"); - if (node_id !== null) { - var node = zTree.getNodesByParam("id", node_id, null); - if (node){ - zTree.selectNode(node[0]); - } + 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]); } } @@ -479,6 +487,31 @@ $(document).ready(function(){ var url = "{% url 'assets:asset-bulk-update' %}?assets_id=" + id_list_string; location.href = url } + + function doRemove() { + var current_node; + var nodes = zTree.getSelectedNodes(); + if (nodes && nodes.length === 1) { + current_node = nodes[0] + } else { + return + } + + var data = { + 'assets': id_list + }; + + var success = function () { + asset_table.ajax.reload() + }; + + APIUpdateAttr({ + 'url': '/api/assets/v1/nodes/' + current_node.id + '/assets/remove/', + 'method': 'PUT', + 'body': JSON.stringify(data), + 'success': success + }) + } switch(action) { case 'deactive': doDeactive(); @@ -492,6 +525,9 @@ $(document).ready(function(){ case 'active': doActive(); break; + case 'remove': + doRemove(); + break; default: break; } diff --git a/apps/assets/urls/api_urls.py b/apps/assets/urls/api_urls.py index 43e8aa711..0e14cda21 100644 --- a/apps/assets/urls/api_urls.py +++ b/apps/assets/urls/api_urls.py @@ -44,6 +44,8 @@ urlpatterns = [ url(r'^v1/system-user/(?P[0-9a-zA-Z\-]{36})/connective/$', api.SystemUserTestConnectiveApi.as_view(), name='system-user-connective'), url(r'^v1/nodes/(?P[0-9a-zA-Z\-]{36})/children/$', api.NodeChildrenApi.as_view(), name='node-children'), + url(r'^v1/nodes/(?P[0-9a-zA-Z\-]{36})/assets/add/$', api.NodeAddAssetsApi.as_view(), name='node-add-assets'), + url(r'^v1/nodes/(?P[0-9a-zA-Z\-]{36})/assets/remove/$', api.NodeRemoveAssetsApi.as_view(), name='node-remove-assets'), ] urlpatterns += router.urls diff --git a/apps/perms/templates/perms/asset_permission_list.html b/apps/perms/templates/perms/asset_permission_list.html index 257dcaf20..9f8e26a43 100644 --- a/apps/perms/templates/perms/asset_permission_list.html +++ b/apps/perms/templates/perms/asset_permission_list.html @@ -135,17 +135,26 @@ function initTable() { function onSelected(event, treeNode) { var url = table.ajax.url(); url = setUrlParam(url, "node_id", treeNode.id); + setCookie('node_selected', treeNode.id); table.ajax.url(url); table.ajax.reload(); } function selectQueryNode() { - var node_id = $.getUrlParam("node"); - if (node_id !== null) { - var node = zTree.getNodesByParam("id", node_id, null); - if (node) { - zTree.selectNode(node[0]); - } + 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]); } } diff --git a/apps/static/js/jumpserver.js b/apps/static/js/jumpserver.js index eee1720c0..178836058 100644 --- a/apps/static/js/jumpserver.js +++ b/apps/static/js/jumpserver.js @@ -562,7 +562,6 @@ function setUrlParam(url, name, value) { url = urlArray[0] + "?"; var newParam = []; $.each(oriParamMap, function (index, value) { - console.log(index, value); newParam.push(index + "=" + value); }); url += newParam.join("&")