mirror of https://github.com/jumpserver/jumpserver
perf: 优化授权规则 user-permission 用户授权相关的 API; 包括 assets, nodes, tree-asset, tree-node, tree-node-with-asset;
parent
1cab84bb62
commit
6cda28c63d
|
@ -30,16 +30,13 @@ __all__ = [
|
||||||
|
|
||||||
class AssetFilterSet(BaseFilterSet):
|
class AssetFilterSet(BaseFilterSet):
|
||||||
type = django_filters.CharFilter(field_name="platform__type", lookup_expr="exact")
|
type = django_filters.CharFilter(field_name="platform__type", lookup_expr="exact")
|
||||||
category = django_filters.CharFilter(
|
category = django_filters.CharFilter(field_name="platform__category", lookup_expr="exact")
|
||||||
field_name="platform__category", lookup_expr="exact"
|
|
||||||
)
|
|
||||||
hostname = django_filters.CharFilter(field_name="name", lookup_expr="exact")
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Asset
|
model = Asset
|
||||||
fields = [
|
fields = [
|
||||||
"id", "name", "address", "is_active",
|
"id", "name", "address", "is_active",
|
||||||
"type", "category", "hostname"
|
"type", "category"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,8 @@ __all__ = [
|
||||||
|
|
||||||
|
|
||||||
class UserGroupGrantedAssetsApi(ListAPIView):
|
class UserGroupGrantedAssetsApi(ListAPIView):
|
||||||
serializer_class = serializers.AssetGrantedSerializer
|
serializer_class = serializers.AssetPermedSerializer
|
||||||
only_fields = serializers.AssetGrantedSerializer.Meta.only_fields
|
only_fields = serializers.AssetPermedSerializer.Meta.only_fields
|
||||||
filterset_fields = ['name', 'address', 'id', 'comment']
|
filterset_fields = ['name', 'address', 'id', 'comment']
|
||||||
search_fields = ['name', 'address', 'comment']
|
search_fields = ['name', 'address', 'comment']
|
||||||
rbac_perms = {
|
rbac_perms = {
|
||||||
|
@ -60,8 +60,8 @@ class UserGroupGrantedAssetsApi(ListAPIView):
|
||||||
|
|
||||||
|
|
||||||
class UserGroupGrantedNodeAssetsApi(ListAPIView):
|
class UserGroupGrantedNodeAssetsApi(ListAPIView):
|
||||||
serializer_class = serializers.AssetGrantedSerializer
|
serializer_class = serializers.AssetPermedSerializer
|
||||||
only_fields = serializers.AssetGrantedSerializer.Meta.only_fields
|
only_fields = serializers.AssetPermedSerializer.Meta.only_fields
|
||||||
filterset_fields = ['name', 'address', 'id', 'comment']
|
filterset_fields = ['name', 'address', 'id', 'comment']
|
||||||
search_fields = ['name', 'address', 'comment']
|
search_fields = ['name', 'address', 'comment']
|
||||||
rbac_perms = {
|
rbac_perms = {
|
||||||
|
|
|
@ -2,5 +2,5 @@
|
||||||
#
|
#
|
||||||
from .nodes import *
|
from .nodes import *
|
||||||
from .assets import *
|
from .assets import *
|
||||||
from .nodes_with_assets import *
|
|
||||||
from .accounts import *
|
from .accounts import *
|
||||||
|
from .tree import *
|
||||||
|
|
|
@ -25,6 +25,5 @@ class UserPermedAssetAccountsApi(SelfOrPKUserMixin, ListAPIView):
|
||||||
return asset
|
return asset
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
util = PermAccountUtil()
|
accounts = PermAccountUtil().get_permed_accounts_for_user(self.user, self.asset)
|
||||||
accounts = util.get_permed_accounts_for_user(self.user, self.asset)
|
|
||||||
return accounts
|
return accounts
|
||||||
|
|
|
@ -1,109 +1,76 @@
|
||||||
from django.conf import settings
|
import abc
|
||||||
from rest_framework.generics import ListAPIView
|
from rest_framework.generics import ListAPIView
|
||||||
|
|
||||||
from assets.models import Asset, Node
|
from assets.models import Asset, Node
|
||||||
from common.utils import get_logger
|
from assets.api.asset.asset import AssetFilterSet
|
||||||
from perms import serializers
|
from perms import serializers
|
||||||
from perms.pagination import AllGrantedAssetPagination
|
from perms.pagination import AllPermedAssetPagination
|
||||||
from perms.pagination import NodeGrantedAssetPagination
|
from perms.pagination import NodePermedAssetPagination
|
||||||
from perms.utils.user_permission import UserGrantedAssetsQueryUtils
|
from perms.utils.user_permission import UserGrantedAssetsQueryUtils
|
||||||
|
from common.utils import get_logger, lazyproperty
|
||||||
|
|
||||||
from .mixin import (
|
from .mixin import (
|
||||||
SelfOrPKUserMixin, RebuildTreeMixin,
|
SelfOrPKUserMixin
|
||||||
PermedAssetSerializerMixin, AssetsTreeFormatMixin
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
'UserAllPermedAssetsApi',
|
||||||
'UserDirectPermedAssetsApi',
|
'UserDirectPermedAssetsApi',
|
||||||
'UserFavoriteAssetsApi',
|
'UserFavoriteAssetsApi',
|
||||||
'UserDirectPermedAssetsAsTreeApi',
|
|
||||||
'UserUngroupAssetsAsTreeApi',
|
|
||||||
'UserAllPermedAssetsApi',
|
|
||||||
'UserPermedNodeAssetsApi',
|
'UserPermedNodeAssetsApi',
|
||||||
]
|
]
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class UserDirectPermedAssetsApi(SelfOrPKUserMixin, PermedAssetSerializerMixin, ListAPIView):
|
class BaseUserPermedAssetsApi(SelfOrPKUserMixin, ListAPIView):
|
||||||
""" 直接授权给用户的资产 """
|
ordering = ('name',)
|
||||||
only_fields = serializers.AssetGrantedSerializer.Meta.only_fields
|
ordering_fields = ("name", "address")
|
||||||
|
search_fields = ('name', 'address', 'comment')
|
||||||
|
filterset_class = AssetFilterSet
|
||||||
|
serializer_class = serializers.AssetPermedSerializer
|
||||||
|
only_fields = serializers.AssetPermedSerializer.Meta.only_fields
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
if getattr(self, 'swagger_fake_view', False):
|
if getattr(self, 'swagger_fake_view', False):
|
||||||
return Asset.objects.none()
|
return Asset.objects.none()
|
||||||
|
assets = self.get_assets()
|
||||||
assets = UserGrantedAssetsQueryUtils(self.user) \
|
|
||||||
.get_direct_granted_assets() \
|
|
||||||
.prefetch_related('platform') \
|
|
||||||
.only(*self.only_fields)
|
|
||||||
return assets
|
|
||||||
|
|
||||||
|
|
||||||
class UserFavoriteAssetsApi(SelfOrPKUserMixin, PermedAssetSerializerMixin, ListAPIView):
|
|
||||||
only_fields = serializers.AssetGrantedSerializer.Meta.only_fields
|
|
||||||
""" 用户收藏的授权资产 """
|
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
if getattr(self, 'swagger_fake_view', False):
|
|
||||||
return Asset.objects.none()
|
|
||||||
|
|
||||||
user = self.user
|
|
||||||
utils = UserGrantedAssetsQueryUtils(user)
|
|
||||||
assets = utils.get_favorite_assets()
|
|
||||||
assets = assets.prefetch_related('platform').only(*self.only_fields)
|
assets = assets.prefetch_related('platform').only(*self.only_fields)
|
||||||
return assets
|
return assets
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
class UserDirectPermedAssetsAsTreeApi(RebuildTreeMixin, AssetsTreeFormatMixin, UserDirectPermedAssetsApi):
|
def get_assets(self):
|
||||||
""" 用户直接授权的资产作为树 """
|
|
||||||
only_fields = serializers.AssetGrantedSerializer.Meta.only_fields
|
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
if getattr(self, 'swagger_fake_view', False):
|
|
||||||
return Asset.objects.none()
|
return Asset.objects.none()
|
||||||
|
|
||||||
assets = UserGrantedAssetsQueryUtils(self.user) \
|
@lazyproperty
|
||||||
.get_direct_granted_assets() \
|
def query_asset_util(self):
|
||||||
.prefetch_related('platform') \
|
return UserGrantedAssetsQueryUtils(self.user)
|
||||||
.only(*self.only_fields)
|
|
||||||
return assets
|
|
||||||
|
|
||||||
|
|
||||||
class UserUngroupAssetsAsTreeApi(UserDirectPermedAssetsAsTreeApi):
|
class UserAllPermedAssetsApi(BaseUserPermedAssetsApi):
|
||||||
""" 用户未分组节点下的资产作为树 """
|
pagination_class = AllPermedAssetPagination
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_assets(self):
|
||||||
queryset = super().get_queryset()
|
return self.query_asset_util.get_all_granted_assets()
|
||||||
if not settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE:
|
|
||||||
queryset = queryset.none()
|
|
||||||
return queryset
|
|
||||||
|
|
||||||
|
|
||||||
class UserAllPermedAssetsApi(SelfOrPKUserMixin, PermedAssetSerializerMixin, ListAPIView):
|
class UserDirectPermedAssetsApi(BaseUserPermedAssetsApi):
|
||||||
only_fields = serializers.AssetGrantedSerializer.Meta.only_fields
|
def get_assets(self):
|
||||||
pagination_class = AllGrantedAssetPagination
|
return self.query_asset_util.get_direct_granted_assets()
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
if getattr(self, 'swagger_fake_view', False):
|
|
||||||
return Asset.objects.none()
|
|
||||||
queryset = UserGrantedAssetsQueryUtils(self.user).get_all_granted_assets()
|
|
||||||
only_fields = [i for i in self.only_fields if i not in ['protocols']]
|
|
||||||
queryset = queryset.prefetch_related('platform', 'protocols').only(*only_fields)
|
|
||||||
return queryset
|
|
||||||
|
|
||||||
|
|
||||||
class UserPermedNodeAssetsApi(SelfOrPKUserMixin, PermedAssetSerializerMixin, ListAPIView):
|
class UserFavoriteAssetsApi(BaseUserPermedAssetsApi):
|
||||||
only_fields = serializers.AssetGrantedSerializer.Meta.only_fields
|
def get_assets(self):
|
||||||
pagination_class = NodeGrantedAssetPagination
|
return self.query_asset_util.get_favorite_assets()
|
||||||
kwargs: dict
|
|
||||||
|
|
||||||
|
class UserPermedNodeAssetsApi(BaseUserPermedAssetsApi):
|
||||||
|
pagination_class = NodePermedAssetPagination
|
||||||
pagination_node: Node
|
pagination_node: Node
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_assets(self):
|
||||||
if getattr(self, 'swagger_fake_view', False):
|
|
||||||
return Asset.objects.none()
|
|
||||||
node_id = self.kwargs.get("node_id")
|
node_id = self.kwargs.get("node_id")
|
||||||
|
node, assets = self.query_asset_util.get_node_all_assets(node_id)
|
||||||
node, assets = UserGrantedAssetsQueryUtils(self.user).get_node_all_assets(node_id)
|
|
||||||
assets = assets.prefetch_related('platform').only(*self.only_fields)
|
|
||||||
self.pagination_node = node
|
self.pagination_node = node
|
||||||
return assets
|
return assets
|
||||||
|
|
|
@ -3,27 +3,13 @@
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from rest_framework.request import Request
|
from rest_framework.request import Request
|
||||||
from rest_framework.response import Response
|
|
||||||
|
|
||||||
from assets.api.asset.asset import AssetFilterSet
|
|
||||||
from assets.api.mixin import SerializeToTreeNodeMixin
|
|
||||||
from common.exceptions import JMSObjectDoesNotExist
|
|
||||||
from common.http import is_true
|
|
||||||
from common.utils import is_uuid
|
|
||||||
from perms import serializers
|
|
||||||
from perms.utils.user_permission import UserGrantedTreeRefreshController
|
|
||||||
from rbac.permissions import RBACPermission
|
|
||||||
from users.models import User
|
from users.models import User
|
||||||
|
from rbac.permissions import RBACPermission
|
||||||
|
from common.utils import is_uuid
|
||||||
|
from common.exceptions import JMSObjectDoesNotExist
|
||||||
|
|
||||||
|
__all__ = ['SelfOrPKUserMixin']
|
||||||
class RebuildTreeMixin:
|
|
||||||
user: User
|
|
||||||
|
|
||||||
def get(self, request: Request, *args, **kwargs):
|
|
||||||
force = is_true(request.query_params.get('rebuild_tree'))
|
|
||||||
controller = UserGrantedTreeRefreshController(self.user)
|
|
||||||
controller.refresh_if_need(force)
|
|
||||||
return super().get(request, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class SelfOrPKUserMixin:
|
class SelfOrPKUserMixin:
|
||||||
|
@ -72,32 +58,3 @@ class SelfOrPKUserMixin:
|
||||||
def request_user_is_self(self):
|
def request_user_is_self(self):
|
||||||
return self.kwargs.get('user') in ['my', 'self']
|
return self.kwargs.get('user') in ['my', 'self']
|
||||||
|
|
||||||
|
|
||||||
class PermedAssetSerializerMixin:
|
|
||||||
serializer_class = serializers.AssetGrantedSerializer
|
|
||||||
filterset_class = AssetFilterSet
|
|
||||||
search_fields = ['name', 'address', 'comment']
|
|
||||||
ordering_fields = ("name", "address")
|
|
||||||
ordering = ('name',)
|
|
||||||
|
|
||||||
|
|
||||||
class AssetsTreeFormatMixin(SerializeToTreeNodeMixin):
|
|
||||||
"""
|
|
||||||
将 资产 序列化成树的结构返回
|
|
||||||
"""
|
|
||||||
filter_queryset: callable
|
|
||||||
get_queryset: callable
|
|
||||||
|
|
||||||
filterset_fields = ['name', 'address', 'id', 'comment']
|
|
||||||
search_fields = ['name', 'address', 'comment']
|
|
||||||
|
|
||||||
def list(self, request: Request, *args, **kwargs):
|
|
||||||
queryset = self.filter_queryset(self.get_queryset())
|
|
||||||
|
|
||||||
if request.query_params.get('search'):
|
|
||||||
# 如果用户搜索的条件不精准,会导致返回大量的无意义数据。
|
|
||||||
# 这里限制一下返回数据的最大条数
|
|
||||||
queryset = queryset[:999]
|
|
||||||
queryset = sorted(queryset, key=lambda asset: asset.name)
|
|
||||||
data = self.serialize_assets(queryset, None)
|
|
||||||
return Response(data=data)
|
|
||||||
|
|
|
@ -1,133 +1,49 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
import abc
|
import abc
|
||||||
from rest_framework.request import Request
|
|
||||||
from rest_framework.response import Response
|
|
||||||
from rest_framework.generics import ListAPIView
|
from rest_framework.generics import ListAPIView
|
||||||
|
|
||||||
from common.utils import get_logger
|
from assets.models import Node
|
||||||
from assets.api.mixin import SerializeToTreeNodeMixin
|
|
||||||
from perms import serializers
|
from perms import serializers
|
||||||
from perms.hands import User
|
|
||||||
from perms.utils.user_permission import UserGrantedNodesQueryUtils
|
from perms.utils.user_permission import UserGrantedNodesQueryUtils
|
||||||
|
from common.utils import get_logger, lazyproperty
|
||||||
|
|
||||||
from .mixin import SelfOrPKUserMixin, RebuildTreeMixin
|
from .mixin import SelfOrPKUserMixin
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'UserPermedNodesApi',
|
'UserAllPermedNodesApi',
|
||||||
'UserPermedNodesAsTreeApi',
|
|
||||||
'UserPermedNodeChildrenApi',
|
'UserPermedNodeChildrenApi',
|
||||||
'UserPermedNodeChildrenAsTreeApi',
|
|
||||||
'BaseGrantedNodeAsTreeApi',
|
|
||||||
'UserGrantedNodesMixin',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class _GrantedNodeStructApi(ListAPIView, metaclass=abc.ABCMeta):
|
class BaseUserPermedNodesApi(SelfOrPKUserMixin, ListAPIView):
|
||||||
@property
|
|
||||||
def user(self):
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def get_nodes(self):
|
|
||||||
# 不使用 `get_queryset` 单独定义 `get_nodes` 的原因是
|
|
||||||
# `get_nodes` 返回的不一定是 `queryset`
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
|
|
||||||
class NodeChildrenMixin:
|
|
||||||
def get_children(self):
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def get_nodes(self):
|
|
||||||
nodes = self.get_children()
|
|
||||||
return nodes
|
|
||||||
|
|
||||||
|
|
||||||
class BaseGrantedNodeApi(_GrantedNodeStructApi, metaclass=abc.ABCMeta):
|
|
||||||
serializer_class = serializers.NodeGrantedSerializer
|
serializer_class = serializers.NodeGrantedSerializer
|
||||||
|
|
||||||
def list(self, request, *args, **kwargs):
|
def get_queryset(self):
|
||||||
nodes = self.get_nodes()
|
if getattr(self, 'swagger_fake_view', False):
|
||||||
serializer = self.get_serializer(nodes, many=True)
|
return Node.objects.none()
|
||||||
return Response(serializer.data)
|
return self.get_nodes()
|
||||||
|
|
||||||
|
|
||||||
class BaseNodeChildrenApi(NodeChildrenMixin, BaseGrantedNodeApi, metaclass=abc.ABCMeta):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class BaseGrantedNodeAsTreeApi(SerializeToTreeNodeMixin, _GrantedNodeStructApi, metaclass=abc.ABCMeta):
|
|
||||||
def list(self, request: Request, *args, **kwargs):
|
|
||||||
nodes = self.get_nodes()
|
|
||||||
nodes = self.serialize_nodes(nodes, with_asset_amount=True)
|
|
||||||
return Response(data=nodes)
|
|
||||||
|
|
||||||
|
|
||||||
class BaseNodeChildrenAsTreeApi(NodeChildrenMixin, BaseGrantedNodeAsTreeApi, metaclass=abc.ABCMeta):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class UserGrantedNodeChildrenMixin:
|
|
||||||
user: User
|
|
||||||
request: Request
|
|
||||||
|
|
||||||
def get_children(self):
|
|
||||||
user = self.user
|
|
||||||
key = self.request.query_params.get('key')
|
|
||||||
nodes = UserGrantedNodesQueryUtils(user).get_node_children(key)
|
|
||||||
return nodes
|
|
||||||
|
|
||||||
|
|
||||||
class UserGrantedNodesMixin:
|
|
||||||
"""
|
|
||||||
查询用户授权的所有节点 直接授权节点 + 授权资产关联的节点
|
|
||||||
"""
|
|
||||||
user: User
|
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
def get_nodes(self):
|
def get_nodes(self):
|
||||||
utils = UserGrantedNodesQueryUtils(self.user)
|
return []
|
||||||
nodes = utils.get_whole_tree_nodes()
|
|
||||||
return nodes
|
@lazyproperty
|
||||||
|
def query_node_util(self):
|
||||||
|
return UserGrantedNodesQueryUtils(self.user)
|
||||||
|
|
||||||
|
|
||||||
# API
|
class UserAllPermedNodesApi(BaseUserPermedNodesApi):
|
||||||
|
|
||||||
|
|
||||||
class UserPermedNodeChildrenApi(
|
|
||||||
SelfOrPKUserMixin,
|
|
||||||
UserGrantedNodeChildrenMixin,
|
|
||||||
BaseNodeChildrenApi
|
|
||||||
):
|
|
||||||
""" 用户授权的节点下的子节点"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class UserPermedNodeChildrenAsTreeApi(
|
|
||||||
SelfOrPKUserMixin,
|
|
||||||
RebuildTreeMixin,
|
|
||||||
UserGrantedNodeChildrenMixin,
|
|
||||||
BaseNodeChildrenAsTreeApi
|
|
||||||
):
|
|
||||||
""" 用户授权的节点下的子节点树"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class UserPermedNodesApi(
|
|
||||||
SelfOrPKUserMixin,
|
|
||||||
UserGrantedNodesMixin,
|
|
||||||
BaseGrantedNodeApi
|
|
||||||
):
|
|
||||||
""" 用户授权的节点 """
|
""" 用户授权的节点 """
|
||||||
pass
|
def get_nodes(self):
|
||||||
|
return self.query_node_util.get_whole_tree_nodes()
|
||||||
|
|
||||||
|
|
||||||
class UserPermedNodesAsTreeApi(
|
class UserPermedNodeChildrenApi(BaseUserPermedNodesApi):
|
||||||
SelfOrPKUserMixin,
|
""" 用户授权的节点下的子节点 """
|
||||||
RebuildTreeMixin,
|
def get_nodes(self):
|
||||||
UserGrantedNodesMixin,
|
key = self.request.query_params.get('key')
|
||||||
BaseGrantedNodeAsTreeApi
|
nodes = self.query_node_util.get_node_children(key)
|
||||||
):
|
return nodes
|
||||||
""" 用户授权的节点树 """
|
|
||||||
pass
|
|
||||||
|
|
|
@ -1,158 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
from django.conf import settings
|
|
||||||
from django.db.models import F, Value, CharField
|
|
||||||
from rest_framework.generics import ListAPIView
|
|
||||||
from rest_framework.request import Request
|
|
||||||
from rest_framework.response import Response
|
|
||||||
|
|
||||||
from common.utils import get_logger, get_object_or_none
|
|
||||||
from common.utils.common import timeit
|
|
||||||
from common.permissions import IsValidUser
|
|
||||||
|
|
||||||
from assets.models import Asset
|
|
||||||
from assets.api import SerializeToTreeNodeMixin
|
|
||||||
from perms.hands import Node
|
|
||||||
from perms.models import AssetPermission, PermNode
|
|
||||||
from perms.utils.user_permission import (
|
|
||||||
UserGrantedTreeBuildUtils, get_user_all_asset_perm_ids,
|
|
||||||
UserGrantedNodesQueryUtils, UserGrantedAssetsQueryUtils,
|
|
||||||
)
|
|
||||||
|
|
||||||
from .mixin import SelfOrPKUserMixin, RebuildTreeMixin
|
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class MyGrantedNodesWithAssetsAsTreeApi(SerializeToTreeNodeMixin, ListAPIView):
|
|
||||||
permission_classes = (IsValidUser,)
|
|
||||||
|
|
||||||
@timeit
|
|
||||||
def add_ungrouped_resource(self, data: list, nodes_query_utils, assets_query_utils):
|
|
||||||
if not settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE:
|
|
||||||
return
|
|
||||||
ungrouped_node = nodes_query_utils.get_ungrouped_node()
|
|
||||||
|
|
||||||
direct_granted_assets = assets_query_utils.get_direct_granted_assets().annotate(
|
|
||||||
parent_key=Value(ungrouped_node.key, output_field=CharField())
|
|
||||||
).prefetch_related('platform')
|
|
||||||
|
|
||||||
data.extend(self.serialize_nodes([ungrouped_node], with_asset_amount=True))
|
|
||||||
data.extend(self.serialize_assets(direct_granted_assets))
|
|
||||||
|
|
||||||
@timeit
|
|
||||||
def add_favorite_resource(self, data: list, nodes_query_utils, assets_query_utils):
|
|
||||||
favorite_node = nodes_query_utils.get_favorite_node()
|
|
||||||
|
|
||||||
favorite_assets = assets_query_utils.get_favorite_assets()
|
|
||||||
favorite_assets = favorite_assets.annotate(
|
|
||||||
parent_key=Value(favorite_node.key, output_field=CharField())
|
|
||||||
).prefetch_related('platform')
|
|
||||||
|
|
||||||
data.extend(self.serialize_nodes([favorite_node], with_asset_amount=True))
|
|
||||||
data.extend(self.serialize_assets(favorite_assets))
|
|
||||||
|
|
||||||
@timeit
|
|
||||||
def add_node_filtered_by_system_user(self, data: list, user, asset_perm_ids):
|
|
||||||
utils = UserGrantedTreeBuildUtils(user, asset_perm_ids)
|
|
||||||
nodes = utils.get_whole_tree_nodes()
|
|
||||||
data.extend(self.serialize_nodes(nodes, with_asset_amount=True))
|
|
||||||
|
|
||||||
def add_assets(self, data: list, assets_query_utils: UserGrantedAssetsQueryUtils):
|
|
||||||
if settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE:
|
|
||||||
all_assets = assets_query_utils.get_direct_granted_nodes_assets()
|
|
||||||
else:
|
|
||||||
all_assets = assets_query_utils.get_all_granted_assets()
|
|
||||||
all_assets = all_assets.annotate(parent_key=F('nodes__key')).prefetch_related('platform')
|
|
||||||
data.extend(self.serialize_assets(all_assets))
|
|
||||||
|
|
||||||
def list(self, request: Request, *args, **kwargs):
|
|
||||||
"""
|
|
||||||
此算法依赖 UserGrantedMappingNode
|
|
||||||
获取所有授权的节点和资产
|
|
||||||
|
|
||||||
Node = UserGrantedMappingNode + 授权节点的子节点
|
|
||||||
Asset = 授权节点的资产 + 直接授权的资产
|
|
||||||
"""
|
|
||||||
|
|
||||||
user = request.user
|
|
||||||
data = []
|
|
||||||
asset_perm_ids = get_user_all_asset_perm_ids(user)
|
|
||||||
|
|
||||||
system_user_id = request.query_params.get('system_user')
|
|
||||||
if system_user_id:
|
|
||||||
asset_perm_ids = list(AssetPermission.objects.valid().filter(
|
|
||||||
id__in=asset_perm_ids, system_users__id=system_user_id, actions__gt=0
|
|
||||||
).values_list('id', flat=True).distinct())
|
|
||||||
|
|
||||||
nodes_query_utils = UserGrantedNodesQueryUtils(user, asset_perm_ids)
|
|
||||||
assets_query_utils = UserGrantedAssetsQueryUtils(user, asset_perm_ids)
|
|
||||||
|
|
||||||
self.add_ungrouped_resource(data, nodes_query_utils, assets_query_utils)
|
|
||||||
self.add_favorite_resource(data, nodes_query_utils, assets_query_utils)
|
|
||||||
|
|
||||||
if system_user_id:
|
|
||||||
# 有系统用户筛选的需要重新计算树结构
|
|
||||||
self.add_node_filtered_by_system_user(data, user, asset_perm_ids)
|
|
||||||
else:
|
|
||||||
all_nodes = nodes_query_utils.get_whole_tree_nodes(with_special=False)
|
|
||||||
data.extend(self.serialize_nodes(all_nodes, with_asset_amount=True))
|
|
||||||
|
|
||||||
self.add_assets(data, assets_query_utils)
|
|
||||||
return Response(data=data)
|
|
||||||
|
|
||||||
|
|
||||||
class GrantedNodeChildrenWithAssetsAsTreeApiMixin(SerializeToTreeNodeMixin,
|
|
||||||
ListAPIView):
|
|
||||||
"""
|
|
||||||
带资产的授权树
|
|
||||||
"""
|
|
||||||
user: None
|
|
||||||
|
|
||||||
def ensure_key(self):
|
|
||||||
key = self.request.query_params.get('key', None)
|
|
||||||
id = self.request.query_params.get('id', None)
|
|
||||||
|
|
||||||
if key is not None:
|
|
||||||
return key
|
|
||||||
|
|
||||||
node = get_object_or_none(Node, id=id)
|
|
||||||
if node:
|
|
||||||
return node.key
|
|
||||||
|
|
||||||
def list(self, request: Request, *args, **kwargs):
|
|
||||||
user = self.user
|
|
||||||
key = self.ensure_key()
|
|
||||||
|
|
||||||
nodes_query_utils = UserGrantedNodesQueryUtils(user)
|
|
||||||
assets_query_utils = UserGrantedAssetsQueryUtils(user)
|
|
||||||
|
|
||||||
nodes = PermNode.objects.none()
|
|
||||||
assets = Asset.objects.none()
|
|
||||||
all_tree_nodes = []
|
|
||||||
|
|
||||||
if not key:
|
|
||||||
nodes = nodes_query_utils.get_top_level_nodes()
|
|
||||||
elif key == PermNode.UNGROUPED_NODE_KEY:
|
|
||||||
assets = assets_query_utils.get_ungroup_assets()
|
|
||||||
elif key == PermNode.FAVORITE_NODE_KEY:
|
|
||||||
assets = assets_query_utils.get_favorite_assets()
|
|
||||||
else:
|
|
||||||
nodes = nodes_query_utils.get_node_children(key)
|
|
||||||
assets = assets_query_utils.get_node_assets(key)
|
|
||||||
assets = assets.prefetch_related('platform')
|
|
||||||
|
|
||||||
tree_nodes = self.serialize_nodes(nodes, with_asset_amount=True)
|
|
||||||
tree_assets = self.serialize_assets(assets, key)
|
|
||||||
all_tree_nodes.extend(tree_nodes)
|
|
||||||
all_tree_nodes.extend(tree_assets)
|
|
||||||
return Response(data=all_tree_nodes)
|
|
||||||
|
|
||||||
|
|
||||||
class UserGrantedNodeChildrenWithAssetsAsTreeApi(
|
|
||||||
SelfOrPKUserMixin,
|
|
||||||
RebuildTreeMixin,
|
|
||||||
GrantedNodeChildrenWithAssetsAsTreeApiMixin
|
|
||||||
):
|
|
||||||
""" 用户授权的节点的子节点与资产树 """
|
|
||||||
pass
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
from .asset import *
|
||||||
|
from .node import *
|
||||||
|
from .node_with_asset import *
|
|
@ -0,0 +1,48 @@
|
||||||
|
from django.conf import settings
|
||||||
|
from rest_framework.response import Response
|
||||||
|
|
||||||
|
from assets.models import Asset
|
||||||
|
from assets.api import SerializeToTreeNodeMixin
|
||||||
|
from common.utils import get_logger
|
||||||
|
|
||||||
|
from ..assets import UserDirectPermedAssetsApi
|
||||||
|
from .mixin import RebuildTreeMixin
|
||||||
|
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'UserDirectPermedAssetsAsTreeApi',
|
||||||
|
'UserUngroupAssetsAsTreeApi',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class AssetTreeMixin(RebuildTreeMixin, SerializeToTreeNodeMixin):
|
||||||
|
""" 将资产序列化成树节点的结构返回 """
|
||||||
|
filter_queryset: callable
|
||||||
|
get_queryset: callable
|
||||||
|
|
||||||
|
ordering = ('name',)
|
||||||
|
filterset_fields = ('id', 'name', 'address', 'comment')
|
||||||
|
search_fields = ('name', 'address', 'comment')
|
||||||
|
|
||||||
|
def list(self, request, *args, **kwargs):
|
||||||
|
assets = self.filter_queryset(self.get_queryset())
|
||||||
|
if request.query_params.get('search'):
|
||||||
|
""" 限制返回数量, 搜索的条件不精准时,会返回大量的无意义数据 """
|
||||||
|
assets = assets[:999]
|
||||||
|
data = self.serialize_assets(assets, None)
|
||||||
|
return Response(data=data)
|
||||||
|
|
||||||
|
|
||||||
|
class UserDirectPermedAssetsAsTreeApi(AssetTreeMixin, UserDirectPermedAssetsApi):
|
||||||
|
""" 用户 '直接授权的资产' 作为树 """
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class UserUngroupAssetsAsTreeApi(UserDirectPermedAssetsAsTreeApi):
|
||||||
|
""" 用户 '未分组节点的资产(直接授权的资产)' 作为树 """
|
||||||
|
def get_assets(self):
|
||||||
|
if settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE:
|
||||||
|
return super().get_assets()
|
||||||
|
return Asset.objects.none()
|
|
@ -0,0 +1,17 @@
|
||||||
|
from rest_framework.request import Request
|
||||||
|
|
||||||
|
from users.models import User
|
||||||
|
from perms.utils.user_permission import UserGrantedTreeRefreshController
|
||||||
|
from common.http import is_true
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = ['RebuildTreeMixin']
|
||||||
|
|
||||||
|
|
||||||
|
class RebuildTreeMixin:
|
||||||
|
user: User
|
||||||
|
|
||||||
|
def get(self, request: Request, *args, **kwargs):
|
||||||
|
force = is_true(request.query_params.get('rebuild_tree'))
|
||||||
|
UserGrantedTreeRefreshController(self.user).refresh_if_need(force)
|
||||||
|
return super().get(request, *args, **kwargs)
|
|
@ -0,0 +1,39 @@
|
||||||
|
from rest_framework.response import Response
|
||||||
|
|
||||||
|
from assets.api import SerializeToTreeNodeMixin
|
||||||
|
from common.utils import get_logger
|
||||||
|
|
||||||
|
from .mixin import RebuildTreeMixin
|
||||||
|
from ..nodes import (
|
||||||
|
UserAllPermedNodesApi,
|
||||||
|
UserPermedNodeChildrenApi,
|
||||||
|
)
|
||||||
|
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'UserAllPermedNodesAsTreeApi',
|
||||||
|
'UserPermedNodeChildrenAsTreeApi',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class NodeTreeMixin(RebuildTreeMixin, SerializeToTreeNodeMixin):
|
||||||
|
filter_queryset: callable
|
||||||
|
get_queryset: callable
|
||||||
|
|
||||||
|
def list(self, request, *args, **kwargs):
|
||||||
|
nodes = self.filter_queryset(self.get_queryset())
|
||||||
|
data = self.serialize_nodes(nodes, with_asset_amount=True)
|
||||||
|
return Response(data)
|
||||||
|
|
||||||
|
|
||||||
|
class UserAllPermedNodesAsTreeApi(NodeTreeMixin, UserAllPermedNodesApi):
|
||||||
|
""" 用户 '授权的节点' 作为树 """
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class UserPermedNodeChildrenAsTreeApi(NodeTreeMixin, UserPermedNodeChildrenApi):
|
||||||
|
""" 用户授权的节点下的子节点树 """
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
import abc
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db.models import F, Value, CharField
|
||||||
|
from rest_framework.generics import ListAPIView
|
||||||
|
from rest_framework.response import Response
|
||||||
|
|
||||||
|
from assets.models import Asset
|
||||||
|
from assets.api import SerializeToTreeNodeMixin
|
||||||
|
from perms.hands import Node
|
||||||
|
from perms.models import PermNode
|
||||||
|
from perms.utils.user_permission import (
|
||||||
|
UserGrantedNodesQueryUtils, UserGrantedAssetsQueryUtils,
|
||||||
|
)
|
||||||
|
from perms.utils.permission import AssetPermissionUtil
|
||||||
|
from common.utils import get_object_or_none, lazyproperty
|
||||||
|
from common.utils.common import timeit
|
||||||
|
|
||||||
|
|
||||||
|
from ..mixin import SelfOrPKUserMixin
|
||||||
|
from .mixin import RebuildTreeMixin
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'UserPermedNodesWithAssetsAsTreeApi',
|
||||||
|
'UserPermedNodeChildrenWithAssetsAsTreeApi'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class BaseUserNodeWithAssetAsTreeApi(SelfOrPKUserMixin, RebuildTreeMixin, SerializeToTreeNodeMixin,
|
||||||
|
ListAPIView):
|
||||||
|
|
||||||
|
def list(self, request, *args, **kwargs):
|
||||||
|
nodes, assets = self.get_nodes_assets()
|
||||||
|
tree_nodes = self.serialize_nodes(nodes, with_asset_amount=True)
|
||||||
|
tree_assets = self.serialize_assets(assets, node_key=self.node_key_for_serializer_assets)
|
||||||
|
data = list(tree_nodes) + list(tree_assets)
|
||||||
|
return Response(data=data)
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_nodes_assets(self):
|
||||||
|
return [], []
|
||||||
|
|
||||||
|
@lazyproperty
|
||||||
|
def node_key_for_serializer_assets(self):
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class UserPermedNodesWithAssetsAsTreeApi(BaseUserNodeWithAssetAsTreeApi):
|
||||||
|
query_node_util: UserGrantedNodesQueryUtils
|
||||||
|
query_asset_util: UserGrantedAssetsQueryUtils
|
||||||
|
|
||||||
|
def get_nodes_assets(self):
|
||||||
|
perm_ids = AssetPermissionUtil().get_permissions_for_user(self.request.user, flat=True)
|
||||||
|
self.query_node_util = UserGrantedNodesQueryUtils(self.request.user, perm_ids)
|
||||||
|
self.query_asset_util = UserGrantedAssetsQueryUtils(self.request.user, perm_ids)
|
||||||
|
ung_nodes, ung_assets = self._get_nodes_assets_for_ungrouped()
|
||||||
|
fav_nodes, fav_assets = self._get_nodes_assets_for_favorite()
|
||||||
|
all_nodes, all_assets = self._get_nodes_assets_for_all()
|
||||||
|
nodes = list(ung_nodes) + list(fav_nodes) + list(all_nodes)
|
||||||
|
assets = list(ung_assets) + list(fav_assets) + list(all_assets)
|
||||||
|
return nodes, assets
|
||||||
|
|
||||||
|
@timeit
|
||||||
|
def _get_nodes_assets_for_ungrouped(self):
|
||||||
|
if not settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE:
|
||||||
|
return [], []
|
||||||
|
node = self.query_node_util.get_ungrouped_node()
|
||||||
|
assets = self.query_asset_util.get_ungroup_assets()
|
||||||
|
assets = assets.annotate(parent_key=Value(node.key, output_field=CharField())) \
|
||||||
|
.prefetch_related('platform')
|
||||||
|
return [node], assets
|
||||||
|
|
||||||
|
@timeit
|
||||||
|
def _get_nodes_assets_for_favorite(self):
|
||||||
|
node = self.query_node_util.get_favorite_node()
|
||||||
|
assets = self.query_asset_util.get_favorite_assets()
|
||||||
|
assets = assets.annotate(parent_key=Value(node.key, output_field=CharField())) \
|
||||||
|
.prefetch_related('platform')
|
||||||
|
return [node], assets
|
||||||
|
|
||||||
|
def _get_nodes_assets_for_all(self):
|
||||||
|
nodes = self.query_node_util.get_whole_tree_nodes(with_special=False)
|
||||||
|
if settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE:
|
||||||
|
assets = self.query_asset_util.get_direct_granted_nodes_assets()
|
||||||
|
else:
|
||||||
|
assets = self.query_asset_util.get_all_granted_assets()
|
||||||
|
assets = assets.annotate(parent_key=F('nodes__key')).prefetch_related('platform')
|
||||||
|
return nodes, assets
|
||||||
|
|
||||||
|
|
||||||
|
class UserPermedNodeChildrenWithAssetsAsTreeApi(BaseUserNodeWithAssetAsTreeApi):
|
||||||
|
""" 用户授权的节点的子节点与资产树 """
|
||||||
|
|
||||||
|
def get_nodes_assets(self):
|
||||||
|
nodes = PermNode.objects.none()
|
||||||
|
assets = Asset.objects.none()
|
||||||
|
query_node_util = UserGrantedNodesQueryUtils(self.user)
|
||||||
|
query_asset_util = UserGrantedAssetsQueryUtils(self.user)
|
||||||
|
node_key = self.query_node_key
|
||||||
|
if not node_key:
|
||||||
|
nodes = query_node_util.get_top_level_nodes()
|
||||||
|
elif node_key == PermNode.UNGROUPED_NODE_KEY:
|
||||||
|
assets = query_asset_util.get_ungroup_assets()
|
||||||
|
elif node_key == PermNode.FAVORITE_NODE_KEY:
|
||||||
|
assets = query_asset_util.get_favorite_assets()
|
||||||
|
else:
|
||||||
|
nodes = query_node_util.get_node_children(node_key)
|
||||||
|
assets = query_asset_util.get_node_assets(node_key)
|
||||||
|
assets = assets.prefetch_related('platform')
|
||||||
|
return nodes, assets
|
||||||
|
|
||||||
|
@lazyproperty
|
||||||
|
def query_node_key(self):
|
||||||
|
node_key = self.request.query_params.get('key', None)
|
||||||
|
if node_key is not None:
|
||||||
|
return node_key
|
||||||
|
node_id = self.request.query_params.get('id', None)
|
||||||
|
node = get_object_or_none(Node, id=node_id)
|
||||||
|
node_key = getattr(node, 'key', None)
|
||||||
|
return node_key
|
||||||
|
|
||||||
|
@lazyproperty
|
||||||
|
def node_key_for_serializer_assets(self):
|
||||||
|
return self.query_node_key
|
||||||
|
|
|
@ -16,7 +16,7 @@ class GrantedAssetPaginationBase(AssetPaginationBase):
|
||||||
self._user = view.user
|
self._user = view.user
|
||||||
|
|
||||||
|
|
||||||
class NodeGrantedAssetPagination(GrantedAssetPaginationBase):
|
class NodePermedAssetPagination(GrantedAssetPaginationBase):
|
||||||
def get_count_from_nodes(self, queryset):
|
def get_count_from_nodes(self, queryset):
|
||||||
node = getattr(self._view, 'pagination_node', None)
|
node = getattr(self._view, 'pagination_node', None)
|
||||||
if node:
|
if node:
|
||||||
|
@ -29,7 +29,7 @@ class NodeGrantedAssetPagination(GrantedAssetPaginationBase):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class AllGrantedAssetPagination(GrantedAssetPaginationBase):
|
class AllPermedAssetPagination(GrantedAssetPaginationBase):
|
||||||
def get_count_from_nodes(self, queryset):
|
def get_count_from_nodes(self, queryset):
|
||||||
if settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE:
|
if settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE:
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -11,12 +11,12 @@ from common.drf.fields import ObjectRelatedField, LabeledChoiceField
|
||||||
from perms.serializers.permission import ActionChoicesField
|
from perms.serializers.permission import ActionChoicesField
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'NodeGrantedSerializer', 'AssetGrantedSerializer',
|
'NodeGrantedSerializer', 'AssetPermedSerializer',
|
||||||
'AccountsPermedSerializer'
|
'AccountsPermedSerializer'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class AssetGrantedSerializer(serializers.ModelSerializer):
|
class AssetPermedSerializer(serializers.ModelSerializer):
|
||||||
""" 被授权资产的数据结构 """
|
""" 被授权资产的数据结构 """
|
||||||
platform = ObjectRelatedField(required=False, queryset=Platform.objects, label=_('Platform'))
|
platform = ObjectRelatedField(required=False, queryset=Platform.objects, label=_('Platform'))
|
||||||
protocols = AssetProtocolsSerializer(many=True, required=False, label=_('Protocols'))
|
protocols = AssetProtocolsSerializer(many=True, required=False, label=_('Protocols'))
|
||||||
|
|
|
@ -4,39 +4,38 @@ from .. import api
|
||||||
|
|
||||||
user_permission_urlpatterns = [
|
user_permission_urlpatterns = [
|
||||||
# <str:user> such as: my | self | user.id
|
# <str:user> such as: my | self | user.id
|
||||||
|
|
||||||
# assets
|
# assets
|
||||||
path('<str:user>/assets/', api.UserAllPermedAssetsApi.as_view(),
|
path('<str:user>/assets/', api.UserAllPermedAssetsApi.as_view(),
|
||||||
name='user-assets'),
|
name='user-all-assets'),
|
||||||
path('<str:user>/assets/tree/', api.UserDirectPermedAssetsAsTreeApi.as_view(),
|
path('<str:user>/nodes/ungrouped/assets/', api.UserDirectPermedAssetsApi.as_view(),
|
||||||
name='user-assets-as-tree'),
|
name='user-direct-assets'),
|
||||||
path('<str:user>/ungroup/assets/tree/', api.UserUngroupAssetsAsTreeApi.as_view(),
|
path('<str:user>/nodes/favorite/assets/', api.UserFavoriteAssetsApi.as_view(),
|
||||||
name='user-ungroup-assets-as-tree'),
|
name='user-favorite-assets'),
|
||||||
|
|
||||||
# nodes
|
|
||||||
path('<str:user>/nodes/', api.UserPermedNodesApi.as_view(),
|
|
||||||
name='user-nodes'),
|
|
||||||
path('<str:user>/nodes/tree/', api.UserPermedNodesAsTreeApi.as_view(),
|
|
||||||
name='user-nodes-as-tree'),
|
|
||||||
path('<str:user>/nodes/children/', api.UserPermedNodeChildrenApi.as_view(),
|
|
||||||
name='user-nodes-children'),
|
|
||||||
path('<str:user>/nodes/children/tree/', api.UserPermedNodeChildrenAsTreeApi.as_view(),
|
|
||||||
name='user-nodes-children-as-tree'),
|
|
||||||
|
|
||||||
# node-assets
|
|
||||||
path('<str:user>/nodes/<uuid:node_id>/assets/', api.UserPermedNodeAssetsApi.as_view(),
|
path('<str:user>/nodes/<uuid:node_id>/assets/', api.UserPermedNodeAssetsApi.as_view(),
|
||||||
name='user-node-assets'),
|
name='user-node-assets'),
|
||||||
path('<str:user>/nodes/ungrouped/assets/', api.UserDirectPermedAssetsApi.as_view(),
|
|
||||||
name='user-ungrouped-assets'),
|
|
||||||
path('<str:user>/nodes/favorite/assets/', api.UserFavoriteAssetsApi.as_view(),
|
|
||||||
name='user-ungrouped-assets'),
|
|
||||||
|
|
||||||
|
# nodes
|
||||||
|
path('<str:user>/nodes/', api.UserAllPermedNodesApi.as_view(),
|
||||||
|
name='user-all-nodes'),
|
||||||
|
path('<str:user>/nodes/children/', api.UserPermedNodeChildrenApi.as_view(),
|
||||||
|
name='user-node-children'),
|
||||||
|
|
||||||
|
# tree-asset
|
||||||
|
path('<str:user>/assets/tree/', api.UserDirectPermedAssetsAsTreeApi.as_view(),
|
||||||
|
name='user-direct-assets-as-tree'),
|
||||||
|
path('<str:user>/ungroup/assets/tree/', api.UserUngroupAssetsAsTreeApi.as_view(),
|
||||||
|
name='user-ungroup-assets-as-tree'),
|
||||||
|
# tree-node
|
||||||
|
path('<str:user>/nodes/tree/', api.UserAllPermedNodesAsTreeApi.as_view(),
|
||||||
|
name='user-all-nodes-as-tree'),
|
||||||
|
path('<str:user>/nodes/children/tree/', api.UserPermedNodeChildrenAsTreeApi.as_view(),
|
||||||
|
name='user-node-children-as-tree'),
|
||||||
|
# tree-node-with-asset
|
||||||
path('<str:user>/nodes/children-with-assets/tree/',
|
path('<str:user>/nodes/children-with-assets/tree/',
|
||||||
api.UserGrantedNodeChildrenWithAssetsAsTreeApi.as_view(),
|
api.UserPermedNodeChildrenWithAssetsAsTreeApi.as_view(),
|
||||||
name='user-nodes-children-with-assets-as-tree'),
|
name='user-node-children-with-assets-as-tree'),
|
||||||
|
path('<str:user>/nodes-with-assets/tree/', api.UserPermedNodesWithAssetsAsTreeApi.as_view(),
|
||||||
path('nodes-with-assets/tree/', api.MyGrantedNodesWithAssetsAsTreeApi.as_view(),
|
name='user-nodes-with-assets-as-tree'),
|
||||||
name='my-nodes-with-assets-as-tree'),
|
|
||||||
|
|
||||||
# accounts
|
# accounts
|
||||||
path('<str:user>/assets/<uuid:asset_id>/accounts/', api.UserPermedAssetAccountsApi.as_view(),
|
path('<str:user>/assets/<uuid:asset_id>/accounts/', api.UserPermedAssetAccountsApi.as_view(),
|
||||||
|
|
|
@ -4,6 +4,8 @@ from perms.models import AssetPermission
|
||||||
|
|
||||||
logger = get_logger(__file__)
|
logger = get_logger(__file__)
|
||||||
|
|
||||||
|
__all__ = ['AssetPermissionUtil']
|
||||||
|
|
||||||
|
|
||||||
class AssetPermissionUtil(object):
|
class AssetPermissionUtil(object):
|
||||||
""" 资产授权相关的方法工具 """
|
""" 资产授权相关的方法工具 """
|
||||||
|
|
Loading…
Reference in New Issue