管理角色与用户授权
本页只讲后台最常见的一件事:创建一个角色,把角色分给用户,再确认这个用户最终有哪些权限。示例假设 pc.init() 已完成,并且 scope 来自可信的租户上下文。
scoped 只管理 acme 租户内的数据。actorId/requestId 在这里绑定一次,后续 roles.*、userRoles.* 管理写入会自动复用这份审计与幂等上下文;只有外部网关或队列已经有自己的幂等协议时,才需要单独传 idempotencyKey。permission-core 不创建用户;示例里的 u-1 是宿主用户系统提供的稳定 ID。
先记住四个方法
1. 创建角色
roles.create() 会在当前 scope 新增角色。常用返回值在 created.data.id 和 created.data.revision;完整响应字段见核心与上下文 API。
2. 给角色加一条权限
roles.allow(roleId, rule) 表示“这个角色允许做某个动作”。本例允许 order-reader 调用 api:GET:/api/orders。没有匹配 allow 的操作默认拒绝,所以通常不需要给每个不能访问的接口写 deny。
3. 给用户绑定角色
单独增加一个角色时使用 assign():
userId 来自宿主用户系统,roleId 必须是当前 scope 内已存在且可用的角色。调用会更新用户的直接角色集合;同一角色已经存在时是幂等操作,不会重复保存。
如果后台页面是角色多选框,保存完整勾选结果时使用 set():
全量替换风险。
set('u-1', ['operator'], ...)不会在原角色旁追加operator,而会把直接角色完整替换为仅operator。
如果 set() 返回 REVISION_CONFLICT,说明读取后有人改过绑定。重新调用 getDirect(),展示最新值并让操作者再次确认。
4. 读取最终结果
编辑页面使用 direct/own;诊断最终结果使用 effective。不要把 effective 结果保存回 direct 集合。
常见问题
assign 和 set 到底有什么区别?
assign() 是追加一个角色;set() 是保存完整角色集合。角色多选框提交时用 set(),单个“授予角色”按钮用 assign()。
为什么读取 direct 后再 set?
set() 是全量替换,带 expectedRevision 可以防止用旧页面覆盖别人刚改过的角色。
更新或删除角色去哪看?
改父角色、禁用角色、替换规则或删除角色会影响继承和用户绑定。先看角色 API里的 previewAccessUpdate()、previewReplaceRules() 和 getRemovalImpact()。
失败时先看什么
下一步进入检查权限,学习 can()、assert()、explain() 以及如何读取用户权限快照。精确签名与全部错误见角色 API和用户角色 API。