From 7dfd0ee8feed076feff7c8e2265f26f61d99ab1d Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 15 Mar 2021 14:53:19 +0800 Subject: [PATCH] =?UTF-8?q?fix(orgs):=20=E4=BF=AE=E5=A4=8D=E8=AE=BF?= =?UTF-8?q?=E9=97=AE=20current=20org=20api=20=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit perf(users): 优化用户删除和移除行为 perf: 优化组织权限判断 --- apps/common/permissions.py | 4 ++-- apps/orgs/api.py | 4 ++-- apps/orgs/models.py | 9 +++++++++ apps/settings/api/common.py | 9 +++------ apps/users/api/user.py | 30 +++++++++++++++++++++--------- apps/users/serializers/profile.py | 2 ++ 6 files changed, 39 insertions(+), 19 deletions(-) diff --git a/apps/common/permissions.py b/apps/common/permissions.py index 32ea8ca94..65a57827d 100644 --- a/apps/common/permissions.py +++ b/apps/common/permissions.py @@ -109,9 +109,9 @@ class PermissionsMixin(UserPassesTestMixin): return True -class UserCanUseCurrentOrg(permissions.BasePermission): +class UserCanAnyPermCurrentOrg(permissions.BasePermission): def has_permission(self, request, view): - return current_org.can_use_by(request.user) + return current_org.can_any_by(request.user) class UserCanUpdatePassword(permissions.BasePermission): diff --git a/apps/orgs/api.py b/apps/orgs/api.py index 618ebe9ed..17b01a092 100644 --- a/apps/orgs/api.py +++ b/apps/orgs/api.py @@ -8,7 +8,7 @@ from rest_framework_bulk import BulkModelViewSet from rest_framework.generics import RetrieveAPIView from rest_framework.exceptions import PermissionDenied -from common.permissions import IsSuperUserOrAppUser, IsValidUser, UserCanUseCurrentOrg +from common.permissions import IsSuperUserOrAppUser, IsValidUser, UserCanAnyPermCurrentOrg from common.drf.api import JMSBulkRelationModelViewSet from .models import Organization, ROLE from .serializers import ( @@ -136,7 +136,7 @@ class OrgMemberUserRelationBulkViewSet(JMSBulkRelationModelViewSet): class CurrentOrgDetailApi(RetrieveAPIView): serializer_class = CurrentOrgSerializer - permission_classes = (IsValidUser, UserCanUseCurrentOrg) + permission_classes = (IsValidUser, UserCanAnyPermCurrentOrg) def get_object(self): return current_org diff --git a/apps/orgs/models.py b/apps/orgs/models.py index 5c0e59538..72231f3c3 100644 --- a/apps/orgs/models.py +++ b/apps/orgs/models.py @@ -118,6 +118,8 @@ class Organization(models.Model): def can_audit_by(self, user): if user.is_superuser or user.is_super_auditor: return True + if self.can_admin_by(user): + return True if self.auditors.filter(id=user.id).exists(): return True return False @@ -125,10 +127,17 @@ class Organization(models.Model): def can_use_by(self, user): if user.is_superuser or user.is_super_auditor: return True + if self.can_audit_by(user): + return True if self.users.filter(id=user.id).exists(): return True return False + def can_any_by(self, user): + if user.is_superuser or user.is_super_auditor: + return True + return self.members.filter(id=user.id).exists() + @classmethod def get_user_orgs_by_role(cls, user, role): if not isinstance(role, (tuple, list)): diff --git a/apps/settings/api/common.py b/apps/settings/api/common.py index 2f01687f9..04674d25b 100644 --- a/apps/settings/api/common.py +++ b/apps/settings/api/common.py @@ -98,12 +98,9 @@ class PublicSettingApi(generics.RetrieveAPIView): def get_xpack_license_is_valid(): if not settings.XPACK_ENABLED: return False - try: - from xpack.plugins.license.models import License - return License.has_valid_license() - except Exception as e: - logger.error(e) - return False + + from xpack.plugins.license.models import License + return License.has_valid_license() @staticmethod def get_login_title(): diff --git a/apps/users/api/user.py b/apps/users/api/user.py index 7f7d91deb..5973be849 100644 --- a/apps/users/api/user.py +++ b/apps/users/api/user.py @@ -2,7 +2,7 @@ from django.core.cache import cache from django.utils.translation import ugettext as _ from rest_framework.decorators import action - +from django.conf import settings from rest_framework import generics from rest_framework.response import Response from rest_framework_bulk import BulkModelViewSet @@ -88,17 +88,14 @@ class UserViewSet(CommonApiMixin, UserQuerysetMixin, BulkModelViewSet): def get_permissions(self): if self.action in ["retrieve", "list"]: - self.permission_classes = (IsOrgAdminOrAppUser,) - if self.request.query_params.get('all'): + if self.request.query_params.get('all'): + self.permission_classes = (IsSuperUser,) + else: + self.permission_classes = (IsOrgAdminOrAppUser,) + elif self.action in ['destroy']: self.permission_classes = (IsSuperUser,) return super().get_permissions() - def perform_destroy(self, instance): - if not current_org.is_root(): - instance.remove() - else: - return super().perform_destroy(instance) - def perform_bulk_destroy(self, objects): for obj in objects: self.check_object_permissions(self.request, obj) @@ -164,6 +161,21 @@ class UserViewSet(CommonApiMixin, UserQuerysetMixin, BulkModelViewSet): OrganizationMember.objects.bulk_create(relations, ignore_conflicts=True) return Response(serializer.data, status=201) + @action(methods=['post'], detail=True, permission_classes=(IsOrgAdmin,)) + def remove(self, request, *args, **kwargs): + instance = self.get_object() + instance.remove() + return Response(status=204) + + @action(methods=['post'], detail=False, permission_classes=(IsOrgAdmin,), url_path='remove') + def bulk_remove(self, request, *args, **kwargs): + qs = self.get_queryset() + filtered = self.filter_queryset(qs) + + for instance in filtered: + instance.remove() + return Response(status=204) + class UserChangePasswordApi(UserQuerysetMixin, generics.RetrieveUpdateAPIView): permission_classes = (IsOrgAdmin,) diff --git a/apps/users/serializers/profile.py b/apps/users/serializers/profile.py index b1611307a..c89b173ff 100644 --- a/apps/users/serializers/profile.py +++ b/apps/users/serializers/profile.py @@ -11,6 +11,8 @@ from .user import UserSerializer class UserOrgSerializer(serializers.Serializer): id = serializers.CharField() name = serializers.CharField() + is_default = serializers.BooleanField(read_only=True) + is_root = serializers.BooleanField(read_only=True) class UserOrgLabelSerializer(serializers.Serializer):