用户角色 API
用途与前置条件
scoped.userRoles 管理某个用户在一个完整 scope 内的直接角色集合。它不创建用户,也不认证用户。引用的每个角色必须已存在于同一 scope。
我想做什么
签名
参数与返回字段
共享的 MutationOptions、RequiredRevisionOptions、MutationResult、VersionedResult 和 PageResult 见核心与公共合同。
UserRoleBindingSet 字段:
方法详解
assign(userId, roleId, options?)
- 用途:在用户现有直接角色旁追加一个角色,适合“给用户再加一个角色”。
- 参数:
userId、roleId必填;options可带 actor/reason/request/idempotency key,不需要先读 revision。 - 状态影响:角色不存在时失败;已绑定同一角色时是幂等/no-op,不会产生重复 ID。
- 原始返回:
MutationResult<UserRoleBindingSet>;data.roleIds是追加后的完整直接集合,changed表示本次是否真的新增。 - 不要混用:保存后台多选框的完整结果时使用
set,不要循环 assign 后再猜哪些旧角色要删除。
revoke(userId, roleId, options?)
- 用途:从直接角色集合中移除一个角色。
- 参数:
userId、roleId必填;options 与 assign 相同。 - 状态影响:只移除直接绑定,不修改角色本身,也不删除通过其他直接角色继承到的有效角色。
- 原始返回:
MutationResult<UserRoleBindingSet>;检查data.roleIds和changed。 - 注意:角色本来就未绑定时通常是 no-op;需要清空所有直接角色时使用
clear。
set(userId, roleIds, options)
- 用途:把用户的完整直接角色集合替换成
roleIds,适合管理后台一次保存。 - 参数:先调用
getDirect(userId),把before.data.revision传为expectedRevision;roleIds是最终集合。 - 状态影响:原子新增列表中新角色并移除未列出的旧角色;不会修改角色继承关系。
- 原始返回:
MutationResult<UserRoleBindingSet>;data.roleIds是提交后的最终集合。 - 常见失败:任一角色不存在返回
ROLE_NOT_FOUND;revision 过期返回REVISION_CONFLICT,应重新读取并让管理员处理冲突。
clear(userId, options)
- 用途:把用户的直接角色集合原子替换为空。
- 参数:
userId和最新expectedRevision必填。 - 状态影响:移除全部直接绑定;用户仍然存在于宿主用户目录,permission-core 不删除用户。
- 原始返回:
MutationResult<UserRoleBindingSet>,成功后data.roleIds=[]。 - 区别:等价目标可用
set(userId, [], options),clear更清楚地表达意图。
getDirect(userId)
- 用途:读取管理后台可编辑的直接角色集合,并取得 set/clear 所需 revision。
- 参数:
userId必填。 - 状态影响:只读。
- 原始返回:
VersionedResult<UserRoleBindingSet>;使用data.roleIds展示选中项,使用data.revision做后续 CAS。 - 边界:不展开父角色;要展示最终生效角色请用
getEffective。
getEffective(userId)
- 用途:诊断用户的直接角色经父链展开后有哪些角色真正参与授权。
- 参数:
userId必填。 - 状态影响:只读。
- 原始返回:
VersionedResult<UserEffectiveRoles>;data.direct是直接集合,data.effective.items每项说明direct/viaRoleIds/depth/included/excludedReason。 - 边界:它只解释角色,不直接列出最终规则;最终规则与冲突用
subject.getPermissions()。
listUsersByRole(roleId, query?)
- 用途:分页查询哪些用户直接绑定了指定角色,适合角色详情页和删除影响排查。
- 参数:
roleId必填;query.first/after可选。 - 状态影响:只读,不包含“仅通过子角色间接获得该角色”的用户。
- 原始返回:
PageResult<UserRoleBindingSet>;渲染items,按pageInfo继续翻页。 - 失败:角色不存在返回
ROLE_NOT_FOUND;无用户时返回空items,不是 404。
assign 与 set 怎么选
assign 是针对单个角色的追加操作,并具备幂等语义。set 替换完整直接角色集合,因此需要当前 user-role-set revision。revoke 移除一个角色;clear 将集合替换为空。
响应与副作用
变更在 data 中返回完整持久化直接集合;发生变化时推进 RBAC/user revision、写入审计证据并使受影响主体缓存失效。读取会区分直接绑定与继承得到的有效角色。
失败与限制
角色不存在返回 ROLE_NOT_FOUND;替换 revision 过期返回 REVISION_CONFLICT。一个用户最多有 128 个直接角色。有效展开上限为 1024 个角色、20000 条语义规则、50000 个来源和 8 MiB 快照。空的/未持久化用户会被显式表示,而不是被当作缺失的用户实体。
示例
上面的 JSON 是示例为便于对比而组装的汇总输出,不是 set() 的原始响应。set() 的原始响应是 MutationResult<UserRoleBindingSet>,其中提交后的角色位于 replaced.data.roleIds。set 不会在旧角色旁追加 operator,而是替换直接集合。