From 4362f8d5afe2cd59c96ff580753b0e9554e9b90b Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Mon, 18 Apr 2022 17:17:23 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E7=BB=84=E7=BB=87=20?= =?UTF-8?q?(#8080)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * perf: 优化用户的orgs * perf: 优化组织 Co-authored-by: ibuler --- apps/rbac/models/permission.py | 1 - apps/rbac/models/role.py | 14 ++++++++++++++ apps/rbac/models/rolebinding.py | 22 ++++++++++++++++++++++ apps/users/models/user.py | 29 +++++++++++++---------------- apps/users/serializers/profile.py | 8 +++++--- 5 files changed, 54 insertions(+), 20 deletions(-) diff --git a/apps/rbac/models/permission.py b/apps/rbac/models/permission.py index a4ea91b15..bc8fa6231 100644 --- a/apps/rbac/models/permission.py +++ b/apps/rbac/models/permission.py @@ -90,4 +90,3 @@ class Permission(DjangoPermission): permissions = cls.objects.all() permissions = cls.clean_permissions(permissions, scope=scope) return permissions - diff --git a/apps/rbac/models/role.py b/apps/rbac/models/role.py index b47bccb5b..98a226e6f 100644 --- a/apps/rbac/models/role.py +++ b/apps/rbac/models/role.py @@ -121,6 +121,20 @@ class Role(JMSModel): def is_org(self): return self.scope == const.Scope.org + @classmethod + def get_roles_by_perm(cls, perm): + app_label, codename = perm.split('.') + p = Permission.objects.filter( + codename=codename, + content_type__app_label=app_label + ).first() + if not p: + return p.roles.none() + role_ids = list(p.roles.all().values_list('id', flat=True)) + admin_ids = [BuiltinRole.system_admin.id, BuiltinRole.org_admin.id] + role_ids += admin_ids + return cls.objects.filter(id__in=role_ids) + class SystemRole(Role): objects = SystemRoleManager() diff --git a/apps/rbac/models/rolebinding.py b/apps/rbac/models/rolebinding.py index a2ee06022..643e38207 100644 --- a/apps/rbac/models/rolebinding.py +++ b/apps/rbac/models/rolebinding.py @@ -100,6 +100,28 @@ class RoleBinding(JMSModel): def is_scope_org(self): return self.scope == Scope.org + @classmethod + def get_user_has_the_perm_orgs(cls, perm, user): + from orgs.models import Organization + + roles = Role.get_roles_by_perm(perm) + bindings = list(cls.objects.root_all().filter(role__in=roles, user=user)) + system_bindings = [b for b in bindings if b.scope == Role.Scope.system.value] + + if perm == 'rbac.view_workbench': + all_orgs = user.orgs.all() + else: + all_orgs = Organization.objects.all() + + if system_bindings: + orgs = all_orgs + else: + org_ids = [b.org.id for b in bindings if b.org] + orgs = all_orgs.filter(id__in=org_ids) + if orgs and user.has_perm('orgs.view_rootorg'): + orgs = [Organization.root(), *list(orgs)] + return orgs + class OrgRoleBindingManager(RoleBindingManager): def get_queryset(self): diff --git a/apps/users/models/user.py b/apps/users/models/user.py index ede795d13..80b938468 100644 --- a/apps/users/models/user.py +++ b/apps/users/models/user.py @@ -863,23 +863,20 @@ class User(AuthMixin, TokenMixin, RoleMixin, MFAMixin, AbstractUser): return None return self.SOURCE_BACKEND_MAPPING.get(self.source, []) - @property - def all_orgs(self): - from rbac.builtin import BuiltinRole - has_system_role = self.system_roles.all() \ - .exclude(name=BuiltinRole.system_user.name) \ - .exists() - if has_system_role: - orgs = list(Organization.objects.all()) - else: - orgs = list(self.orgs.distinct()) - if self.has_perm('orgs.view_rootorg'): - orgs = [Organization.root()] + orgs - return orgs + @lazyproperty + def console_orgs(self): + from rbac.models import RoleBinding + return RoleBinding.get_user_has_the_perm_orgs('rbac.view_console', self) - @property - def my_orgs(self): - return list(self.orgs.distinct()) + @lazyproperty + def audit_orgs(self): + from rbac.models import RoleBinding + return RoleBinding.get_user_has_the_perm_orgs('rbac.view_audit', self) + + @lazyproperty + def workbench_orgs(self): + from rbac.models import RoleBinding + return RoleBinding.get_user_has_the_perm_orgs('rbac.view_workbench', self) class Meta: ordering = ['username'] diff --git a/apps/users/serializers/profile.py b/apps/users/serializers/profile.py index 55083c23d..ac9671d23 100644 --- a/apps/users/serializers/profile.py +++ b/apps/users/serializers/profile.py @@ -121,14 +121,16 @@ class UserProfileSerializer(UserSerializer): mfa_level = serializers.ChoiceField(choices=MFA_LEVEL_CHOICES, label=_('MFA'), required=False) guide_url = serializers.SerializerMethodField() receive_backends = serializers.ListField(child=serializers.CharField(), read_only=True) - orgs = UserOrgSerializer(many=True, read_only=True, source='all_orgs') - myorgs = UserOrgSerializer(many=True, read_only=True, source='my_orgs') + console_orgs = UserOrgSerializer(many=True, read_only=True) + audit_orgs = UserOrgSerializer(many=True, read_only=True) + workbench_orgs = UserOrgSerializer(many=True, read_only=True) perms = serializers.ListField(label=_("Perms"), read_only=True) class Meta(UserSerializer.Meta): read_only_fields = [ 'date_joined', 'last_login', 'created_by', 'source', - 'receive_backends', 'orgs', 'myorgs', 'perms', + 'console_orgs', 'audit_orgs', 'workbench_orgs', + 'receive_backends', 'perms', ] fields = UserSerializer.Meta.fields + [ 'public_key_comment', 'public_key_hash_md5', 'guide_url',