mirror of https://github.com/jumpserver/jumpserver
perf: 优化用户授权 api
parent
61e6ab20a2
commit
2d771eedc1
|
@ -37,7 +37,10 @@ class AssetFilterSet(BaseFilterSet):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Asset
|
model = Asset
|
||||||
fields = ["name", "address", "is_active", "type", "category", "hostname"]
|
fields = [
|
||||||
|
"id", "name", "address", "is_active",
|
||||||
|
"type", "category", "hostname"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class AssetViewSet(SuggestionMixin, NodeFilterMixin, OrgBulkModelViewSet):
|
class AssetViewSet(SuggestionMixin, NodeFilterMixin, OrgBulkModelViewSet):
|
||||||
|
|
|
@ -1,25 +1,37 @@
|
||||||
from rest_framework.request import Request
|
from django.conf import settings
|
||||||
from rest_framework.response import Response
|
from rest_framework.generics import ListAPIView
|
||||||
|
|
||||||
from common.utils import get_logger
|
|
||||||
from users.models import User
|
|
||||||
from assets.api.asset.asset import AssetFilterSet
|
|
||||||
from assets.api.mixin import SerializeToTreeNodeMixin
|
|
||||||
from assets.models import Asset, Node
|
from assets.models import Asset, Node
|
||||||
|
from common.utils import get_logger
|
||||||
from perms import serializers
|
from perms import serializers
|
||||||
from perms.pagination import NodeGrantedAssetPagination, AllGrantedAssetPagination
|
from perms.pagination import AllGrantedAssetPagination
|
||||||
|
from perms.pagination import NodeGrantedAssetPagination
|
||||||
from perms.utils.user_permission import UserGrantedAssetsQueryUtils
|
from perms.utils.user_permission import UserGrantedAssetsQueryUtils
|
||||||
|
from .mixin import (
|
||||||
|
SelfOrPKUserMixin, RebuildTreeMixin,
|
||||||
|
PermedAssetSerializerMixin, AssetsTreeFormatMixin
|
||||||
|
)
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'UserDirectPermedAssetsApi',
|
||||||
|
'UserFavoriteAssetsApi',
|
||||||
|
'UserDirectPermedAssetsAsTreeApi',
|
||||||
|
'UserUngroupAssetsAsTreeApi',
|
||||||
|
'UserAllPermedAssetsApi',
|
||||||
|
'UserPermedNodeAssetsApi',
|
||||||
|
]
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class UserDirectGrantedAssetsQuerysetMixin:
|
class UserDirectPermedAssetsApi(SelfOrPKUserMixin, PermedAssetSerializerMixin, ListAPIView):
|
||||||
|
""" 直接授权给用户的资产 """
|
||||||
only_fields = serializers.AssetGrantedSerializer.Meta.only_fields
|
only_fields = serializers.AssetGrantedSerializer.Meta.only_fields
|
||||||
user: User
|
|
||||||
|
|
||||||
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 = UserGrantedAssetsQueryUtils(self.user) \
|
assets = UserGrantedAssetsQueryUtils(self.user) \
|
||||||
.get_direct_granted_assets() \
|
.get_direct_granted_assets() \
|
||||||
.prefetch_related('platform') \
|
.prefetch_related('platform') \
|
||||||
|
@ -27,14 +39,49 @@ class UserDirectGrantedAssetsQuerysetMixin:
|
||||||
return assets
|
return assets
|
||||||
|
|
||||||
|
|
||||||
class UserAllGrantedAssetsQuerysetMixin:
|
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)
|
||||||
|
return assets
|
||||||
|
|
||||||
|
|
||||||
|
class UserDirectPermedAssetsAsTreeApi(RebuildTreeMixin, AssetsTreeFormatMixin, UserDirectPermedAssetsApi):
|
||||||
|
""" 用户直接授权的资产作为树 """
|
||||||
|
only_fields = serializers.AssetGrantedSerializer.Meta.only_fields
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
if getattr(self, 'swagger_fake_view', False):
|
||||||
|
return Asset.objects.none()
|
||||||
|
|
||||||
|
assets = UserGrantedAssetsQueryUtils(self.user) \
|
||||||
|
.get_direct_granted_assets() \
|
||||||
|
.prefetch_related('platform') \
|
||||||
|
.only(*self.only_fields)
|
||||||
|
return assets
|
||||||
|
|
||||||
|
|
||||||
|
class UserUngroupAssetsAsTreeApi(UserDirectPermedAssetsAsTreeApi):
|
||||||
|
""" 用户未分组节点下的资产作为树 """
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
queryset = super().get_queryset()
|
||||||
|
if not settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE:
|
||||||
|
queryset = queryset.none()
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
|
class UserAllPermedAssetsApi(SelfOrPKUserMixin, PermedAssetSerializerMixin, ListAPIView):
|
||||||
only_fields = serializers.AssetGrantedSerializer.Meta.only_fields
|
only_fields = serializers.AssetGrantedSerializer.Meta.only_fields
|
||||||
pagination_class = AllGrantedAssetPagination
|
pagination_class = AllGrantedAssetPagination
|
||||||
ordering_fields = ("name", "address")
|
|
||||||
filterset_class = AssetFilterSet
|
|
||||||
ordering = ('name',)
|
|
||||||
|
|
||||||
user: User
|
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
if getattr(self, 'swagger_fake_view', False):
|
if getattr(self, 'swagger_fake_view', False):
|
||||||
|
@ -45,26 +92,11 @@ class UserAllGrantedAssetsQuerysetMixin:
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
class UserFavoriteGrantedAssetsMixin:
|
class UserPermedNodeAssetsApi(SelfOrPKUserMixin, PermedAssetSerializerMixin, ListAPIView):
|
||||||
only_fields = serializers.AssetGrantedSerializer.Meta.only_fields
|
|
||||||
user: User
|
|
||||||
|
|
||||||
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)
|
|
||||||
return assets
|
|
||||||
|
|
||||||
|
|
||||||
class UserGrantedNodeAssetsMixin:
|
|
||||||
only_fields = serializers.AssetGrantedSerializer.Meta.only_fields
|
only_fields = serializers.AssetGrantedSerializer.Meta.only_fields
|
||||||
pagination_class = NodeGrantedAssetPagination
|
pagination_class = NodeGrantedAssetPagination
|
||||||
pagination_node: Node
|
|
||||||
user: User
|
|
||||||
kwargs: dict
|
kwargs: dict
|
||||||
|
pagination_node: Node
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
if getattr(self, 'swagger_fake_view', False):
|
if getattr(self, 'swagger_fake_view', False):
|
||||||
|
@ -75,34 +107,3 @@ class UserGrantedNodeAssetsMixin:
|
||||||
assets = assets.prefetch_related('platform').only(*self.only_fields)
|
assets = assets.prefetch_related('platform').only(*self.only_fields)
|
||||||
self.pagination_node = node
|
self.pagination_node = node
|
||||||
return assets
|
return assets
|
||||||
|
|
||||||
|
|
||||||
class AssetSerializerFormatMixin:
|
|
||||||
serializer_class = serializers.AssetGrantedSerializer
|
|
||||||
filterset_fields = ['name', 'address', 'id', 'comment']
|
|
||||||
search_fields = ['name', 'address', 'comment']
|
|
||||||
filterset_class = AssetFilterSet
|
|
||||||
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 +0,0 @@
|
||||||
from .api import *
|
|
|
@ -1,82 +0,0 @@
|
||||||
from django.conf import settings
|
|
||||||
from rest_framework.generics import ListAPIView
|
|
||||||
|
|
||||||
from common.utils import get_logger
|
|
||||||
from .mixin import (
|
|
||||||
AssetsTreeFormatMixin,
|
|
||||||
UserGrantedNodeAssetsMixin,
|
|
||||||
AssetSerializerFormatMixin,
|
|
||||||
UserFavoriteGrantedAssetsMixin,
|
|
||||||
UserAllGrantedAssetsQuerysetMixin,
|
|
||||||
UserDirectGrantedAssetsQuerysetMixin,
|
|
||||||
)
|
|
||||||
from ..mixin import SelfOrPKUserMixin, RebuildTreeMixin
|
|
||||||
|
|
||||||
__all__ = [
|
|
||||||
'UserDirectGrantedAssetsApi',
|
|
||||||
'UserFavoriteGrantedAssetsApi',
|
|
||||||
'UserDirectGrantedAssetsAsTreeApi',
|
|
||||||
'UserUngroupAssetsAsTreeApi',
|
|
||||||
'UserAllGrantedAssetsApi',
|
|
||||||
'UserGrantedNodeAssetsApi',
|
|
||||||
]
|
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class UserDirectGrantedAssetsApi(
|
|
||||||
SelfOrPKUserMixin,
|
|
||||||
UserDirectGrantedAssetsQuerysetMixin,
|
|
||||||
AssetSerializerFormatMixin,
|
|
||||||
ListAPIView
|
|
||||||
):
|
|
||||||
""" 直接授权给用户的资产 """
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class UserFavoriteGrantedAssetsApi(
|
|
||||||
SelfOrPKUserMixin,
|
|
||||||
UserFavoriteGrantedAssetsMixin,
|
|
||||||
AssetSerializerFormatMixin,
|
|
||||||
ListAPIView
|
|
||||||
):
|
|
||||||
""" 用户收藏的授权资产 """
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class UserDirectGrantedAssetsAsTreeApi(
|
|
||||||
RebuildTreeMixin,
|
|
||||||
AssetsTreeFormatMixin,
|
|
||||||
UserDirectGrantedAssetsApi
|
|
||||||
):
|
|
||||||
""" 用户直接授权的资产作为树 """
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class UserUngroupAssetsAsTreeApi(UserDirectGrantedAssetsAsTreeApi):
|
|
||||||
""" 用户未分组节点下的资产作为树 """
|
|
||||||
def get_queryset(self):
|
|
||||||
queryset = super().get_queryset()
|
|
||||||
if not settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE:
|
|
||||||
queryset = queryset.none()
|
|
||||||
return queryset
|
|
||||||
|
|
||||||
|
|
||||||
class UserAllGrantedAssetsApi(
|
|
||||||
SelfOrPKUserMixin,
|
|
||||||
UserAllGrantedAssetsQuerysetMixin,
|
|
||||||
AssetSerializerFormatMixin,
|
|
||||||
ListAPIView
|
|
||||||
):
|
|
||||||
""" 授权给用户的所有资产 """
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class UserGrantedNodeAssetsApi(
|
|
||||||
SelfOrPKUserMixin,
|
|
||||||
UserGrantedNodeAssetsMixin,
|
|
||||||
AssetSerializerFormatMixin,
|
|
||||||
ListAPIView
|
|
||||||
):
|
|
||||||
""" 授权给用户的节点资产 """
|
|
||||||
pass
|
|
|
@ -1,12 +1,16 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from rest_framework.request import Request
|
|
||||||
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.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.http import is_true
|
||||||
from common.utils import is_uuid
|
from common.utils import is_uuid
|
||||||
from common.exceptions import JMSObjectDoesNotExist
|
from perms import serializers
|
||||||
from perms.utils.user_permission import UserGrantedTreeRefreshController
|
from perms.utils.user_permission import UserGrantedTreeRefreshController
|
||||||
from rbac.permissions import RBACPermission
|
from rbac.permissions import RBACPermission
|
||||||
from users.models import User
|
from users.models import User
|
||||||
|
@ -67,3 +71,33 @@ 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)
|
||||||
|
|
|
@ -6,9 +6,9 @@ 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.UserAllGrantedAssetsApi.as_view(),
|
path('<str:user>/assets/', api.UserAllPermedAssetsApi.as_view(),
|
||||||
name='user-assets'),
|
name='user-assets'),
|
||||||
path('<str:user>/assets/tree/', api.UserDirectGrantedAssetsAsTreeApi.as_view(),
|
path('<str:user>/assets/tree/', api.UserDirectPermedAssetsAsTreeApi.as_view(),
|
||||||
name='user-assets-as-tree'),
|
name='user-assets-as-tree'),
|
||||||
path('<str:user>/ungroup/assets/tree/', api.UserUngroupAssetsAsTreeApi.as_view(),
|
path('<str:user>/ungroup/assets/tree/', api.UserUngroupAssetsAsTreeApi.as_view(),
|
||||||
name='user-ungroup-assets-as-tree'),
|
name='user-ungroup-assets-as-tree'),
|
||||||
|
@ -24,11 +24,11 @@ user_permission_urlpatterns = [
|
||||||
name='user-nodes-children-as-tree'),
|
name='user-nodes-children-as-tree'),
|
||||||
|
|
||||||
# node-assets
|
# node-assets
|
||||||
path('<str:user>/nodes/<uuid:node_id>/assets/', api.UserGrantedNodeAssetsApi.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.UserDirectGrantedAssetsApi.as_view(),
|
path('<str:user>/nodes/ungrouped/assets/', api.UserDirectPermedAssetsApi.as_view(),
|
||||||
name='user-ungrouped-assets'),
|
name='user-ungrouped-assets'),
|
||||||
path('<str:user>/nodes/favorite/assets/', api.UserFavoriteGrantedAssetsApi.as_view(),
|
path('<str:user>/nodes/favorite/assets/', api.UserFavoriteAssetsApi.as_view(),
|
||||||
name='user-ungrouped-assets'),
|
name='user-ungrouped-assets'),
|
||||||
|
|
||||||
path('<str:user>/nodes/children-with-assets/tree/',
|
path('<str:user>/nodes/children-with-assets/tree/',
|
||||||
|
|
Loading…
Reference in New Issue