Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
179 changes: 177 additions & 2 deletions apps/system_manage/api/user_resource_permission.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The provided code snippet is a series of serializer definitions and API methods related to managing user resource permissions within a Django application. While the structure looks comprehensive, there are a few areas that could be improved for better clarity and functionality:

  1. Translation Usage: The _ function is used as a translation context in the ResultSerializer, but it seems unnecessary since these fields (user id, name, etc.) do not actually require translation. Consider removing the translations.

  2. Duplicate Parameter Definitions: There might be duplicate parameters across different serializers or classes if they all use similar paths or query strings.

  3. Simplified Query Parameters: For pagination requests, you can simplify the syntax by using generic parameter names like page_number instead of current_page. This enhances readability and consistency with other systems and libraries.

  4. Field Descriptions Alignment: Ensure consistent descriptions for each field to maintain clear understanding across serializers.

  5. Error Handling: Adding error handling logic would improve the robustness and user experience of the APIs.

  6. Code Structure Review: It would be beneficial to review the overall structural organization of the module to ensure logical flow and modularity.

Here's an updated version addressing some of these points:

from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import OpenApiParameter
from rest_framework import serializers

from common.mixins.api_mixin import APIMixin
from common.result import ResultSerializer, ResultPageSerializer

class APIUserResourcePermissionResponse(ResultSerializer):
    pass

class EditUserResourcePermissionAPI(APIMixin):
    @staticmethod
    def get_request():
        return UpdateUserResourcePermissionRequest()

# New Response Serializer with Simple Field Labels
class ResourceUserPermissionSimpleResponse(serializers.Serializer):
    id = serializers.CharField(label='id')
    nick_name = serializers.CharField(allow_null=True, allow_blank=True)
    username = serializers.CharField(allow_null=True, allow_blank=True)
    permission = serializers.CharField()  # Simplified to string

class APIResourceUserPermissionResponse(ResultSerializer):
    def get_data(self):
        return ResourceUserPermissionSimpleResponse(many=True)

class ResourceUserPermissionAPI(APIMixin):
    @staticmethod
    def get_parameters():
        return [
            OpenApiParameter(
                name="workspace_id",
                description="Workspace ID",
                type=OpenApiTypes.STRING,
                location='path',
                required=True,
            ),
            OpenApiParameter(
                name="target",
                description="Target resource ID",
                type=OpenApiTypes.STRING,
                location='path',
                required=True,
            ),
            OpenApiParameter(
                name="resource_type",
                description="Resource type",
                type=OpenApiTypes.STRING,
                location='path',
                required=True,
            ),
            OpenApiParameter(
                name="username",
                description="Username (optional)",
                type=OpenApiTypes.STRING,
                location='query',
                required=False,
            ),
            OpenApiParameter(
                name="nickname",
                description="Nickname (optional)",
                type=OpenApiTypes.STRING,
                location='query',
                required=False,
            ),
            OpenApiParameter(
                name="permission",
                description="Permission value (optional)",
                type=OpenApiTypes.STRING,
                location='query',
                required=False,
            ),
        ]

    @staticmethod
    def get_response():
        return APIResourceUserPermissionResponse


class ResourceUserPermissionPageAPI(APIMixin):
    @staticmethod
    def get_parameters():
        return [
            OpenApiParameter(
                name="workspace_id",
                description="Workspace ID",
                type=OpenApiTypes.STRING,
                location='path',
                required=True,
            ),
            OpenApiParameter(
                name="target",
                description="Target resource ID",
                type=OpenApiTypes.STRING,
                location='path',
                required=True,
            ),
            OpenApiParameter(
                name="resource_type",
                description="Resource type",
                type=OpenApiTypes.STRING,
                location='path',
                required=True,
            ),
            OpenApiParameter(
                name="page_number",
                description="Page number",
                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="Username (optional)",
                type=OpenApiTypes.STRING,
                location='query',
                required=False,
            ),
            OpenApiParameter(
                name="nickname",
                description="Nickname (optional)",
                type=OpenApiTypes.STRING,
                location='query',
                required=False,
            ),
            OpenApiParameter(
                name="permission",
                description="Permission value (optional)",
                type=OpenApiTypes.STRING,
                location='query',
                required=False,
            ),
        ]

    @staticmethod
    def get_response():
        return ResourceUserPermissionPageResponse()


class ResourceUserPermissionEditAPI(APIMixin):
    @staticmethod
    def get_parameters():
        return [
            OpenApiParameter(
                name="workspace_id",
                description="Workspace ID",
                type=OpenApiTypes.STRING,
                location='path',
                required=True,
            ),
            OpenApiParameter(
                name="target",
                description="Target resource ID",
                type=OpenApiTypes.STRING,
                location='path',
                required=True,
            ),
            OpenApiParameter(
                name="resource_type",
                description="Resource type",
                type=OpenApiTypes.STRING,
                location='path',
                required=True,
            ),
        ]
    
    @staticmethod
    def get_request():
        return [ResourceUserPermissionEditRequest(), ]  # Use list for multiple instances
        
    @staticmethod
    def get_response():
        return APIResourceUserPermissionResponse()

These changes aim to enhance readability and maintainability while ensuring that the API remains functional.

124 changes: 123 additions & 1 deletion apps/system_manage/serializers/user_resource_permission.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
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
Expand All @@ -19,7 +20,7 @@
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
Expand All @@ -30,6 +31,7 @@
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


Expand Down Expand Up @@ -260,3 +262,123 @@ def edit(self, instance, user, with_valid=True):
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
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{
  "error": "The patch contains multiple issues:"
}

30 changes: 30 additions & 0 deletions apps/system_manage/sql/get_resource_user_permission_detail.sql
Original file line number Diff line number Diff line change
@@ -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}
2 changes: 2 additions & 0 deletions apps/system_manage/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
# @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())
Expand Down
Loading
Loading