From eb44598743e28f8e2cf8f401485c838254477c47 Mon Sep 17 00:00:00 2001 From: "xinxin.wu" Date: Thu, 22 Oct 2026 15:50:32 +0800 Subject: [PATCH] feat: access restriction --- ui/src/api/API_README.md | 9 + .../system/chat-management/chat-user-auth.ts | 7 +- .../application/application.ts | 7 +- .../workspace/application/application.ts | 6 +- ui/src/api/types/application.ts | 26 ++- .../api-key-list/EditApiKeyDrawer.vue | 8 +- .../business/api-key-list/index.vue | 49 ++-- .../layout/avatar-dropdown/ApiKeyDialog.vue | 8 +- ui/src/views/VIEW_README.md | 13 +- .../AccessRestrictionDialog.vue | 20 -- .../AccessRestrictionDrawer.vue | 131 +++++++++++ .../ButtonAccessRestriction.vue | 16 +- .../XpackAccessRestrictionDrawer.vue | 212 ++++++++++++++++++ .../overview/api-key/ApiKeyDialog.vue | 8 +- 14 files changed, 447 insertions(+), 73 deletions(-) delete mode 100644 ui/src/views/application-detail/overview/access-restriction/AccessRestrictionDialog.vue create mode 100644 ui/src/views/application-detail/overview/access-restriction/AccessRestrictionDrawer.vue create mode 100644 ui/src/views/application-detail/overview/access-restriction/XpackAccessRestrictionDrawer.vue diff --git a/ui/src/api/API_README.md b/ui/src/api/API_README.md index a0e54d6ed52..2b7a1ca3945 100644 --- a/ui/src/api/API_README.md +++ b/ui/src/api/API_README.md @@ -383,6 +383,15 @@ Workspace 与 System 资源管理的 `application/application.ts` 提供 `getAcc 概览使用 `access_token` 拼接 Web 链接,不使用智能体 ID 或 API Key 替代;API 文档地址使用 Chat 部署前缀。 两范围的 `putAccessToken` 向同一路径提交 `{ access_token_reset: true }` 重置链接,或 `{ is_active: boolean }` 修改 Web 访问状态; 载荷复用 `ApplicationAccessTokenPayload`,使用返回的访问凭证与启用状态回显,不二次查询。 +访问限制复用上述 GET/PUT,读取与保存 `access_num`、`white_active`、`white_list`、`authentication` 和 +`authentication_value`。提问次数为 0~10000000 的整数;社区版仅编辑认证开关,保留已有 `authentication_value`, +不生成登录配置字段,身份认证读写待后台联调。Xpack 版认证配置使用 `type: 'login'`、`login_value`、 +`max_attempts`,保留原配置中的其他字段;已有认证 `type` 不自动转换,缺省为 `login`。 +保存访问限制携带原 `language`,避免后台省略字段时清空语言配置。 +默认登录方式与账号锁定暂按 `authentication_value.default_value / failed_attempts / lock_time` 提交, +字段及认证配置生效能力待后台联调;前端不因认证字段缺失禁用编辑。System 资源管理的访问限制仍需部署环境联调。 +Xpack 版可用登录方式统一调用 `system/chat-management/chat-user-auth.ts` 的 `getChatUserAuthType`, +GET `/chat_user/auth/types` 返回 `{ label, value }[]`,两种智能体入口共用。 展示设置共用 `ApplicationDisplaySetting`;`ApplicationAccessToken` 兼容可选展示字段,缺失字段由弹窗补齐默认值。 两范围的 `putDisplaySetting` 沿用 V2 的 `//setting` PUT 接口,提交 FormData: diff --git a/ui/src/api/admin/system/chat-management/chat-user-auth.ts b/ui/src/api/admin/system/chat-management/chat-user-auth.ts index 8317d159938..6a9e2af8173 100644 --- a/ui/src/api/admin/system/chat-management/chat-user-auth.ts +++ b/ui/src/api/admin/system/chat-management/chat-user-auth.ts @@ -1,8 +1,11 @@ import { get, post, put } from '../../core/request' -import type { AuthProviderSettingPayload, AuthProviderType } from '@/api/types' +import type { AuthProviderSettingPayload, AuthProviderType, OptionItem } from '@/api/types' const prefix = '/chat_user/auth' +/** 获取对话用户可用的登录方式。 */ +const getChatUserAuthType = () => get[]>(`${prefix}/types`) + /** 获取对话用户指定认证源配置。 */ const getAuthSetting = (authType: AuthProviderType) => { return get>(`${prefix}/${authType}/detail`) @@ -17,4 +20,4 @@ const postAuthSettingConnection = (payload: AuthProviderSettingPayload) => { const putAuthSetting = (authType: AuthProviderType, payload: AuthProviderSettingPayload) => { return put(`${prefix}/${authType}/info`, payload) } -export default { getAuthSetting, postAuthSettingConnection, putAuthSetting } +export default { getChatUserAuthType, getAuthSetting, postAuthSettingConnection, putAuthSetting } diff --git a/ui/src/api/admin/system/resource-management/application/application.ts b/ui/src/api/admin/system/resource-management/application/application.ts index 9febd2ebc94..cdd7482413a 100644 --- a/ui/src/api/admin/system/resource-management/application/application.ts +++ b/ui/src/api/admin/system/resource-management/application/application.ts @@ -32,10 +32,13 @@ const putApplicationPortal = (applicationId: string, isPortal: boolean) => Promi /** 获取 System 资源管理智能体详情。 */ const getApplicationDetail = (applicationId: string) => get(`${prefix}/${applicationId}`) -/** 获取 System 资源管理智能体公开访问凭证。 */ +/** 获取 System 资源管理智能体公开访问凭证与访问限制。 */ +// TODO:访问限制接口待联调。 +// TODO:社区版身份认证读写待后台联调。 const getAccessToken = (applicationId: string) => get(`${prefix}/${applicationId}/access_token`) -/** 修改 System 资源管理智能体公开访问状态或重置凭证,返回更新后的配置。 */ +/** 修改 System 资源管理智能体访问配置或重置凭证,返回更新后的配置。 */ +// TODO:身份认证、默认登录方式及账号锁定配置待后台联调。 const putAccessToken = (applicationId: string, payload: ApplicationAccessTokenPayload) => put(`${prefix}/${applicationId}/access_token`, payload) diff --git a/ui/src/api/admin/workspace/application/application.ts b/ui/src/api/admin/workspace/application/application.ts index 0ff7057e732..fc7bbe99a80 100644 --- a/ui/src/api/admin/workspace/application/application.ts +++ b/ui/src/api/admin/workspace/application/application.ts @@ -25,10 +25,12 @@ const getApplicationDetail = (applicationId: string) => { return get(`${getPrefix()}/${applicationId}`) } -/** 获取智能体公开访问凭证。 */ +/** 获取智能体公开访问凭证与访问限制。 */ +// TODO:社区版身份认证读写待后台联调。 const getAccessToken = (applicationId: string) => get(`${getPrefix()}/${applicationId}/access_token`) -/** 修改智能体公开访问状态或重置凭证,返回更新后的配置。 */ +/** 修改智能体访问配置或重置凭证,返回更新后的配置。 */ +// TODO:身份认证、默认登录方式及账号锁定配置待后台联调。 const putAccessToken = (applicationId: string, payload: ApplicationAccessTokenPayload) => put(`${getPrefix()}/${applicationId}/access_token`, payload) diff --git a/ui/src/api/types/application.ts b/ui/src/api/types/application.ts index 3c1956971a4..51eff76b6aa 100644 --- a/ui/src/api/types/application.ts +++ b/ui/src/api/types/application.ts @@ -49,17 +49,39 @@ export interface ApplicationDisplaySetting { show_user_avatar: boolean } -/** 智能体公开访问链接使用的凭证。 */ +/** 智能体登录认证配置;保留后端返回的其他认证字段。 */ +export interface ApplicationAuthenticationConfig extends Dict { + type?: 'login' | 'password' + login_value?: string[] + max_attempts?: number + // TODO:默认登录方式、账号锁定字段待后台联调。 + default_value?: string + failed_attempts?: number + lock_time?: number +} + +/** 智能体公开访问凭证与访问限制配置。 */ export interface ApplicationAccessToken extends Partial { application_id: string access_token: string is_active: boolean + access_num: number + white_active: boolean + white_list: string[] + authentication?: boolean + authentication_value?: ApplicationAuthenticationConfig | null } -/** 智能体公开访问状态修改或令牌重置参数。 */ +/** 智能体访问配置修改或令牌重置参数。 */ export interface ApplicationAccessTokenPayload { is_active?: boolean access_token_reset?: boolean + access_num?: number + white_active?: boolean + white_list?: string[] + language?: string | null + authentication?: boolean + authentication_value?: ApplicationAuthenticationConfig } export interface ApplicationDetail extends Omit { diff --git a/ui/src/components/business/api-key-list/EditApiKeyDrawer.vue b/ui/src/components/business/api-key-list/EditApiKeyDrawer.vue index 7aa0ef7ce8e..193bdc4f787 100644 --- a/ui/src/components/business/api-key-list/EditApiKeyDrawer.vue +++ b/ui/src/components/business/api-key-list/EditApiKeyDrawer.vue @@ -134,11 +134,9 @@ defineExpose({ open }) diff --git a/ui/src/components/business/api-key-list/index.vue b/ui/src/components/business/api-key-list/index.vue index 3645f60e1a0..11b6c6a930f 100644 --- a/ui/src/components/business/api-key-list/index.vue +++ b/ui/src/components/business/api-key-list/index.vue @@ -18,13 +18,13 @@ const props = defineProps<{ }>() const loading = ref(false) const apiKeys = ref([]) -const revealedIds = ref(new Set()) +const createdApiKey = ref('') +const createdDialogVisible = ref(false) const pagination = ref({ currentPage: 1, pageSize: 20, total: 0 }) const editDrawerRef = useTemplateRef>('editDrawerRef') const apiKeyRows = computed(() => apiKeys.value.map((record) => ({ ...record, expiration: getApiKeyExpiration(record) }))) function fetchApiKeys() { - revealedIds.value.clear() const request = props.applicationId !== undefined ? (props.api as typeof ApplicationApiKeyApi | typeof SystemResourceApiKeyApi).getApiKeyPage(props.applicationId, pagination.value) @@ -51,8 +51,9 @@ function handleCreate() { ? (props.api as typeof ApplicationApiKeyApi | typeof SystemResourceApiKeyApi).postApiKey(props.applicationId) : (props.api as typeof SystemApiKeyApi).postApiKey() return request - .then(() => { - MsgSuccess('创建成功') + .then((record) => { + createdApiKey.value = record.secret_key + createdDialogVisible.value = true pagination.value.currentPage = 1 return fetchApiKeys() }) @@ -108,11 +109,6 @@ function handleOpenEdit(record: ApiKeyRecord) { editDrawerRef.value?.open(record) } -function handleToggleVisible(id: string) { - if (revealedIds.value.has(id)) revealedIds.value.delete(id) - else revealedIds.value.add(id) -} - onMounted(loadApiKeys) @@ -130,24 +126,16 @@ onMounted(loadApiKeys) @current-change="loadApiKeys" @size-change="loadApiKeys" > - + @@ -202,5 +190,20 @@ onMounted(loadApiKeys) + + + + + + + diff --git a/ui/src/layout/avatar-dropdown/ApiKeyDialog.vue b/ui/src/layout/avatar-dropdown/ApiKeyDialog.vue index c65db827c6f..9b0a9b7fd50 100644 --- a/ui/src/layout/avatar-dropdown/ApiKeyDialog.vue +++ b/ui/src/layout/avatar-dropdown/ApiKeyDialog.vue @@ -24,11 +24,9 @@ defineExpose({ open }) diff --git a/ui/src/views/VIEW_README.md b/ui/src/views/VIEW_README.md index fbd8e439393..1ed64b07342 100644 --- a/ui/src/views/VIEW_README.md +++ b/ui/src/views/VIEW_README.md @@ -344,11 +344,20 @@ View 负责路由、资源与模式、图加载、保存/发布/调试编排 Workspace 与 System 资源管理共用智能体弹窗,分别使用各自接口,不回退或使用头像菜单的全局系统 API Key。 嵌入第三方弹窗接收概览已有的 Web 链接与访问凭证,不额外请求接口;按全屏、浮窗、移动端单选切换并复制代码, 关闭后恢复全屏模式。iframe 沿用 Web 链接,移动端增加 `mode=mobile`;浮窗使用 Chat API 前缀下的 - `/embed`,携带协议、主机和访问凭证,生成 HTML 时转义属性值。无访问凭证时禁用入口。 + `/embed`,携带协议、主机和访问凭证;若传入链接含查询参数则一并保留,生成 HTML 时转义属性值。无访问凭证时禁用入口。 显示设置每次打开通过当前范围的 Application API 查询访问配置,支持主题色、语言、五类图片、 头像与对话展示开关、浮窗位置及免责声明,本地草稿实时预览。恢复默认仅改草稿,保存成功关闭, 失败保留输入;图片限 JPG/PNG/GIF、10 MB,替换、恢复默认、关闭及卸载时释放临时 URL。 - 展示配置保存协议及后端支持情况见 API 文档。访问限制弹窗业务尚待接入,不模拟保存。 + 展示配置保存协议及后端支持情况见 API 文档。 + 访问限制位于本地 `access-restriction/`,入口按 `auth.isCE` 选择社区版 `AccessRestrictionDrawer.vue`, + 其他版本使用 `XpackAccessRestrictionDrawer.vue`;按需挂载,关闭动画后卸载。 + 每次打开通过当前范围 Application API 查询配置;支持提问次数、登录认证及嵌入白名单,开关只修改草稿,保存时统一提交。 + 社区版身份认证只有开关,不查询登录方式、不生成登录配置字段,保存时保留已有认证配置。 + Xpack 版可用登录方式查询 `/chat_user/auth/types`,开启认证时至少选一种;账号登录的验证码阈值沿用 -1~10。 + 默认登录方式从已勾选的登录方式中选择,取消对应登录方式时同步调整默认值;账号锁定次数与分钟数正常编辑。 + 前端开放认证配置,不因字段缺失或旧版密码模式禁用;保留已有认证类型,字段生效能力由后台联调确认。 + 未取得完整配置时不提交保存,不提供失败空态或重试按钮;提交失败保留草稿。 + 白名单逐行去空白,保存时保留原语言和其他认证字段。 三类场景统一调用 `getMonitoring(workspaceId, range, applicationId)`;全部智能体使用空 ID, 两类首页不提交智能体筛选,概览传当前智能体 ID。页面直接传入完整 API,不包装接口。 排行由概览本地 `components/ApplicationRanking.vue` 调用 Overview API,展示用户 Tokens 消耗与提问次数两类 TOP5。 diff --git a/ui/src/views/application-detail/overview/access-restriction/AccessRestrictionDialog.vue b/ui/src/views/application-detail/overview/access-restriction/AccessRestrictionDialog.vue deleted file mode 100644 index eecb03a9392..00000000000 --- a/ui/src/views/application-detail/overview/access-restriction/AccessRestrictionDialog.vue +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/ui/src/views/application-detail/overview/access-restriction/AccessRestrictionDrawer.vue b/ui/src/views/application-detail/overview/access-restriction/AccessRestrictionDrawer.vue new file mode 100644 index 00000000000..c205066fe11 --- /dev/null +++ b/ui/src/views/application-detail/overview/access-restriction/AccessRestrictionDrawer.vue @@ -0,0 +1,131 @@ + + + diff --git a/ui/src/views/application-detail/overview/access-restriction/ButtonAccessRestriction.vue b/ui/src/views/application-detail/overview/access-restriction/ButtonAccessRestriction.vue index 081c45093ad..fa671659b05 100644 --- a/ui/src/views/application-detail/overview/access-restriction/ButtonAccessRestriction.vue +++ b/ui/src/views/application-detail/overview/access-restriction/ButtonAccessRestriction.vue @@ -1,13 +1,16 @@ @@ -17,5 +20,8 @@ function handleOpenAccessRestriction() { 访问限制 - + diff --git a/ui/src/views/application-detail/overview/access-restriction/XpackAccessRestrictionDrawer.vue b/ui/src/views/application-detail/overview/access-restriction/XpackAccessRestrictionDrawer.vue new file mode 100644 index 00000000000..72c3c109d5d --- /dev/null +++ b/ui/src/views/application-detail/overview/access-restriction/XpackAccessRestrictionDrawer.vue @@ -0,0 +1,212 @@ + + + diff --git a/ui/src/views/application-detail/overview/api-key/ApiKeyDialog.vue b/ui/src/views/application-detail/overview/api-key/ApiKeyDialog.vue index 87a85dfcc82..37d37826d52 100644 --- a/ui/src/views/application-detail/overview/api-key/ApiKeyDialog.vue +++ b/ui/src/views/application-detail/overview/api-key/ApiKeyDialog.vue @@ -26,11 +26,9 @@ defineExpose({ open })