diff --git a/apps/perms/api/user_permission/assets.py b/apps/perms/api/user_permission/assets.py index dadd3f1f1..7a3c571e5 100644 --- a/apps/perms/api/user_permission/assets.py +++ b/apps/perms/api/user_permission/assets.py @@ -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): diff --git a/apps/perms/api/user_permission/tree.py b/apps/perms/api/user_permission/tree.py index c77a0c143..deb4e3224 100644 --- a/apps/perms/api/user_permission/tree.py +++ b/apps/perms/api/user_permission/tree.py @@ -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 \ No newline at end of file diff --git a/apps/perms/tree.py b/apps/perms/tree.py index 49119f82e..b5f36cf90 100644 --- a/apps/perms/tree.py +++ b/apps/perms/tree.py @@ -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 diff --git a/apps/perms/urls/user_permission.py b/apps/perms/urls/user_permission.py index 248ae1c2f..10b8063da 100644 --- a/apps/perms/urls/user_permission.py +++ b/apps/perms/urls/user_permission.py @@ -3,54 +3,11 @@ from django.urls import path, include from .. import api user_permission_urlpatterns = [ - # such as: my | self | user.id - # assets - path('/assets//', api.UserPermedAssetRetrieveApi.as_view(), - name='user-permed-asset'), - path('/assets/', api.UserAllPermedAssetsApi.as_view(), - name='user-all-assets'), - - path('/nodes/ungrouped/assets/', api.UserDirectPermedAssetsApi.as_view(), - name='user-direct-assets'), - path('/nodes/favorite/assets/', api.UserFavoriteAssetsApi.as_view(), - name='user-favorite-assets'), - path('/nodes//assets/', api.UserPermedNodeAssetsApi.as_view(), - name='user-node-assets'), - - # nodes - path('/nodes/', api.UserAllPermedNodesApi.as_view(), - name='user-all-nodes'), - path('/nodes/children/', api.UserPermedNodeChildrenApi.as_view(), - name='user-node-children'), - - # 授权树只通过这一个 API 获取, 类似资产树 - path('/nodes/children/tree/', api.UserPermNodeChildrenAsTreeApi.as_view(), - name='user-perm-node-children-tree'), - - # tree-asset -# path('/assets/tree/', api.UserAllPermedAssetsAsTreeApi.as_view(), -# name='user-direct-assets-as-tree'), -# path('/ungroup/assets/tree/', api.UserUngroupAssetsAsTreeApi.as_view(), -# name='user-ungroup-assets-as-tree'), - - # tree-node,不包含资产 -# path('/nodes/tree/', api.UserAllPermedNodesAsTreeApi.as_view(), -# name='user-all-nodes-as-tree'), -# path('/nodes/children/tree/', api.UserPermedNodeChildrenAsTreeApi.as_view(), -# name='user-node-children-as-tree'), - - # tree-node-with-asset - # 异步树 -# path('/nodes/children-with-assets/tree/', -# api.UserPermedNodeChildrenWithAssetsAsTreeApi.as_view(), -# name='user-node-children-with-assets-as-tree'), -# path('/nodes/children-with-assets/category/tree/', -# api.UserPermedNodeChildrenWithAssetsAsCategoryTreeApi.as_view(), -# name='user-node-children-with-assets-as-category-tree'), - # 同步树 -# path('/nodes/all-with-assets/tree/', -# api.UserPermedNodesWithAssetsAsTreeApi.as_view(), -# name='user-nodes-with-assets-as-tree'), + path('/assets//', api.UserPermedAssetRetrieveApi.as_view(), name='user-permed-asset'), + path('/assets/', api.UserAllPermedAssetsApi.as_view(), name='user-all-assets'), + path('/nodes/favorite/assets/', api.UserFavoriteAssetsApi.as_view(), name='user-favorite-assets'), + # 用户授权树只通过这一个 API 获取, 类似资产树 + path('/nodes/children/tree/', api.UserPermNodeChildrenAsTreeApi.as_view(), name='user-perm-node-children-tree'), ] user_group_permission_urlpatterns = [ diff --git a/apps/perms/utils/utils.py b/apps/perms/utils/utils.py index 60ef890bc..16b7d3e99 100644 --- a/apps/perms/utils/utils.py +++ b/apps/perms/utils/utils.py @@ -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):