签入版本

This commit is contained in:
小蚂蚁云
2026-10-20 21:53:26 +08:00
parent 5cc3da657c
commit b33799aa63
427 changed files with 32547 additions and 1 deletions
@@ -0,0 +1,83 @@
# 5.9 数据权限
:::tip 概述
角色数据权限(role.data_scope)是叠加在租户隔离之上的第二层行级过滤,四档可配置。模块通过 `DataScope: ApplyDataScope("dept_id")` 一行声明接线,仅作用于 Page/List/导出。
:::
## 四档数据范围
| 档位 | 含义 | 过滤条件(作用于挂接模块的列表行) |
|------|------|----------------------------------|
| 1 | 全部 | 不过滤(租户隔离之内全量) |
| 2 | 本部门及以下 | dept_id IN (自身部门 + 全部子孙部门 ID) |
| 3 | 本部门 | dept_id = 自身部门 ID |
| 4 | 仅本人 | id = 自身用户 ID |
档位文案走字典 `role_data_scope`(定稿种子已写入 dict/dict_item),角色表单"数据范围"下拉由字典驱动。
## 模块接线(一行声明)
```go
// internal/logic/user.go(真实接线方式)
userSpec = ModuleSpec[...]{ ...,
DataScope: ApplyDataScope("dept_id"),
}
```
`ApplyDataScope(deptColumn)` 返回 DataScopeFunc 闭包(logic/data_scope.go,共享工厂),挂进 applyFilters 末环:
```text
Like → Eq → Keyword → Filter → DataScope
租户/软删隔离由 dao.Ctx 先于本链注入
```
接线后 **Page/List/导出自动生效**。目前仅 user 模块接线(全库仅 goframe_user 有 dept_id 列);其他模块需要时声明同款闭包即可,无部门归属列的表可按需扩展"按创建人过滤"变体。
## 与租户隔离的叠加关系
```text
第一层(硬规则,不可配置):租户隔离
dao.Ctx 注入 tenant_id IN(0,自身),先于一切业务过滤,任何模块不可绕过
第二层(可配置):角色数据范围
ModuleSpec.DataScope 挂点,applyFilters 末环叠加
两层独立:先租户收窄,再数据范围收窄
```
## 安全语义(与直觉不同的点)
::: warning 五条语义
1. **多角色取最宽松**(并集直觉)——合并发生在 LoadIdentity 缓存层(数值 min,1 最宽),热路径零额外查询
2. **超管/平台完全绕过**(IsPlatform 或 Roles 含 ROLE_SUPER_ADMIN,dataScopeBypass 双判断)
3. **未分配部门(dept_id=0)用户挂档 2/3 时降级为"仅本人"**(防 dept_id=0 意外放大可见面)
4. **仅作用于 Page/List/导出**(applyFilters 链);Detail/Update/Delete 不过滤,由 permission 节点与租户隔离兜底——管理端点授予权限时应评估该角色是否应有写权限
5. 部门子树 deptSubtreeIds:拉全租户部门行(id,parent_id)后 BFS(树小直查无缓存;成热点可加短时缓存)
:::
## 配置链路(修改如何生效)
```text
role 表 data_scope 列(默认 1)
→ 角色表单"数据范围"下拉(字典 role_data_scope 驱动,值 1/2/3/4)
→ roleToData 归一(缺省回 1,gvalid in:1,2,3,4 校验)
→ 角色 Update 后 AfterUpdate 清该角色全部用户身份缓存
→ 生效(新请求的 LoadIdentity 读到新档位)
```
Page/Detail 返回 `dataScope + dataScopeText`(字典驱动),前端可展示当前角色数据范围。
## 上下文读取
```text
GetDataScope(ctx) 档位(1-全部;未注入视为全部——旧缓存缺字段回退安全值)
GetDeptID(ctx) 当前用户部门 ID(0=未分配)
```
两者由 JWT 中间件从身份缓存注入,业务代码一般不直接读(基座 DataScope 闭包内部消费)。
## 已知边界
+ 数据权限当前仅 user 模块接线;其他模块行级可见性由租户隔离单层兜底
+ Detail/Update/Delete 不做行级过滤——越权改删他人记录的防线是接口 permission + 租户隔离
+ 身份缓存 300s 窗口内直接改库的 dept_id/data_scope 不即时生效(API 路径均主动清缓存)
+ 第 5 档自定义范围(如按部门多选)为预留能力,需部门关联表 + 角色表单扩展