6.2 角色管理
概述
角色模块(goframe_role,租户级表)承载 RBAC 分配与数据权限四档:MenuList 返回带勾选状态的全量菜单树,SavePermission 全量重写角色菜单并清理身份缓存,data_scope 经字典驱动展示。
接口清单
| 方法 | 路由 | 权限 | 说明 |
|---|---|---|---|
| GET | /api/role/page | sys:role:page | 分页(含 dataScope + dataScopeText) |
| GET | /api/role/list | sys:role:list | 列表 |
| GET | /api/role/detail/:id | sys:role:detail | 详情 |
| POST | /api/role/add | sys:role:add | 新增(data_scope 缺省归一 1) |
| PUT | /api/role/update | sys:role:update | 修改 |
| DELETE | /api/role/delete/:id | sys:role:delete | 软删(存在用户引用则拒绝) |
| DELETE | /api/role/batchDelete | sys:role:batchDelete | 批量删除 |
| GET | /api/role/menu/list/:roleId | sys:role:getPermission | 查询角色菜单(带勾选状态) |
| POST | /api/role/menu/save | sys:role:savePermission | 保存权限(全量重写) |
权限勾选(MenuList / SavePermission)
text
MenuList(GET /api/role/menu/list/:roleId):
返回全量菜单树(type 0/1 均含,供勾选界面展示目录+菜单+按钮三层),
每节点带 Checked = role_menu 是否含该 id(checkedSet 预构建)
SavePermission(POST /api/role/menu/save)——语义为"全量重写":
1) 先 Delete 该角色全部 role_menu(软删)
2) 逐个 Insert req.MenuIds
3) clearRoleIdentityCache(roleId)
缓存清理链:按 roleId 查受影响 user_id 列表 → 逐个 Del
easygoadmin:user:identity:{uid}data_scope 数据范围链路
text
roleToData:Add/Update 均带 data_scope,入参 ≤0 归一为 1(全部),
gvalid in:1,2,3,4 校验
roleSpec.SerializeMaps = {"data_scope": "role_data_scope"}
→ 列表行 dataScopeText 由字典填充
AfterUpdate(roleClearCache):数据范围变更后失效该角色全部用户身份缓存
→ 下一次请求 LoadIdentity 重取 min(data_scope) 即生效四档语义与安全边界见 5.9 数据权限。
删除守卫
存在用户引用则拒绝删除(1014/1011 语义)——先给用户换角色,再删空角色。
已知偏差(如实记录)
唯一预检范围偏差
role 的 spec 唯一预检当前声明为 UniqueFields{Field:"code"}(未带 Group),而索引 uk_tenant_code 是"租户内唯一"——预检范围偏宽:超管为不同租户创建相同角色编码时会被误报"已存在"(数据库层不会冲突)。
修复方向:补 Group:"tenant_id",使预检范围等于索引范围。
排障
| 症状 | 原因 |
|---|---|
| 保存权限后用户仍 403 | 身份缓存未清(SavePermission 应触发清理链);DEL easygoadmin:user:identity:{uid} |
| 改 data_scope 不生效 | 同上——AfterUpdate 应清该角色全部用户缓存 |
| 删除角色报"存在关联" | 有用户挂该角色,先在用户管理换角色 |
| 不同租户建同名角色编码被拒 | 上述已知偏差(预检缺 Group) |