邀请制入驻 + 组织管理员
组织(多租户)场景下,新用户不能自由注册到任意组织,须由 org_admin / 平台 admin 发邀请链接,自助注册时消费 → 落到指定组织(+ 可选角色)。配套有 org_admin 角色层与提权封堵。
1. 邀请链接
端点
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
| POST | /api/admin/invites | system:user:create | 生成一次性邀请链接 |
system:user:create由 org_admin 和平台 admin 持有。
请求体:
{
"org_id": "acme",
"role_id": 5,
"ttl_hours": 168
}
org_id:目标组织。org_admin 只能填自己所在 org(强制);平台 admin 可指定任意 orgrole_id:可选。不填则注册后由 register 兜底分配该 org 的默认 user 角色;填了会校验该角色必须属于目标 org 且启用(防跨组织借邀请塞角色)ttl_hours:可选,默认 7 天
响应:
{
"success": true,
"data": {
"token": "<43 字符 base64url>",
"url": "/admin/#/register?invite=<token>",
"org_id": "acme"
}
}
前端把 url 拼成绝对地址发给被邀请人。
token 机制
- 256-bit 熵随机 token,base64url(URL 安全,无
+/=) - 存 Redis,单次使用(
GETDEL原子消费,防重放),与邮箱验证 token 一致 - TTL 到期自动失效
注册消费
被邀请人打开 register?invite=<token>,注册时带上 token。后端 consume_invite 原子取出 → 用户落到 org_id、绑 role_id(或兜底默认角色)→ token 失效。
2. 组织管理员(org_admin)角色层
每个组织有一组供 org_admin 使用的角色模板(持 system:user:create 等本组织管理权限)。org_admin 在本组织内可:
- 邀请新成员、分配角色
- 管理
visibility=org的 OAuth client - 审批
to=org的 client 提升申请
平台 admin(持 admin:manage / system:org:*)跨组织,可管任意 org。
3. 提权封堵(跨组织防护)
org::resolve_create_org 强制:组织用户创建用户 / client / 邀请时,目标 org 必须是自己所在 org,不能用 body 传别人的 org_id 越权。平台 admin 不受此限。
配套的多租户唯一性约束(早期全局 UNIQUE 在多租户下的断点修复):
users.username:全局 UNIQUE →(org_id, username)(不同组织可同名用户)roles.role_name:全局 UNIQUE →(org_id, role_name)(不同组织可同名角色)
收敛到 org 维度后,跨组织同名撞 UNIQUE 报错的断点消除。