From 5d8818e69ed624d6a4fcde2cd62752ffef6b7386 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Fri, 15 Oct 2021 14:02:32 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E8=B5=84=E4=BA=A7?= =?UTF-8?q?=E6=8E=88=E6=9D=83=E7=94=A8=E6=88=B7API=E3=80=81=E8=B5=84?= =?UTF-8?q?=E4=BA=A7=E6=8E=88=E6=9D=83=E7=94=A8=E6=88=B7=E7=9A=84=E6=8E=88?= =?UTF-8?q?=E6=9D=83=E8=A7=84=E5=88=99API=20(#7008)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 添加资产授权用户API、资产授权用户的授权规则API * feat: 添加资产授权用户组API、资产授权用户组的授权规则API * feat: 抽象API类 Co-authored-by: Michael Bai --- apps/assets/api/asset.py | 110 ++++++++++++++++++++++++++++++- apps/assets/serializers/asset.py | 4 +- apps/assets/urls/api_urls.py | 4 ++ apps/authentication/utils.py | 2 +- 4 files changed, 117 insertions(+), 3 deletions(-) diff --git a/apps/assets/api/asset.py b/apps/assets/api/asset.py index 5fe0152d7..79229e832 100644 --- a/apps/assets/api/asset.py +++ b/apps/assets/api/asset.py @@ -2,12 +2,19 @@ # from assets.api import FilterAssetByNodeMixin from rest_framework.viewsets import ModelViewSet -from rest_framework.generics import RetrieveAPIView +from rest_framework.generics import RetrieveAPIView, ListAPIView from django.shortcuts import get_object_or_404 +from django.db.models import Q from common.utils import get_logger, get_object_or_none from common.permissions import IsOrgAdmin, IsOrgAdminOrAppUser, IsSuperUser from common.mixins.views import SuggestionMixin +from users.models import User, UserGroup +from users.serializers import UserSerializer, UserGroupSerializer +from users.filters import UserFilter +from perms.models import AssetPermission +from perms.serializers import AssetPermissionSerializer +from perms.filters import AssetPermissionFilter from orgs.mixins.api import OrgBulkModelViewSet from orgs.mixins import generics from ..models import Asset, Node, Platform @@ -23,6 +30,8 @@ __all__ = [ 'AssetViewSet', 'AssetPlatformRetrieveApi', 'AssetGatewayListApi', 'AssetPlatformViewSet', 'AssetTaskCreateApi', 'AssetsTaskCreateApi', + 'AssetPermUserListApi', 'AssetPermUserPermissionsListApi', + 'AssetPermUserGroupListApi', 'AssetPermUserGroupPermissionsListApi', ] @@ -170,3 +179,102 @@ class AssetGatewayListApi(generics.ListAPIView): return [] queryset = asset.domain.gateways.filter(protocol='ssh') return queryset + + +class BaseAssetPermUserOrUserGroupListApi(ListAPIView): + permission_classes = (IsOrgAdmin,) + + def get_object(self): + asset_id = self.kwargs.get('pk') + asset = get_object_or_404(Asset, pk=asset_id) + return asset + + def get_asset_related_perms(self): + asset = self.get_object() + nodes = asset.get_all_nodes(flat=True) + perms = AssetPermission.objects.filter(Q(assets=asset) | Q(nodes__in=nodes)) + return perms + + +class AssetPermUserListApi(BaseAssetPermUserOrUserGroupListApi): + filterset_class = UserFilter + search_fields = ('username', 'email', 'name', 'id', 'source', 'role') + serializer_class = UserSerializer + + def get_queryset(self): + perms = self.get_asset_related_perms() + users = User.objects.filter( + Q(assetpermissions__in=perms) | Q(groups__assetpermissions__in=perms) + ).distinct() + return users + + +class AssetPermUserGroupListApi(BaseAssetPermUserOrUserGroupListApi): + serializer_class = UserGroupSerializer + + def get_queryset(self): + perms = self.get_asset_related_perms() + user_groups = UserGroup.objects.filter(assetpermissions__in=perms).distinct() + return user_groups + + +class BaseAssetPermUserOrUserGroupPermissionsListApiMixin(generics.ListAPIView): + permission_classes = (IsOrgAdmin,) + model = AssetPermission + serializer_class = AssetPermissionSerializer + filterset_class = AssetPermissionFilter + search_fields = ('name',) + + def get_object(self): + asset_id = self.kwargs.get('pk') + asset = get_object_or_404(Asset, pk=asset_id) + return asset + + def filter_asset_related(self, queryset): + asset = self.get_object() + nodes = asset.get_all_nodes(flat=True) + perms = queryset.filter(Q(assets=asset) | Q(nodes__in=nodes)) + return perms + + def filter_queryset(self, queryset): + queryset = super().filter_queryset(queryset) + queryset = self.filter_asset_related(queryset) + return queryset + + +class AssetPermUserPermissionsListApi(BaseAssetPermUserOrUserGroupPermissionsListApiMixin): + def filter_queryset(self, queryset): + queryset = super().filter_queryset(queryset) + queryset = self.filter_user_related(queryset) + queryset = queryset.distinct() + return queryset + + def filter_user_related(self, queryset): + user = self.get_perm_user() + user_groups = user.groups.all() + perms = queryset.filter(Q(users=user) | Q(user_groups__in=user_groups)) + return perms + + def get_perm_user(self): + user_id = self.kwargs.get('perm_user_id') + user = get_object_or_404(User, pk=user_id) + return user + + +class AssetPermUserGroupPermissionsListApi(BaseAssetPermUserOrUserGroupPermissionsListApiMixin): + def filter_queryset(self, queryset): + queryset = super().filter_queryset(queryset) + queryset = self.filter_user_group_related(queryset) + queryset = queryset.distinct() + return queryset + + def filter_user_group_related(self, queryset): + user_group = self.get_perm_user_group() + perms = queryset.filter(user_groups=user_group) + return perms + + def get_perm_user_group(self): + user_group_id = self.kwargs.get('perm_user_group_id') + user_group = get_object_or_404(UserGroup, pk=user_group_id) + return user_group + diff --git a/apps/assets/serializers/asset.py b/apps/assets/serializers/asset.py index 7f7e6fb53..fccbcaa9e 100644 --- a/apps/assets/serializers/asset.py +++ b/apps/assets/serializers/asset.py @@ -5,12 +5,14 @@ from django.core.validators import RegexValidator from django.utils.translation import ugettext_lazy as _ from orgs.mixins.serializers import BulkOrgResourceModelSerializer +from users.models import User, UserGroup +from perms.models import AssetPermission from ..models import Asset, Node, Platform, SystemUser __all__ = [ 'AssetSerializer', 'AssetSimpleSerializer', 'MiniAssetSerializer', 'ProtocolsField', 'PlatformSerializer', - 'AssetTaskSerializer', 'AssetsTaskSerializer', 'ProtocolsField' + 'AssetTaskSerializer', 'AssetsTaskSerializer', 'ProtocolsField', ] diff --git a/apps/assets/urls/api_urls.py b/apps/assets/urls/api_urls.py index 57bace221..0e3306a36 100644 --- a/apps/assets/urls/api_urls.py +++ b/apps/assets/urls/api_urls.py @@ -36,6 +36,10 @@ urlpatterns = [ path('assets//platform/', api.AssetPlatformRetrieveApi.as_view(), name='asset-platform-detail'), path('assets//tasks/', api.AssetTaskCreateApi.as_view(), name='asset-task-create'), path('assets/tasks/', api.AssetsTaskCreateApi.as_view(), name='assets-task-create'), + path('assets//perm-users/', api.AssetPermUserListApi.as_view(), name='asset-perm-user-list'), + path('assets//perm-users//permissions/', api.AssetPermUserPermissionsListApi.as_view(), name='asset-perm-user-permission-list'), + path('assets//perm-user-groups/', api.AssetPermUserGroupListApi.as_view(), name='asset-perm-user-group-list'), + path('assets//perm-user-groups//permissions/', api.AssetPermUserGroupPermissionsListApi.as_view(), name='asset-perm-user-group-permission-list'), path('system-users//auth-info/', api.SystemUserAuthInfoApi.as_view(), name='system-user-auth-info'), path('system-users//assets/', api.SystemUserAssetsListView.as_view(), name='system-user-assets'), diff --git a/apps/authentication/utils.py b/apps/authentication/utils.py index 8c3820eb8..6e8e45570 100644 --- a/apps/authentication/utils.py +++ b/apps/authentication/utils.py @@ -60,5 +60,5 @@ def check_different_city_login(user, request): city = get_ip_city(ip) or DEFAULT_CITY last_user_login = UserLoginLog.objects.filter(username=user.username, status=True).first() - if last_user_login.city != city: + if last_user_login and last_user_login.city != city: DifferentCityLoginMessage(user, ip, city).publish_async()