From efbb772d1d4d449c1dc322ca6aebae84b8815a96 Mon Sep 17 00:00:00 2001 From: wxg0103 <727495428@qq.com> Date: Wed, 4 Nov 2026 16:29:55 +0800 Subject: [PATCH] feat: update permission constants and enhance backend API access and export skills functionality --- .../test_application_advanced_permissions.py | 70 +++++++++++ apps/application/views/application.py | 4 +- apps/application/views/application_api_key.py | 4 +- .../auth/constants/operate_constants.py | 1 + .../auth/constants/permission_constants.py | 110 ++++++++++++++++++ apps/locales/en_US/LC_MESSAGES/django.po | 2 +- apps/locales/zh_CN/LC_MESSAGES/django.po | 34 ++++-- apps/locales/zh_Hant/LC_MESSAGES/django.po | 34 ++++-- ui/src/permission/core/common.ts | 1 + ui/src/permission/core/data.ts | 8 ++ .../permission/modules/application/system.ts | 12 ++ .../modules/application/workspace.ts | 12 ++ ui/src/router/admin/system/index.ts | 6 +- .../application-detail/overview/index.vue | 15 ++- .../ExportApplicationAction.vue | 14 ++- ui/src/views/application/index.vue | 8 +- .../resource-management/application/index.vue | 10 +- 17 files changed, 315 insertions(+), 30 deletions(-) create mode 100644 apps/application/tests/test_application_advanced_permissions.py diff --git a/apps/application/tests/test_application_advanced_permissions.py b/apps/application/tests/test_application_advanced_permissions.py new file mode 100644 index 00000000000..2cf21c4d5fd --- /dev/null +++ b/apps/application/tests/test_application_advanced_permissions.py @@ -0,0 +1,70 @@ +from types import SimpleNamespace +from unittest.mock import patch + +from django.test import TestCase + +from application.views.application import ApplicationAPI +from application.views.application_api_key import ApplicationApiKeyEnable +from common.auth.constants.operate_constants import Operate +from common.auth.constants.permission_constants import PermissionConstants +from common.auth.struct.permission import Role +from common.exception.app_exception import AppUnauthorizedFailed + + +class ApplicationAdvancedPermissionTests(TestCase): + workspace_id = "workspace-a" + application_id = "00000000-0000-0000-0000-000000000001" + + def kwargs(self): + return {"workspace_id": self.workspace_id, "application_id": self.application_id} + + def request_with_permission(self, permission_constant): + permission = permission_constant.get_workspace_application_permission()(None, self.kwargs()) + permissions = {permission.get_resource_permission_key(permission.resource_id): permission.bit()} + return SimpleNamespace( + auth=SimpleNamespace(roles=[Role("USER", self.workspace_id)], permissions=permissions), + user=SimpleNamespace(id=self.application_id, type="test"), + META={"REMOTE_ADDR": "127.0.0.1"}, + path="/test", + data={"enable_api_key": True}, + query_params={}, + build_absolute_uri=lambda _: "http://localhost/", + ) + + def test_backend_api_access_uses_dedicated_permission(self): + request = self.request_with_permission(PermissionConstants.APPLICATION_OVERVIEW_BACKEND_API_ACCESS) + with ( + patch("application.views.application_api_key.ApiKeyEnableSerializer") as serializer, + patch("application.views.application_api_key.get_application_operation_object", return_value={}), + ): + serializer.return_value.edit.return_value = {} + ApplicationApiKeyEnable.put(ApplicationApiKeyEnable(), request, **self.kwargs()) + serializer.assert_called_once() + + def test_backend_api_access_rejects_legacy_api_key_permission(self): + request = self.request_with_permission(PermissionConstants.APPLICATION_OVERVIEW_API_KEY) + with self.assertRaises(AppUnauthorizedFailed): + ApplicationApiKeyEnable.put(ApplicationApiKeyEnable(), request, **self.kwargs()) + + def test_export_skills_uses_dedicated_permission(self): + request = self.request_with_permission(PermissionConstants.APPLICATION_EXPORT_SKILLS) + with ( + patch("application.views.application.ApplicationOperateSerializer") as serializer, + patch("application.views.application.get_application_operation_object", return_value={}), + ): + serializer.return_value.export_skills.return_value = {} + ApplicationAPI.ExportSkills.get(ApplicationAPI.ExportSkills(), request, **self.kwargs()) + serializer.assert_called_once() + + def test_export_skills_rejects_application_export_permission(self): + request = self.request_with_permission(PermissionConstants.APPLICATION_EXPORT) + with self.assertRaises(AppUnauthorizedFailed): + ApplicationAPI.ExportSkills.get(ApplicationAPI.ExportSkills(), request, **self.kwargs()) + + def test_mcp_permission_bits_exist_for_role_tree(self): + self.assertEqual(PermissionConstants.APPLICATION_MCP_CONFIG.value.operate, Operate.MCP_CONFIG) + self.assertEqual(PermissionConstants.RESOURCE_APPLICATION_MCP_CONFIG.value.operate, Operate.MCP_CONFIG) + self.assertEqual( + PermissionConstants.APPLICATION_OVERVIEW_BACKEND_API_ACCESS.value.operate, + Operate.BACKEND_API_ACCESS, + ) diff --git a/apps/application/views/application.py b/apps/application/views/application.py index 9bb7c3b3bde..c49210f6a3f 100644 --- a/apps/application/views/application.py +++ b/apps/application/views/application.py @@ -220,8 +220,8 @@ class ExportSkills(APIView): tags=[_("Application")], # type: ignore ) @has_permissions( - PermissionConstants.APPLICATION_EXPORT.get_workspace_application_permission(), - PermissionConstants.APPLICATION_EXPORT.get_workspace_permission_workspace_manage_role(), + PermissionConstants.APPLICATION_EXPORT_SKILLS.get_workspace_application_permission(), + PermissionConstants.APPLICATION_EXPORT_SKILLS.get_workspace_permission_workspace_manage_role(), ViewPermission( [RoleConstants.USER.get_workspace_role()], [PermissionConstants.APPLICATION.get_workspace_application_permission()], diff --git a/apps/application/views/application_api_key.py b/apps/application/views/application_api_key.py index f614e287619..e3a67463f44 100644 --- a/apps/application/views/application_api_key.py +++ b/apps/application/views/application_api_key.py @@ -179,8 +179,8 @@ class ApplicationApiKeyEnable(APIView): get_operation_object=lambda r, k: get_application_operation_object(k.get("application_id")), ) @has_permissions( - PermissionConstants.APPLICATION_OVERVIEW_API_KEY.get_workspace_application_permission(), - PermissionConstants.APPLICATION_OVERVIEW_API_KEY.get_workspace_permission_workspace_manage_role(), + PermissionConstants.APPLICATION_OVERVIEW_BACKEND_API_ACCESS.get_workspace_application_permission(), + PermissionConstants.APPLICATION_OVERVIEW_BACKEND_API_ACCESS.get_workspace_permission_workspace_manage_role(), ViewPermission( [RoleConstants.USER.get_workspace_role()], [PermissionConstants.APPLICATION.get_workspace_application_permission()], diff --git a/apps/common/auth/constants/operate_constants.py b/apps/common/auth/constants/operate_constants.py index 9de69083923..8da9165dcf3 100644 --- a/apps/common/auth/constants/operate_constants.py +++ b/apps/common/auth/constants/operate_constants.py @@ -43,6 +43,7 @@ class Operate(Enum): DISPLAY = ("READ+DISPLAY", _("Display Settings")) API_KEY = ("READ+API_KEY", _("API KEY")) PUBLIC_ACCESS = ("READ+PUBLIC_ACCESS", _("Public access link")) + BACKEND_API_ACCESS = ("READ+BACKEND_API_ACCESS", _("Backend API access")) Q_WEIXIN = ("READ+Q_WEIXIN", _("Enterprise WeiXin")) FEISHU = ("READ+FEISHU", _("Feishu")) DD = ("READ+DD", _("Dingding")) diff --git a/apps/common/auth/constants/permission_constants.py b/apps/common/auth/constants/permission_constants.py index fb11c86b2cb..9fca224c9c2 100644 --- a/apps/common/auth/constants/permission_constants.py +++ b/apps/common/auth/constants/permission_constants.py @@ -1608,6 +1608,26 @@ class PermissionConstants(Enum): ), ) + APPLICATION_MCP_CONFIG = ( + Permission(group=Group.APPLICATION, sub_group=Group.APPLICATION, operate=Operate.MCP_CONFIG, bit_index=39), + PermissionMeta( + role_list=[RoleConstants.WORKSPACE_MANAGE, RoleConstants.USER], + category=Category.WORKSPACE, + scope=[PermissionScopeConstants.WORKSPACE_RESOURCE, PermissionScopeConstants.WORKSPACE], + resource_permission_group_list=[ResourcePermissionConst.APPLICATION_MANAGE], + ), + ) + + APPLICATION_EXPORT_SKILLS = ( + Permission(group=Group.APPLICATION, sub_group=Group.APPLICATION, operate=Operate.EXPORT_SKILLS, bit_index=40), + PermissionMeta( + role_list=[RoleConstants.WORKSPACE_MANAGE, RoleConstants.USER], + category=Category.WORKSPACE, + scope=[PermissionScopeConstants.WORKSPACE_RESOURCE, PermissionScopeConstants.WORKSPACE], + resource_permission_group_list=[ResourcePermissionConst.APPLICATION_MANAGE], + ), + ) + APPLICATION_PUBLISH = ( Permission(group=Group.APPLICATION, sub_group=Group.APPLICATION, operate=Operate.PUBLISH, bit_index=7), PermissionMeta( @@ -1827,6 +1847,21 @@ class PermissionConstants(Enum): ), ) + APPLICATION_OVERVIEW_BACKEND_API_ACCESS = ( + Permission( + group=Group.APPLICATION, + sub_group=Group.OVERVIEW, + operate=Operate.BACKEND_API_ACCESS, + bit_index=38, + ), + PermissionMeta( + role_list=[RoleConstants.WORKSPACE_MANAGE, RoleConstants.USER], + category=Category.WORKSPACE, + scope=[PermissionScopeConstants.WORKSPACE_RESOURCE, PermissionScopeConstants.WORKSPACE], + resource_permission_group_list=[ResourcePermissionConst.APPLICATION_MANAGE], + ), + ) + # ==================== 应用接入 ==================== APPLICATION_ACCESS_READ = ( Permission(group=Group.APPLICATION, sub_group=Group.ACCESS, operate=Operate.READ, bit_index=29), @@ -2446,6 +2481,36 @@ class PermissionConstants(Enum): ), ) + SHARED_KNOWLEDGE_MCP_CONFIG = ( + Permission( + group=Group.SYSTEM_SHARED_KNOWLEDGE, + sub_group=Group.SYSTEM_SHARED_KNOWLEDGE, + operate=Operate.MCP_CONFIG, + bit_index=63, + ), + PermissionMeta( + role_list=[RoleConstants.ADMIN], + category=Category.SHARED, + is_ee=is_ee, + scope=[PermissionScopeConstants.SYSTEM], + ), + ) + + SHARED_KNOWLEDGE_EXPORT_SKILLS = ( + Permission( + group=Group.SYSTEM_SHARED_KNOWLEDGE, + sub_group=Group.SYSTEM_SHARED_KNOWLEDGE, + operate=Operate.EXPORT_SKILLS, + bit_index=64, + ), + PermissionMeta( + role_list=[RoleConstants.ADMIN], + category=Category.SHARED, + is_ee=is_ee, + scope=[PermissionScopeConstants.SYSTEM], + ), + ) + # 共享知识库工作流 SHARED_KNOWLEDGE_WORKFLOW_READ = ( Permission( @@ -3370,6 +3435,36 @@ class PermissionConstants(Enum): ), ) + RESOURCE_APPLICATION_MCP_CONFIG = ( + Permission( + group=Group.SYSTEM_RES_APPLICATION, + sub_group=Group.SYSTEM_RES_APPLICATION, + operate=Operate.MCP_CONFIG, + bit_index=30, + ), + PermissionMeta( + role_list=[RoleConstants.ADMIN], + category=Category.RESOURCE, + is_ee=is_ee, + scope=[PermissionScopeConstants.SYSTEM], + ), + ) + + RESOURCE_APPLICATION_EXPORT_SKILLS = ( + Permission( + group=Group.SYSTEM_RES_APPLICATION, + sub_group=Group.SYSTEM_RES_APPLICATION, + operate=Operate.EXPORT_SKILLS, + bit_index=31, + ), + PermissionMeta( + role_list=[RoleConstants.ADMIN], + category=Category.RESOURCE, + is_ee=is_ee, + scope=[PermissionScopeConstants.SYSTEM], + ), + ) + RESOURCE_APPLICATION_COPY = ( Permission( group=Group.SYSTEM_RES_APPLICATION, @@ -3596,6 +3691,21 @@ class PermissionConstants(Enum): ), ) + RESOURCE_APPLICATION_OVERVIEW_BACKEND_API_ACCESS = ( + Permission( + group=Group.SYSTEM_RES_APPLICATION, + sub_group=Group.SYSTEM_OVERVIEW, + operate=Operate.BACKEND_API_ACCESS, + bit_index=29, + ), + PermissionMeta( + role_list=[RoleConstants.ADMIN], + category=Category.RESOURCE, + is_ee=is_ee, + scope=[PermissionScopeConstants.SYSTEM], + ), + ) + # 资源管理 - 应用接入 RESOURCE_APPLICATION_ACCESS_READ = ( Permission( diff --git a/apps/locales/en_US/LC_MESSAGES/django.po b/apps/locales/en_US/LC_MESSAGES/django.po index 4f92eeb895e..f381652d908 100644 --- a/apps/locales/en_US/LC_MESSAGES/django.po +++ b/apps/locales/en_US/LC_MESSAGES/django.po @@ -3978,7 +3978,7 @@ msgstr "Overview" #: apps/common/auth/constants/group_constants.py:51 #: apps/common/auth/constants/group_constants.py:140 msgid "Application Access" -msgstr "Application Access" +msgstr "Distribution Channels" #: apps/common/auth/constants/group_constants.py:52 #: apps/common/auth/constants/group_constants.py:141 diff --git a/apps/locales/zh_CN/LC_MESSAGES/django.po b/apps/locales/zh_CN/LC_MESSAGES/django.po index d28db167263..7b041bf9c42 100644 --- a/apps/locales/zh_CN/LC_MESSAGES/django.po +++ b/apps/locales/zh_CN/LC_MESSAGES/django.po @@ -3950,7 +3950,7 @@ msgstr "问题" #: apps/common/auth/constants/group_constants.py:116 #: apps/common/auth/constants/group_constants.py:136 msgid "Termbase" -msgstr "词库" +msgstr "自定义分词" #: apps/common/auth/constants/group_constants.py:47 #: apps/common/auth/constants/group_constants.py:117 @@ -3966,7 +3966,7 @@ msgstr "概览" #: apps/common/auth/constants/group_constants.py:51 #: apps/common/auth/constants/group_constants.py:140 msgid "Application Access" -msgstr "智能体接入" +msgstr "发布渠道" #: apps/common/auth/constants/group_constants.py:52 #: apps/common/auth/constants/group_constants.py:141 @@ -3997,7 +3997,7 @@ msgstr "邮箱设置" #: apps/common/auth/constants/group_constants.py:63 msgid "Login Auth" -msgstr "登录认证" +msgstr "系统用户认证" #: apps/common/auth/constants/group_constants.py:64 #: apps/xpack/views/system_params.py:24 apps/xpack/views/system_params.py:40 @@ -4020,7 +4020,7 @@ msgstr "对话用户认证" #: apps/common/auth/constants/group_constants.py:70 msgid "Portal Setting" -msgstr "门户设置" +msgstr "门户访问设置" #: apps/common/auth/constants/group_constants.py:78 #: apps/common/auth/constants/group_constants.py:91 @@ -4101,12 +4101,32 @@ msgstr "访问限制" #: apps/common/auth/constants/operate_constants.py:44 msgid "API KEY" -msgstr "API KEY" +msgstr "API Key" #: apps/common/auth/constants/operate_constants.py:45 msgid "Public access link" msgstr "公共访问链接" +#: apps/common/auth/constants/operate_constants.py:46 +msgid "Backend API access" +msgstr "后端API访问" + +#: apps/role_setting/constants/permission_display.py +msgid "Web access" +msgstr "Web 访问" + +#: apps/role_setting/constants/permission_display.py +msgid "MCP configuration details" +msgstr "MCP配置详情" + +#: apps/role_setting/constants/permission_display.py +msgid "View settings" +msgstr "查看设置" + +#: apps/role_setting/constants/permission_display.py +msgid "Edit settings" +msgstr "编辑设置" + #: apps/common/auth/constants/operate_constants.py:46 msgid "Enterprise WeiXin" msgstr "企业微信" @@ -4202,11 +4222,11 @@ msgstr "设置角色" #: apps/common/auth/constants/operate_constants.py:71 msgid "MCP service configuration" -msgstr "MCP 服务配置" +msgstr "MCP服务配置" #: apps/common/auth/constants/operate_constants.py:72 msgid "Export skills" -msgstr "导出 skills" +msgstr "导出skills" #: apps/common/auth/constants/operate_constants.py:73 msgid "Quota Setting" diff --git a/apps/locales/zh_Hant/LC_MESSAGES/django.po b/apps/locales/zh_Hant/LC_MESSAGES/django.po index fc7c9d383a0..f716210d188 100644 --- a/apps/locales/zh_Hant/LC_MESSAGES/django.po +++ b/apps/locales/zh_Hant/LC_MESSAGES/django.po @@ -3950,7 +3950,7 @@ msgstr "問題" #: apps/common/auth/constants/group_constants.py:116 #: apps/common/auth/constants/group_constants.py:136 msgid "Termbase" -msgstr "詞庫" +msgstr "自定義分詞" #: apps/common/auth/constants/group_constants.py:47 #: apps/common/auth/constants/group_constants.py:117 @@ -3966,7 +3966,7 @@ msgstr "概覽" #: apps/common/auth/constants/group_constants.py:51 #: apps/common/auth/constants/group_constants.py:140 msgid "Application Access" -msgstr "智慧體接入" +msgstr "發布管道" #: apps/common/auth/constants/group_constants.py:52 #: apps/common/auth/constants/group_constants.py:141 @@ -3997,7 +3997,7 @@ msgstr "郵箱設定" #: apps/common/auth/constants/group_constants.py:63 msgid "Login Auth" -msgstr "登入認證" +msgstr "系統用戶認證" #: apps/common/auth/constants/group_constants.py:64 #: apps/xpack/views/system_params.py:24 apps/xpack/views/system_params.py:40 @@ -4020,7 +4020,7 @@ msgstr "對話使用者認證" #: apps/common/auth/constants/group_constants.py:70 msgid "Portal Setting" -msgstr "門戶設定" +msgstr "門戶訪問設定" #: apps/common/auth/constants/group_constants.py:78 #: apps/common/auth/constants/group_constants.py:91 @@ -4101,12 +4101,32 @@ msgstr "訪問限制" #: apps/common/auth/constants/operate_constants.py:44 msgid "API KEY" -msgstr "API KEY" +msgstr "API Key" #: apps/common/auth/constants/operate_constants.py:45 msgid "Public access link" msgstr "公共訪問連結" +#: apps/common/auth/constants/operate_constants.py:46 +msgid "Backend API access" +msgstr "後端API訪問" + +#: apps/role_setting/constants/permission_display.py +msgid "Web access" +msgstr "Web 訪問" + +#: apps/role_setting/constants/permission_display.py +msgid "MCP configuration details" +msgstr "MCP配置詳情" + +#: apps/role_setting/constants/permission_display.py +msgid "View settings" +msgstr "檢視設定" + +#: apps/role_setting/constants/permission_display.py +msgid "Edit settings" +msgstr "編輯設定" + #: apps/common/auth/constants/operate_constants.py:46 msgid "Enterprise WeiXin" msgstr "企業微信" @@ -4202,11 +4222,11 @@ msgstr "設定角色" #: apps/common/auth/constants/operate_constants.py:71 msgid "MCP service configuration" -msgstr "MCP 服務配置" +msgstr "MCP服務配置" #: apps/common/auth/constants/operate_constants.py:72 msgid "Export skills" -msgstr "匯出 skills" +msgstr "匯出skills" #: apps/common/auth/constants/operate_constants.py:73 msgid "Quota Setting" diff --git a/ui/src/permission/core/common.ts b/ui/src/permission/core/common.ts index 5f21549f69a..9ba9cc07370 100644 --- a/ui/src/permission/core/common.ts +++ b/ui/src/permission/core/common.ts @@ -139,6 +139,7 @@ export enum Operate { DISPLAY = 'READ+DISPLAY', API_KEY = 'READ+API_KEY', PUBLIC_ACCESS = 'READ+PUBLIC_ACCESS', + BACKEND_API_ACCESS = 'READ+BACKEND_API_ACCESS', Q_WEIXIN = 'READ+Q_WEIXIN', FEISHU = 'READ+FEISHU', DD = 'READ+DD', diff --git a/ui/src/permission/core/data.ts b/ui/src/permission/core/data.ts index f5b105906d3..954c3fe4ad6 100644 --- a/ui/src/permission/core/data.ts +++ b/ui/src/permission/core/data.ts @@ -199,6 +199,8 @@ export const PermissionConstants = { APPLICATION_DELETE: p(Group.APPLICATION, Group.APPLICATION, Operate.DELETE, 4), APPLICATION_IMPORT: p(Group.APPLICATION, Group.APPLICATION, Operate.IMPORT, 5), APPLICATION_EXPORT: p(Group.APPLICATION, Group.APPLICATION, Operate.EXPORT, 6), + APPLICATION_MCP_CONFIG: p(Group.APPLICATION, Group.APPLICATION, Operate.MCP_CONFIG, 39), + APPLICATION_EXPORT_SKILLS: p(Group.APPLICATION, Group.APPLICATION, Operate.EXPORT_SKILLS, 40), APPLICATION_PUBLISH: p(Group.APPLICATION, Group.APPLICATION, Operate.PUBLISH, 7), APPLICATION_BATCH_DELETE: p(Group.APPLICATION, Group.APPLICATION, Operate.BATCH_DELETE, 8), APPLICATION_BATCH_MOVE: p(Group.APPLICATION, Group.APPLICATION, Operate.BATCH_MOVE, 9), @@ -221,6 +223,7 @@ export const PermissionConstants = { APPLICATION_OVERVIEW_DISPLAY: p(Group.APPLICATION, Group.OVERVIEW, Operate.DISPLAY, 26), APPLICATION_OVERVIEW_API_KEY: p(Group.APPLICATION, Group.OVERVIEW, Operate.API_KEY, 27), APPLICATION_OVERVIEW_PUBLIC: p(Group.APPLICATION, Group.OVERVIEW, Operate.PUBLIC_ACCESS, 28), + APPLICATION_OVERVIEW_BACKEND_API_ACCESS: p(Group.APPLICATION, Group.OVERVIEW, Operate.BACKEND_API_ACCESS, 38), APPLICATION_ACCESS_READ: p(Group.APPLICATION, Group.ACCESS, Operate.READ, 29), APPLICATION_ACCESS_EDIT: p(Group.APPLICATION, Group.ACCESS, Operate.EDIT, 30), APPLICATION_CHAT_USER_READ: p(Group.APPLICATION, Group.CHAT_USER, Operate.READ, 31), @@ -291,6 +294,8 @@ export const PermissionConstants = { SHARED_KNOWLEDGE_DELETE: p(Group.SYSTEM_SHARED_KNOWLEDGE, Group.SYSTEM_SHARED_KNOWLEDGE, Operate.DELETE, 7), SHARED_KNOWLEDGE_RELATE_RESOURCE_VIEW: p(Group.SYSTEM_SHARED_KNOWLEDGE, Group.SYSTEM_SHARED_KNOWLEDGE, Operate.RELATE_VIEW, 8), SHARED_KNOWLEDGE_TO_WORKSPACE: p(Group.SYSTEM_SHARED_KNOWLEDGE, Group.SYSTEM_SHARED_KNOWLEDGE, Operate.TO_WORKSPACE, 9), + SHARED_KNOWLEDGE_MCP_CONFIG: p(Group.SYSTEM_SHARED_KNOWLEDGE, Group.SYSTEM_SHARED_KNOWLEDGE, Operate.MCP_CONFIG, 63), + SHARED_KNOWLEDGE_EXPORT_SKILLS: p(Group.SYSTEM_SHARED_KNOWLEDGE, Group.SYSTEM_SHARED_KNOWLEDGE, Operate.EXPORT_SKILLS, 64), SHARED_KNOWLEDGE_WORKFLOW_READ: p(Group.SYSTEM_SHARED_KNOWLEDGE, Group.SYSTEM_SHARED_WORKFLOW, Operate.READ, 10), SHARED_KNOWLEDGE_WORKFLOW_EDIT: p(Group.SYSTEM_SHARED_KNOWLEDGE, Group.SYSTEM_SHARED_WORKFLOW, Operate.EDIT, 11), SHARED_KNOWLEDGE_WORKFLOW_EXPORT: p(Group.SYSTEM_SHARED_KNOWLEDGE, Group.SYSTEM_SHARED_WORKFLOW, Operate.EXPORT, 12), @@ -358,6 +363,8 @@ export const PermissionConstants = { RESOURCE_APPLICATION_EDIT: p(Group.SYSTEM_RES_APPLICATION, Group.SYSTEM_RES_APPLICATION, Operate.EDIT, 1), RESOURCE_APPLICATION_DELETE: p(Group.SYSTEM_RES_APPLICATION, Group.SYSTEM_RES_APPLICATION, Operate.DELETE, 2), RESOURCE_APPLICATION_EXPORT: p(Group.SYSTEM_RES_APPLICATION, Group.SYSTEM_RES_APPLICATION, Operate.EXPORT, 3), + RESOURCE_APPLICATION_MCP_CONFIG: p(Group.SYSTEM_RES_APPLICATION, Group.SYSTEM_RES_APPLICATION, Operate.MCP_CONFIG, 30), + RESOURCE_APPLICATION_EXPORT_SKILLS: p(Group.SYSTEM_RES_APPLICATION, Group.SYSTEM_RES_APPLICATION, Operate.EXPORT_SKILLS, 31), RESOURCE_APPLICATION_COPY: p(Group.SYSTEM_RES_APPLICATION, Group.SYSTEM_RES_APPLICATION, Operate.COPY, 4), RESOURCE_APPLICATION_AUTH: p(Group.SYSTEM_RES_APPLICATION, Group.SYSTEM_RES_APPLICATION, Operate.AUTH, 5), RESOURCE_APPLICATION_PUBLISH: p(Group.SYSTEM_RES_APPLICATION, Group.SYSTEM_RES_APPLICATION, Operate.PUBLISH, 6), @@ -374,6 +381,7 @@ export const PermissionConstants = { RESOURCE_APPLICATION_OVERVIEW_DISPLAY: p(Group.SYSTEM_RES_APPLICATION, Group.SYSTEM_OVERVIEW, Operate.DISPLAY, 17), RESOURCE_APPLICATION_OVERVIEW_API_KEY: p(Group.SYSTEM_RES_APPLICATION, Group.SYSTEM_OVERVIEW, Operate.API_KEY, 18), RESOURCE_APPLICATION_OVERVIEW_PUBLIC: p(Group.SYSTEM_RES_APPLICATION, Group.SYSTEM_OVERVIEW, Operate.PUBLIC_ACCESS, 19), + RESOURCE_APPLICATION_OVERVIEW_BACKEND_API_ACCESS: p(Group.SYSTEM_RES_APPLICATION, Group.SYSTEM_OVERVIEW, Operate.BACKEND_API_ACCESS, 29), RESOURCE_APPLICATION_ACCESS_READ: p(Group.SYSTEM_RES_APPLICATION, Group.SYSTEM_ACCESS, Operate.READ, 20), RESOURCE_APPLICATION_ACCESS_EDIT: p(Group.SYSTEM_RES_APPLICATION, Group.SYSTEM_ACCESS, Operate.EDIT, 21), RESOURCE_APPLICATION_CHAT_USER_READ: p(Group.SYSTEM_RES_APPLICATION, Group.SYSTEM_CHAT_USER, Operate.READ, 22), diff --git a/ui/src/permission/modules/application/system.ts b/ui/src/permission/modules/application/system.ts index 4091c3e2fed..17925cc65ff 100644 --- a/ui/src/permission/modules/application/system.ts +++ b/ui/src/permission/modules/application/system.ts @@ -57,6 +57,14 @@ const system = { * 系统「智能体」查看关联资源权限 */ relateMap: () => canSys(P.RESOURCE_APPLICATION_RELATE_RESOURCE_VIEW), +/** + * 系统「智能体」MCP 配置详情权限 + */ + mcpConfig: () => canSys(P.RESOURCE_APPLICATION_MCP_CONFIG), +/** + * 系统「智能体」导出 skills 权限 + */ + exportSkills: () => canSys(P.RESOURCE_APPLICATION_EXPORT_SKILLS), debug: () => canSys(P.RESOURCE_APPLICATION_EDIT), // —— 触发器 —— @@ -98,6 +106,10 @@ const system = { * 系统「智能体」「概览」API KEY权限 */ overviewApiKey: () => canSys(P.RESOURCE_APPLICATION_OVERVIEW_API_KEY), +/** + * 系统「智能体」「概览」后端 API 访问权限 + */ + overviewBackendApiAccess: () => canSys(P.RESOURCE_APPLICATION_OVERVIEW_BACKEND_API_ACCESS), // —— 访问 / 访客 / 对话日志 —— /** diff --git a/ui/src/permission/modules/application/workspace.ts b/ui/src/permission/modules/application/workspace.ts index 4e4ca7299a2..6b0e145a3a2 100644 --- a/ui/src/permission/modules/application/workspace.ts +++ b/ui/src/permission/modules/application/workspace.ts @@ -59,6 +59,14 @@ const workspace = { * 工作空间「智能体」查看关联资源权限 */ relateMap: (id: string) => canRes(P.APPLICATION_RELATE_RESOURCE_VIEW, id), +/** + * 工作空间「智能体」MCP 配置详情权限 + */ + mcpConfig: (id: string) => canRes(P.APPLICATION_MCP_CONFIG, id), +/** + * 工作空间「智能体」导出 skills 权限 + */ + exportSkills: (id: string) => canRes(P.APPLICATION_EXPORT_SKILLS, id), debug: (id: string) => canRes(P.APPLICATION_READ, id), // —— 文件夹 —— @@ -123,6 +131,10 @@ const workspace = { * 工作空间「智能体」「概览」API KEY权限 */ overviewApiKey: (id: string) => canRes(P.APPLICATION_OVERVIEW_API_KEY, id), +/** + * 工作空间「智能体」「概览」后端 API 访问权限 + */ + overviewBackendApiAccess: (id: string) => canRes(P.APPLICATION_OVERVIEW_BACKEND_API_ACCESS, id), // —— 访问 / 访客 / 对话日志 —— /** diff --git a/ui/src/router/admin/system/index.ts b/ui/src/router/admin/system/index.ts index a750ecfd00f..9b7d30c567e 100644 --- a/ui/src/router/admin/system/index.ts +++ b/ui/src/router/admin/system/index.ts @@ -50,19 +50,19 @@ export const systemRoutes: RouteRecordRaw = { path: 'users', name: 'system-users', component: () => import('@/views/system/identity/users/index.vue'), - meta: { title: '用户管理', order: 10, permission: perm.system.user.read, next: 'system-workspace' }, + meta: { title: '用户管理', order: 10, permission: perm.system.user.read, next: 'system-roles' }, }, { path: 'workspace', name: 'system-workspace', component: () => import('@/views/system/identity/workspaces/index.vue'), - meta: { title: '工作空间', order: 20, permission: perm.system.workspace.read, next: 'system-roles' }, + meta: { title: '工作空间', order: 30, permission: perm.system.workspace.read, next: 'system-groups' }, }, { path: 'roles', name: 'system-roles', component: () => import('@/views/system/identity/roles/index.vue'), - meta: { title: '角色管理', order: 30, permission: perm.system.role.read, next: 'system-groups' }, + meta: { title: '角色管理', order: 20, permission: perm.system.role.read, next: 'system-workspace' }, }, { path: 'groups', diff --git a/ui/src/views/application-detail/overview/index.vue b/ui/src/views/application-detail/overview/index.vue index f0d16070a91..5c4e2e189e3 100644 --- a/ui/src/views/application-detail/overview/index.vue +++ b/ui/src/views/application-detail/overview/index.vue @@ -25,7 +25,13 @@ const route = useRoute() const workspaceId = computed(() => String(route.params.workspaceId ?? '')) const { application, applicationId, resourceApi } = useApplicationDetailContext() -type ApplicationOverviewPermissionMethod = 'overviewRead' | 'overviewEmbed' | 'overviewAccess' | 'overviewDisplay' | 'overviewApiKey' +type ApplicationOverviewPermissionMethod = + | 'overviewRead' + | 'overviewEmbed' + | 'overviewAccess' + | 'overviewDisplay' + | 'overviewApiKey' + | 'overviewBackendApiAccess' function applicationOverviewPermission(method: ApplicationOverviewPermissionMethod): boolean { if (isSystemResource()) return Boolean(perm.application.system[method]()) return Boolean(perm.application.workspace[method](applicationId.value)) @@ -169,7 +175,12 @@ onMounted(() => {
后端 API 访问
- +
API 文档
diff --git a/ui/src/views/application/application-card/action-dropdown/ExportApplicationAction.vue b/ui/src/views/application/application-card/action-dropdown/ExportApplicationAction.vue index 9e10ddf064d..16038029f13 100644 --- a/ui/src/views/application/application-card/action-dropdown/ExportApplicationAction.vue +++ b/ui/src/views/application/application-card/action-dropdown/ExportApplicationAction.vue @@ -5,6 +5,7 @@ import type ApplicationApi from '@/api/admin/workspace/application/application' import type SystemResourceApplicationApi from '@/api/admin/system/resource-management/application/application' import type { ApplicationDetail, ExportError } from '@/api/types' import { MsgError } from '@/utils/message' +import perm from '@/permission' defineOptions({ name: 'ExportApplicationAction' }) @@ -12,6 +13,15 @@ const props = defineProps<{ api: typeof ApplicationApi | typeof SystemResourceAp const loading = defineModel('loading', { default: false }) +/** 依据 api 是否含工作空间独有方法区分工作空间/系统资源管理场景,用于选择对应权限。 */ +const isSystem = computed(() => !('putMoveApplication' in props.api)) +const canExportApplication = computed(() => + isSystem.value ? perm.application.system.export() : perm.application.workspace.export(props.application.id), +) +const canExportSkills = computed(() => + isSystem.value ? perm.application.system.exportSkills() : perm.application.workspace.exportSkills(props.application.id), +) + // 二级菜单留在所属一级浮层内,避免焦点移入时关闭一级菜单,并避开滚动容器裁剪。 const exportTriggerRef = useTemplateRef('exportTriggerRef') const exportMenuContainer = computed(() => exportTriggerRef.value?.closest('.el-dropdown__popper')) @@ -89,9 +99,9 @@ function handleExportApplication() { diff --git a/ui/src/views/application/index.vue b/ui/src/views/application/index.vue index 32273c408a4..e7c3ae907de 100644 --- a/ui/src/views/application/index.vue +++ b/ui/src/views/application/index.vue @@ -257,7 +257,11 @@ function handleBatchDelete() { :application="application" /> - + @@ -300,7 +304,7 @@ function handleBatchDelete() { label="导出" :api="ApplicationApi" :application="application" - v-if="perm.application.workspace.export(application.id)" + v-if="perm.application.workspace.export(application.id) || perm.application.workspace.exportSkills(application.id)" /> { - + { v-if="perm.application.system.portalUp() && row.is_publish" /> - +