mirror of
https://github.com/jumpserver/jumpserver.git
synced 2026-03-18 19:12:07 +00:00
perf: support UserPermTreeAPI finished.
This commit is contained in:
@@ -7,10 +7,13 @@ from assets.api.asset.asset import AssetFilterSet
|
||||
from assets.models import Asset, Node, MyAsset
|
||||
from common.api.mixin import ExtraFilterFieldsMixin
|
||||
from common.utils import get_logger, lazyproperty, is_uuid
|
||||
from common.utils.django import get_object_or_none
|
||||
from orgs.utils import tmp_to_root_org
|
||||
from perms import serializers
|
||||
from perms.pagination import NodePermedAssetPagination, AllPermedAssetPagination
|
||||
from perms.utils import UserPermAssetUtil, PermAssetDetailUtil
|
||||
from perms.utils.utils import UserPermUtil
|
||||
from perms.tree import PermTreeNode
|
||||
from .mixin import (
|
||||
SelfOrPKUserMixin
|
||||
)
|
||||
@@ -65,36 +68,46 @@ class BaseUserPermedAssetsApi(SelfOrPKUserMixin, ExtraFilterFieldsMixin, ListAPI
|
||||
def get_assets(self):
|
||||
return Asset.objects.none()
|
||||
|
||||
query_asset_util: UserPermAssetUtil
|
||||
|
||||
@lazyproperty
|
||||
def query_asset_util(self):
|
||||
return UserPermAssetUtil(self.user)
|
||||
def _util(self):
|
||||
return UserPermUtil(user=self.user)
|
||||
|
||||
|
||||
class UserAllPermedAssetsApi(BaseUserPermedAssetsApi):
|
||||
pagination_class = AllPermedAssetPagination
|
||||
|
||||
def get_assets(self):
|
||||
if self.user.is_superuser and self.request.query_params.get('id'):
|
||||
return Asset.objects.filter(id=self.request.query_params.get('id'))
|
||||
|
||||
node_id = self.request.query_params.get('node_id')
|
||||
if is_uuid(node_id):
|
||||
__, assets = self.query_asset_util.get_node_all_assets(node_id)
|
||||
else:
|
||||
assets = self.query_asset_util.get_all_assets()
|
||||
|
||||
if node_id == PermTreeNode.SpecialKey.FAVORITE:
|
||||
return UserPermUtil.get_favorite_assets(user=self.user)
|
||||
|
||||
if node_id == PermTreeNode.SpecialKey.UNGROUPED:
|
||||
return self._util.get_ungrouped_assets()
|
||||
|
||||
node = get_object_or_none(Node, id=node_id)
|
||||
if node:
|
||||
assets = self._util.get_node_all_assets(node)
|
||||
return assets
|
||||
|
||||
assets = UserPermUtil.get_all_assets(user=self.user)
|
||||
return assets
|
||||
|
||||
|
||||
class UserDirectPermedAssetsApi(BaseUserPermedAssetsApi):
|
||||
|
||||
def get_assets(self):
|
||||
return self.query_asset_util.get_direct_assets()
|
||||
assets = self._util.get_ungrouped_assets()
|
||||
return assets
|
||||
|
||||
|
||||
class UserFavoriteAssetsApi(BaseUserPermedAssetsApi):
|
||||
|
||||
def get_assets(self):
|
||||
return self.query_asset_util.get_favorite_assets()
|
||||
assets = UserPermUtil.get_favorite_assets(user=self.user)
|
||||
return assets
|
||||
|
||||
|
||||
class UserPermedNodeAssetsApi(BaseUserPermedAssetsApi):
|
||||
|
||||
@@ -27,8 +27,13 @@ class UserPermNodeChildrenAsTreeApi(SelfOrPKUserMixin, SerializeToTreeNodeMixin,
|
||||
|
||||
@timeit
|
||||
def list(self, request, *args, **kwargs):
|
||||
with_assets = request.query_params.get('assets', '0') == '1'
|
||||
search = request.query_params.get('search')
|
||||
key = request.query_params.get('key')
|
||||
|
||||
if not with_assets:
|
||||
return self.init_user_perm_tree()
|
||||
|
||||
if search:
|
||||
return self.search_user_perm_tree_with_assets(search)
|
||||
|
||||
@@ -36,6 +41,38 @@ class UserPermNodeChildrenAsTreeApi(SelfOrPKUserMixin, SerializeToTreeNodeMixin,
|
||||
return self.expand_tree_node_with_assets(key)
|
||||
|
||||
return self.init_user_perm_tree_with_assets()
|
||||
|
||||
def init_user_perm_tree(self):
|
||||
''' 初始化用户权限树 - 不包含资产
|
||||
前端搜索
|
||||
|
||||
全局组织: 返回所有节点,不返回资产,不展开节点
|
||||
实体组织:返回所有节点,不返回资产,展开第1级节点
|
||||
|
||||
返回收藏节点
|
||||
返回未分组节点 (如果需要)
|
||||
'''
|
||||
if current_org.is_root():
|
||||
orgs = self.user.orgs.all()
|
||||
expand_level = 0
|
||||
else:
|
||||
orgs = self.user.orgs.filter(id=current_org.id)
|
||||
expand_level = 1
|
||||
|
||||
if not orgs.exists():
|
||||
return Response(data=[])
|
||||
|
||||
nodes = []
|
||||
for org in orgs:
|
||||
tree = UserPermTree(user=self.user, org=org)
|
||||
_nodes = tree.get_nodes()
|
||||
nodes.extend(_nodes)
|
||||
nodes = self.serialize_nodes(
|
||||
nodes, with_asset_amount=True, expand_level=expand_level
|
||||
)
|
||||
data = nodes
|
||||
data = self.add_favorites_and_ungrouped_node(data, with_assets=False)
|
||||
return Response(data=data)
|
||||
|
||||
def init_user_perm_tree_with_assets(self):
|
||||
''' 初始化用户权限资产树 - 包含资产
|
||||
@@ -60,22 +97,6 @@ class UserPermNodeChildrenAsTreeApi(SelfOrPKUserMixin, SerializeToTreeNodeMixin,
|
||||
if not orgs.exists():
|
||||
return Response(data=[])
|
||||
|
||||
# 收藏节点和资产
|
||||
f_node, f_assets = self.get_favorite_node_with_assets()
|
||||
f_nodes = []
|
||||
if f_node:
|
||||
f_nodes = self.serialize_nodes(
|
||||
[f_node], with_asset_amount=True, expand_level=0, with_assets=True
|
||||
)
|
||||
|
||||
# 未分组节点和资产
|
||||
u_node, u_assets = self.get_ungrouped_node_with_assets_if_need()
|
||||
u_nodes = []
|
||||
if u_node:
|
||||
u_nodes = self.serialize_nodes(
|
||||
[u_node], with_asset_amount=True, expand_level=0, with_assets=True
|
||||
)
|
||||
|
||||
nodes = []
|
||||
assets = []
|
||||
|
||||
@@ -91,10 +112,10 @@ class UserPermNodeChildrenAsTreeApi(SelfOrPKUserMixin, SerializeToTreeNodeMixin,
|
||||
nodes = self.serialize_nodes(
|
||||
nodes, with_asset_amount=True, expand_level=expand_level, with_assets=True
|
||||
)
|
||||
assets = [*f_assets, *u_assets, *assets]
|
||||
assets = self.serialize_assets(assets)
|
||||
data = [*f_nodes, *u_nodes, *nodes, *assets]
|
||||
return Response(data)
|
||||
data = [*nodes, *assets]
|
||||
data = self.add_favorites_and_ungrouped_node(data, with_assets=True)
|
||||
return Response(data=data)
|
||||
|
||||
def expand_tree_node_with_assets(self, key):
|
||||
''' 展开用户权限资产树节点 - 包含资产
|
||||
@@ -160,28 +181,48 @@ class UserPermNodeChildrenAsTreeApi(SelfOrPKUserMixin, SerializeToTreeNodeMixin,
|
||||
assets = self.serialize_assets(assets)
|
||||
data = [*nodes, *assets]
|
||||
return Response(data=data)
|
||||
|
||||
def add_favorites_and_ungrouped_node(self, data: list, with_assets=False):
|
||||
# 未分组节点和资产
|
||||
u_node, u_assets = self.get_ungrouped_node_if_need()
|
||||
if u_node:
|
||||
data.insert(0, u_node)
|
||||
data.extend(u_assets)
|
||||
|
||||
# 收藏节点和资产
|
||||
f_node, f_assets = self.get_favorite_node()
|
||||
if f_node:
|
||||
data.insert(0, f_node)
|
||||
data.extend(f_assets)
|
||||
return data
|
||||
|
||||
def get_favorite_node_with_assets(self):
|
||||
asset_ids = FavoriteAsset.get_user_favorite_asset_ids(self.user)
|
||||
assets_amount = len(asset_ids)
|
||||
def get_favorite_node(self, with_assets=False):
|
||||
assets = UserPermUtil.get_favorite_assets(self.user)
|
||||
assets_amount = assets.count()
|
||||
node = PermTreeNode(
|
||||
_id='favorite',
|
||||
key='favorite',
|
||||
value=_('Favorite'),
|
||||
_id=PermTreeNode.SpecialKey.FAVORITE.value,
|
||||
key=PermTreeNode.SpecialKey.FAVORITE.value,
|
||||
value=PermTreeNode.SpecialKey.FAVORITE.label,
|
||||
assets_amount=assets_amount
|
||||
)
|
||||
node.assets_amount_total = assets_amount
|
||||
nodes = self.serialize_nodes(
|
||||
[node], with_asset_amount=True, expand_level=0, with_assets=with_assets
|
||||
)
|
||||
serialized_node = nodes[0] if nodes else None
|
||||
|
||||
if not asset_ids:
|
||||
return node, []
|
||||
if not with_assets:
|
||||
return serialized_node, []
|
||||
|
||||
if assets_amount == 0:
|
||||
return serialized_node, []
|
||||
|
||||
assets = Asset.objects.filter(id__in=asset_ids).values(*AssetTreeNodeAsset.model_values)
|
||||
assets = list(assets)
|
||||
node.init_assets(assets)
|
||||
assets = node.get_assets()
|
||||
return node, assets
|
||||
assets = list(assets.values(*AssetTreeNodeAsset.model_values))
|
||||
assets = node.init_assets(assets)
|
||||
serialized_assets = self.serialize_assets(assets)
|
||||
return serialized_node, serialized_assets
|
||||
|
||||
def get_ungrouped_node_with_assets_if_need(self):
|
||||
def get_ungrouped_node_if_need(self, with_assets=False):
|
||||
if not settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE:
|
||||
return None, []
|
||||
|
||||
@@ -193,18 +234,27 @@ class UserPermNodeChildrenAsTreeApi(SelfOrPKUserMixin, SerializeToTreeNodeMixin,
|
||||
return None, []
|
||||
|
||||
_util = UserPermUtil(user=self.user, org=org)
|
||||
direct_asset_ids = _util._user_direct_asset_ids
|
||||
assets_amount = len(direct_asset_ids)
|
||||
assets = _util.get_ungrouped_assets()
|
||||
assets_amount = assets.count()
|
||||
node = PermTreeNode(
|
||||
_id='ungrouped',
|
||||
key='ungrouped',
|
||||
value=_('Ungrouped'),
|
||||
_id=PermTreeNode.SpecialKey.UNGROUPED.value,
|
||||
key=PermTreeNode.SpecialKey.UNGROUPED.value,
|
||||
value=PermTreeNode.SpecialKey.UNGROUPED.label,
|
||||
assets_amount=assets_amount
|
||||
)
|
||||
node.assets_amount_total = assets_amount
|
||||
if not direct_asset_ids:
|
||||
return node, []
|
||||
assets = Asset.objects.filter(id__in=direct_asset_ids).values(*AssetTreeNodeAsset.model_values)
|
||||
node.init_assets(list(assets))
|
||||
assets = node.get_assets()
|
||||
return node, assets
|
||||
nodes = self.serialize_nodes(
|
||||
[node], with_asset_amount=True, expand_level=0, with_assets=with_assets
|
||||
)
|
||||
serialized_node = nodes[0] if nodes else None
|
||||
|
||||
if not with_assets:
|
||||
return serialized_node, []
|
||||
|
||||
if assets_amount == 0:
|
||||
return serialized_node, []
|
||||
|
||||
assets = assets.values(*AssetTreeNodeAsset.model_values)
|
||||
assets = node.init_assets(list(assets))
|
||||
serialized_assets = self.serialize_assets(assets)
|
||||
return serialized_node, serialized_assets
|
||||
@@ -25,6 +25,10 @@ class PermTreeNode(AssetTreeNode):
|
||||
DN = 'dn'
|
||||
# Node with only direct permission assets
|
||||
DA = 'da'
|
||||
|
||||
class SpecialKey(TextChoices):
|
||||
FAVORITE = 'favorite', _('Favorite')
|
||||
UNGROUPED = 'ungrouped', _('Ungrouped')
|
||||
|
||||
def __init__(self, tp=None, **kwargs):
|
||||
self.type = tp or self.Type.BRIDGE
|
||||
|
||||
@@ -3,54 +3,11 @@ from django.urls import path, include
|
||||
from .. import api
|
||||
|
||||
user_permission_urlpatterns = [
|
||||
# <str:user> such as: my | self | user.id
|
||||
# assets
|
||||
path('<str:user>/assets/<uuid:pk>/', api.UserPermedAssetRetrieveApi.as_view(),
|
||||
name='user-permed-asset'),
|
||||
path('<str:user>/assets/', api.UserAllPermedAssetsApi.as_view(),
|
||||
name='user-all-assets'),
|
||||
|
||||
path('<str:user>/nodes/ungrouped/assets/', api.UserDirectPermedAssetsApi.as_view(),
|
||||
name='user-direct-assets'),
|
||||
path('<str:user>/nodes/favorite/assets/', api.UserFavoriteAssetsApi.as_view(),
|
||||
name='user-favorite-assets'),
|
||||
path('<str:user>/nodes/<uuid:node_id>/assets/', api.UserPermedNodeAssetsApi.as_view(),
|
||||
name='user-node-assets'),
|
||||
|
||||
# nodes
|
||||
path('<str:user>/nodes/', api.UserAllPermedNodesApi.as_view(),
|
||||
name='user-all-nodes'),
|
||||
path('<str:user>/nodes/children/', api.UserPermedNodeChildrenApi.as_view(),
|
||||
name='user-node-children'),
|
||||
|
||||
# 授权树只通过这一个 API 获取, 类似资产树
|
||||
path('<str:user>/nodes/children/tree/', api.UserPermNodeChildrenAsTreeApi.as_view(),
|
||||
name='user-perm-node-children-tree'),
|
||||
|
||||
# tree-asset
|
||||
# path('<str:user>/assets/tree/', api.UserAllPermedAssetsAsTreeApi.as_view(),
|
||||
# name='user-direct-assets-as-tree'),
|
||||
# path('<str:user>/ungroup/assets/tree/', api.UserUngroupAssetsAsTreeApi.as_view(),
|
||||
# name='user-ungroup-assets-as-tree'),
|
||||
|
||||
# tree-node,不包含资产
|
||||
# path('<str:user>/nodes/tree/', api.UserAllPermedNodesAsTreeApi.as_view(),
|
||||
# name='user-all-nodes-as-tree'),
|
||||
# path('<str:user>/nodes/children/tree/', api.UserPermedNodeChildrenAsTreeApi.as_view(),
|
||||
# name='user-node-children-as-tree'),
|
||||
|
||||
# tree-node-with-asset
|
||||
# 异步树
|
||||
# path('<str:user>/nodes/children-with-assets/tree/',
|
||||
# api.UserPermedNodeChildrenWithAssetsAsTreeApi.as_view(),
|
||||
# name='user-node-children-with-assets-as-tree'),
|
||||
# path('<str:user>/nodes/children-with-assets/category/tree/',
|
||||
# api.UserPermedNodeChildrenWithAssetsAsCategoryTreeApi.as_view(),
|
||||
# name='user-node-children-with-assets-as-category-tree'),
|
||||
# 同步树
|
||||
# path('<str:user>/nodes/all-with-assets/tree/',
|
||||
# api.UserPermedNodesWithAssetsAsTreeApi.as_view(),
|
||||
# name='user-nodes-with-assets-as-tree'),
|
||||
path('<str:user>/assets/<uuid:pk>/', api.UserPermedAssetRetrieveApi.as_view(), name='user-permed-asset'),
|
||||
path('<str:user>/assets/', api.UserAllPermedAssetsApi.as_view(), name='user-all-assets'),
|
||||
path('<str:user>/nodes/favorite/assets/', api.UserFavoriteAssetsApi.as_view(), name='user-favorite-assets'),
|
||||
# 用户授权树只通过这一个 API 获取, 类似资产树
|
||||
path('<str:user>/nodes/children/tree/', api.UserPermNodeChildrenAsTreeApi.as_view(), name='user-perm-node-children-tree'),
|
||||
]
|
||||
|
||||
user_group_permission_urlpatterns = [
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
from django.db.models import Q
|
||||
|
||||
from common.utils import timeit, lazyproperty, get_logger, is_uuid
|
||||
from orgs.utils import current_org
|
||||
from orgs.utils import current_org, tmp_to_org
|
||||
from users.models import User
|
||||
from assets.models import Node, Asset
|
||||
from assets.models import Node, Asset, FavoriteAsset
|
||||
from perms.models import AssetPermission
|
||||
|
||||
|
||||
@@ -133,7 +133,37 @@ class UserPermUtil(object):
|
||||
|
||||
q = Q(node_id__in=dn_all_nodes_ids)
|
||||
q |= Q(node_id__in=other_nodes_ids) & Q(id__in=self._user_direct_asset_ids)
|
||||
assets = Asset.objects.filter(org_id=self._org.id).filter(q)
|
||||
assets = Asset.objects.filter(org_id=self._org.id).filter(q).valid()
|
||||
return assets
|
||||
|
||||
def get_all_assets_of_org(self):
|
||||
with tmp_to_org(self._org):
|
||||
root_node = Node.org_root()
|
||||
assets = self.get_node_all_assets(root_node)
|
||||
return assets
|
||||
|
||||
@classmethod
|
||||
def get_all_assets(cls, user):
|
||||
if current_org.is_root():
|
||||
orgs = user.orgs.all()
|
||||
else:
|
||||
orgs = user.orgs.filter(id=current_org.id)
|
||||
|
||||
assets = Asset.objects.none()
|
||||
for org in orgs:
|
||||
_util = cls(user=user, org=org)
|
||||
org_assets = _util.get_all_assets_of_org()
|
||||
assets |= org_assets
|
||||
return assets
|
||||
|
||||
@classmethod
|
||||
def get_favorite_assets(cls, user: User):
|
||||
asset_ids = FavoriteAsset.get_user_favorite_asset_ids(user)
|
||||
assets = Asset.objects.filter(id__in=asset_ids).valid()
|
||||
return assets
|
||||
|
||||
def get_ungrouped_assets(self):
|
||||
assets = Asset.objects.filter(id__in=self._user_direct_asset_ids).valid()
|
||||
return assets
|
||||
|
||||
def _uuids_to_string(self, uuids):
|
||||
|
||||
Reference in New Issue
Block a user