update: API.md
This commit is contained in:
@@ -45,7 +45,9 @@
|
||||
- 缺失或过期 → HTTP `401`。
|
||||
- 有效但用户不在 workspace → HTTP `403`(由 Nginx `auth_request` 透传给客户端)。
|
||||
|
||||
> `/api/v1/auth/me` 与 `/api/v1/auth/login` 响应中的 `data.user` 对象额外携带 `is_system_admin: bool` 字段,派生自 `users.platform_role_id` 指向的角色 `role_code == 'admin'` 且用户状态为 `active`。前端据此决定是否渲染"系统管理"入口。详见 §七。
|
||||
> `/api/v1/auth/me` 与 `/api/v1/auth/login` 响应中的 `data.user` 对象额外携带以下两个字段:
|
||||
> - `is_system_admin: bool` —— 派生自 `users.platform_role_id` 指向的角色 `role_code == 'admin'` 且用户状态为 `active`。前端据此决定是否渲染"系统管理"入口。
|
||||
> - `permissions: string[]` —— 当前用户通过其平台角色(`platform_role_id`)间接持有的菜单权限码列表(`permission_code`),按字典序排列;未分配平台角色时为空数组。前端据此过滤菜单与 `<RequirePermission>` 路由守卫。**仅控制前端展示,不参与后端 endpoint 鉴权**——后端鉴权继续由 `system_admin_context`(`role_code == 'admin'`)与 workspace membership 负责。详见 §7.12-7.14。
|
||||
|
||||
---
|
||||
|
||||
@@ -512,6 +514,9 @@ Base 前缀 `/api/v1/admin`。
|
||||
| `POST` | `/api/v1/platform/workspaces/{workspace_id}/members` | 添加成员(返回 201) |
|
||||
| `PATCH` | `/api/v1/platform/workspaces/{workspace_id}/members/{user_id}` | 改成员角色/状态 |
|
||||
| `DELETE` | `/api/v1/platform/workspaces/{workspace_id}/members/{user_id}` | 软删成员 |
|
||||
| `GET` | `/api/v1/platform/roles` | 列全部 `role_scope='platform'` 的角色及其 `permission_codes`(仅系统管理员) |
|
||||
| `GET` | `/api/v1/platform/roles/{role_code}/permissions` | 单个平台角色的 `permission_codes`(仅系统管理员) |
|
||||
| `PATCH` | `/api/v1/platform/roles/{role_code}/permissions` | 整体替换角色权限集合;对 `admin` 角色保留 `system.view` + `system.manage` 的最后系统管理员保护(仅系统管理员) |
|
||||
|
||||
> **不变量**:
|
||||
> - 每个 workspace 必须始终保留至少一个 `admin` 角色的活跃成员;对最后 admin 做降级 / 停用 / 删除 → 409。
|
||||
@@ -722,6 +727,134 @@ Base 前缀 `/api/v1/admin`。
|
||||
}
|
||||
```
|
||||
|
||||
### 7.12 `GET /api/v1/platform/roles`
|
||||
|
||||
列出所有 `role_scope='platform'` 的角色及其当前 `permission_codes`。调用者必须是系统管理员。
|
||||
|
||||
- 用于平台管理员配置页加载左侧"角色"下拉与权限矩阵。
|
||||
- 返回结果按 `role_code` 升序。
|
||||
- `permission_codes` 与 DB 中 `role_permissions` 关联表的活跃(`is_deleted = 0`)行一致,按字典序排列;空集合表示该角色当前没有任何菜单权限。
|
||||
- `is_builtin` 反映 `roles.is_builtin`;当前 seed 的 `admin` / `developer` 均为 `1`。
|
||||
|
||||
- **响应 200**:
|
||||
```json
|
||||
{
|
||||
"request_id": "...",
|
||||
"data": [
|
||||
{
|
||||
"role_id": "01HXY...",
|
||||
"role_code": "admin",
|
||||
"role_name": "管理员",
|
||||
"is_builtin": true,
|
||||
"permission_codes": [
|
||||
"dashboard.view", "experiment.all", "experiment.own",
|
||||
"resource.personal", "resource.public.manage",
|
||||
"resource.public.upload", "schedule.all", "schedule.own",
|
||||
"script.build", "script.public.manage", "system.manage",
|
||||
"system.view"
|
||||
]
|
||||
},
|
||||
{
|
||||
"role_id": "01HXY...",
|
||||
"role_code": "developer",
|
||||
"role_name": "开发人员",
|
||||
"is_builtin": true,
|
||||
"permission_codes": [
|
||||
"dashboard.view", "experiment.own", "resource.personal",
|
||||
"schedule.own", "script.build", "script.public.manage"
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": { "count": 2 }
|
||||
}
|
||||
```
|
||||
|
||||
### 7.13 `GET /api/v1/platform/roles/{role_code}/permissions`
|
||||
|
||||
获取单个平台角色的当前 `permission_codes`。调用者必须是系统管理员。
|
||||
|
||||
- 用途:角色权限管理面板加载右侧"已分配"列;也用于前端做 diff 显示。
|
||||
|
||||
- 角色不存在 → 404;角色存在但 `role_scope != 'platform'`(例如只有 `workspace` 角色行匹配) → 404。
|
||||
|
||||
- **响应 200**:
|
||||
```json
|
||||
{
|
||||
"request_id": "...",
|
||||
"data": {
|
||||
"role_id": "01HXY...",
|
||||
"role_code": "admin",
|
||||
"role_name": "管理员",
|
||||
"is_builtin": true,
|
||||
"permission_codes": [
|
||||
"dashboard.view", "experiment.all", "experiment.own",
|
||||
"resource.personal", "resource.public.manage",
|
||||
"resource.public.upload", "schedule.all", "schedule.own",
|
||||
"script.build", "script.public.manage", "system.manage",
|
||||
"system.view"
|
||||
]
|
||||
},
|
||||
"meta": {}
|
||||
}
|
||||
```
|
||||
|
||||
### 7.14 `PATCH /api/v1/platform/roles/{role_code}/permissions`
|
||||
|
||||
整体替换指定平台角色的 `permission_codes`(diff-based 写入,见下文)。调用者必须是系统管理员。
|
||||
|
||||
> **本端点只控制前端菜单可见性**——不修改 `system_admin_context` 的鉴权判定(`role_code == "admin"` 始终等价于"拥有所有平台菜单权限")。若需调整 API 鉴权,请改 `backend.platform.system_admin_context`,不要绕过本端点。
|
||||
|
||||
- **请求体字段**:
|
||||
|
||||
| 字段 | 类型 | 必填 | 限制 | 说明 |
|
||||
|---|---|---|---|---|
|
||||
| `permission_codes` | string[] | 是 | 0~64 项;内部去重(首次出现优先);元素必须是现存且未软删的 `permissions.permission_code` | 完整替换集合(非 patch);传 `[]` 表示清空该角色的全部菜单权限 |
|
||||
|
||||
- **守卫顺序(load-bearing,不可调换)**:
|
||||
1. 角色不存在 / `role_scope != 'platform'` → 404。
|
||||
2. **`admin` 角色**:提交的 `permission_codes` 必须同时包含 `system.view` 与 `system.manage`,否则 → 409 "admin 角色必须保留 system.view 与 system.manage 权限"。这一条**先于**最后系统管理员计数,目的是让"把 admin 角色自己锁出系统管理入口"的操作在前置路径上就 409,便于前端直接报错而不必再走"我是最后一个 admin"分支。
|
||||
3. **`admin` 角色 + 当前调用者修改的恰好是自己 `platform_role_id` 指向的角色**:若操作会让平台剩余 active 系统管理员为 0 → 409 "platform 必须保留至少一个 active 系统管理员"。**自保护检查先于计数检查**(参考 CLAUDE.md 工程笔记;放在最后会导致单测 mock 在 `is_system_admin=False` 时绕过计数 helper)。
|
||||
4. 任意 `permission_code` 不在 `permissions` 表活跃行中 → 422 "未知的 permission_code: [...]"。
|
||||
5. 写入策略:diff-based —— 只 soft-delete `current \ new` 的关联,只 INSERT `new \ current` 的关联。重复提交同 payload 是 no-op;包含原有 codes 的 patch 不会触发 `(role_id, permission_id)` 主键冲突。**严禁**先全量 soft-delete 再全量 INSERT(会 `IntegrityError`,因为软删行仍占主键 slot)。
|
||||
- 写入后,响应 `data.permission_codes` 为本次写入后的活跃集合,与再次 `GET §7.13` 完全一致。
|
||||
|
||||
- **响应 200**:
|
||||
```json
|
||||
{
|
||||
"request_id": "...",
|
||||
"data": {
|
||||
"role_id": "01HXY...",
|
||||
"role_code": "admin",
|
||||
"role_name": "管理员",
|
||||
"is_builtin": true,
|
||||
"permission_codes": ["dashboard.view", "system.manage", "system.view"]
|
||||
},
|
||||
"meta": {}
|
||||
}
|
||||
```
|
||||
|
||||
- **当前 seed 的 permission_code 全集**(来自迁移 `f6a7b8c9d0e1`,与 `migrations/data/migrate_system_json.py::PERMISSION_NAMES` 真值对齐,不要在客户端另造一份):
|
||||
|
||||
| `permission_code` | `module_code` | admin | developer |
|
||||
|---|---|:-:|:-:|
|
||||
| `dashboard.view` | dashboard | ✓ | ✓ |
|
||||
| `script.build` | script | ✓ | ✓ |
|
||||
| `script.public.manage` | script | ✓ | ✓ |
|
||||
| `schedule.own` | schedule | ✓ | ✓ |
|
||||
| `schedule.all` | schedule | ✓ | |
|
||||
| `experiment.own` | experiment | ✓ | ✓ |
|
||||
| `experiment.all` | experiment | ✓ | |
|
||||
| `resource.personal` | resource | ✓ | ✓ |
|
||||
| `resource.public.upload` | resource | ✓ | |
|
||||
| `resource.public.manage` | resource | ✓ | |
|
||||
| `system.view` | system | ✓ | |
|
||||
| `system.manage` | system | ✓ | |
|
||||
|
||||
> **与现有 7.x 端点的语义差异**(避免 reviewer 误读):
|
||||
> - 本端点不修改 `users.platform_role_id`,只调整 `role_permissions` 关联表。
|
||||
> - "清空 developer 的全部权限"是合法操作;只有 `admin` 受 `system.*` 强制约束。
|
||||
> - `role_code` 不是 `permission_code`,前端不要用前者去判断菜单可见性。
|
||||
|
||||
---
|
||||
|
||||
## 八、Jupyter 路由
|
||||
|
||||
Reference in New Issue
Block a user