From 3e78d627f8260da8b7ea0f7db90af968e10d462c Mon Sep 17 00:00:00 2001 From: xinwen Date: Tue, 17 Nov 2020 18:27:09 +0800 Subject: [PATCH] =?UTF-8?q?fix(perms):=20=E4=BD=9C=E4=B8=9A=E4=B8=AD?= =?UTF-8?q?=E5=BF=83-=E6=89=B9=E9=87=8F=E5=91=BD=E4=BB=A4-=E9=80=89?= =?UTF-8?q?=E6=8B=A9=E7=B3=BB=E7=BB=9F=E7=94=A8=E6=88=B7=E4=B9=8B=E5=90=8E?= =?UTF-8?q?=EF=BC=8C=E5=B7=A6=E4=BE=A7=E8=B5=84=E4=BA=A7=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E6=9C=AA=E7=AD=9B=E9=80=89=EF=BC=8C=E8=BF=98=E6=98=AF=E5=85=A8?= =?UTF-8?q?=E9=83=A8=E8=B5=84=E4=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/models/favorite_asset.py | 8 +- .../user_permission/user_permission_nodes.py | 11 +- .../user_permission_nodes_with_assets.py | 111 ++++++++++++++++-- apps/perms/utils/asset/user_permission.py | 38 ++++-- 4 files changed, 139 insertions(+), 29 deletions(-) diff --git a/apps/assets/models/favorite_asset.py b/apps/assets/models/favorite_asset.py index 3497a075c..b176c8105 100644 --- a/apps/assets/models/favorite_asset.py +++ b/apps/assets/models/favorite_asset.py @@ -20,9 +20,13 @@ class FavoriteAsset(CommonModelMixin): return cls.objects.filter(user=user).values_list('asset', flat=True) @classmethod - def get_user_favorite_assets(cls, user): + def get_user_favorite_assets(cls, user, asset_perms_id=None): from assets.models import Asset from perms.utils.asset.user_permission import get_user_granted_all_assets - asset_ids = get_user_granted_all_assets(user).values_list('id', flat=True) + asset_ids = get_user_granted_all_assets( + user, + via_mapping_node=False, + asset_perms_id=asset_perms_id + ).values_list('id', flat=True) query_name = cls.asset.field.related_query_name() return Asset.org_objects.filter(**{f'{query_name}__user_id': user.id}, id__in=asset_ids).distinct() diff --git a/apps/perms/api/asset/user_permission/user_permission_nodes.py b/apps/perms/api/asset/user_permission/user_permission_nodes.py index 72e7d4e33..58af37090 100644 --- a/apps/perms/api/asset/user_permission/user_permission_nodes.py +++ b/apps/perms/api/asset/user_permission/user_permission_nodes.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # import abc +from django.conf import settings from rest_framework.generics import ( ListAPIView ) @@ -16,7 +17,8 @@ from perms.utils.asset.user_permission import ( get_indirect_granted_node_children, get_user_granted_nodes_list_via_mapping_node, get_top_level_granted_nodes, - rebuild_user_tree_if_need, + rebuild_user_tree_if_need, get_favorite_node, + get_ungrouped_node ) @@ -113,7 +115,12 @@ class UserGrantedNodesMixin: user: User def get_nodes(self): - return get_user_granted_nodes_list_via_mapping_node(self.user) + nodes = [] + if settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE: + nodes.append(get_ungrouped_node(self.user)) + nodes.append(get_favorite_node(self.user)) + nodes.extend(get_user_granted_nodes_list_via_mapping_node(self.user)) + return nodes # ------------------------------------------ diff --git a/apps/perms/api/asset/user_permission/user_permission_nodes_with_assets.py b/apps/perms/api/asset/user_permission/user_permission_nodes_with_assets.py index 63e46aefd..28491ca8a 100644 --- a/apps/perms/api/asset/user_permission/user_permission_nodes_with_assets.py +++ b/apps/perms/api/asset/user_permission/user_permission_nodes_with_assets.py @@ -1,9 +1,12 @@ # -*- coding: utf-8 -*- # +from itertools import chain + from rest_framework.generics import ListAPIView from rest_framework.request import Request from rest_framework.response import Response -from django.db.models import F +from django.db.models import F, Value, CharField, Q +from django.conf import settings from orgs.utils import tmp_to_root_org from common.permissions import IsValidUser @@ -14,9 +17,12 @@ from perms.utils.asset.user_permission import ( get_user_direct_granted_assets, get_top_level_granted_nodes, get_user_granted_nodes_list_via_mapping_node, get_user_granted_all_assets, rebuild_user_tree_if_need, - get_user_all_assetpermissions_id, + get_user_all_assetpermissions_id, get_favorite_node, + get_ungrouped_node, compute_tmp_mapping_node_from_perm, + TMP_GRANTED_FIELD, count_direct_granted_node_assets, + count_node_all_granted_assets ) - +from perms.models import AssetPermission from assets.models import Asset, FavoriteAsset from assets.api import SerializeToTreeNodeMixin from perms.hands import Node @@ -27,6 +33,78 @@ logger = get_logger(__name__) class MyGrantedNodesWithAssetsAsTreeApi(SerializeToTreeNodeMixin, ListAPIView): permission_classes = (IsValidUser,) + def add_ungrouped_resource(self, data: list, user, asset_perms_id): + if not settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE: + return + + ungrouped_node = get_ungrouped_node(user, asset_perms_id=asset_perms_id) + direct_granted_assets = get_user_direct_granted_assets( + user, asset_perms_id=asset_perms_id + ).annotate( + parent_key=Value(ungrouped_node.key, output_field=CharField()) + ).prefetch_related('platform') + + data.extend(self.serialize_nodes([ungrouped_node], with_asset_amount=True)) + data.extend(self.serialize_assets(direct_granted_assets)) + + def add_favorite_resource(self, data: list, user, asset_perms_id): + favorite_node = get_favorite_node(user, asset_perms_id) + favorite_assets = FavoriteAsset.get_user_favorite_assets( + user, asset_perms_id=asset_perms_id + ).annotate( + parent_key=Value(favorite_node.key, output_field=CharField()) + ).prefetch_related('platform') + + data.extend(self.serialize_nodes([favorite_node], with_asset_amount=True)) + data.extend(self.serialize_assets(favorite_assets)) + + def add_node_filtered_by_system_user(self, data: list, user, asset_perms_id): + tmp_nodes = compute_tmp_mapping_node_from_perm(user, asset_perms_id=asset_perms_id) + granted_nodes_key = [] + for _node in tmp_nodes: + _granted = getattr(_node, TMP_GRANTED_FIELD, False) + if not _granted: + if settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE: + assets_amount = count_direct_granted_node_assets(user, _node.key, asset_perms_id) + else: + assets_amount = count_node_all_granted_assets(user, _node.key, asset_perms_id) + _node.assets_amount = assets_amount + else: + granted_nodes_key.append(_node.key) + + # 查询他们的子节点 + q = Q() + for _key in granted_nodes_key: + q |= Q(key__startswith=f'{_key}:') + + if q: + descendant_nodes = Node.objects.filter(q).distinct() + else: + descendant_nodes = Node.objects.none() + + data.extend(self.serialize_nodes(chain(tmp_nodes, descendant_nodes), with_asset_amount=True)) + + def add_assets(self, data: list, user, asset_perms_id): + if settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE: + all_assets = get_user_granted_all_assets( + user, + via_mapping_node=False, + include_direct_granted_assets=False, + asset_perms_id=asset_perms_id + ) + else: + all_assets = get_user_granted_all_assets( + user, + via_mapping_node=False, + include_direct_granted_assets=True, + asset_perms_id=asset_perms_id + ) + + all_assets = all_assets.annotate( + parent_key=F('nodes__key') + ).prefetch_related('platform') + data.extend(self.serialize_assets(all_assets)) + @tmp_to_root_org() def list(self, request: Request, *args, **kwargs): """ @@ -38,16 +116,25 @@ class MyGrantedNodesWithAssetsAsTreeApi(SerializeToTreeNodeMixin, ListAPIView): """ user = request.user - rebuild_user_tree_if_need(request, user) - all_nodes = get_user_granted_nodes_list_via_mapping_node(user) - all_assets = get_user_granted_all_assets(user) - all_assets = all_assets.annotate(parent_key=F('nodes__key')) - all_assets = all_assets.prefetch_related('platform') + data = [] + asset_perms_id = get_user_all_assetpermissions_id(user) - data = [ - *self.serialize_nodes(all_nodes, with_asset_amount=True), - *self.serialize_assets(all_assets) - ] + system_user_id = request.query_params.get('system_user') + if system_user_id: + asset_perms_id = list(AssetPermission.objects.valid().filter( + id__in=asset_perms_id, system_users__id=system_user_id, actions__gt=0 + ).values_list('id', flat=True).distinct()) + + self.add_ungrouped_resource(data, user, asset_perms_id) + self.add_favorite_resource(data, user, asset_perms_id) + + if system_user_id: + self.add_node_filtered_by_system_user(data, user, asset_perms_id) + else: + all_nodes = get_user_granted_nodes_list_via_mapping_node(user) + data.extend(self.serialize_nodes(all_nodes, with_asset_amount=True)) + + self.add_assets(data, user, asset_perms_id) return Response(data=data) diff --git a/apps/perms/utils/asset/user_permission.py b/apps/perms/utils/asset/user_permission.py index 91ad87143..274a27d4d 100644 --- a/apps/perms/utils/asset/user_permission.py +++ b/apps/perms/utils/asset/user_permission.py @@ -311,8 +311,12 @@ def get_user_granted_nodes_list_via_mapping_node(user): return all_nodes -def get_user_granted_all_assets(user, via_mapping_node=True): - asset_perms_id = get_user_all_assetpermissions_id(user) +def get_user_granted_all_assets( + user, via_mapping_node=True, + include_direct_granted_assets=True, asset_perms_id=None): + if asset_perms_id is None: + asset_perms_id = get_user_all_assetpermissions_id(user) + if via_mapping_node: granted_node_keys = UserGrantedMappingNode.objects.filter( user=user, granted=True, @@ -328,10 +332,16 @@ def get_user_granted_all_assets(user, via_mapping_node=True): granted_node_q |= Q(nodes__key__startswith=f'{_key}:') granted_node_q |= Q(nodes__key=_key) - assets__id = get_user_direct_granted_assets(user, asset_perms_id).values_list('id', flat=True) + if include_direct_granted_assets: + assets__id = get_user_direct_granted_assets(user, asset_perms_id).values_list('id', flat=True) + q = granted_node_q | Q(id__in=list(assets__id)) + else: + q = granted_node_q - q = granted_node_q | Q(id__in=list(assets__id)) - return Asset.org_objects.filter(q).distinct() + if q: + return Asset.org_objects.filter(q).distinct() + else: + return Asset.org_objects.none() def get_node_all_granted_assets(user: User, key): @@ -484,13 +494,15 @@ def get_user_direct_granted_assets(user, asset_perms_id=None): return assets -def count_user_direct_granted_assets(user): - count = get_user_direct_granted_assets(user).values_list('id').count() +def count_user_direct_granted_assets(user, asset_perms_id=None): + count = get_user_direct_granted_assets( + user, asset_perms_id=asset_perms_id + ).values_list('id').count() return count -def get_ungrouped_node(user): - assets_amount = count_user_direct_granted_assets(user) +def get_ungrouped_node(user, asset_perms_id=None): + assets_amount = count_user_direct_granted_assets(user, asset_perms_id) return Node( id=UNGROUPED_NODE_KEY, key=UNGROUPED_NODE_KEY, @@ -499,10 +511,10 @@ def get_ungrouped_node(user): ) -def get_favorite_node(user): - assets_amount = FavoriteAsset.get_user_favorite_assets(user)\ - .values_list('id')\ - .count() +def get_favorite_node(user, asset_perms_id=None): + assets_amount = FavoriteAsset.get_user_favorite_assets( + user, asset_perms_id=asset_perms_id + ).values_list('id').count() return Node( id=FAVORITE_NODE_KEY, key=FAVORITE_NODE_KEY,