diff --git a/apps/assets/api/asset/asset.py b/apps/assets/api/asset/asset.py index 04da13061..72264048a 100644 --- a/apps/assets/api/asset/asset.py +++ b/apps/assets/api/asset/asset.py @@ -37,7 +37,10 @@ class AssetFilterSet(BaseFilterSet): class Meta: model = Asset - fields = ["name", "address", "is_active", "type", "category", "hostname"] + fields = [ + "id", "name", "address", "is_active", + "type", "category", "hostname" + ] class AssetViewSet(SuggestionMixin, NodeFilterMixin, OrgBulkModelViewSet): diff --git a/apps/perms/api/user_permission/assets/mixin.py b/apps/perms/api/user_permission/assets.py similarity index 53% rename from apps/perms/api/user_permission/assets/mixin.py rename to apps/perms/api/user_permission/assets.py index 58832cdee..d3ee274aa 100644 --- a/apps/perms/api/user_permission/assets/mixin.py +++ b/apps/perms/api/user_permission/assets.py @@ -1,25 +1,37 @@ -from rest_framework.request import Request -from rest_framework.response import Response +from django.conf import settings +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 common.utils import get_logger 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 .mixin import ( + SelfOrPKUserMixin, RebuildTreeMixin, + PermedAssetSerializerMixin, AssetsTreeFormatMixin +) + +__all__ = [ + 'UserDirectPermedAssetsApi', + 'UserFavoriteAssetsApi', + 'UserDirectPermedAssetsAsTreeApi', + 'UserUngroupAssetsAsTreeApi', + 'UserAllPermedAssetsApi', + 'UserPermedNodeAssetsApi', +] logger = get_logger(__name__) -class UserDirectGrantedAssetsQuerysetMixin: +class UserDirectPermedAssetsApi(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() + assets = UserGrantedAssetsQueryUtils(self.user) \ .get_direct_granted_assets() \ .prefetch_related('platform') \ @@ -27,14 +39,49 @@ class UserDirectGrantedAssetsQuerysetMixin: 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 pagination_class = AllGrantedAssetPagination - ordering_fields = ("name", "address") - filterset_class = AssetFilterSet - ordering = ('name',) - - user: User def get_queryset(self): if getattr(self, 'swagger_fake_view', False): @@ -45,26 +92,11 @@ class UserAllGrantedAssetsQuerysetMixin: return queryset -class UserFavoriteGrantedAssetsMixin: - 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: +class UserPermedNodeAssetsApi(SelfOrPKUserMixin, PermedAssetSerializerMixin, ListAPIView): only_fields = serializers.AssetGrantedSerializer.Meta.only_fields pagination_class = NodeGrantedAssetPagination - pagination_node: Node - user: User kwargs: dict + pagination_node: Node def get_queryset(self): if getattr(self, 'swagger_fake_view', False): @@ -75,34 +107,3 @@ class UserGrantedNodeAssetsMixin: assets = assets.prefetch_related('platform').only(*self.only_fields) self.pagination_node = node 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) diff --git a/apps/perms/api/user_permission/assets/__init__.py b/apps/perms/api/user_permission/assets/__init__.py deleted file mode 100644 index 0a0e47b0b..000000000 --- a/apps/perms/api/user_permission/assets/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .api import * diff --git a/apps/perms/api/user_permission/assets/api.py b/apps/perms/api/user_permission/assets/api.py deleted file mode 100644 index a08644449..000000000 --- a/apps/perms/api/user_permission/assets/api.py +++ /dev/null @@ -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 diff --git a/apps/perms/api/user_permission/mixin.py b/apps/perms/api/user_permission/mixin.py index 2c145221a..7be96caed 100644 --- a/apps/perms/api/user_permission/mixin.py +++ b/apps/perms/api/user_permission/mixin.py @@ -1,12 +1,16 @@ # -*- coding: utf-8 -*- # from django.shortcuts import get_object_or_404 -from rest_framework.request import Request 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.utils import is_uuid -from common.exceptions import JMSObjectDoesNotExist +from perms import serializers from perms.utils.user_permission import UserGrantedTreeRefreshController from rbac.permissions import RBACPermission from users.models import User @@ -67,3 +71,33 @@ class SelfOrPKUserMixin: def request_user_is_self(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) diff --git a/apps/perms/urls/user_permission.py b/apps/perms/urls/user_permission.py index 973374b7a..c3a555375 100644 --- a/apps/perms/urls/user_permission.py +++ b/apps/perms/urls/user_permission.py @@ -6,9 +6,9 @@ user_permission_urlpatterns = [ # such as: my | self | user.id # assets - path('/assets/', api.UserAllGrantedAssetsApi.as_view(), + path('/assets/', api.UserAllPermedAssetsApi.as_view(), name='user-assets'), - path('/assets/tree/', api.UserDirectGrantedAssetsAsTreeApi.as_view(), + path('/assets/tree/', api.UserDirectPermedAssetsAsTreeApi.as_view(), name='user-assets-as-tree'), path('/ungroup/assets/tree/', api.UserUngroupAssetsAsTreeApi.as_view(), name='user-ungroup-assets-as-tree'), @@ -24,11 +24,11 @@ user_permission_urlpatterns = [ name='user-nodes-children-as-tree'), # node-assets - path('/nodes//assets/', api.UserGrantedNodeAssetsApi.as_view(), + path('/nodes//assets/', api.UserPermedNodeAssetsApi.as_view(), name='user-node-assets'), - path('/nodes/ungrouped/assets/', api.UserDirectGrantedAssetsApi.as_view(), + path('/nodes/ungrouped/assets/', api.UserDirectPermedAssetsApi.as_view(), name='user-ungrouped-assets'), - path('/nodes/favorite/assets/', api.UserFavoriteGrantedAssetsApi.as_view(), + path('/nodes/favorite/assets/', api.UserFavoriteAssetsApi.as_view(), name='user-ungrouped-assets'), path('/nodes/children-with-assets/tree/',