From cd6dc6a72219aae4015923aa99821204f4b93f00 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Mon, 9 Nov 2020 17:30:50 +0800 Subject: [PATCH] =?UTF-8?q?fix(perms):=20=E7=94=B1=E4=BA=8E=E7=BB=84?= =?UTF-8?q?=E7=BB=87=E4=B8=8D=E5=AF=B9=EF=BC=8C=E5=AF=BC=E8=87=B4=E7=94=9F?= =?UTF-8?q?=E6=88=90=E6=88=96=E6=98=BE=E7=A4=BA=E6=8E=88=E6=9D=83=E6=A0=91?= =?UTF-8?q?=E9=94=99=E8=AF=AF=20(#4957)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * perf(perms): 优化授权树生成速度 * fix(perms): 由于组织不对,导致生成或显示授权树错误 Co-authored-by: xinwen --- .../user_permission_nodes_with_assets.py | 2 + apps/perms/utils/asset/user_permission.py | 59 ++++++++++++------- 2 files changed, 39 insertions(+), 22 deletions(-) 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 995c5362a..63e46aefd 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 @@ -5,6 +5,7 @@ from rest_framework.request import Request from rest_framework.response import Response from django.db.models import F +from orgs.utils import tmp_to_root_org from common.permissions import IsValidUser from common.utils import get_logger, get_object_or_none from .mixin import UserNodeGrantStatusDispatchMixin, ForUserMixin, ForAdminMixin @@ -26,6 +27,7 @@ logger = get_logger(__name__) class MyGrantedNodesWithAssetsAsTreeApi(SerializeToTreeNodeMixin, ListAPIView): permission_classes = (IsValidUser,) + @tmp_to_root_org() def list(self, request: Request, *args, **kwargs): """ 此算法依赖 UserGrantedMappingNode diff --git a/apps/perms/utils/asset/user_permission.py b/apps/perms/utils/asset/user_permission.py index 8ca7789f1..91ad87143 100644 --- a/apps/perms/utils/asset/user_permission.py +++ b/apps/perms/utils/asset/user_permission.py @@ -148,13 +148,15 @@ def rebuild_user_mapping_nodes_with_lock(user: User): rebuild_user_mapping_nodes(user) -@tmp_to_root_org() -def compute_tmp_mapping_node_from_perm(user: User): +def compute_tmp_mapping_node_from_perm(user: User, asset_perms_id=None): node_only_fields = ('id', 'key', 'parent_key', 'assets_amount') + if asset_perms_id is None: + asset_perms_id = get_user_all_assetpermissions_id(user) + # 查询直接授权节点 nodes = Node.objects.filter( - get_user_resources_q_granted_by_permissions(user) + granted_by_permissions__id__in=asset_perms_id ).distinct().only(*node_only_fields) granted_key_set = {_node.key for _node in nodes} @@ -180,7 +182,7 @@ def compute_tmp_mapping_node_from_perm(user: User): def process_direct_granted_assets(): # 查询直接授权资产 asset_ids = Asset.objects.filter( - get_user_resources_q_granted_by_permissions(user) + granted_by_permissions__id__in=asset_perms_id ).distinct().values_list('id', flat=True) # 查询授权资产关联的节点设置 granted_asset_nodes = Node.objects.filter( @@ -234,7 +236,7 @@ def create_mapping_nodes(user, nodes, clear=True): UserGrantedMappingNode.objects.bulk_create(to_create) -def set_node_granted_assets_amount(user, node): +def set_node_granted_assets_amount(user, node, asset_perms_id=None): """ 不依赖`UserGrantedMappingNode`直接查询授权计算资产数量 """ @@ -243,17 +245,22 @@ def set_node_granted_assets_amount(user, node): assets_amount = node.assets_amount else: if settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE: - assets_amount = count_direct_granted_node_assets(user, node.key) + assets_amount = count_direct_granted_node_assets(user, node.key, asset_perms_id) else: - assets_amount = count_node_all_granted_assets(user, node.key) + assets_amount = count_node_all_granted_assets(user, node.key, asset_perms_id) setattr(node, TMP_GRANTED_ASSETS_AMOUNT_FIELD, assets_amount) +@tmp_to_root_org() def rebuild_user_mapping_nodes(user): logger.info(f'>>> {dt_formater(now())} start rebuild {user} mapping nodes') - tmp_nodes = compute_tmp_mapping_node_from_perm(user) + asset_perms_id = get_user_all_assetpermissions_id(user) + if not asset_perms_id: + # 没有授权直接返回 + return + tmp_nodes = compute_tmp_mapping_node_from_perm(user, asset_perms_id=asset_perms_id) for _node in tmp_nodes: - set_node_granted_assets_amount(user, _node) + set_node_granted_assets_amount(user, _node, asset_perms_id) create_mapping_nodes(user, tmp_nodes) logger.info(f'>>> {dt_formater(now())} end rebuild {user} mapping nodes') @@ -375,13 +382,16 @@ def get_node_all_granted_assets(user: User, key): return assets -def get_direct_granted_node_ids(user: User, key): - granted_q = get_user_resources_q_granted_by_permissions(user) +def get_direct_granted_node_ids(user: User, key, asset_perms_id=None): + if asset_perms_id is None: + asset_perms_id = get_user_all_assetpermissions_id(user) # 先查出该节点下的直接授权节点 granted_nodes = Node.objects.filter( Q(key__startswith=f'{key}:') | Q(key=key) - ).filter(granted_q).distinct().only('id', 'key') + ).filter( + granted_by_permissions__id__in=asset_perms_id + ).distinct().only('id', 'key') node_ids = set() # 根据直接授权节点查询他们的子节点 @@ -396,33 +406,38 @@ def get_direct_granted_node_ids(user: User, key): return node_ids -def get_node_all_granted_assets_from_perm(user: User, key): +def get_node_all_granted_assets_from_perm(user: User, key, asset_perms_id=None): """ 此算法依据 `AssetPermission` 的数据查询 1. 查询该节点下的直接授权节点 2. 查询该节点下授权资产关联的节点 """ - granted_q = get_user_resources_q_granted_by_permissions(user) + if asset_perms_id is None: + asset_perms_id = get_user_all_assetpermissions_id(user) + # 直接授权资产查询条件 - q = (Q(nodes__key__startswith=f'{key}:') | Q(nodes__key=key)) & granted_q - node_ids = get_direct_granted_node_ids(user, key) + q = ( + Q(nodes__key__startswith=f'{key}:') | Q(nodes__key=key) + ) & Q(granted_by_permissions__id__in=asset_perms_id) + + node_ids = get_direct_granted_node_ids(user, key, asset_perms_id) q |= Q(nodes__id__in=node_ids) asset_qs = Asset.objects.filter(q).distinct() return asset_qs -def get_direct_granted_node_assets_from_perm(user: User, key): - node_ids = get_direct_granted_node_ids(user, key) +def get_direct_granted_node_assets_from_perm(user: User, key, asset_perms_id=None): + node_ids = get_direct_granted_node_ids(user, key, asset_perms_id) asset_qs = Asset.objects.filter(nodes__id__in=node_ids).distinct() return asset_qs -def count_node_all_granted_assets(user: User, key): - return get_node_all_granted_assets_from_perm(user, key).count() +def count_node_all_granted_assets(user: User, key, asset_perms_id=None): + return get_node_all_granted_assets_from_perm(user, key, asset_perms_id).count() -def count_direct_granted_node_assets(user: User, key): - return get_direct_granted_node_assets_from_perm(user, key).count() +def count_direct_granted_node_assets(user: User, key, asset_perms_id=None): + return get_direct_granted_node_assets_from_perm(user, key, asset_perms_id).count() def get_indirect_granted_node_children(user, key=''):