perf: ROOT Org show orgs-and-roles in user-detail page

pull/12954/head
Bai 2024-04-07 20:09:17 +08:00 committed by Bryan
parent 9776d35140
commit 45bac09dc7
5 changed files with 31 additions and 4 deletions

1
.gitignore vendored
View File

@ -43,3 +43,4 @@ releashe
data/* data/*
test.py test.py
.history/ .history/
.test/

View File

@ -56,6 +56,7 @@ class RoleBinding(JMSBaseModel):
on_delete=models.CASCADE, verbose_name=_('Organization') on_delete=models.CASCADE, verbose_name=_('Organization')
) )
objects = RoleBindingManager() objects = RoleBindingManager()
objects_raw = models.Manager()
class Meta: class Meta:
verbose_name = _('Role binding') verbose_name = _('Role binding')

View File

@ -22,8 +22,7 @@ from ..models import User
from ..notifications import ResetMFAMsg from ..notifications import ResetMFAMsg
from ..permissions import UserObjectPermission from ..permissions import UserObjectPermission
from ..serializers import ( from ..serializers import (
UserSerializer, UserSerializer, MiniUserSerializer, InviteSerializer, UserRetrieveSerializer
MiniUserSerializer, InviteSerializer
) )
from ..signals import post_user_create from ..signals import post_user_create
@ -43,6 +42,7 @@ class UserViewSet(CommonApiMixin, UserQuerysetMixin, SuggestionMixin, BulkModelV
'default': UserSerializer, 'default': UserSerializer,
'suggestion': MiniUserSerializer, 'suggestion': MiniUserSerializer,
'invite': InviteSerializer, 'invite': InviteSerializer,
'retrieve': UserRetrieveSerializer,
} }
rbac_perms = { rbac_perms = {
'match': 'users.match_user', 'match': 'users.match_user',

View File

@ -5,6 +5,7 @@ import base64
import datetime import datetime
import uuid import uuid
from typing import Callable from typing import Callable
from collections import defaultdict
import sshpubkeys import sshpubkeys
from django.conf import settings from django.conf import settings
@ -27,6 +28,7 @@ from common.utils import (
from labels.mixins import LabeledMixin from labels.mixins import LabeledMixin
from orgs.utils import current_org from orgs.utils import current_org
from rbac.const import Scope from rbac.const import Scope
from rbac.models import RoleBinding
from ..signals import ( from ..signals import (
post_user_change_password, post_user_leave_org, pre_user_leave_org post_user_change_password, post_user_leave_org, pre_user_leave_org
) )
@ -926,6 +928,14 @@ class User(AuthMixin, TokenMixin, RoleMixin, MFAMixin, LabeledMixin, JSONFilterM
def is_local(self): def is_local(self):
return self.source == self.Source.local.value return self.source == self.Source.local.value
@property
def orgs_roles(self):
orgs_roles = defaultdict(set)
rbs = RoleBinding.objects_raw.filter(user=self, scope='org').prefetch_related('role', 'org')
for rb in rbs:
orgs_roles[rb.org_name].add(str(rb.role.display_name))
return orgs_roles
def is_password_authenticate(self): def is_password_authenticate(self):
cas = self.Source.cas cas = self.Source.cas
saml2 = self.Source.saml2 saml2 = self.Source.saml2

View File

@ -12,6 +12,7 @@ from common.serializers.fields import (
) )
from common.utils import pretty_string, get_logger from common.utils import pretty_string, get_logger
from common.validators import PhoneValidator from common.validators import PhoneValidator
from orgs.utils import current_org
from rbac.builtin import BuiltinRole from rbac.builtin import BuiltinRole
from rbac.models import OrgRoleBinding, SystemRoleBinding, Role from rbac.models import OrgRoleBinding, SystemRoleBinding, Role
from rbac.permissions import RBACPermission from rbac.permissions import RBACPermission
@ -23,6 +24,7 @@ __all__ = [
"MiniUserSerializer", "MiniUserSerializer",
"InviteSerializer", "InviteSerializer",
"ServiceAccountSerializer", "ServiceAccountSerializer",
"UserRetrieveSerializer",
] ]
logger = get_logger(__file__) logger = get_logger(__file__)
@ -46,6 +48,7 @@ class RolesSerializerMixin(serializers.Serializer):
label=_("Org roles"), many=True, required=False, label=_("Org roles"), many=True, required=False,
default=default_org_roles default=default_org_roles
) )
orgs_roles = serializers.JSONField(read_only=True, label=_("Organization and roles relations"))
def pop_roles_if_need(self, fields): def pop_roles_if_need(self, fields):
request = self.context.get("request") request = self.context.get("request")
@ -58,7 +61,7 @@ class RolesSerializerMixin(serializers.Serializer):
model_cls_field_mapper = { model_cls_field_mapper = {
SystemRoleBinding: ["system_roles"], SystemRoleBinding: ["system_roles"],
OrgRoleBinding: ["org_roles"], OrgRoleBinding: ["org_roles", "orgs_roles"],
} }
update_actions = ("partial_bulk_update", "bulk_update", "partial_update", "update") update_actions = ("partial_bulk_update", "bulk_update", "partial_update", "update")
@ -156,6 +159,7 @@ class UserSerializer(RolesSerializerMixin, CommonBulkSerializerMixin, ResourceLa
"is_first_login", "wecom_id", "dingtalk_id", "is_first_login", "wecom_id", "dingtalk_id",
"feishu_id", "lark_id", "date_api_key_last_used", "feishu_id", "lark_id", "date_api_key_last_used",
] ]
fields_only_root_org = ["orgs_roles"]
disallow_self_update_fields = ["is_active", "system_roles", "org_roles"] disallow_self_update_fields = ["is_active", "system_roles", "org_roles"]
extra_kwargs = { extra_kwargs = {
"password": { "password": {
@ -178,6 +182,17 @@ class UserSerializer(RolesSerializerMixin, CommonBulkSerializerMixin, ResourceLa
'mfa_level': {'label': _("MFA level")}, 'mfa_level': {'label': _("MFA level")},
} }
def get_fields(self):
fields = super().get_fields()
self.pop_fields_if_need(fields)
return fields
def pop_fields_if_need(self, fields):
# pop only root org fields
if not current_org.is_root():
for f in self.Meta.fields_only_root_org:
fields.pop(f, None)
def validate_password(self, password): def validate_password(self, password):
password_strategy = self.initial_data.get("password_strategy") password_strategy = self.initial_data.get("password_strategy")
if self.instance is None and password_strategy != PasswordStrategy.custom: if self.instance is None and password_strategy != PasswordStrategy.custom:
@ -273,7 +288,7 @@ class UserRetrieveSerializer(UserSerializer):
) )
class Meta(UserSerializer.Meta): class Meta(UserSerializer.Meta):
fields = UserSerializer.Meta.fields + ["login_confirm_settings"] fields = UserSerializer.Meta.fields + ["login_confirm_settings", "orgs_roles"]
class MiniUserSerializer(serializers.ModelSerializer): class MiniUserSerializer(serializers.ModelSerializer):