fix(perms): 由于组织不对,导致生成或显示授权树错误 (#4957)

* perf(perms): 优化授权树生成速度

* fix(perms): 由于组织不对,导致生成或显示授权树错误

Co-authored-by: xinwen <coderWen@126.com>
pull/4966/head
fit2bot 2020-11-09 17:30:50 +08:00 committed by GitHub
parent 150552d734
commit cd6dc6a722
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 22 deletions

View File

@ -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

View File

@ -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=''):