# IAM Service — Scalar 调用顺序指南(v0.1.0) ## Authentication(认证方式) 本服务使用 **JWT Bearer Token**: - 登录成功后拿到 `access_token` - 后续请求在 Header 中带: - `Authorization: Bearer ` - 租户上下文: - 保护接口默认从 Token claim 的 `tenant_id` 推导租户 - 可选兼容 `X-Tenant-ID: `,若同时提供 Header 与 Token,则必须一致,否则返回 403 访问令牌(JWT)除 `tenant_id/user_id/roles/permissions` 外,还包含: - `apps`:租户已开通应用列表(如 `["cms","tms"]`) - `apps_version`:租户 enabled_apps 版本号(用于客户端判断是否需要刷新会话) ## OpenAPI/Scalar 可配置参数(环境变量) 为方便本地调试与演示,服务会在生成 OpenAPI 文档时,将部分 Header 参数的示例值按环境变量动态注入(影响 `/scalar` 展示,不影响服务鉴权逻辑): - `IAM_DOCS_DEFAULT_TENANT_ID`:默认租户 ID(用于 `X-Tenant-ID` Header 的 example) - 未设置时默认:`11111111-1111-1111-1111-111111111111` - 可选强制:`IAM_DOCS_REQUIRE_TENANT_ID=1`(未设置则启动时直接失败) - `IAM_DOCS_DEFAULT_TOKEN`:默认 Token(用于 `Authorization` Header 的 example) - 可填写裸 JWT 或 `Bearer `;裸 JWT 会自动补齐 `Bearer ` - 未设置时默认:`Bearer ` - 可选强制:`IAM_DOCS_REQUIRE_TOKEN=1`(未设置则启动时直接失败) ## 通用响应结构 成功响应: ```json { "code": 0, "message": "Success|Created|Accepted", "data": {}, "trace_id": null } ``` 错误响应(示例): ```json { "code": 20006, "message": "Missing authorization header", "details": null, "trace_id": null } ``` 常见错误码(节选): - 20006:缺少必要 Header(如 Authorization) - 20003:无权限(403) - 20005:账号或密码错误 - 30000:请求参数错误(400) - 30002:资源不存在(404) - 30003:资源冲突(409) - 40000:请求过于频繁(429) - 10001:数据库错误(500) ## Step-by-step(可复制流程) ### Step -1:数据库初始化 / 迁移(开发/测试/生产) 本服务新增了“租户已开通应用(enabled_apps)”与“平台超级管理员(SuperAdmin)”能力,对应数据库新增表: - `apps` - `tenant_entitlements` - `tenant_enabled_apps_history` 推荐使用版本化迁移脚本初始化与升级: - 执行迁移:`scripts/db/migrate.sh` - 执行校验:`scripts/db/verify.sh` - 回滚(按版本):`scripts/db/rollback.sh` 本仓库同时保留开发用的一键重建脚本:`scripts/db/rebuild_iam_db.sh`(会清库重建,不适合生产)。 ### Step 0:创建租户(可选) **POST** `/tenants/register` - Tag:`Tenant` - Header:无 - Body: ```json { "name": "Tenant A", "config": { "theme": { "primary": "#1d4ed8" } } } ``` 成功(201)从 `data.id` 取出租户 ID: ```json { "code": 0, "message": "Created", "data": { "id": "", "name": "Tenant A", "status": "active", "config": {} }, "trace_id": null } ``` 下一步依赖:`tenant_id`(用于注册/登录时的 `X-Tenant-ID`)。 ### Step 0.1:平台超级管理员(可选,但推荐先完成) 数据库已内置平台租户(Platform tenant): - `tenant_id = 00000000-0000-0000-0000-000000000001` 在平台租户下注册首个用户,将自动获得平台级权限(用于管理各租户 enabled_apps): **POST** `/auth/register` - Tag:`Auth` - Header:`X-Tenant-ID: 00000000-0000-0000-0000-000000000001` - Body: ```json { "email": "superadmin@example.com", "password": "securePassword123" } ``` ### Step 1:注册用户 **POST** `/auth/register` - Tag:`Auth` - 必需 Header:`X-Tenant-ID: ` - Body: ```json { "email": "user@example.com", "password": "securePassword123" } ``` 成功(201)从 `data.id` 取出 `user_id`(后续可用于用户管理接口): ```json { "code": 0, "message": "Created", "data": { "id": "", "email": "user@example.com" }, "trace_id": null } ``` ### Step 2:登录获取访问令牌(Authentication 入口) **POST** `/auth/login` - Tag:`Auth` - 必需 Header:`X-Tenant-ID: ` - Body: ```json { "email": "user@example.com", "password": "securePassword123" } ``` 成功(200)从 `data.access_token` 取出访问令牌: ```json { "code": 0, "message": "Success", "data": { "access_token": "", "refresh_token": "", "token_type": "Bearer", "expires_in": 900 }, "trace_id": null } ``` 下一步依赖:`access_token`。 ### Step 3:获取当前租户信息(Tenant) **GET** `/tenants/me` - Tag:`Tenant` - 必需 Header:`Authorization: Bearer ` - 可选 Header:`X-Tenant-ID: `(如提供必须与 token tenant_id 一致) 成功(200): ```json { "code": 0, "message": "Success", "data": { "id": "", "name": "Tenant A", "status": "active", "config": {} }, "trace_id": null } ``` ### Step 4:查看当前用户权限(Me) **GET** `/me/permissions` - Tag:`Me` - 必需 Header:`Authorization: Bearer ` 成功(200): ```json { "code": 0, "message": "Success", "data": ["tenant:read","tenant:write"], "trace_id": null } ``` 下一步依赖:确认具备目标权限(例如 `user:read` / `role:read`)。 ### Step 4.1:平台层设置租户已开通应用(SuperAdmin) 该能力仅允许拥有平台级权限的用户调用: - `iam:tenant:enabled_apps:read` - `iam:tenant:enabled_apps:write` #### 4.1.1 查询某租户 enabled_apps **GET** `/platform/tenants/{tenant_id}/enabled-apps` - Tag:`Tenant` - Header:`Authorization: Bearer `(平台租户下登录得到的 token) #### 4.1.2 设置某租户 enabled_apps(全量覆盖,幂等) **PUT** `/platform/tenants/{tenant_id}/enabled-apps` - Tag:`Tenant` - Header:`Authorization: Bearer ` - Body: ```json { "enabled_apps": ["cms", "tms"], "expected_version": 0 } ``` 说明: - `expected_version` 可选,用于并发控制;不匹配会返回 409。 - 登录签发 token 时会自动把 `apps/apps_version` 注入到 JWT,并对 `permissions` 按 enabled_apps 过滤。 - `enabled_apps` 必须是“应用注册表 apps 表”中存在且 `status=active` 的应用 ID;若传入未知/已下线应用(例如 `dms`),接口会返回 400。 enabled_apps 维护建议: - 新增应用:通过数据库迁移向 `apps(id,name,description,status)` 插入一行(`id` 推荐全小写短标识,如 `cms` / `tms`)。 - 下线应用:将 `apps.status` 置为非 `active`(例如 `disabled`),之后将无法再被设置进任何租户的 enabled_apps。 - 查询可用应用(示例 SQL):`SELECT id, name, status FROM apps ORDER BY id;` ### Step 5:列出用户(User) **GET** `/users?page=1&page_size=20` - Tag:`User` - 必需 Header:`Authorization: Bearer ` - 分页规则: - `page` 默认 1,必须 >= 1 - `page_size` 默认 20,范围 1..=200 成功(200): ```json { "code": 0, "message": "Success", "data": [{ "id": "", "email": "user@example.com" }], "trace_id": null } ``` ### Step 6:列出角色(Role) **GET** `/roles` - Tag:`Role` - 必需 Header:`Authorization: Bearer ` 成功(200): ```json { "code": 0, "message": "Success", "data": [{ "id": "", "name": "Admin", "description": "..." }], "trace_id": null } ``` ### Step 7:用户-角色绑定(User) 用户注册后默认无角色;通常由具备 `user:write` 的管理员进行角色分配。 #### 7.1 查询用户角色列表(需要 user:read) **GET** `/users/{id}/roles` - Tag:`User` - Header:`Authorization: Bearer ` #### 7.2 设置用户角色(全量覆盖,幂等;需要 user:write) **PUT** `/users/{id}/roles` - Tag:`User` - Header:`Authorization: Bearer ` - Body: ```json { "role_ids": ["", ""] } ``` 说明: - `role_ids` 必须全部属于当前租户,否则返回 400。 ## 限流说明(Auth) - `/auth/login`:约 2 req/s,burst 10(同一 IP) - `/auth/register`:约 1 req/s,burst 5(同一 IP) - 触发后返回:HTTP 429 + `code=40000`