feat: Modify the authorization information of resources for users

This commit is contained in:
zhangzhanwei 2025-08-11 15:51:34 +08:00 committed by zhanweizhang7
parent 154fd5e52b
commit 919c4e3f7f
5 changed files with 393 additions and 5 deletions

View File

@ -8,11 +8,13 @@
"""
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import OpenApiParameter
from rest_framework import serializers
from django.utils.translation import gettext_lazy as _
from common.mixins.api_mixin import APIMixin
from common.result import ResultSerializer
from common.result import ResultSerializer, ResultPageSerializer
from system_manage.serializers.user_resource_permission import UserResourcePermissionResponse, \
UpdateUserResourcePermissionRequest
UpdateUserResourcePermissionRequest, ResourceUserPermissionEditRequest
class APIUserResourcePermissionResponse(ResultSerializer):
@ -49,3 +51,176 @@ class EditUserResourcePermissionAPI(APIMixin):
@staticmethod
def get_request():
return UpdateUserResourcePermissionRequest()
class ResourceUserPermissionResponse(serializers.Serializer):
id = serializers.CharField(required=True, label=_('user id'))
nick_name = serializers.CharField(required=True, allow_null=True, allow_blank=True, label=_('nick_name'))
username = serializers.CharField(required=True, allow_null=True, allow_blank=True, label=_('username'))
permission = serializers.CharField(required=True, label=_('permission'))
class APIResourceUserPermissionResponse(ResultSerializer):
def get_data(self):
return ResourceUserPermissionResponse(many=True)
class ResourceUserPermissionAPI(APIMixin):
@staticmethod
def get_parameters():
return [
OpenApiParameter(
name="workspace_id",
description="工作空间id",
type=OpenApiTypes.STR,
location='path',
required=True
),
OpenApiParameter(
name="target",
description="资源id",
type=OpenApiTypes.STR,
location='path',
required=True
),
OpenApiParameter(
name="resource",
description="资源类型",
type=OpenApiTypes.STR,
location='path',
required=True
),
OpenApiParameter(
name="username",
description="用户名",
type=OpenApiTypes.STR,
location='query',
required=False
),
OpenApiParameter(
name="nick_name",
description="姓名",
type=OpenApiTypes.STR,
location='query',
required=False
),
OpenApiParameter(
name="permission",
description="权限",
type=OpenApiTypes.STR,
location='query',
required=False
),
]
@staticmethod
def get_response():
return APIResourceUserPermissionResponse
class APIResourceUserPermissionPageResponse(ResultPageSerializer):
def get_data(self):
return ResourceUserPermissionResponse(many=True)
class ResourceUserPermissionPageAPI(APIMixin):
@staticmethod
def get_parameters():
return [
OpenApiParameter(
name="workspace_id",
description="工作空间id",
type=OpenApiTypes.STR,
location='path',
required=True
),
OpenApiParameter(
name="target",
description="资源id",
type=OpenApiTypes.STR,
location='path',
required=True
),
OpenApiParameter(
name="resource",
description="资源类型",
type=OpenApiTypes.STR,
location='path',
required=True
),
OpenApiParameter(
name="current_page",
description=_("Current page"),
type=OpenApiTypes.INT,
location='path',
required=True,
),
OpenApiParameter(
name="page_size",
description=_("Page size"),
type=OpenApiTypes.INT,
location='path',
required=True,
),
OpenApiParameter(
name="username",
description="用户名",
type=OpenApiTypes.STR,
location='query',
required=False
),
OpenApiParameter(
name="nick_name",
description="姓名",
type=OpenApiTypes.STR,
location='query',
required=False
),
OpenApiParameter(
name="permission",
description="权限",
type=OpenApiTypes.STR,
location='query',
required=False
),
]
@staticmethod
def get_response():
return APIResourceUserPermissionPageResponse
class ResourceUserPermissionEditAPI(APIMixin):
@staticmethod
def get_parameters():
return [
OpenApiParameter(
name="workspace_id",
description="工作空间id",
type=OpenApiTypes.STR,
location='path',
required=True
),
OpenApiParameter(
name="target",
description="资源id",
type=OpenApiTypes.STR,
location='path',
required=True
),
OpenApiParameter(
name="resource",
description="资源类型",
type=OpenApiTypes.STR,
location='path',
required=True
),
]
@staticmethod
def get_request():
return ResourceUserPermissionEditRequest(required=True, many=True, label=_('users_permission'))
@staticmethod
def get_response():
return APIResourceUserPermissionResponse()

View File

@ -10,6 +10,7 @@ import json
import os
from django.core.cache import cache
from django.db import models
from django.db.models import QuerySet
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
@ -19,7 +20,7 @@ from common.constants.cache_version import Cache_Version
from common.constants.permission_constants import get_default_workspace_user_role_mapping_list, RoleConstants, \
ResourcePermission, ResourcePermissionRole, ResourceAuthType
from common.database_model_manage.database_model_manage import DatabaseModelManage
from common.db.search import native_search
from common.db.search import native_search, native_page_search, get_dynamics_model
from common.db.sql_execute import select_list
from common.exception.app_exception import AppApiException
from common.utils.common import get_file_content
@ -30,6 +31,7 @@ from maxkb.settings import edition
from models_provider.models import Model
from system_manage.models import WorkspaceUserResourcePermission, AuthTargetType
from tools.models import Tool
from users.models import User
from users.serializers.user import is_workspace_manage
@ -260,3 +262,123 @@ class UserResourcePermissionSerializer(serializers.Serializer):
key = Cache_Version.PERMISSION_LIST.get_key(user_id=user_id)
cache.delete(key, version=version)
return True
class ResourceUserPermissionUserListRequest(serializers.Serializer):
nick_name = serializers.CharField(required=False, allow_null=True, allow_blank=True, label=_('workspace id'))
username = serializers.CharField(required=False, allow_null=True, allow_blank=True, label=_('workspace id'))
permission = serializers.ChoiceField(required=True, choices=['NOT_AUTH', 'MANAGE', 'VIEW', 'ROLE'],
label=_('permission'))
class ResourceUserPermissionEditRequest(serializers.Serializer):
user_id = serializers.CharField(required=True, label=_('workspace id'))
permission = serializers.ChoiceField(required=True, choices=['NOT_AUTH', 'MANAGE', 'VIEW', 'ROLE'],
label=_('permission'))
permission_map = {
"ROLE": ("ROLE", ["ROLE"]),
"MANAGE": ("RESOURCE_PERMISSION_GROUP", ["MANAGE", "VIEW"]),
"VIEW": ("RESOURCE_PERMISSION_GROUP", ["VIEW"]),
"NOT_AUTH": ("RESOURCE_PERMISSION_GROUP", []),
}
class ResourceUserPermissionSerializer(serializers.Serializer):
workspace_id = serializers.CharField(required=True, label=_('workspace id'))
target = serializers.CharField(required=True, label=_('resource id'))
auth_target_type = serializers.CharField(required=True, label=_('resource'))
users_permission = ResourceUserPermissionEditRequest(required=False, many=True, label=_('users_permission'))
def get_queryset(self, instance):
user_query_set = QuerySet(model=get_dynamics_model({
'nick_name': models.CharField(),
'username': models.CharField(),
"permission": models.CharField(),
}))
nick_name = instance.get('nick_name')
username = instance.get('username')
permission = instance.get('permission')
workspace_user_resource_permission_query_set = QuerySet(WorkspaceUserResourcePermission).filter(
workspace_id=self.data.get('workspace_id'),
auth_target_type=self.data.get('auth_target_type'),
target=self.data.get('target'))
if nick_name:
user_query_set = user_query_set.filter(nick_name__contains=nick_name)
if username:
user_query_set = user_query_set.filter(username__contains=username)
if permission:
user_query_set = user_query_set.filter(
permission=None if instance.get('permission') == 'NOT_AUTH' else instance.get('permission'))
return {
'workspace_user_resource_permission_query_set': workspace_user_resource_permission_query_set,
'user_query_set': user_query_set
}
def list(self, instance, with_valid=True):
if with_valid:
self.is_valid(raise_exception=True)
ResourceUserPermissionUserListRequest(data=instance).is_valid(raise_exception=True)
# 资源的用户授权列表
resource_user_permission_list = native_search(self.get_queryset(instance), get_file_content(
os.path.join(PROJECT_DIR, "apps", "system_manage", 'sql', 'get_resource_user_permission_detail.sql')
))
return resource_user_permission_list
def page(self, instance, current_page: int, page_size: int, with_valid=True):
if with_valid:
self.is_valid(raise_exception=True)
ResourceUserPermissionUserListRequest(data=instance).is_valid(raise_exception=True)
# 分页列表
resource_user_permission_page_list = native_page_search(current_page, page_size, self.get_queryset(instance),
get_file_content(
os.path.join(PROJECT_DIR, "apps", "system_manage",
'sql',
'get_resource_user_permission_detail.sql')
))
return resource_user_permission_page_list
def edit(self, instance, with_valid=True):
if with_valid:
self.is_valid(raise_exception=True)
ResourceUserPermissionEditRequest(data=instance, many=True).is_valid(
raise_exception=True)
workspace_id = self.data.get("workspace_id")
target = self.data.get("target")
auth_target_type = self.data.get("auth_target_type")
users_permission = instance
users_id = [item["user_id"] for item in users_permission]
# 删除已存在的对应的用户在该资源下的权限
QuerySet(WorkspaceUserResourcePermission).filter(
workspace_id=workspace_id,
target=target,
auth_target_type=auth_target_type,
user_id__in=users_id
).delete()
save_list = []
for item in users_permission:
permission = item['permission']
auth_type, permission_list = permission_map[permission]
save_list.append(WorkspaceUserResourcePermission(
target=target,
auth_target_type=auth_target_type,
workspace_id=workspace_id,
auth_type=auth_type,
user_id=item["user_id"],
permission_list=permission_list
))
if save_list:
QuerySet(WorkspaceUserResourcePermission).bulk_create(save_list)
version = Cache_Version.PERMISSION_LIST.get_version()
for user_id in users_id:
key = Cache_Version.PERMISSION_LIST.get_key(user_id=user_id)
cache.delete(key, version=version)
return True

View File

@ -0,0 +1,30 @@
SELECT
u.id,
u.nick_name,
u.username,
case
when
wurp."permission" is null then 'NOT_AUTH'
else wurp."permission"
end
FROM
public."user" u
LEFT JOIN (
SELECT
user_id ,
(case
when auth_type = 'ROLE'
and 'ROLE' = any( permission_list) then 'ROLE'
when auth_type = 'RESOURCE_PERMISSION_GROUP'
and 'MANAGE'= any(permission_list) then 'MANAGE'
when auth_type = 'RESOURCE_PERMISSION_GROUP'
and 'VIEW' = any( permission_list) then 'VIEW'
else 'NO_AUTH'
end) as "permission"
FROM
workspace_user_resource_permission
${workspace_user_resource_permission_query_set}
) wurp
ON
u.id = wurp.user_id
${user_query_set}

View File

@ -6,6 +6,8 @@ app_name = "system_manage"
# @formatter:off
urlpatterns = [
path('workspace/<str:workspace_id>/user_resource_permission/user/<str:user_id>/resource/<str:resource>', views.WorkSpaceUserResourcePermissionView.as_view()),
path('workspace/<str:workspace_id>/resource_user_permission/resource/<str:target>/resource/<str:resource>', views.WorkspaceResourceUserPermissionView.as_view()),
path('workspace/<str:workspace_id>/resource_user_permission/resource/<str:target>/resource/<str:resource>/<int:current_page>/<int:page_size>', views.WorkspaceResourceUserPermissionView.Page.as_view()),
path('email_setting', views.SystemSetting.Email.as_view()),
path('profile', views.SystemProfile.as_view()),
path('valid/<str:valid_type>/<int:valid_count>', views.Valid.as_view())

View File

@ -18,8 +18,10 @@ from common.auth.authentication import has_permissions
from common.constants.permission_constants import PermissionConstants, RoleConstants, Permission, Group, Operate
from common.log.log import log
from common.result import DefaultResultSerializer
from system_manage.api.user_resource_permission import UserResourcePermissionAPI, EditUserResourcePermissionAPI
from system_manage.serializers.user_resource_permission import UserResourcePermissionSerializer
from system_manage.api.user_resource_permission import UserResourcePermissionAPI, EditUserResourcePermissionAPI, \
ResourceUserPermissionAPI, ResourceUserPermissionPageAPI, ResourceUserPermissionEditAPI
from system_manage.serializers.user_resource_permission import UserResourcePermissionSerializer, \
ResourceUserPermissionSerializer
from users.models import User
@ -72,3 +74,60 @@ class WorkSpaceUserResourcePermissionView(APIView):
return result.success(UserResourcePermissionSerializer(
data={'workspace_id': workspace_id, 'user_id': user_id, 'auth_target_type': resource}
).edit(request.data, request.user))
class WorkspaceResourceUserPermissionView(APIView):
authentication_classes = [TokenAuth]
@extend_schema(
methods=['GET'],
description=_('Get user authorization status of resource'),
summary=_('Get user authorization status of resource'),
operation_id=_('Get user authorization status of resource'), # type: ignore
parameters=ResourceUserPermissionAPI.get_parameters(),
responses=ResourceUserPermissionAPI.get_response(),
tags=[_('Resources authorization')] # type: ignore
)
def get(self, request: Request, workspace_id: str, target: str, resource: str):
return result.success(ResourceUserPermissionSerializer(
data={'workspace_id': workspace_id, "target": target, 'auth_target_type': resource,
}).list(
{'username': request.query_params.get("username"), 'nick_name': request.query_params.get("nick_name"),
'permission': request.query_params.get("permission")
}))
@extend_schema(
methods=['PUT'],
description=_('Edit user authorization status of resource'),
summary=_('Edit user authorization status of resource'),
operation_id=_('Edit user authorization status of resource'), # type: ignore
parameters=ResourceUserPermissionEditAPI.get_parameters(),
request=ResourceUserPermissionEditAPI.get_request(),
responses=ResourceUserPermissionEditAPI.get_response(),
tags=[_('Resources authorization')] # type: ignore
)
def put(self, request: Request, workspace_id: str, target: str, resource: str):
return result.success(ResourceUserPermissionSerializer(
data={'workspace_id': workspace_id, "target": target, 'auth_target_type': resource, })
.edit(instance=request.data))
class Page(APIView):
authentication_classes = [TokenAuth]
@extend_schema(
methods=['GET'],
description=_('Get user authorization status of resource by page'),
summary=_('Get user authorization status of resource by page'),
operation_id=_('Get user authorization status of resource by page'), # type: ignore
parameters=ResourceUserPermissionPageAPI.get_parameters(),
responses=ResourceUserPermissionPageAPI.get_response(),
tags=[_('Resources authorization')] # type: ignore
)
def get(self, request: Request, workspace_id: str, target: str, resource: str, current_page: int,
page_size: int):
return result.success(ResourceUserPermissionSerializer(
data={'workspace_id': workspace_id, "target": target, 'auth_target_type': resource, }
).page({'username': request.query_params.get("username"),
'nick_name': request.query_params.get("nick_name"), 'permission': request.query_params.get("permission")}, current_page, page_size,
))