From f5baae4117d31a8d5b317bfb7c0c00f705db09c3 Mon Sep 17 00:00:00 2001 From: shaohuzhang1 <80892890+shaohuzhang1@users.noreply.github.com> Date: Wed, 11 Jun 2025 12:21:13 +0800 Subject: [PATCH] fix: application page (#3233) --- apps/application/serializers/application.py | 34 ++++++++++++++----- apps/application/sql/list_application.sql | 5 +-- .../application/sql/list_application_user.sql | 31 +++++++++++++++++ ...on_ee.sql => list_application_user_ee.sql} | 0 .../views/application_chat_record.py | 5 +-- apps/common/auth/handle/impl/user_token.py | 17 ++++++++-- apps/common/constants/permission_constants.py | 4 +++ apps/users/serializers/user.py | 11 ++++++ 8 files changed, 90 insertions(+), 17 deletions(-) create mode 100644 apps/application/sql/list_application_user.sql rename apps/application/sql/{list_application_ee.sql => list_application_user_ee.sql} (100%) diff --git a/apps/application/serializers/application.py b/apps/application/serializers/application.py index 4d2e41ed4..5011d8b8d 100644 --- a/apps/application/serializers/application.py +++ b/apps/application/serializers/application.py @@ -38,6 +38,7 @@ from models_provider.models import Model from tools.models import Tool, ToolScope from tools.serializers.tool import ToolModelSerializer from users.models import User +from users.serializers.user import is_workspace_manage def get_base_node_work_flow(work_flow): @@ -290,9 +291,10 @@ class ApplicationListResponse(serializers.Serializer): class Query(serializers.Serializer): - workspace_id = serializers.CharField(required=False, label=_('workspace id')) + workspace_id = serializers.CharField(required=False, label=_('Workspace ID')) + user_id = serializers.UUIDField(required=True, label=_("User ID")) - def get_query_set(self, instance: Dict): + def get_query_set(self, instance: Dict, workspace_manage: bool): folder_query_set = QuerySet(ApplicationFolder) application_query_set = QuerySet(Application) workspace_id = self.data.get('workspace_id') @@ -315,11 +317,14 @@ class Query(serializers.Serializer): if desc is not None: folder_query_set = folder_query_set.filter(desc__contains=desc) application_query_set = application_query_set.filter(desc__contains=desc) + application_custom_sql_query_set = application_query_set application_query_set = application_query_set.order_by("-update_time") return { 'folder_query_set': folder_query_set, - 'application_query_set': application_query_set - } + 'application_query_set': application_query_set, + 'application_custom_sql': application_custom_sql_query_set + } if workspace_manage else {'folder_query_set': folder_query_set, + 'application_query_set': application_query_set} @staticmethod def is_x_pack_ee(): @@ -329,17 +334,28 @@ class Query(serializers.Serializer): def list(self, instance: Dict): self.is_valid(raise_exception=True) + workspace_id = self.data.get('workspace_id') + user_id = self.data.get("user_id") ApplicationQueryRequest(data=instance).is_valid(raise_exception=True) - return native_search(self.get_query_set(instance), select_string=get_file_content( + workspace_manage = is_workspace_manage(user_id, workspace_id) + + return native_search(self.get_query_set(instance, workspace_manage), select_string=get_file_content( os.path.join(PROJECT_DIR, "apps", "application", 'sql', - 'list_application_ee.sql' if self.is_x_pack_ee() else 'list_application.sql'))) + 'list_application.sql' if workspace_manage else ( + 'list_application_user_ee.sql' if self.is_x_pack_ee() else 'list_application_user.sql') + ))) def page(self, current_page: int, page_size: int, instance: Dict): self.is_valid(raise_exception=True) ApplicationQueryRequest(data=instance).is_valid(raise_exception=True) - return native_page_search(current_page, page_size, self.get_query_set(instance), get_file_content( - os.path.join(PROJECT_DIR, "apps", "application", 'sql', - 'list_application_ee.sql' if self.is_x_pack_ee() else 'list_application.sql')), + workspace_id = self.data.get('workspace_id') + user_id = self.data.get("user_id") + workspace_manage = is_workspace_manage(user_id, workspace_id) + return native_page_search(current_page, page_size, self.get_query_set(instance, workspace_manage), + get_file_content( + os.path.join(PROJECT_DIR, "apps", "application", 'sql', + 'list_application.sql' if workspace_manage else ( + 'list_application_user_ee.sql' if self.is_x_pack_ee() else 'list_application_user.sql'))), ) diff --git a/apps/application/sql/list_application.sql b/apps/application/sql/list_application.sql index edc889120..811bfe544 100644 --- a/apps/application/sql/list_application.sql +++ b/apps/application/sql/list_application.sql @@ -11,10 +11,7 @@ from (select "id"::text, "create_time", "update_time" from application - where id in (select target - from workspace_user_resource_permission - where auth_target_type = 'APPLICATION' - and 'VIEW' = any (permission_list)) + ${application_custom_sql} UNION select "id", "name", diff --git a/apps/application/sql/list_application_user.sql b/apps/application/sql/list_application_user.sql new file mode 100644 index 000000000..edc889120 --- /dev/null +++ b/apps/application/sql/list_application_user.sql @@ -0,0 +1,31 @@ +select * +from (select "id"::text, + "name", + "desc", + "is_publish", + "type", + 'application' as "resource_type", + "workspace_id", + "folder_id", + "user_id", + "create_time", + "update_time" + from application + where id in (select target + from workspace_user_resource_permission + where auth_target_type = 'APPLICATION' + and 'VIEW' = any (permission_list)) + UNION + select "id", + "name", + "desc", + true as "is_publish", + 'folder' as "type", + 'folder' as "resource_type", + "workspace_id", + "parent_id" as "folder_id", + "user_id", + "create_time", + "update_time" + from application_folder ${folder_query_set}) temp +${application_query_set} \ No newline at end of file diff --git a/apps/application/sql/list_application_ee.sql b/apps/application/sql/list_application_user_ee.sql similarity index 100% rename from apps/application/sql/list_application_ee.sql rename to apps/application/sql/list_application_user_ee.sql diff --git a/apps/application/views/application_chat_record.py b/apps/application/views/application_chat_record.py index b1da497c3..0a0db4dd8 100644 --- a/apps/application/views/application_chat_record.py +++ b/apps/application/views/application_chat_record.py @@ -18,7 +18,7 @@ from application.serializers.application_chat_record import ApplicationChatRecor from common import result from common.auth import TokenAuth from common.auth.authentication import has_permissions -from common.constants.permission_constants import PermissionConstants +from common.constants.permission_constants import PermissionConstants, RoleConstants from common.utils.common import query_params_to_single_dict @@ -35,7 +35,8 @@ class ApplicationChatRecord(APIView): responses=ApplicationChatRecordQueryAPI.get_response(), tags=[_("Application/Conversation Log")] # type: ignore ) - @has_permissions(PermissionConstants.APPLICATION_CHAT_LOG.get_workspace_application_permission()) + @has_permissions(PermissionConstants.APPLICATION_CHAT_LOG.get_workspace_application_permission(), + RoleConstants.WORKSPACE_MANAGE.get_workspace_role()) def get(self, request: Request, workspace_id: str, application_id: str, chat_id: str): return result.success(ApplicationChatRecordQuerySerializers( data={**query_params_to_single_dict(request.query_params), 'application_id': application_id, diff --git a/apps/common/auth/handle/impl/user_token.py b/apps/common/auth/handle/impl/user_token.py index 5c15d11bb..d9450cfdb 100644 --- a/apps/common/auth/handle/impl/user_token.py +++ b/apps/common/auth/handle/impl/user_token.py @@ -19,7 +19,8 @@ from common.constants.authentication_type import AuthenticationType from common.constants.cache_version import Cache_Version from common.constants.permission_constants import Auth, PermissionConstants, ResourcePermissionGroup, \ get_permission_list_by_resource_group, ResourceAuthType, \ - ResourcePermissionRole, get_default_role_permission_mapping_list, get_default_workspace_user_role_mapping_list + ResourcePermissionRole, get_default_role_permission_mapping_list, get_default_workspace_user_role_mapping_list, \ + RoleConstants from common.database_model_manage.database_model_manage import DatabaseModelManage from common.exception.app_exception import AppAuthenticationFailed from common.utils.common import group_by @@ -50,6 +51,18 @@ def get_workspace_permission(permission_id, workspace_id): return f"{permission_id}:/WORKSPACE/{workspace_id}" +def get_role_permission(role, workspace_id): + """ + 获取工作空间角色 + @param role: 角色 + @param workspace_id: 工作空间id + @return: + """ + if isinstance(role, RoleConstants): + role = role.value + return f"{role}:/WORKSPACE/{workspace_id}" + + def get_workspace_permission_list(role_permission_mapping_dict, workspace_user_role_mapping_list): """ 获取工作空间下所有的权限 @@ -212,7 +225,7 @@ def get_role_list(user, workspace_user_role_mapping_list] + [user.role], version=version) else: cache.set(key, [user.role], version=version) - return [user.role] + return [user.role, get_role_permission(RoleConstants.WORKSPACE_MANAGE, 'default')] return workspace_list diff --git a/apps/common/constants/permission_constants.py b/apps/common/constants/permission_constants.py index 2abb6dc34..dc6e4f0b4 100644 --- a/apps/common/constants/permission_constants.py +++ b/apps/common/constants/permission_constants.py @@ -184,6 +184,10 @@ class Role: def __eq__(self, other): return str(self) == str(other) + def get_workspace_role(self): + return lambda r, kwargs: Role(self.name, self.decs, self.group, + resource_path=f"/WORKSPACE/{kwargs.get('workspace_id')}") + class RoleConstants(Enum): ADMIN = Role("ADMIN", '超级管理员', RoleGroup.SYSTEM_USER) diff --git a/apps/users/serializers/user.py b/apps/users/serializers/user.py index 75391273f..a6cfeb572 100644 --- a/apps/users/serializers/user.py +++ b/apps/users/serializers/user.py @@ -60,6 +60,17 @@ class CreateUserSerializer(serializers.Serializer): phone = serializers.CharField(required=False, label=_('Phone')) +def is_workspace_manage(user_id: str, workspace_id: str): + workspace_user_role_mapping_model = DatabaseModelManage.get_model("workspace_user_role_mapping") + role_permission_mapping_model = DatabaseModelManage.get_model("role_permission_mapping_model") + is_x_pack_ee = workspace_user_role_mapping_model is not None and role_permission_mapping_model is not None + if is_x_pack_ee: + return QuerySet(workspace_user_role_mapping_model).select_related('role', 'user').filter( + workspace_id=workspace_id, user_id=user_id, + role_type=RoleConstants.WORKSPACE_MANAGE.value.__str__()).exists() + return QuerySet(User).filter(id=user_id, role=RoleConstants.ADMIN.value.__str__()).exists() + + class UserProfileSerializer(serializers.Serializer): @staticmethod def profile(user: User, auth: Auth):