mirror of https://github.com/jumpserver/jumpserver
perf(perms): 优化授权树生成速度
parent
5c46ff20de
commit
02b8533ea0
|
@ -9,12 +9,11 @@ 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
|
||||||
from ...utils.user_asset_permission import (
|
from ...utils.user_asset_permission import (
|
||||||
get_user_resources_q_granted_by_permissions,
|
|
||||||
get_indirect_granted_node_children, UNGROUPED_NODE_KEY, FAVORITE_NODE_KEY,
|
get_indirect_granted_node_children, UNGROUPED_NODE_KEY, FAVORITE_NODE_KEY,
|
||||||
get_user_direct_granted_assets, get_top_level_granted_nodes,
|
get_user_direct_granted_assets, get_top_level_granted_nodes,
|
||||||
get_user_granted_nodes_list_via_mapping_node,
|
get_user_granted_nodes_list_via_mapping_node,
|
||||||
get_user_granted_all_assets, rebuild_user_tree_if_need,
|
get_user_granted_all_assets, rebuild_user_tree_if_need,
|
||||||
get_user_all_assetpermission_ids,
|
get_user_all_assetpermissions_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
from assets.models import Asset, FavoriteAsset
|
from assets.models import Asset, FavoriteAsset
|
||||||
|
@ -64,7 +63,7 @@ class UserGrantedNodeChildrenWithAssetsAsTreeForAdminApi(ForAdminMixin, UserNode
|
||||||
|
|
||||||
def get_data_on_node_indirect_granted(self, key):
|
def get_data_on_node_indirect_granted(self, key):
|
||||||
user = self.user
|
user = self.user
|
||||||
asset_perm_ids = get_user_all_assetpermission_ids(user)
|
asset_perm_ids = get_user_all_assetpermissions_id(user)
|
||||||
|
|
||||||
nodes = get_indirect_granted_node_children(user, key)
|
nodes = get_indirect_granted_node_children(user, key)
|
||||||
|
|
||||||
|
|
|
@ -32,27 +32,6 @@ TMP_ASSET_GRANTED_FIELD = '_asset_granted'
|
||||||
TMP_GRANTED_ASSETS_AMOUNT_FIELD = '_granted_assets_amount'
|
TMP_GRANTED_ASSETS_AMOUNT_FIELD = '_granted_assets_amount'
|
||||||
|
|
||||||
|
|
||||||
# 使用场景
|
|
||||||
# Asset.objects.filter(get_user_resources_q_granted_by_permissions(user))
|
|
||||||
def get_user_resources_q_granted_by_permissions(user: User):
|
|
||||||
"""
|
|
||||||
获取用户关联的 asset permission 或者 用户组关联的 asset permission 获取规则,
|
|
||||||
前提 AssetPermission 对象中的 related_name 为 granted_by_permissions
|
|
||||||
:param user:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
_now = now()
|
|
||||||
return reduce(and_, (
|
|
||||||
Q(granted_by_permissions__date_start__lt=_now),
|
|
||||||
Q(granted_by_permissions__date_expired__gt=_now),
|
|
||||||
Q(granted_by_permissions__is_active=True),
|
|
||||||
(
|
|
||||||
Q(granted_by_permissions__users=user) |
|
|
||||||
Q(granted_by_permissions__user_groups__users=user)
|
|
||||||
)
|
|
||||||
))
|
|
||||||
|
|
||||||
|
|
||||||
# 使用场景
|
# 使用场景
|
||||||
# `Node.objects.annotate(**node_annotate_mapping_node)`
|
# `Node.objects.annotate(**node_annotate_mapping_node)`
|
||||||
node_annotate_mapping_node = {
|
node_annotate_mapping_node = {
|
||||||
|
@ -147,12 +126,15 @@ def rebuild_user_mapping_nodes_with_lock(user: User):
|
||||||
|
|
||||||
|
|
||||||
@tmp_to_root_org()
|
@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')
|
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}
|
||||||
|
|
||||||
|
@ -178,7 +160,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(
|
||||||
|
@ -232,7 +214,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`直接查询授权计算资产数量
|
||||||
"""
|
"""
|
||||||
|
@ -241,17 +223,18 @@ 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)
|
||||||
|
|
||||||
|
|
||||||
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)
|
||||||
|
tmp_nodes = compute_tmp_mapping_node_from_perm(user, 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')
|
||||||
|
|
||||||
|
@ -303,7 +286,7 @@ def get_user_granted_nodes_list_via_mapping_node(user):
|
||||||
|
|
||||||
|
|
||||||
def get_user_granted_all_assets(user, via_mapping_node=True):
|
def get_user_granted_all_assets(user, via_mapping_node=True):
|
||||||
asset_perm_ids = get_user_all_assetpermission_ids(user)
|
asset_perm_ids = get_user_all_assetpermissions_id(user)
|
||||||
if via_mapping_node:
|
if via_mapping_node:
|
||||||
granted_node_keys = UserGrantedMappingNode.objects.filter(
|
granted_node_keys = UserGrantedMappingNode.objects.filter(
|
||||||
user=user, granted=True,
|
user=user, granted=True,
|
||||||
|
@ -365,7 +348,7 @@ def get_node_all_granted_assets(user: User, key):
|
||||||
|
|
||||||
if only_asset_granted_nodes_qs:
|
if only_asset_granted_nodes_qs:
|
||||||
only_asset_granted_nodes_q = reduce(or_, only_asset_granted_nodes_qs)
|
only_asset_granted_nodes_q = reduce(or_, only_asset_granted_nodes_qs)
|
||||||
asset_perms_id = get_user_all_assetpermission_ids(user)
|
asset_perms_id = get_user_all_assetpermissions_id(user)
|
||||||
only_asset_granted_nodes_q &= Q(granted_by_permissions__id__in=asset_perms_id)
|
only_asset_granted_nodes_q &= Q(granted_by_permissions__id__in=asset_perms_id)
|
||||||
q.append(only_asset_granted_nodes_q)
|
q.append(only_asset_granted_nodes_q)
|
||||||
|
|
||||||
|
@ -374,13 +357,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()
|
||||||
# 根据直接授权节点查询他们的子节点
|
# 根据直接授权节点查询他们的子节点
|
||||||
|
@ -395,33 +381,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=''):
|
||||||
|
@ -454,7 +445,7 @@ def get_top_level_granted_nodes(user):
|
||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
|
|
||||||
def get_user_all_assetpermission_ids(user: User):
|
def get_user_all_assetpermissions_id(user: User):
|
||||||
asset_perm_ids = set()
|
asset_perm_ids = set()
|
||||||
asset_perm_ids.update(
|
asset_perm_ids.update(
|
||||||
AssetPermission.objects.valid().filter(users=user).distinct().values_list('id', flat=True)
|
AssetPermission.objects.valid().filter(users=user).distinct().values_list('id', flat=True)
|
||||||
|
@ -467,7 +458,7 @@ def get_user_all_assetpermission_ids(user: User):
|
||||||
|
|
||||||
def get_user_direct_granted_assets(user, asset_perm_ids=None):
|
def get_user_direct_granted_assets(user, asset_perm_ids=None):
|
||||||
if asset_perm_ids is None:
|
if asset_perm_ids is None:
|
||||||
asset_perm_ids = get_user_all_assetpermission_ids(user)
|
asset_perm_ids = get_user_all_assetpermissions_id(user)
|
||||||
assets = Asset.org_objects.filter(granted_by_permissions__id__in=asset_perm_ids).distinct()
|
assets = Asset.org_objects.filter(granted_by_permissions__id__in=asset_perm_ids).distinct()
|
||||||
return assets
|
return assets
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue