fix(access): 统一 API Key 模型权限与列表契约

将全局启用、用户组基线、API Key 专属或排除规则及 scope 按固定顺序求值,避免 Key 越过所属用户组权限,并让运行时候选与模型列表共用同一权限链。

新增 Key 级可分配模型与失效规则诊断接口、OpenAI 兼容 /v1/models 及 rich 列表迁移路径;前端权限弹窗改为按当前 Key 实时加载并支持清理失效规则。

验证:Go 全量测试与 go vet 通过;Web 22 个测试文件共 142 项通过;pnpm lint、pnpm openapi、pnpm build、Compose 配置、gofmt、ShellCheck 和 git diff --check 通过;独立 PostgreSQL 真实配置验收通过。
This commit is contained in:
2026-08-03 09:17:15 +08:00
parent c28bf74230
commit cc97e6649c
26 changed files with 2249 additions and 220 deletions
+160 -18
View File
@@ -47,6 +47,17 @@ definitions:
username:
type: string
type: object
httpapi.APIKeyAssignableModelsResponse:
properties:
items:
items:
$ref: '#/definitions/store.PlatformModel'
type: array
ruleDiagnostics:
items:
$ref: '#/definitions/store.APIKeyAccessRuleDiagnostic'
type: array
type: object
httpapi.APIKeyListResponse:
properties:
items:
@@ -989,6 +1000,31 @@ definitions:
$ref: '#/definitions/httpapi.OpenAIImageData'
type: array
type: object
httpapi.OpenAIModel:
properties:
created:
example: 1710000000
type: integer
id:
example: gpt-4o-mini
type: string
object:
example: model
type: string
owned_by:
example: easyai
type: string
type: object
httpapi.OpenAIModelListResponse:
properties:
data:
items:
$ref: '#/definitions/httpapi.OpenAIModel'
type: array
object:
example: list
type: string
type: object
httpapi.PlatformListResponse:
properties:
items:
@@ -1999,6 +2035,27 @@ definitions:
userId:
type: string
type: object
store.APIKeyAccessRuleDiagnostic:
properties:
effect:
type: string
effective:
type: boolean
reason:
enum:
- resource_unavailable
- owner_access_revoked
- scope_not_allowed
type: string
resourceId:
type: string
resourceName:
type: string
resourceType:
type: string
ruleId:
type: string
type: object
store.AcceptanceRun:
properties:
apiImageDigest:
@@ -7879,6 +7936,43 @@ paths:
summary: 删除 API Key
tags:
- api-keys
/api/v1/api-keys/{apiKeyID}/assignable-models:
get:
description: 返回指定 API Key 所属用户组允许、全局启用且符合 KEY scope 的平台来源,并附带已有规则有效性诊断。
parameters:
- description: API Key ID
in: path
name: apiKeyID
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/httpapi.APIKeyAssignableModelsResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/httpapi.ErrorEnvelope'
"404":
description: Not Found
schema:
$ref: '#/definitions/httpapi.ErrorEnvelope'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/httpapi.ErrorEnvelope'
"503":
description: Service Unavailable
schema:
$ref: '#/definitions/httpapi.ErrorEnvelope'
security:
- BearerAuth: []
summary: 列出指定 API Key 可分配模型
tags:
- api-keys
/api/v1/api-keys/{apiKeyID}/disable:
patch:
description: 禁用当前用户拥有的 API Key,保留记录但不再允许调用。
@@ -8038,6 +8132,7 @@ paths:
- api-keys
/api/v1/api-keys/assignable-models:
get:
deprecated: true
description: 按当前用户自身的用户、租户和用户组权限返回可分配给 API Key 的启用模型,不受任何 API Key 权限规则影响。
produces:
- application/json
@@ -8954,15 +9049,8 @@ paths:
- model-catalog
/api/v1/models:
get:
description: 按当前用户权限返回可用于 Playground 或 API 调用的模型列表。
parameters:
- description: 模型可选场景;不传时保持原有行为
enum:
- canvas_model_node
- desktop
in: query
name: usage_scene
type: string
deprecated: true
description: 兼容期 rich 平台来源明细;新客户端应改用 /api/v1/platform-modelsOpenAI 客户端使用 /v1/models。
produces:
- application/json
responses:
@@ -8970,10 +9058,6 @@ paths:
description: OK
schema:
$ref: '#/definitions/httpapi.PlatformModelListResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/httpapi.ErrorEnvelope'
"401":
description: Unauthorized
schema:
@@ -8982,13 +9066,9 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/httpapi.ErrorEnvelope'
"502":
description: Bad Gateway
schema:
$ref: '#/definitions/httpapi.ErrorEnvelope'
security:
- BearerAuth: []
summary: 列出可调用模型
summary: 列出可调用平台模型(已弃用)
tags:
- playground
/api/v1/models/{model}:generateContent:
@@ -9195,6 +9275,45 @@ paths:
summary: 获取 AI Gateway Swagger YAML
tags:
- agent-resources
/api/v1/platform-models:
get:
description: 按当前用户权限返回可用于 Playground 或 API 调用的模型列表。
parameters:
- description: 模型可选场景;不传时保持原有行为
enum:
- canvas_model_node
- desktop
in: query
name: usage_scene
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/httpapi.PlatformModelListResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/httpapi.ErrorEnvelope'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/httpapi.ErrorEnvelope'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/httpapi.ErrorEnvelope'
"502":
description: Bad Gateway
schema:
$ref: '#/definitions/httpapi.ErrorEnvelope'
security:
- BearerAuth: []
summary: 列出可调用模型
tags:
- playground
/api/v1/platforms:
get:
description: 按当前用户可访问模型过滤平台,仅返回启用且存在可访问模型的平台。
@@ -10853,6 +10972,29 @@ paths:
summary: 获取本地上传资源
tags:
- static
/v1/models:
get:
description: 按当前身份、API Key 访问规则及 scope 返回去重后的逻辑模型列表。
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/httpapi.OpenAIModelListResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/httpapi.ErrorEnvelope'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/httpapi.ErrorEnvelope'
security:
- BearerAuth: []
summary: 列出 OpenAI 兼容模型
tags:
- openai-compatible
schemes:
- http
- https