2021-02-05 05:29:29 +00:00
|
|
|
|
from collections import defaultdict
|
|
|
|
|
from typing import List, Tuple
|
2020-08-16 15:08:58 +00:00
|
|
|
|
|
|
|
|
|
from django.conf import settings
|
2021-02-05 05:29:29 +00:00
|
|
|
|
from django.db.models import Q, QuerySet
|
2022-06-06 05:30:04 +00:00
|
|
|
|
from django.utils.translation import gettext as _
|
2020-08-16 15:08:58 +00:00
|
|
|
|
|
2022-12-09 05:05:34 +00:00
|
|
|
|
from users.models import User
|
|
|
|
|
from assets.utils import NodeAssetsUtil
|
2022-11-15 07:26:31 +00:00
|
|
|
|
from assets.models import (
|
2022-12-09 05:05:34 +00:00
|
|
|
|
Asset,
|
|
|
|
|
FavoriteAsset,
|
|
|
|
|
AssetQuerySet,
|
|
|
|
|
NodeQuerySet
|
|
|
|
|
)
|
|
|
|
|
from orgs.utils import (
|
|
|
|
|
tmp_to_org,
|
|
|
|
|
current_org,
|
|
|
|
|
ensure_in_real_or_default_org,
|
2022-11-15 07:26:31 +00:00
|
|
|
|
)
|
|
|
|
|
from common.db.models import output_as_string, UnionQuerySet
|
|
|
|
|
from common.utils import get_logger
|
|
|
|
|
from common.utils.common import lazyproperty, timeit
|
2022-12-09 05:05:34 +00:00
|
|
|
|
|
2021-02-05 05:29:29 +00:00
|
|
|
|
from perms.models import (
|
2022-12-09 05:05:34 +00:00
|
|
|
|
AssetPermission,
|
|
|
|
|
PermNode,
|
|
|
|
|
UserAssetGrantedTreeNodeRelation
|
2021-02-05 05:29:29 +00:00
|
|
|
|
)
|
2022-12-08 11:30:16 +00:00
|
|
|
|
from .permission import AssetPermissionUtil
|
2022-11-15 07:26:31 +00:00
|
|
|
|
|
2021-02-05 05:29:29 +00:00
|
|
|
|
NodeFrom = UserAssetGrantedTreeNodeRelation.NodeFrom
|
|
|
|
|
NODE_ONLY_FIELDS = ('id', 'key', 'parent_key', 'org_id')
|
2020-08-16 15:08:58 +00:00
|
|
|
|
|
2021-02-05 05:29:29 +00:00
|
|
|
|
logger = get_logger(__name__)
|
2020-08-16 15:08:58 +00:00
|
|
|
|
|
|
|
|
|
|
2021-02-05 05:29:29 +00:00
|
|
|
|
class UserGrantedUtilsBase:
|
|
|
|
|
user: User
|
2020-08-16 15:08:58 +00:00
|
|
|
|
|
2021-02-05 05:29:29 +00:00
|
|
|
|
def __init__(self, user, asset_perm_ids=None):
|
|
|
|
|
self.user = user
|
2021-02-25 06:45:21 +00:00
|
|
|
|
self._asset_perm_ids = asset_perm_ids and set(asset_perm_ids)
|
2020-08-16 15:08:58 +00:00
|
|
|
|
|
2021-02-05 05:29:29 +00:00
|
|
|
|
@lazyproperty
|
|
|
|
|
def asset_perm_ids(self) -> set:
|
|
|
|
|
if self._asset_perm_ids:
|
|
|
|
|
return self._asset_perm_ids
|
2020-08-16 15:08:58 +00:00
|
|
|
|
|
2022-12-08 11:30:16 +00:00
|
|
|
|
asset_perm_ids = AssetPermissionUtil().get_permissions_for_user(self.user, flat=True)
|
2021-02-05 05:29:29 +00:00
|
|
|
|
return asset_perm_ids
|
2020-08-16 15:08:58 +00:00
|
|
|
|
|
|
|
|
|
|
2021-02-05 05:29:29 +00:00
|
|
|
|
class UserGrantedAssetsQueryUtils(UserGrantedUtilsBase):
|
|
|
|
|
|
2021-02-08 06:59:20 +00:00
|
|
|
|
def get_favorite_assets(self) -> QuerySet:
|
2021-02-07 02:15:39 +00:00
|
|
|
|
assets = self.get_all_granted_assets()
|
2022-12-20 03:25:44 +00:00
|
|
|
|
asset_ids = FavoriteAsset.objects.filter(user=self.user).values_list('asset_id', flat=True)
|
|
|
|
|
assets = assets.filter(id__in=list(asset_ids))
|
2021-02-05 05:29:29 +00:00
|
|
|
|
return assets
|
|
|
|
|
|
|
|
|
|
def get_ungroup_assets(self) -> AssetQuerySet:
|
|
|
|
|
return self.get_direct_granted_assets()
|
|
|
|
|
|
|
|
|
|
def get_direct_granted_assets(self) -> AssetQuerySet:
|
|
|
|
|
queryset = Asset.objects.order_by().filter(
|
|
|
|
|
granted_by_permissions__id__in=self.asset_perm_ids
|
|
|
|
|
).distinct()
|
|
|
|
|
return queryset
|
|
|
|
|
|
2021-02-07 02:15:39 +00:00
|
|
|
|
def get_direct_granted_nodes_assets(self) -> AssetQuerySet:
|
2021-02-05 05:29:29 +00:00
|
|
|
|
granted_node_ids = AssetPermission.nodes.through.objects.filter(
|
|
|
|
|
assetpermission_id__in=self.asset_perm_ids
|
|
|
|
|
).values_list('node_id', flat=True).distinct()
|
|
|
|
|
granted_node_ids = list(granted_node_ids)
|
|
|
|
|
granted_nodes = PermNode.objects.filter(id__in=granted_node_ids).only('id', 'key')
|
|
|
|
|
queryset = PermNode.get_nodes_all_assets(*granted_nodes)
|
|
|
|
|
return queryset
|
|
|
|
|
|
2021-02-07 02:15:39 +00:00
|
|
|
|
def get_all_granted_assets(self) -> QuerySet:
|
2021-02-05 05:29:29 +00:00
|
|
|
|
nodes_assets = self.get_direct_granted_nodes_assets()
|
|
|
|
|
assets = self.get_direct_granted_assets()
|
2022-12-20 03:25:44 +00:00
|
|
|
|
# queryset = UnionQuerySet(nodes_assets, assets)
|
|
|
|
|
# return queryset
|
|
|
|
|
node_asset_ids = nodes_assets.values_list('id', flat=True)
|
|
|
|
|
direct_asset_ids = assets.values_list('id', flat=True)
|
|
|
|
|
asset_ids = list(node_asset_ids) + list(direct_asset_ids)
|
|
|
|
|
asset = Asset.objects.filter(id__in=asset_ids)
|
|
|
|
|
return asset
|
2021-02-05 05:29:29 +00:00
|
|
|
|
|
2021-02-07 02:15:39 +00:00
|
|
|
|
def get_node_all_assets(self, id) -> Tuple[PermNode, QuerySet]:
|
2021-02-05 05:29:29 +00:00
|
|
|
|
node = PermNode.objects.get(id=id)
|
|
|
|
|
granted_status = node.get_granted_status(self.user)
|
|
|
|
|
if granted_status == NodeFrom.granted:
|
|
|
|
|
assets = PermNode.get_nodes_all_assets(node)
|
|
|
|
|
return node, assets
|
|
|
|
|
elif granted_status in (NodeFrom.asset, NodeFrom.child):
|
|
|
|
|
node.use_granted_assets_amount()
|
2021-02-07 02:15:39 +00:00
|
|
|
|
assets = self._get_indirect_granted_node_all_assets(node)
|
2021-02-05 05:29:29 +00:00
|
|
|
|
return node, assets
|
|
|
|
|
else:
|
|
|
|
|
node.assets_amount = 0
|
|
|
|
|
return node, Asset.objects.none()
|
|
|
|
|
|
|
|
|
|
def get_node_assets(self, key) -> AssetQuerySet:
|
|
|
|
|
node = PermNode.objects.get(key=key)
|
|
|
|
|
granted_status = node.get_granted_status(self.user)
|
|
|
|
|
|
|
|
|
|
if granted_status == NodeFrom.granted:
|
2021-02-08 06:59:20 +00:00
|
|
|
|
assets = Asset.objects.order_by().filter(nodes__id=node.id)
|
2021-02-05 05:29:29 +00:00
|
|
|
|
elif granted_status == NodeFrom.asset:
|
2021-03-23 10:36:25 +00:00
|
|
|
|
assets = self._get_indirect_granted_node_assets(node.id)
|
2021-02-05 05:29:29 +00:00
|
|
|
|
else:
|
2021-03-23 10:36:25 +00:00
|
|
|
|
assets = Asset.objects.none()
|
2022-08-11 07:45:03 +00:00
|
|
|
|
assets = assets.order_by('name')
|
2021-03-23 10:36:25 +00:00
|
|
|
|
return assets
|
2020-11-09 09:30:50 +00:00
|
|
|
|
|
2021-02-05 05:29:29 +00:00
|
|
|
|
def _get_indirect_granted_node_assets(self, id) -> AssetQuerySet:
|
2021-02-08 06:59:20 +00:00
|
|
|
|
assets = Asset.objects.order_by().filter(nodes__id=id).distinct() & self.get_direct_granted_assets()
|
2021-02-05 05:29:29 +00:00
|
|
|
|
return assets
|
2020-08-16 15:08:58 +00:00
|
|
|
|
|
2021-02-07 02:15:39 +00:00
|
|
|
|
def _get_indirect_granted_node_all_assets(self, node) -> QuerySet:
|
2020-08-16 15:08:58 +00:00
|
|
|
|
"""
|
2021-02-05 05:29:29 +00:00
|
|
|
|
此算法依据 `UserAssetGrantedTreeNodeRelation` 的数据查询
|
|
|
|
|
1. 查询该节点下的直接授权节点
|
|
|
|
|
2. 查询该节点下授权资产关联的节点
|
2020-08-16 15:08:58 +00:00
|
|
|
|
"""
|
2021-02-05 05:29:29 +00:00
|
|
|
|
user = self.user
|
|
|
|
|
|
|
|
|
|
# 查询该节点下的授权节点
|
|
|
|
|
granted_nodes = UserAssetGrantedTreeNodeRelation.objects.filter(
|
|
|
|
|
user=user, node_from=NodeFrom.granted
|
|
|
|
|
).filter(
|
|
|
|
|
Q(node_key__startswith=f'{node.key}:')
|
|
|
|
|
).only('node_id', 'node_key')
|
2021-02-25 06:45:21 +00:00
|
|
|
|
|
|
|
|
|
for n in granted_nodes:
|
|
|
|
|
n.id = n.node_id
|
|
|
|
|
|
2021-02-05 05:29:29 +00:00
|
|
|
|
node_assets = PermNode.get_nodes_all_assets(*granted_nodes)
|
|
|
|
|
|
|
|
|
|
# 查询该节点下的资产授权节点
|
|
|
|
|
only_asset_granted_node_ids = UserAssetGrantedTreeNodeRelation.objects.filter(
|
|
|
|
|
user=user, node_from=NodeFrom.asset
|
|
|
|
|
).filter(
|
|
|
|
|
Q(node_key__startswith=f'{node.key}:')
|
|
|
|
|
).values_list('node_id', flat=True)
|
|
|
|
|
|
|
|
|
|
only_asset_granted_node_ids = list(only_asset_granted_node_ids)
|
|
|
|
|
if node.node_from == NodeFrom.asset:
|
|
|
|
|
only_asset_granted_node_ids.append(node.id)
|
|
|
|
|
|
|
|
|
|
assets = Asset.objects.filter(
|
|
|
|
|
nodes__id__in=only_asset_granted_node_ids,
|
|
|
|
|
granted_by_permissions__id__in=self.asset_perm_ids
|
|
|
|
|
).distinct().order_by()
|
2021-02-07 02:15:39 +00:00
|
|
|
|
granted_assets = UnionQuerySet(node_assets, assets)
|
2021-02-05 05:29:29 +00:00
|
|
|
|
return granted_assets
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class UserGrantedNodesQueryUtils(UserGrantedUtilsBase):
|
2021-03-23 10:36:25 +00:00
|
|
|
|
def sort(self, nodes):
|
|
|
|
|
nodes = sorted(nodes, key=lambda x: x.value)
|
|
|
|
|
return nodes
|
|
|
|
|
|
2021-02-05 05:29:29 +00:00
|
|
|
|
def get_node_children(self, key):
|
|
|
|
|
if not key:
|
|
|
|
|
return self.get_top_level_nodes()
|
|
|
|
|
|
2021-07-28 06:21:53 +00:00
|
|
|
|
nodes = PermNode.objects.none()
|
2021-09-13 07:23:12 +00:00
|
|
|
|
if key in [PermNode.FAVORITE_NODE_KEY, PermNode.UNGROUPED_NODE_KEY]:
|
2021-07-28 06:33:02 +00:00
|
|
|
|
return nodes
|
|
|
|
|
|
|
|
|
|
node = PermNode.objects.get(key=key)
|
|
|
|
|
granted_status = node.get_granted_status(self.user)
|
|
|
|
|
if granted_status == NodeFrom.granted:
|
|
|
|
|
nodes = PermNode.objects.filter(parent_key=key)
|
|
|
|
|
elif granted_status in (NodeFrom.asset, NodeFrom.child):
|
|
|
|
|
nodes = self.get_indirect_granted_node_children(key)
|
2021-03-23 10:36:25 +00:00
|
|
|
|
nodes = self.sort(nodes)
|
|
|
|
|
return nodes
|
2020-08-16 15:08:58 +00:00
|
|
|
|
|
2021-02-05 05:29:29 +00:00
|
|
|
|
def get_indirect_granted_node_children(self, key):
|
|
|
|
|
"""
|
|
|
|
|
获取用户授权树中未授权节点的子节点
|
|
|
|
|
只匹配在 `UserAssetGrantedTreeNodeRelation` 中存在的节点
|
|
|
|
|
"""
|
|
|
|
|
user = self.user
|
|
|
|
|
nodes = PermNode.objects.filter(
|
|
|
|
|
granted_node_rels__user=user,
|
|
|
|
|
parent_key=key
|
|
|
|
|
).annotate(
|
|
|
|
|
**PermNode.annotate_granted_node_rel_fields
|
|
|
|
|
).distinct()
|
|
|
|
|
|
|
|
|
|
# 设置节点授权资产数量
|
|
|
|
|
for node in nodes:
|
|
|
|
|
node.use_granted_assets_amount()
|
|
|
|
|
return nodes
|
|
|
|
|
|
|
|
|
|
def get_top_level_nodes(self):
|
|
|
|
|
nodes = self.get_special_nodes()
|
2021-03-23 10:36:25 +00:00
|
|
|
|
real_nodes = self.get_indirect_granted_node_children('')
|
2022-11-15 07:26:31 +00:00
|
|
|
|
nodes.extend(real_nodes)
|
|
|
|
|
if len(real_nodes) == 1:
|
|
|
|
|
children = self.get_node_children(real_nodes[0].key)
|
|
|
|
|
nodes.extend(children)
|
2021-02-05 05:29:29 +00:00
|
|
|
|
return nodes
|
|
|
|
|
|
|
|
|
|
def get_ungrouped_node(self):
|
|
|
|
|
assets_util = UserGrantedAssetsQueryUtils(self.user, self.asset_perm_ids)
|
|
|
|
|
assets_amount = assets_util.get_direct_granted_assets().count()
|
|
|
|
|
return PermNode.get_ungrouped_node(assets_amount)
|
|
|
|
|
|
|
|
|
|
def get_favorite_node(self):
|
|
|
|
|
assets_query_utils = UserGrantedAssetsQueryUtils(self.user, self.asset_perm_ids)
|
|
|
|
|
assets_amount = assets_query_utils.get_favorite_assets().values_list('id').count()
|
|
|
|
|
return PermNode.get_favorite_node(assets_amount)
|
|
|
|
|
|
2022-06-06 05:30:04 +00:00
|
|
|
|
@staticmethod
|
|
|
|
|
def get_root_node():
|
|
|
|
|
name = _('My assets')
|
|
|
|
|
node = {
|
|
|
|
|
'id': '',
|
|
|
|
|
'name': name,
|
|
|
|
|
'title': name,
|
|
|
|
|
'pId': '',
|
|
|
|
|
'open': True,
|
|
|
|
|
'isParent': True,
|
|
|
|
|
'meta': {
|
|
|
|
|
'type': 'root'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return node
|
|
|
|
|
|
2021-02-05 05:29:29 +00:00
|
|
|
|
def get_special_nodes(self):
|
|
|
|
|
nodes = []
|
2020-09-27 08:02:44 +00:00
|
|
|
|
if settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE:
|
2021-02-05 05:29:29 +00:00
|
|
|
|
ungrouped_node = self.get_ungrouped_node()
|
|
|
|
|
nodes.append(ungrouped_node)
|
|
|
|
|
favorite_node = self.get_favorite_node()
|
|
|
|
|
nodes.append(favorite_node)
|
|
|
|
|
return nodes
|
|
|
|
|
|
|
|
|
|
@timeit
|
|
|
|
|
def get_whole_tree_nodes(self, with_special=True):
|
|
|
|
|
"""
|
|
|
|
|
这里的 granted nodes, 是整棵树需要的node,推算出来的也算
|
2022-09-30 08:08:28 +00:00
|
|
|
|
:param with_special:
|
2021-02-05 05:29:29 +00:00
|
|
|
|
:return:
|
|
|
|
|
"""
|
2022-11-15 07:26:31 +00:00
|
|
|
|
nodes = PermNode.objects.filter(granted_node_rels__user=self.user) \
|
|
|
|
|
.annotate(**PermNode.annotate_granted_node_rel_fields) \
|
|
|
|
|
.distinct()
|
2021-02-05 05:29:29 +00:00
|
|
|
|
|
|
|
|
|
key_to_node_mapper = {}
|
|
|
|
|
nodes_descendant_q = Q()
|
|
|
|
|
|
|
|
|
|
for node in nodes:
|
|
|
|
|
node.use_granted_assets_amount()
|
2021-03-12 10:40:24 +00:00
|
|
|
|
key_to_node_mapper[node.key] = node
|
2021-02-05 05:29:29 +00:00
|
|
|
|
|
|
|
|
|
if node.node_from == NodeFrom.granted:
|
|
|
|
|
# 直接授权的节点
|
|
|
|
|
# 增加查询后代节点的过滤条件
|
|
|
|
|
nodes_descendant_q |= Q(key__startswith=f'{node.key}:')
|
|
|
|
|
|
|
|
|
|
if nodes_descendant_q:
|
|
|
|
|
descendant_nodes = PermNode.objects.filter(
|
|
|
|
|
nodes_descendant_q
|
2020-11-03 09:31:25 +00:00
|
|
|
|
)
|
2021-02-05 05:29:29 +00:00
|
|
|
|
for node in descendant_nodes:
|
|
|
|
|
key_to_node_mapper[node.key] = node
|
|
|
|
|
|
|
|
|
|
all_nodes = []
|
|
|
|
|
if with_special:
|
|
|
|
|
special_nodes = self.get_special_nodes()
|
|
|
|
|
all_nodes.extend(special_nodes)
|
|
|
|
|
all_nodes.extend(key_to_node_mapper.values())
|
|
|
|
|
return all_nodes
|