mirror of https://github.com/jumpserver/jumpserver
Merge branch 'dev' of github.com:jumpserver/jumpserver into dev
commit
6cb9ae69b2
|
@ -34,7 +34,6 @@ var actions = {
|
|||
}};
|
||||
$(document).ready(function () {
|
||||
initTree();
|
||||
initTable();
|
||||
}).on('click', '.labels li', function () {
|
||||
var val = $(this).text();
|
||||
$("#user_assets_table_filter input").val(val);
|
||||
|
|
|
@ -51,15 +51,15 @@ urlpatterns = [
|
|||
|
||||
path('system-users/<uuid:pk>/auth-info/',
|
||||
api.SystemUserAuthInfoApi.as_view(), name='system-user-auth-info'),
|
||||
path('system-users/<uuid:pk>/asset/<uuid:aid>/auth-info/',
|
||||
path('system-users/<uuid:pk>/assets/<uuid:aid>/auth-info/',
|
||||
api.SystemUserAssetAuthInfoApi.as_view(), name='system-user-asset-auth-info'),
|
||||
path('system-users/<uuid:pk>/assets/',
|
||||
api.SystemUserAssetsListView.as_view(), name='system-user-assets'),
|
||||
path('system-users/<uuid:pk>/push/',
|
||||
api.SystemUserPushApi.as_view(), name='system-user-push'),
|
||||
path('system-users/<uuid:pk>/asset/<uuid:aid>/push/',
|
||||
path('system-users/<uuid:pk>/assets/<uuid:aid>/push/',
|
||||
api.SystemUserPushToAssetApi.as_view(), name='system-user-push-to-asset'),
|
||||
path('system-users/<uuid:pk>/asset/<uuid:aid>/test/',
|
||||
path('system-users/<uuid:pk>/assets/<uuid:aid>/test/',
|
||||
api.SystemUserTestAssetConnectivityApi.as_view(), name='system-user-test-to-asset'),
|
||||
path('system-users/<uuid:pk>/connective/',
|
||||
api.SystemUserTestConnectiveApi.as_view(), name='system-user-connective'),
|
||||
|
|
|
@ -66,27 +66,23 @@ class TreeService(Tree):
|
|||
super().__init__(*args, **kwargs)
|
||||
self.nodes_assets_map = defaultdict(set)
|
||||
self.all_nodes_assets_map = {}
|
||||
self.mutex = threading.Lock()
|
||||
|
||||
@classmethod
|
||||
@timeit
|
||||
def new(cls):
|
||||
from .models import Node
|
||||
from orgs.utils import get_current_org, set_to_root_org
|
||||
from orgs.utils import tmp_to_root_org
|
||||
|
||||
origin_org = get_current_org()
|
||||
set_to_root_org()
|
||||
all_nodes = Node.objects.all()
|
||||
origin_org.change_to()
|
||||
|
||||
tree = cls()
|
||||
tree.create_node(tag='', identifier='')
|
||||
for node in all_nodes:
|
||||
tree.create_node(
|
||||
tag=node.value, identifier=node.key,
|
||||
parent=node.parent_key,
|
||||
)
|
||||
tree.init_assets_async()
|
||||
with tmp_to_root_org():
|
||||
all_nodes = Node.objects.all()
|
||||
tree = cls()
|
||||
tree.create_node(tag='', identifier='')
|
||||
for node in all_nodes:
|
||||
tree.create_node(
|
||||
tag=node.value, identifier=node.key,
|
||||
parent=node.parent_key,
|
||||
)
|
||||
tree.init_assets()
|
||||
return tree
|
||||
|
||||
def init_assets_async(self):
|
||||
|
@ -95,17 +91,16 @@ class TreeService(Tree):
|
|||
|
||||
def init_assets(self):
|
||||
from orgs.utils import get_current_org, set_to_root_org
|
||||
with self.mutex:
|
||||
origin_org = get_current_org()
|
||||
set_to_root_org()
|
||||
queryset = Asset.objects.all().valid().values_list('id', 'nodes__key')
|
||||
origin_org = get_current_org()
|
||||
set_to_root_org()
|
||||
queryset = Asset.objects.all().valid().values_list('id', 'nodes__key')
|
||||
|
||||
if origin_org:
|
||||
origin_org.change_to()
|
||||
for asset_id, key in queryset:
|
||||
if not key:
|
||||
continue
|
||||
self.nodes_assets_map[key].add(asset_id)
|
||||
if origin_org:
|
||||
origin_org.change_to()
|
||||
for asset_id, key in queryset:
|
||||
if not key:
|
||||
continue
|
||||
self.nodes_assets_map[key].add(asset_id)
|
||||
|
||||
def all_children(self, nid, with_self=True, deep=False):
|
||||
children_ids = self.expand_tree(nid)
|
||||
|
@ -146,13 +141,11 @@ class TreeService(Tree):
|
|||
return parent
|
||||
|
||||
def assets(self, nid):
|
||||
with self.mutex:
|
||||
assets = self.nodes_assets_map[nid]
|
||||
return assets
|
||||
assets = self.nodes_assets_map[nid]
|
||||
return assets
|
||||
|
||||
def set_assets(self, nid, assets):
|
||||
with self.mutex:
|
||||
self.nodes_assets_map[nid] = assets
|
||||
self.nodes_assets_map[nid] = assets
|
||||
|
||||
def all_assets(self, nid):
|
||||
assets = self.all_nodes_assets_map.get(nid)
|
||||
|
@ -186,12 +179,17 @@ class TreeService(Tree):
|
|||
self.safe_add_ancestors(ancestors)
|
||||
parent = self.get_node(parent_id)
|
||||
|
||||
print("Add node: {} {}".format(node.identifier, parent.identifier))
|
||||
# 如果当前节点已再树中,则移动当前节点到父节点中
|
||||
# 这个是由于 当前节点放到了二级节点中
|
||||
if self.contains(node.identifier):
|
||||
self.move_node(node.identifier, parent.identifier)
|
||||
else:
|
||||
self.add_node(node, parent)
|
||||
|
||||
|
||||
#
|
||||
# def __getstate__(self):
|
||||
# self.mutex = None
|
||||
# return self.__dict__
|
||||
#
|
||||
# def __setstate__(self, state):
|
||||
# self.__dict__ = state
|
||||
# self.mutex = threading.Lock()
|
||||
|
|
|
@ -1,17 +1,23 @@
|
|||
# ~*~ coding: utf-8 ~*~
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf.urls import url
|
||||
from django.urls.conf import re_path
|
||||
from rest_framework.routers import DefaultRouter
|
||||
|
||||
from common import api as capi
|
||||
from .. import api
|
||||
|
||||
|
||||
app_name = "audits"
|
||||
|
||||
router = DefaultRouter()
|
||||
router.register(r'ftp-log', api.FTPLogViewSet, 'ftp-log')
|
||||
router.register(r'ftp-logs', api.FTPLogViewSet, 'ftp-log')
|
||||
|
||||
urlpatterns = [
|
||||
]
|
||||
|
||||
old_version_urlpatterns = [
|
||||
re_path('(?P<resource>ftp-log)/.*', capi.redirect_plural_name_api)
|
||||
]
|
||||
|
||||
urlpatterns += router.urls
|
||||
|
|
|
@ -12,11 +12,14 @@ from rest_framework import generics, serializers
|
|||
|
||||
from .http import HttpResponseTemporaryRedirect
|
||||
from .const import KEY_CACHE_RESOURCES_ID
|
||||
from .utils import get_logger
|
||||
|
||||
__all__ = [
|
||||
'LogTailApi', 'ResourcesIDCacheApi',
|
||||
]
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
||||
|
||||
class OutputSerializer(serializers.Serializer):
|
||||
output = serializers.CharField()
|
||||
|
@ -93,6 +96,7 @@ class ResourcesIDCacheApi(APIView):
|
|||
@csrf_exempt
|
||||
def redirect_plural_name_api(request, *args, **kwargs):
|
||||
resource = kwargs.get("resource", "")
|
||||
full_path = request.get_full_path()
|
||||
full_path = full_path.replace(resource, resource+"s", 1)
|
||||
org_full_path = request.get_full_path()
|
||||
full_path = org_full_path.replace(resource, resource+"s", 1)
|
||||
logger.debug("Redirect {} => {}".format(org_full_path, full_path))
|
||||
return HttpResponseTemporaryRedirect(full_path)
|
||||
|
|
|
@ -10,9 +10,10 @@ from . import user_permission as uapi
|
|||
__all__ = [
|
||||
'UserGroupGrantedAssetsApi', 'UserGroupGrantedNodesApi',
|
||||
'UserGroupGrantedNodeAssetsApi', 'UserGroupGrantedNodeChildrenApi',
|
||||
'UserGroupGrantedNodeChildrenAsTreeApi', 'UserGroupGrantedNodesWithAssetsAsTreeApi',
|
||||
'UserGroupGrantedNodeChildrenAsTreeApi',
|
||||
'UserGroupGrantedNodeChildrenWithAssetsAsTreeApi',
|
||||
'UserGroupGrantedAssetSystemUsersApi',
|
||||
# 'UserGroupGrantedNodesWithAssetsAsTreeApi',
|
||||
# 'UserGroupGrantedNodeChildrenWithAssetsAsTreeApi',
|
||||
]
|
||||
|
||||
|
||||
|
@ -45,7 +46,7 @@ class UserGroupGrantedNodeChildrenAsTreeApi(UserGroupPermissionMixin, uapi.UserG
|
|||
pass
|
||||
|
||||
|
||||
class UserGroupGrantedNodesWithAssetsAsTreeApi(UserGroupPermissionMixin, uapi.UserGrantedNodesWithAssetsAsTreeApi):
|
||||
class UserGroupGrantedNodeChildrenWithAssetsAsTreeApi(UserGroupPermissionMixin, uapi.UserGrantedNodeChildrenWithAssetsAsTreeApi):
|
||||
pass
|
||||
|
||||
|
||||
|
|
|
@ -23,12 +23,19 @@ from ..models import Action
|
|||
logger = get_logger(__name__)
|
||||
|
||||
__all__ = [
|
||||
'UserGrantedAssetsApi', 'UserGrantedNodesApi',
|
||||
'UserGrantedAssetsApi',
|
||||
'UserGrantedAssetsAsTreeApi',
|
||||
'UserGrantedNodeAssetsApi',
|
||||
'UserGrantedNodesApi',
|
||||
'UserGrantedNodesAsTreeApi',
|
||||
'UserGrantedNodesWithAssetsAsTreeApi',
|
||||
'UserGrantedNodeChildrenApi',
|
||||
'UserGrantedNodeChildrenAsTreeApi',
|
||||
'UserGrantedNodeChildrenWithAssetsAsTreeApi',
|
||||
'RefreshAssetPermissionCacheApi',
|
||||
'UserGrantedAssetSystemUsersApi',
|
||||
'ValidateUserAssetPermissionApi',
|
||||
'UserGrantedNodesWithAssetsAsTreeApi', 'GetUserAssetPermissionActionsApi',
|
||||
'RefreshAssetPermissionCacheApi', 'UserGrantedAssetSystemUsersApi',
|
||||
'UserGrantedNodeChildrenAsTreeApi', 'UserGrantedNodesWithAssetsAsTreeApi',
|
||||
'GetUserAssetPermissionActionsApi',
|
||||
]
|
||||
|
||||
|
||||
|
@ -58,6 +65,66 @@ class UserPermissionMixin:
|
|||
return super().get_permissions()
|
||||
|
||||
|
||||
class UserNodePermissionMixin(UserPermissionMixin):
|
||||
util = None
|
||||
|
||||
def initial(self, *args, **kwargs):
|
||||
super().initial(*args, *kwargs)
|
||||
self.util = AssetPermissionUtilV2(self.obj)
|
||||
|
||||
|
||||
class UserNodeTreeMixin:
|
||||
serializer_class = TreeNodeSerializer
|
||||
nodes_only_fields = ParserNode.nodes_only_fields
|
||||
tree = None
|
||||
|
||||
def parse_nodes_to_queryset(self, nodes):
|
||||
nodes = nodes.only(*self.nodes_only_fields)
|
||||
_queryset = []
|
||||
|
||||
tree = self.util.get_user_tree()
|
||||
for node in nodes:
|
||||
assets_amount = tree.assets_amount(node.key)
|
||||
if assets_amount == 0:
|
||||
continue
|
||||
node._assets_amount = assets_amount
|
||||
data = ParserNode.parse_node_to_tree_node(node)
|
||||
_queryset.append(data)
|
||||
return _queryset
|
||||
|
||||
def get_serializer_queryset(self, queryset):
|
||||
queryset = self.parse_nodes_to_queryset(queryset)
|
||||
return queryset
|
||||
|
||||
def get_serializer(self, queryset, many=True, **kwargs):
|
||||
queryset = self.get_serializer_queryset(queryset)
|
||||
queryset.sort()
|
||||
return super().get_serializer(queryset, many=many, **kwargs)
|
||||
|
||||
|
||||
class UserAssetTreeMixin:
|
||||
serializer_class = TreeNodeSerializer
|
||||
nodes_only_fields = ParserNode.assets_only_fields
|
||||
|
||||
@staticmethod
|
||||
def parse_assets_to_queryset(assets, node):
|
||||
_queryset = []
|
||||
for asset in assets:
|
||||
data = ParserNode.parse_asset_to_tree_node(node, asset)
|
||||
_queryset.append(data)
|
||||
return _queryset
|
||||
|
||||
def get_serializer_queryset(self, queryset):
|
||||
queryset = queryset.only(*self.nodes_only_fields)
|
||||
_queryset = self.parse_assets_to_queryset(queryset, None)
|
||||
return _queryset
|
||||
|
||||
def get_serializer(self, queryset, many=True, **kwargs):
|
||||
queryset = self.get_serializer_queryset(queryset)
|
||||
queryset.sort()
|
||||
return super().get_serializer(queryset, many=many, **kwargs)
|
||||
|
||||
|
||||
class UserGrantedAssetsApi(UserPermissionMixin, ListAPIView):
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
serializer_class = serializers.AssetGrantedSerializer
|
||||
|
@ -89,6 +156,10 @@ class UserGrantedAssetsApi(UserPermissionMixin, ListAPIView):
|
|||
return queryset
|
||||
|
||||
|
||||
class UserGrantedAssetsAsTreeApi(UserAssetTreeMixin, UserGrantedAssetsApi):
|
||||
pass
|
||||
|
||||
|
||||
class UserGrantedNodeAssetsApi(UserGrantedAssetsApi):
|
||||
def get_queryset(self):
|
||||
node_id = self.kwargs.get("node_id")
|
||||
|
@ -100,18 +171,13 @@ class UserGrantedNodeAssetsApi(UserGrantedAssetsApi):
|
|||
return queryset
|
||||
|
||||
|
||||
class UserGrantedNodesApi(UserPermissionMixin, ListAPIView):
|
||||
class UserGrantedNodesApi(UserNodePermissionMixin, ListAPIView):
|
||||
"""
|
||||
查询用户授权的所有节点的API
|
||||
"""
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
serializer_class = serializers.NodeGrantedSerializer
|
||||
only_fields = NodeSerializer.Meta.only_fields
|
||||
util = None
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.util = AssetPermissionUtilV2(self.obj)
|
||||
return super().get(request, *args, **kwargs)
|
||||
nodes_only_fields = NodeSerializer.Meta.only_fields
|
||||
|
||||
def get_serializer_context(self):
|
||||
context = super().get_serializer_context()
|
||||
|
@ -120,21 +186,35 @@ class UserGrantedNodesApi(UserPermissionMixin, ListAPIView):
|
|||
|
||||
def get_queryset(self):
|
||||
node_keys = self.util.get_nodes()
|
||||
queryset = Node.objects.filter(key__in=node_keys)
|
||||
queryset = Node.objects.filter(key__in=node_keys)\
|
||||
.only(*self.nodes_only_fields)
|
||||
return queryset
|
||||
|
||||
|
||||
class UserGrantedNodesAsTreeApi(UserNodeTreeMixin, UserGrantedNodesApi):
|
||||
pass
|
||||
|
||||
|
||||
class UserGrantedNodesWithAssetsAsTreeApi(UserGrantedNodesAsTreeApi):
|
||||
def get_serializer_queryset(self, queryset):
|
||||
_queryset = super().get_serializer_queryset(queryset)
|
||||
for node in queryset:
|
||||
assets = self.util.get_nodes_assets(node)
|
||||
_queryset.extend(
|
||||
UserAssetTreeMixin.parse_assets_to_queryset(assets, node)
|
||||
)
|
||||
return _queryset
|
||||
|
||||
|
||||
class UserGrantedNodeChildrenApi(UserGrantedNodesApi):
|
||||
node = None
|
||||
util = None
|
||||
tree = None
|
||||
root_keys = None
|
||||
root_keys = None # 如果是第一次访问,则需要把二级节点添加进去,这个 roots_keys
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
key = self.request.query_params.get("key")
|
||||
pk = self.request.query_params.get("id")
|
||||
system_user_id = self.request.query_params.get("system_user")
|
||||
self.util = AssetPermissionUtilV2(self.obj)
|
||||
if system_user_id:
|
||||
self.util.filter_permissions(system_users=system_user_id)
|
||||
self.tree = self.util.get_user_tree()
|
||||
|
@ -161,26 +241,16 @@ class UserGrantedNodeChildrenApi(UserGrantedNodesApi):
|
|||
return queryset
|
||||
|
||||
|
||||
class UserGrantedNodeChildrenAsTreeApi(UserGrantedNodeChildrenApi):
|
||||
serializer_class = TreeNodeSerializer
|
||||
only_fields = ParserNode.nodes_only_fields
|
||||
|
||||
def get_queryset(self):
|
||||
nodes = super().get_queryset()
|
||||
queryset = []
|
||||
for node in nodes:
|
||||
node._assets_amount = self.tree.assets_amount(node.key)
|
||||
data = ParserNode.parse_node_to_tree_node(node)
|
||||
queryset.append(data)
|
||||
return queryset
|
||||
class UserGrantedNodeChildrenAsTreeApi(UserNodeTreeMixin, UserGrantedNodeChildrenApi):
|
||||
pass
|
||||
|
||||
|
||||
class UserGrantedNodesWithAssetsAsTreeApi(UserGrantedNodeChildrenAsTreeApi):
|
||||
class UserGrantedNodeChildrenWithAssetsAsTreeApi(UserGrantedNodeChildrenAsTreeApi):
|
||||
nodes_only_fields = ParserNode.nodes_only_fields
|
||||
assets_only_fields = ParserNode.assets_only_fields
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
def get_serializer_queryset(self, queryset):
|
||||
_queryset = super().get_serializer_queryset(queryset)
|
||||
nodes = []
|
||||
if self.node:
|
||||
nodes.append(self.node)
|
||||
|
@ -188,12 +258,13 @@ class UserGrantedNodesWithAssetsAsTreeApi(UserGrantedNodeChildrenAsTreeApi):
|
|||
nodes = Node.objects.filter(key__in=self.root_keys)
|
||||
|
||||
for node in nodes:
|
||||
assets = self.util.get_nodes_assets(node).only(*self.assets_only_fields)
|
||||
for asset in assets:
|
||||
data = ParserNode.parse_asset_to_tree_node(node, asset)
|
||||
queryset.append(data)
|
||||
queryset = sorted(queryset)
|
||||
return queryset
|
||||
assets = self.util.get_nodes_assets(node).only(
|
||||
*self.assets_only_fields
|
||||
)
|
||||
_queryset.extend(
|
||||
UserAssetTreeMixin.parse_assets_to_queryset(assets, node)
|
||||
)
|
||||
return _queryset
|
||||
|
||||
|
||||
class GetUserAssetPermissionActionsApi(RetrieveAPIView):
|
||||
|
|
|
@ -17,16 +17,34 @@ asset_permission_urlpatterns = [
|
|||
path('users/<uuid:pk>/assets/', api.UserGrantedAssetsApi.as_view(), name='user-assets'),
|
||||
path('users/assets/', api.UserGrantedAssetsApi.as_view(), name='my-assets'),
|
||||
|
||||
# Assets as tree
|
||||
path('users/<uuid:pk>/assets/tree/', api.UserGrantedAssetsAsTreeApi.as_view(), name='user-assets-as-tree'),
|
||||
path('users/assets/tree/', api.UserGrantedAssetsAsTreeApi.as_view(), name='my-assets-as-tree'),
|
||||
|
||||
# Nodes
|
||||
path('users/<uuid:pk>/nodes/', api.UserGrantedNodesApi.as_view(), name='user-nodes'),
|
||||
path('users/nodes/', api.UserGrantedNodesApi.as_view(), name='my-nodes'),
|
||||
|
||||
# Node children
|
||||
path('users/<uuid:pk>/nodes/children/', api.UserGrantedNodesApi.as_view(), name='user-nodes-children'),
|
||||
path('users/nodes/children/', api.UserGrantedNodesApi.as_view(), name='my-nodes-children'),
|
||||
|
||||
# Node as tree
|
||||
path('users/<uuid:pk>/nodes/tree/', api.UserGrantedNodesAsTreeApi.as_view(), name='user-nodes-as-tree'),
|
||||
path('users/nodes/tree/', api.UserGrantedNodesAsTreeApi.as_view(), name='my-nodes-as-tree'),
|
||||
|
||||
# Node with assets as tree
|
||||
path('users/<uuid:pk>/nodes-with-assets/tree/', api.UserGrantedNodesWithAssetsAsTreeApi.as_view(), name='user-nodes-with-assets-as-tree'),
|
||||
path('users/nodes-with-assets/tree/', api.UserGrantedNodesWithAssetsAsTreeApi.as_view(), name='my-nodes-with-assets-as-tree'),
|
||||
|
||||
# Node children as tree
|
||||
path('users/<uuid:pk>/nodes/children/tree/', api.UserGrantedNodeChildrenAsTreeApi.as_view(), name='user-nodes-children-as-tree'),
|
||||
path('users/nodes/children/tree/', api.UserGrantedNodeChildrenAsTreeApi.as_view(), name='my-nodes-children-as-tree'),
|
||||
|
||||
# Node children with assets as tree
|
||||
path('users/<uuid:pk>/nodes/children-with-assets/tree/', api.UserGrantedNodeChildrenWithAssetsAsTreeApi.as_view(), name='user-nodes-children-with-assets-as-tree'),
|
||||
path('users/nodes/children-with-assets/tree/', api.UserGrantedNodeChildrenWithAssetsAsTreeApi.as_view(), name='my-nodes-children-with-assets-as-tree'),
|
||||
|
||||
# Node assets
|
||||
path('users/<uuid:pk>/nodes/<uuid:node_id>/assets/', api.UserGrantedNodeAssetsApi.as_view(), name='user-node-assets'),
|
||||
path('users/nodes/<uuid:node_id>/assets/', api.UserGrantedNodeAssetsApi.as_view(), name='my-node-assets'),
|
||||
|
@ -35,10 +53,6 @@ asset_permission_urlpatterns = [
|
|||
path('users/<uuid:pk>/assets/<uuid:asset_id>/system-users/', api.UserGrantedAssetSystemUsersApi.as_view(), name='user-asset-system-users'),
|
||||
path('users/assets/<uuid:asset_id>/system-users/', api.UserGrantedAssetSystemUsersApi.as_view(), name='my-asset-system-users'),
|
||||
|
||||
# Node assets as tree
|
||||
path('users/<uuid:pk>/nodes/children-with-assets/tree/', api.UserGrantedNodesWithAssetsAsTreeApi.as_view(), name='user-nodes-children-with-assets-as-tree'),
|
||||
path('users/nodes/children-with-assets/tree/', api.UserGrantedNodesWithAssetsAsTreeApi.as_view(), name='my-nodes-children-with-assets-as-tree'),
|
||||
|
||||
# 查询某个用户组授权的资产和资产组
|
||||
path('user-groups/<uuid:pk>/assets/', api.UserGroupGrantedAssetsApi.as_view(), name='user-group-assets'),
|
||||
path('user-groups/<uuid:pk>/nodes/', api.UserGroupGrantedNodesApi.as_view(), name='user-group-nodes'),
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
# coding: utf-8
|
||||
|
||||
import pickle
|
||||
import threading
|
||||
from collections import defaultdict
|
||||
from functools import reduce
|
||||
|
||||
from django.core.cache import cache
|
||||
from django.db.models import Q
|
||||
from django.conf import settings
|
||||
|
||||
|
@ -12,7 +15,6 @@ from common.tree import TreeNode
|
|||
from assets.utils import TreeService
|
||||
from ..models import AssetPermission
|
||||
from ..hands import Node, Asset, SystemUser
|
||||
from .. import const
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
||||
|
@ -69,9 +71,12 @@ class AssetPermissionUtilV2:
|
|||
'id', 'hostname', 'ip', "platform", "domain_id",
|
||||
'comment', 'is_active', 'os', 'org_id'
|
||||
)
|
||||
user_tree_cache_key = 'USER_PERM_TREE_{}'
|
||||
user_tree_cache_ttl = 3600
|
||||
|
||||
def __init__(self, obj, cache_policy='0'):
|
||||
self.object = obj
|
||||
self.cache_policy = cache_policy
|
||||
self.obj_id = str(obj.id)
|
||||
self._permissions = None
|
||||
self._permissions_id = None # 标记_permission的唯一值
|
||||
|
@ -84,6 +89,7 @@ class AssetPermissionUtilV2:
|
|||
self._nodes_direct = None
|
||||
self._user_tree = None
|
||||
self.full_tree = Node.tree()
|
||||
self.mutex = threading.Lock()
|
||||
|
||||
@staticmethod
|
||||
def change_org_if_need():
|
||||
|
@ -103,6 +109,31 @@ class AssetPermissionUtilV2:
|
|||
def filter_permissions(self, **filters):
|
||||
self._permissions = self.permissions.filter(**filters)
|
||||
|
||||
@classmethod
|
||||
def get_user_tree_from_cache(cls, obj_id):
|
||||
return None
|
||||
key = cls.user_tree_cache_key.format(obj_id)
|
||||
data = cache.get(key)
|
||||
if not data:
|
||||
return None
|
||||
user_tree = pickle.loads(data)
|
||||
return user_tree
|
||||
|
||||
@classmethod
|
||||
def expire_user_tree_cache(cls, obj_id):
|
||||
if obj_id == 'all':
|
||||
key = cls.user_tree_cache_key.format('*')
|
||||
cache.delete_pattern(key)
|
||||
else:
|
||||
key = cls.user_tree_cache_key.format(obj_id)
|
||||
cache.delete(key)
|
||||
|
||||
@classmethod
|
||||
def set_user_tree_to_cache(cls, obj_id, user_tree):
|
||||
data = pickle.dumps(user_tree)
|
||||
key = cls.user_tree_cache_key.format(obj_id)
|
||||
cache.set(key, data, cls.user_tree_cache_ttl)
|
||||
|
||||
@property
|
||||
def user_tree(self):
|
||||
return self.get_user_tree()
|
||||
|
@ -237,20 +268,26 @@ class AssetPermissionUtilV2:
|
|||
|
||||
@timeit
|
||||
def get_user_tree(self):
|
||||
if self._user_tree:
|
||||
return self._user_tree
|
||||
user_tree = TreeService()
|
||||
full_tree_root = self.full_tree.root_node()
|
||||
user_tree.create_node(
|
||||
tag=full_tree_root.tag,
|
||||
identifier=full_tree_root.identifier
|
||||
)
|
||||
self.add_direct_nodes_to_user_tree(user_tree)
|
||||
self.add_single_assets_node_to_user_tree(user_tree)
|
||||
self.parse_user_tree_to_full_tree(user_tree)
|
||||
self.add_empty_node_if_need(user_tree)
|
||||
self._user_tree = user_tree
|
||||
return user_tree
|
||||
with self.mutex:
|
||||
if self._user_tree:
|
||||
return self._user_tree
|
||||
print(id(self), self._user_tree)
|
||||
user_tree = self.__class__.get_user_tree_from_cache(self.obj_id)
|
||||
if user_tree:
|
||||
self._user_tree = user_tree
|
||||
return user_tree
|
||||
user_tree = TreeService()
|
||||
full_tree_root = self.full_tree.root_node()
|
||||
user_tree.create_node(
|
||||
tag=full_tree_root.tag,
|
||||
identifier=full_tree_root.identifier
|
||||
)
|
||||
self.add_direct_nodes_to_user_tree(user_tree)
|
||||
self.add_single_assets_node_to_user_tree(user_tree)
|
||||
self.parse_user_tree_to_full_tree(user_tree)
|
||||
self.add_empty_node_if_need(user_tree)
|
||||
self.__class__.set_user_tree_to_cache(self.obj_id, user_tree)
|
||||
return user_tree
|
||||
|
||||
# Todo: 是否可以获取多个资产的系统用户
|
||||
def get_asset_system_users_with_actions(self, asset):
|
||||
|
@ -401,15 +438,17 @@ class ParserNode:
|
|||
@staticmethod
|
||||
def parse_asset_to_tree_node(node, asset):
|
||||
icon_skin = 'file'
|
||||
if asset.platform.lower() == 'windows':
|
||||
platform = asset.platform.lower()
|
||||
if platform == 'windows':
|
||||
icon_skin = 'windows'
|
||||
elif asset.platform.lower() == 'linux':
|
||||
elif platform == 'linux':
|
||||
icon_skin = 'linux'
|
||||
parent_id = node.key if node else ''
|
||||
data = {
|
||||
'id': str(asset.id),
|
||||
'name': asset.hostname,
|
||||
'title': asset.ip,
|
||||
'pId': node.key,
|
||||
'pId': parent_id,
|
||||
'isParent': False,
|
||||
'open': False,
|
||||
'iconSkin': icon_skin,
|
||||
|
|
|
@ -2,20 +2,21 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from django.urls import path, include
|
||||
from django.urls import path, include, re_path
|
||||
from rest_framework_bulk.routes import BulkRouter
|
||||
|
||||
from common import api as capi
|
||||
from .. import api
|
||||
|
||||
app_name = 'terminal'
|
||||
|
||||
router = BulkRouter()
|
||||
router.register(r'sessions', api.SessionViewSet, 'session')
|
||||
router.register(r'terminal/(?P<terminal>[a-zA-Z0-9\-]{36})?/?status', api.StatusViewSet, 'terminal-status')
|
||||
router.register(r'terminal/(?P<terminal>[a-zA-Z0-9\-]{36})?/?sessions', api.SessionViewSet, 'terminal-sessions')
|
||||
router.register(r'terminal', api.TerminalViewSet, 'terminal')
|
||||
router.register(r'terminals/(?P<terminal>[a-zA-Z0-9\-]{36})?/?status', api.StatusViewSet, 'terminal-status')
|
||||
router.register(r'terminals/(?P<terminal>[a-zA-Z0-9\-]{36})?/?sessions', api.SessionViewSet, 'terminal-sessions')
|
||||
router.register(r'terminals', api.TerminalViewSet, 'terminal')
|
||||
router.register(r'tasks', api.TaskViewSet, 'tasks')
|
||||
router.register(r'command', api.CommandViewSet, 'command')
|
||||
router.register(r'commands', api.CommandViewSet, 'command')
|
||||
router.register(r'status', api.StatusViewSet, 'status')
|
||||
|
||||
urlpatterns = [
|
||||
|
@ -23,9 +24,9 @@ urlpatterns = [
|
|||
api.SessionReplayViewSet.as_view({'get': 'retrieve', 'post': 'create'}),
|
||||
name='session-replay'),
|
||||
path('tasks/kill-session/', api.KillSessionAPI.as_view(), name='kill-session'),
|
||||
path('terminal/<uuid:terminal>/access-key/', api.TerminalTokenApi.as_view(),
|
||||
path('terminals/<uuid:terminal>/access-key/', api.TerminalTokenApi.as_view(),
|
||||
name='terminal-access-key'),
|
||||
path('terminal/config/', api.TerminalConfig.as_view(), name='terminal-config'),
|
||||
path('terminals/config/', api.TerminalConfig.as_view(), name='terminal-config'),
|
||||
path('commands/export/', api.CommandExportApi.as_view(), name="command-export")
|
||||
# v2: get session's replay
|
||||
# path('v2/sessions/<uuid:pk>/replay/',
|
||||
|
@ -33,7 +34,11 @@ urlpatterns = [
|
|||
# name='session-replay-v2'),
|
||||
]
|
||||
|
||||
urlpatterns += router.urls
|
||||
old_version_urlpatterns = [
|
||||
re_path('(?P<resource>terminal|command)/.*', capi.redirect_plural_name_api)
|
||||
]
|
||||
|
||||
urlpatterns += router.urls + old_version_urlpatterns
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -2,15 +2,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from django.urls import path
|
||||
from django.urls import path, re_path
|
||||
from rest_framework_bulk.routes import BulkRouter
|
||||
|
||||
from common import api as capi
|
||||
from .. import api_v2 as api
|
||||
|
||||
app_name = 'terminal'
|
||||
|
||||
router = BulkRouter()
|
||||
router.register(r'terminal', api.TerminalViewSet, 'terminal')
|
||||
router.register(r'terminals', api.TerminalViewSet, 'terminal')
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
|
@ -18,4 +19,8 @@ urlpatterns = [
|
|||
name='terminal-registration')
|
||||
]
|
||||
|
||||
old_version_urlpatterns = [
|
||||
re_path('(?P<resource>terminal)/.*', capi.redirect_plural_name_api)
|
||||
]
|
||||
|
||||
urlpatterns += router.urls
|
||||
|
|
|
@ -108,7 +108,7 @@ function onSelected(event, treeNode) {
|
|||
}
|
||||
|
||||
|
||||
function initTree() {
|
||||
function initTree(refresh) {
|
||||
var setting = {
|
||||
view: {
|
||||
dblClickExpand: false,
|
||||
|
@ -131,11 +131,13 @@ function initTree() {
|
|||
};
|
||||
|
||||
$.get(treeUrl, function(data, status) {
|
||||
$.fn.zTree.init($("#assetTree"), setting, data);
|
||||
zTree = $.fn.zTree.getZTreeObj("assetTree");
|
||||
zTree = $.fn.zTree.init($("#assetTree"), setting, data);
|
||||
if (!refresh) {
|
||||
initTable();
|
||||
}
|
||||
rootNodeAddDom(zTree, function () {
|
||||
treeUrl = setUrlParam(treeUrl, 'cache_policy', '2');
|
||||
initTree();
|
||||
initTree(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -39,7 +39,6 @@ var systemUsersUrl = "{% url 'api-perms:user-asset-system-users' pk=object.id as
|
|||
|
||||
$(document).ready(function () {
|
||||
initTree();
|
||||
initTable();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -42,7 +42,6 @@ var showAssetHref = true; // Need input default true
|
|||
|
||||
$(document).ready(function () {
|
||||
initTree();
|
||||
initTable();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
Loading…
Reference in New Issue