我已经完整阅读了后端的 API 密钥系统代码。下面是完整的接口文档: --- # 工单系统 — 外部 API 密钥调用接口文档 ## 一、认证方式 所有请求通过 HTTP 请求头 `X-Api-Key` 传递 API 密钥进行认证。 ``` X-Api-Key: gd_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ``` - 密钥格式:`gd_live_` + 40 位十六进制字符 - 密钥仅在创建时返回一次明文,之后无法再次获取 - 密钥支持过期时间和启用/禁用控制 ## 二、权限模型 ### 2.1 模块权限 每个 API 密钥创建时需指定 `allowedModules`,限制可访问的模块范围。合法模块如下: | 模块键 | 路由前缀 | 说明 | |---|---|---| | `ticket` | `/api/tickets` | 工单管理 | | `customer` | `/api/customers` | 客户管理 | | `engineer` | `/api/engineers` | 工程师/运维管理 | | `attachment` | `/api/attachments` | 附件上传 | | `statusMonitor` | `/api/status` | 状态监控 | 请求路径不在上述模块范围内的,跳过模块权限检查。 ### 2.2 角色映射 API 密钥通过认证后,系统会生成一个**合成 ADMIN 用户**(`id: api-key:`, `role: ADMIN`)。因此 API 密钥只能访问 `@Roles(...)` 中包含 `ADMIN` 的接口。 ### 2.3 禁止访问的路径 以下管理端路径**明确禁止** API 密钥访问(即使密钥有效也返回 `401`): - `/api/api-keys/**` — API 密钥管理 - `/api/api-permissions/**` — API 模块权限管理 --- ## 三、接口列表 > 基础路径:`/api` > 所有请求需携带 `X-Api-Key` 请求头 > 返回格式:JSON --- ### 3.1 工单模块 (`ticket`) 需要 `allowedModules` 包含 `"ticket"`。 #### 3.1.1 创建工单 ``` POST /api/tickets ``` **请求体:** | 字段 | 类型 | 必填 | 说明 | |---|---|---|---| | `platform` | string | ✅ | 平台类型:`taiji` / `xm` / `original` | | `accountInfo` | string | ✅ | 账号信息 | | `modelUsed` | string | ✅ | 使用的模型 | | `description` | string | ✅ | 问题描述 | | `requestExample` | string | ✅ | 请求示例 | | `contactInfo` | string | ❌ | 联系方式 | | `framework` | string | ❌ | 使用框架 | | `networkEnv` | string | ❌ | 网络环境:`local` / `cloud` | | `attachmentUrls` | string[] | ❌ | 附件 URL 列表 | | `requestedLevel` | string | ❌ | 请求工程师等级:`L1` / `L2` / `L3` | #### 3.1.2 为指定客户创建工单 ``` POST /api/tickets/for-customer/:customerId ``` **路径参数:** `customerId` — 客户 ID **请求体:** 同 3.1.1 #### 3.1.3 查询工单列表 ``` GET /api/tickets?page=1&pageSize=20&status=PENDING ``` **查询参数:** | 参数 | 类型 | 必填 | 默认值 | 说明 | |---|---|---|---|---| | `page` | number | ❌ | 1 | 页码 | | `pageSize` | number | ❌ | 20 | 每页条数 | | `status` | string | ❌ | — | 筛选状态:`PENDING` / `ACCEPTED` / `IN_PROGRESS` / `PENDING_CLOSE` / `CLOSED` | #### 3.1.4 查询单个工单 ``` GET /api/tickets/:id ``` #### 3.1.5 更新工单状态 ``` PUT /api/tickets/:id/status ``` **请求体:** | 字段 | 类型 | 必填 | 说明 | |---|---|---|---| | `status` | string | ✅ | 目标状态 | #### 3.1.6 自行接单 ``` PUT /api/tickets/:id/self-assign ``` #### 3.1.7 分配工程师 ``` PUT /api/tickets/:id/assign ``` **请求体:** | 字段 | 类型 | 必填 | 说明 | |---|---|---|---| | `engineerId` | string | ✅ | 工程师 ID | #### 3.1.8 客户关闭工单 ``` PUT /api/tickets/:id/customer-close ``` #### 3.1.9 申请关闭工单 ``` PUT /api/tickets/:id/close-request ``` #### 3.1.10 审批关闭工单 ``` PUT /api/tickets/:id/close-approve ``` #### 3.1.11 拒绝关闭工单 ``` PUT /api/tickets/:id/close-reject ``` #### 3.1.12 催单 ``` POST /api/tickets/:id/urge ``` **请求体:** | 字段 | 类型 | 必填 | 说明 | |---|---|---|---| | `note` | string | ❌ | 催单备注 | #### 3.1.13 获取工单留言列表 ``` GET /api/tickets/:id/messages ``` #### 3.1.14 添加工单留言 ``` POST /api/tickets/:id/messages ``` **请求体:** | 字段 | 类型 | 必填 | 说明 | |---|---|---|---| | `content` | string | ✅ | 留言内容 | | `attachmentUrls` | string[] | ❌ | 附件 URL 列表 | #### 3.1.15 删除工单留言 ``` DELETE /api/tickets/messages/:messageId ``` #### ⚠️ 不可访问的接口 | 接口 | 原因 | |---|---| | `GET /api/tickets/daily-usage/me` | 仅限 `CUSTOMER` 角色,API 密钥为 `ADMIN` 角色,无权限 | --- ### 3.2 客户模块 (`customer`) 需要 `allowedModules` 包含 `"customer"`。 #### 3.2.1 查询客户列表 ``` GET /api/customers ``` #### 3.2.2 查询单个客户 ``` GET /api/customers/:id ``` #### ⚠️ 不可访问的接口 以下接口仅限 `OPERATOR` 角色,API 密钥(`ADMIN`)无权访问: | 接口 | 方法 | |---|---| | `POST /api/customers` | 创建客户 | | `PATCH /api/customers/:id/tier` | 更新客户等级 | | `PATCH /api/customers/:id/bind-engineer` | 绑定工程师 | --- ### 3.3 工程师/运维模块 (`engineer`) 需要 `allowedModules` 包含 `"engineer"`。 #### 3.3.1 查询工程师列表 ``` GET /api/engineers ``` #### 3.3.2 创建工程师 ``` POST /api/engineers ``` **请求体:** | 字段 | 类型 | 必填 | 说明 | |---|---|---|---| | `username` | string | ✅ | 用户名 | | `email` | string | ✅ | 邮箱 | | `password` | string | ✅ | 密码 | | `level` | string | ✅ | 等级:`L1` / `L2` / `L3` | | `isAdmin` | boolean | ❌ | 是否管理员 | #### 3.3.3 创建运维人员 ``` POST /api/engineers/operators ``` **请求体:** | 字段 | 类型 | 必填 | 说明 | |---|---|---|---| | `username` | string | ✅ | 用户名 | | `email` | string | ✅ | 邮箱 | | `password` | string | ✅ | 密码 | #### 3.3.4 管理端 — 查询工程师列表 ``` GET /api/engineers/admin/engineers ``` #### 3.3.5 管理端 — 更新工程师信息 ``` PATCH /api/engineers/admin/engineers/:id ``` **请求体(均可选):** | 字段 | 类型 | 说明 | |---|---|---| | `username` | string | 用户名 | | `email` | string | 邮箱 | | `level` | string | 等级:`L1` / `L2` / `L3` | | `isAvailable` | boolean | 是否可用 | #### 3.3.6 管理端 — 重置工程师密码 ``` PATCH /api/engineers/admin/engineers/:id/password ``` **请求体:** | 字段 | 类型 | 必填 | 说明 | |---|---|---|---| | `newPassword` | string | ✅ | 新密码 | #### 3.3.7 管理端 — 删除工程师 ``` DELETE /api/engineers/admin/engineers/:id ``` #### 3.3.8 管理端 — 查询运维人员列表 ``` GET /api/engineers/admin/operators ``` #### 3.3.9 管理端 — 更新运维人员信息 ``` PATCH /api/engineers/admin/operators/:id ``` **请求体(均可选):** | 字段 | 类型 | 说明 | |---|---|---| | `username` | string | 用户名 | | `email` | string | 邮箱 | #### 3.3.10 管理端 — 重置运维人员密码 ``` PATCH /api/engineers/admin/operators/:id/password ``` **请求体:** | 字段 | 类型 | 必填 | 说明 | |---|---|---|---| | `newPassword` | string | ✅ | 新密码 | #### 3.3.11 管理端 — 删除运维人员 ``` DELETE /api/engineers/admin/operators/:id ``` #### ⚠️ 注意 — `me` 接口的局限性 以下接口虽然角色上允许 `ADMIN` 访问,但 API 密钥的合成用户 ID 为 `api-key:`,不对应真实工程师账号,**调用会在服务层失败**: | 接口 | 说明 | |---|---| | `PATCH /api/engineers/me/availability` | 更新可用状态 | | `PATCH /api/engineers/me/email` | 更新邮箱 | | `PATCH /api/engineers/me/password` | 修改密码 | --- ### 3.4 附件模块 (`attachment`) 需要 `allowedModules` 包含 `"attachment"`。 #### 3.4.1 获取上传 SAS Token ``` POST /api/attachments/sas-token ``` **请求体:** | 字段 | 类型 | 必填 | 说明 | |---|---|---|---| | `fileName` | string | ✅ | 文件名(会被安全化处理) | **返回:** 包含 Azure Blob Storage 上传所需的 SAS Token。 --- ### 3.5 状态监控模块 (`statusMonitor`) 需要 `allowedModules` 包含 `"statusMonitor"`。 #### 3.5.1 获取外部服务状态 ``` GET /api/status/external ``` #### 3.5.2 获取运维仪表盘 ``` GET /api/status/dashboard ``` #### 3.5.3 获取公开仪表盘 ``` GET /api/status/public-dashboard ``` > 注:此接口本身无需认证即可访问。使用 API 密钥访问时会消耗模块权限检查。 --- ## 四、白名单路径(无需模块检查) 以下路径不受 API 模块权限限制,但部分仍需 JWT 认证(API 密钥不可替代): | 路径 | 说明 | |---|---| | `/api/auth/*` | 认证相关 | | `/api/health` | 健康检查 | | `/api/public/bing-background` | 必应壁纸 | | `/api/api-permissions/*` | 权限管理(**禁止**API密钥访问) | | `/api/api-keys*` | 密钥管理(**禁止**API密钥访问) | --- ## 五、错误码说明 | HTTP 状态码 | 说明 | |---|---| | `401 Unauthorized` | 密钥无效、已禁用、已过期,或尝试访问禁止路径 | | `403 Forbidden` | 密钥的 `allowedModules` 不包含请求的模块 / 角色不足 | | `400 Bad Request` | 请求参数校验失败 | | `404 Not Found` | 资源不存在 | --- ## 六、示例调用 ```bash # 查询工单列表 curl -H "X-Api-Key: gd_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ "https://your-domain/api/tickets?page=1&pageSize=10" # 创建工单 curl -X POST \ -H "X-Api-Key: gd_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "platform": "taiji", "accountInfo": "test-account", "modelUsed": "gpt-4", "description": "API调用异常", "requestExample": "curl https://api.example.com/v1/chat" }' \ "https://your-domain/api/tickets" ``` --- ## 七、认证流程总结 ``` 请求 → [全局 ApiKeyGuard] 读取 X-Api-Key → 验证密钥 → 设置 req.apiClient → [全局 ApiModulePermissionGuard] 解析路径模块 → 检查 allowedModules → [控制器 JwtAuthGuard] 检测 apiClient → 合成 ADMIN 用户 → 跳过 JWT 校验 → [控制器 RolesGuard] 检查 ADMIN 是否在 @Roles() 的允许列表中 → 执行业务逻辑 ``` 关键源码参考: - 密钥验证:api-key.service.ts(`validateKey` 方法) - 密钥 Guard:api-key.guard.ts - 模块权限 Guard:api-module-permission.guard.ts - JWT Guard 中的 API Key 处理:jwt-auth.guard.ts