mirror of https://github.com/jumpserver/jumpserver
fix(perms): 由于组织不对,导致生成或显示授权树错误 (#4957)
* perf(perms): 优化授权树生成速度 * fix(perms): 由于组织不对,导致生成或显示授权树错误 Co-authored-by: xinwen <coderWen@126.com>pull/4966/head
parent
150552d734
commit
cd6dc6a722
|
@ -5,6 +5,7 @@ from rest_framework.request import Request
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from django.db.models import F
|
from django.db.models import F
|
||||||
|
|
||||||
|
from orgs.utils import tmp_to_root_org
|
||||||
from common.permissions import IsValidUser
|
from common.permissions import IsValidUser
|
||||||
from common.utils import get_logger, get_object_or_none
|
from common.utils import get_logger, get_object_or_none
|
||||||
from .mixin import UserNodeGrantStatusDispatchMixin, ForUserMixin, ForAdminMixin
|
from .mixin import UserNodeGrantStatusDispatchMixin, ForUserMixin, ForAdminMixin
|
||||||
|
@ -26,6 +27,7 @@ logger = get_logger(__name__)
|
||||||
class MyGrantedNodesWithAssetsAsTreeApi(SerializeToTreeNodeMixin, ListAPIView):
|
class MyGrantedNodesWithAssetsAsTreeApi(SerializeToTreeNodeMixin, ListAPIView):
|
||||||
permission_classes = (IsValidUser,)
|
permission_classes = (IsValidUser,)
|
||||||
|
|
||||||
|
@tmp_to_root_org()
|
||||||
def list(self, request: Request, *args, **kwargs):
|
def list(self, request: Request, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
此算法依赖 UserGrantedMappingNode
|
此算法依赖 UserGrantedMappingNode
|
||||||
|
|
|
@ -148,13 +148,15 @@ def rebuild_user_mapping_nodes_with_lock(user: User):
|
||||||
rebuild_user_mapping_nodes(user)
|
rebuild_user_mapping_nodes(user)
|
||||||
|
|
||||||
|
|
||||||
@tmp_to_root_org()
|
def compute_tmp_mapping_node_from_perm(user: User, asset_perms_id=None):
|
||||||
def compute_tmp_mapping_node_from_perm(user: User):
|
|
||||||
node_only_fields = ('id', 'key', 'parent_key', 'assets_amount')
|
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(
|
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)
|
).distinct().only(*node_only_fields)
|
||||||
granted_key_set = {_node.key for _node in nodes}
|
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():
|
def process_direct_granted_assets():
|
||||||
# 查询直接授权资产
|
# 查询直接授权资产
|
||||||
asset_ids = Asset.objects.filter(
|
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)
|
).distinct().values_list('id', flat=True)
|
||||||
# 查询授权资产关联的节点设置
|
# 查询授权资产关联的节点设置
|
||||||
granted_asset_nodes = Node.objects.filter(
|
granted_asset_nodes = Node.objects.filter(
|
||||||
|
@ -234,7 +236,7 @@ def create_mapping_nodes(user, nodes, clear=True):
|
||||||
UserGrantedMappingNode.objects.bulk_create(to_create)
|
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`直接查询授权计算资产数量
|
不依赖`UserGrantedMappingNode`直接查询授权计算资产数量
|
||||||
"""
|
"""
|
||||||
|
@ -243,17 +245,22 @@ def set_node_granted_assets_amount(user, node):
|
||||||
assets_amount = node.assets_amount
|
assets_amount = node.assets_amount
|
||||||
else:
|
else:
|
||||||
if settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE:
|
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:
|
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)
|
setattr(node, TMP_GRANTED_ASSETS_AMOUNT_FIELD, assets_amount)
|
||||||
|
|
||||||
|
|
||||||
|
@tmp_to_root_org()
|
||||||
def rebuild_user_mapping_nodes(user):
|
def rebuild_user_mapping_nodes(user):
|
||||||
logger.info(f'>>> {dt_formater(now())} start rebuild {user} mapping nodes')
|
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:
|
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)
|
create_mapping_nodes(user, tmp_nodes)
|
||||||
logger.info(f'>>> {dt_formater(now())} end rebuild {user} mapping 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
|
return assets
|
||||||
|
|
||||||
|
|
||||||
def get_direct_granted_node_ids(user: User, key):
|
def get_direct_granted_node_ids(user: User, key, asset_perms_id=None):
|
||||||
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)
|
||||||
|
|
||||||
# 先查出该节点下的直接授权节点
|
# 先查出该节点下的直接授权节点
|
||||||
granted_nodes = Node.objects.filter(
|
granted_nodes = Node.objects.filter(
|
||||||
Q(key__startswith=f'{key}:') | Q(key=key)
|
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()
|
node_ids = set()
|
||||||
# 根据直接授权节点查询他们的子节点
|
# 根据直接授权节点查询他们的子节点
|
||||||
|
@ -396,33 +406,38 @@ def get_direct_granted_node_ids(user: User, key):
|
||||||
return node_ids
|
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` 的数据查询
|
此算法依据 `AssetPermission` 的数据查询
|
||||||
1. 查询该节点下的直接授权节点
|
1. 查询该节点下的直接授权节点
|
||||||
2. 查询该节点下授权资产关联的节点
|
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
|
q = (
|
||||||
node_ids = get_direct_granted_node_ids(user, key)
|
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)
|
q |= Q(nodes__id__in=node_ids)
|
||||||
asset_qs = Asset.objects.filter(q).distinct()
|
asset_qs = Asset.objects.filter(q).distinct()
|
||||||
return asset_qs
|
return asset_qs
|
||||||
|
|
||||||
|
|
||||||
def get_direct_granted_node_assets_from_perm(user: 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)
|
node_ids = get_direct_granted_node_ids(user, key, asset_perms_id)
|
||||||
asset_qs = Asset.objects.filter(nodes__id__in=node_ids).distinct()
|
asset_qs = Asset.objects.filter(nodes__id__in=node_ids).distinct()
|
||||||
return asset_qs
|
return asset_qs
|
||||||
|
|
||||||
|
|
||||||
def count_node_all_granted_assets(user: User, key):
|
def count_node_all_granted_assets(user: User, key, asset_perms_id=None):
|
||||||
return get_node_all_granted_assets_from_perm(user, key).count()
|
return get_node_all_granted_assets_from_perm(user, key, asset_perms_id).count()
|
||||||
|
|
||||||
|
|
||||||
def count_direct_granted_node_assets(user: User, key):
|
def count_direct_granted_node_assets(user: User, key, asset_perms_id=None):
|
||||||
return get_direct_granted_node_assets_from_perm(user, key).count()
|
return get_direct_granted_node_assets_from_perm(user, key, asset_perms_id).count()
|
||||||
|
|
||||||
|
|
||||||
def get_indirect_granted_node_children(user, key=''):
|
def get_indirect_granted_node_children(user, key=''):
|
||||||
|
|
Loading…
Reference in New Issue