Skip to content

Commit 6d5664c

Browse files
committed
chore: add default permission handling and update user permissions logic
1 parent ed45fab commit 6d5664c

File tree

2 files changed

+261
-3
lines changed

2 files changed

+261
-3
lines changed

apps/users/serializers/user.py

Lines changed: 259 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@
2121

2222
from common.constants.cache_version import Cache_Version
2323
from common.constants.exception_code_constants import ExceptionCodeConstants
24-
from common.constants.permission_constants import RoleConstants, Auth
24+
from common.constants.permission_constants import RoleConstants, Auth, ResourceAuthType, ResourcePermissionRole, \
25+
ResourcePermission
2526
from common.database_model_manage.database_model_manage import DatabaseModelManage
2627
from common.db.search import page_search
2728
from common.exception.app_exception import AppApiException
2829
from common.utils.common import valid_license, password_encrypt
30+
from maxkb import settings
2931
from maxkb.conf import PROJECT_DIR
30-
from system_manage.models import SystemSetting, SettingType
32+
from system_manage.models import SystemSetting, SettingType, AuthTargetType, WorkspaceUserResourcePermission
3133
from users.models import User
3234
from django.utils.translation import gettext_lazy as _, to_locale
3335
from django.core import validators
@@ -62,6 +64,7 @@ class CreateUserSerializer(serializers.Serializer):
6264
nick_name = serializers.CharField(required=False, label=_('Nick name'))
6365
phone = serializers.CharField(required=False, label=_('Phone'))
6466
source = serializers.CharField(required=False, label=_('Source'), default='LOCAL')
67+
defaultPermission = serializers.CharField(required=False, label=_('defaultPermission'))
6568

6669

6770
def is_workspace_manage(user_id: str, workspace_id: str):
@@ -181,7 +184,6 @@ class UserInstance(serializers.Serializer):
181184
default="LOCAL"
182185
)
183186

184-
185187
def is_valid(self, *, raise_exception=True):
186188
super().is_valid(raise_exception=True)
187189
self._check_unique_username_and_email()
@@ -345,6 +347,7 @@ def save(self, instance, user_id, with_valid=True):
345347
is_active=True
346348
)
347349
update_user_role(instance, user, user_id)
350+
set_default_permission(user.id, instance)
348351
user.save()
349352
return UserInstanceSerializer(user).data
350353

@@ -639,6 +642,7 @@ def update_user_role(instance, user, user_id=None):
639642
else:
640643
workspace_user_role_mapping_model.objects.filter(user_id=user.id).exclude(
641644
role__type=RoleConstants.ADMIN.name).delete()
645+
642646
relations = set()
643647
for item in role_setting:
644648
role_id = item['role_id']
@@ -656,6 +660,258 @@ def update_user_role(instance, user, user_id=None):
656660
cache.delete(permission_get_key(str(user.id)), version=permission_version)
657661

658662

663+
def set_default_permission(user_id, instance):
664+
"""
665+
为用户设置默认权限
666+
"""
667+
default_permission = instance.get('defaultPermission', 'NOT_AUTH')
668+
669+
# 获取工作空间ID列表
670+
workspace_ids = _get_workspace_ids(instance, default_permission)
671+
if not workspace_ids:
672+
return
673+
674+
# 根据权限类型确定认证类型
675+
auth_type = (ResourceAuthType.ROLE
676+
if default_permission == ResourceAuthType.ROLE
677+
else ResourceAuthType.RESOURCE_PERMISSION_GROUP)
678+
679+
# 设置根目录权限
680+
_set_root_permissions(user_id, workspace_ids)
681+
682+
# 如果是无权限设置,直接返回
683+
if default_permission == 'NOT_AUTH':
684+
return
685+
686+
# 设置具体资源权限
687+
_set_resource_permissions(user_id, workspace_ids, default_permission, auth_type)
688+
689+
690+
def _get_workspace_ids(instance, default_permission):
691+
"""
692+
获取工作空间ID列表
693+
"""
694+
role_setting_model = DatabaseModelManage.get_model("role_model")
695+
696+
if not role_setting_model:
697+
return ['default']
698+
699+
# 检查许可证有效性
700+
license_is_valid = DatabaseModelManage.get_model('license_is_valid') or (lambda: False)
701+
if default_permission == ResourceAuthType.ROLE and not license_is_valid():
702+
return []
703+
704+
role_setting = instance.get('role_setting')
705+
if not role_setting:
706+
return ['default']
707+
708+
# 获取用户角色的工作空间ID
709+
all_role_ids = [item['role_id'] for item in role_setting]
710+
user_role_ids = set(role_setting_model.objects.filter(
711+
id__in=all_role_ids,
712+
type=RoleConstants.USER.name
713+
).values_list('id', flat=True))
714+
715+
workspace_ids = set()
716+
for item in role_setting:
717+
role_id = item['role_id']
718+
if role_id in user_role_ids:
719+
workspace_ids.update(item.get('workspace_ids', []))
720+
721+
return list(workspace_ids) if workspace_ids else []
722+
723+
724+
def _set_root_permissions(user_id, workspace_ids):
725+
"""
726+
设置根目录权限(默认为查看权限)
727+
"""
728+
root_permissions = []
729+
for ws in workspace_ids:
730+
root_permissions.extend([
731+
WorkspaceUserResourcePermission(
732+
target=ws,
733+
auth_target_type=auth_target_type,
734+
permission_list=[ResourcePermission.VIEW],
735+
workspace_id=ws,
736+
user_id=user_id,
737+
auth_type=ResourceAuthType.RESOURCE_PERMISSION_GROUP
738+
)
739+
for auth_target_type in [
740+
AuthTargetType.APPLICATION.value,
741+
AuthTargetType.KNOWLEDGE.value,
742+
AuthTargetType.TOOL.value
743+
]
744+
])
745+
746+
_batch_create_permissions(root_permissions)
747+
748+
749+
def _set_resource_permissions(user_id, workspace_ids, default_permission, auth_type):
750+
"""
751+
设置具体资源权限
752+
"""
753+
# 批量查询资源并按工作空间分组
754+
resource_maps = _get_resource_maps(workspace_ids)
755+
756+
# 构造权限实例
757+
instances = []
758+
for ws in workspace_ids:
759+
instances.extend(_create_resource_permission_instances(
760+
ws, resource_maps, user_id, default_permission, auth_type))
761+
762+
# 批量创建权限
763+
_batch_create_permissions(instances)
764+
765+
766+
def _get_resource_maps(workspace_ids):
767+
"""
768+
获取各类型资源按工作空间的映射
769+
"""
770+
from application.models import Application, ApplicationFolder
771+
from knowledge.models import Knowledge, KnowledgeFolder
772+
from tools.models import Tool, ToolFolder
773+
from models_provider.models import Model
774+
from collections import defaultdict
775+
776+
resource_maps = {
777+
'apps': defaultdict(list),
778+
'app_folders': defaultdict(list),
779+
'knowledge': defaultdict(list),
780+
'knowledge_folders': defaultdict(list),
781+
'tools': defaultdict(list),
782+
'tool_folders': defaultdict(list),
783+
'models': defaultdict(list)
784+
}
785+
786+
# 查询应用资源
787+
for ws, rid in Application.objects.filter(workspace_id__in=workspace_ids).values_list('workspace_id', 'id'):
788+
resource_maps['apps'][ws].append(rid)
789+
790+
for ws, fid in ApplicationFolder.objects.filter(workspace_id__in=workspace_ids).exclude(
791+
id__in=workspace_ids).values_list('workspace_id', 'id'):
792+
resource_maps['app_folders'][ws].append(fid)
793+
794+
# 查询知识库资源
795+
for ws, kid in Knowledge.objects.filter(workspace_id__in=workspace_ids).values_list('workspace_id', 'id'):
796+
resource_maps['knowledge'][ws].append(kid)
797+
798+
for ws, kfid in KnowledgeFolder.objects.filter(workspace_id__in=workspace_ids).exclude(
799+
id__in=workspace_ids).values_list('workspace_id', 'id'):
800+
resource_maps['knowledge_folders'][ws].append(kfid)
801+
802+
# 查询工具资源
803+
for ws, tid in Tool.objects.filter(workspace_id__in=workspace_ids).values_list('workspace_id', 'id'):
804+
resource_maps['tools'][ws].append(tid)
805+
806+
for ws, tfid in ToolFolder.objects.filter(workspace_id__in=workspace_ids).exclude(
807+
id__in=workspace_ids).values_list('workspace_id', 'id'):
808+
resource_maps['tool_folders'][ws].append(tfid)
809+
810+
# 查询模型资源
811+
for ws, mid in Model.objects.filter(workspace_id__in=workspace_ids).values_list('workspace_id', 'id'):
812+
resource_maps['models'][ws].append(mid)
813+
814+
return resource_maps
815+
816+
817+
def _create_resource_permission_instances(workspace_id, resource_maps, user_id, permission, auth_type):
818+
"""
819+
创建资源权限实例列表
820+
"""
821+
instances = []
822+
823+
# 应用权限
824+
for rid in resource_maps['apps'].get(workspace_id, []):
825+
instances.append(WorkspaceUserResourcePermission(
826+
target=rid,
827+
auth_target_type=AuthTargetType.APPLICATION.value,
828+
permission_list=[permission],
829+
workspace_id=workspace_id,
830+
user_id=user_id,
831+
auth_type=auth_type
832+
))
833+
834+
# 应用文件夹权限
835+
for fid in resource_maps['app_folders'].get(workspace_id, []):
836+
instances.append(WorkspaceUserResourcePermission(
837+
target=fid,
838+
auth_target_type=AuthTargetType.APPLICATION.value,
839+
permission_list=[permission],
840+
workspace_id=workspace_id,
841+
user_id=user_id,
842+
auth_type=auth_type
843+
))
844+
845+
# 知识库权限
846+
for kid in resource_maps['knowledge'].get(workspace_id, []):
847+
instances.append(WorkspaceUserResourcePermission(
848+
target=kid,
849+
auth_target_type=AuthTargetType.KNOWLEDGE.value,
850+
permission_list=[permission],
851+
workspace_id=workspace_id,
852+
user_id=user_id,
853+
auth_type=auth_type
854+
))
855+
856+
# 知识库文件夹权限
857+
for kf in resource_maps['knowledge_folders'].get(workspace_id, []):
858+
instances.append(WorkspaceUserResourcePermission(
859+
target=kf,
860+
auth_target_type=AuthTargetType.KNOWLEDGE.value,
861+
permission_list=[permission],
862+
workspace_id=workspace_id,
863+
user_id=user_id,
864+
auth_type=auth_type
865+
))
866+
867+
# 工具权限
868+
for tid in resource_maps['tools'].get(workspace_id, []):
869+
instances.append(WorkspaceUserResourcePermission(
870+
target=tid,
871+
auth_target_type=AuthTargetType.TOOL.value,
872+
permission_list=[permission],
873+
workspace_id=workspace_id,
874+
user_id=user_id,
875+
auth_type=auth_type
876+
))
877+
878+
# 工具文件夹权限
879+
for tf in resource_maps['tool_folders'].get(workspace_id, []):
880+
instances.append(WorkspaceUserResourcePermission(
881+
target=tf,
882+
auth_target_type=AuthTargetType.TOOL.value,
883+
permission_list=[permission],
884+
workspace_id=workspace_id,
885+
user_id=user_id,
886+
auth_type=auth_type
887+
))
888+
889+
# 模型权限
890+
for mid in resource_maps['models'].get(workspace_id, []):
891+
instances.append(WorkspaceUserResourcePermission(
892+
target=mid,
893+
auth_target_type=AuthTargetType.MODEL.value,
894+
permission_list=[permission],
895+
workspace_id=workspace_id,
896+
user_id=user_id,
897+
auth_type=auth_type
898+
))
899+
900+
return instances
901+
902+
903+
def _batch_create_permissions(instances, batch_size=500):
904+
"""
905+
批量创建权限实例
906+
"""
907+
if not instances:
908+
return
909+
910+
objs = WorkspaceUserResourcePermission.objects
911+
for i in range(0, len(instances), batch_size):
912+
objs.bulk_create(instances[i:i + batch_size])
913+
914+
659915
class RePasswordSerializer(serializers.Serializer):
660916
email = serializers.EmailField(
661917
required=True,

apps/users/views/user.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ class UserList(APIView):
125125
operation_id=_("Get all user"), # type: ignore
126126
tags=[_("User Management")], # type: ignore
127127
responses=UserListApi.get_response())
128+
@has_permissions(RoleConstants.WORKSPACE_MANAGE, RoleConstants.ADMIN, RoleConstants.EXTENDS_ADMIN,
129+
RoleConstants.EXTENDS_WORKSPACE_MANAGE)
128130
def get(self, request: Request):
129131
return result.success(UserManageSerializer().get_all_user_list())
130132

0 commit comments

Comments
 (0)