背景
XCode 已具备数据范围模型:DataScopes(全部=0 … 自定义=4)、Role.DataScope / DataDepartmentIds / ViewSensitive,以及 DataScopeContext、DataScopeHelper.GetFilter/CanAccess、DataScopeInterceptor。
NewLife.Cube WebAPI版本( 前后端分离 ) 希望行级权限唯一跟角色 DataScope 走。当前 Cube 只能用 [DataPermission(null, "ID={#userId}")] 做成「非系统仅本人」,忽略 DataScope。要把行权接到 GetFilter,下列问题必须在 XCode 修:Cube 无法跨程序集给 User/Department/Log 补 partial 接口,也无法挡住 Role.Valid 在 Insert/Update 时把 0 改写成「本部门」。
消费方已锁定:
- 实现
IDataScope / IUserScope / IDepartmentScope 的实体自动按 DataScope 过滤。
- 仅
IUserScope、无部门列的表(日志等):本部门/自定义 不要 join 用户表放大成同事数据。
- 普通角色允许把
DataScope 存成全部(0)。
IFieldScope 脱敏由 Cube 调用现有 MaskSensitiveFields。
问题 1(P0):Role.Valid 把 DataScope==0 当成未设置
文件:XCode/Membership/角色.Biz.cs(约 133–142 行)
DataScopes.全部 == 0。普通角色保存「全部」时,entity.Valid 会改成「本部门」或「本部门及下级」。Cube 控制器无法覆盖(Save 会再跑一遍 Valid)。
期望: 仅 Insert 且 DataScope 不在脏数据中 时按 Type 填默认;Update 或已显式赋值时,0 就是全部。
问题 2(P0):拦截器校验失败仍 return true
文件:XCode/Membership/DataScopeModule.cs OnValid(约 52–79 行)
无权时 throw InvalidOperationException,被 catch 写日志后 return true。挂上拦截器后,越权写入仍成功。
期望: return false 或继续抛出。无上下文时保持不校验。
问题 3(P0):内置实体未挂载,GetFilter 无效
| 实体 |
现状 |
期望 |
| User |
已有 IDataScope + FieldProvider,无 DataScopeInterceptor |
修完问题 2 后 Add<DataScopeInterceptor>() |
| Department |
仅 ITenantScope |
IDepartmentScope(DepartmentId→ID)+ FieldProvider + 拦截器 |
| Log |
无接口,列是 CreateUserID |
IUserScope 显式映射 + GetUserField() => _.CreateUserID + 拦截器 |
问题 4(P1):仅 IDepartmentScope + 仅本人 → 空表
仅本人 时 AccessibleDepartmentIds 为空数组,BuildDepartmentFilter 变成 Equal(-1);CanAccess 也对空数组返回 false。部门表「一行一个部门」时,仅本人/本部门应为 ID = 当前用户.DepartmentID。不要改 IDataScope(User)仅本人走 UserId 的语义。
问题 5(P1):纯 IUserScope 保持按用户过滤
非全部时 userField.Equal(当前用户) 请保持,并写进注释:无部门列时本部门不会变成同事可见。
问题 6(P1):缓存键没有 DepartmentID
DataScope:{userId}:{scope} 导致调岗后最多 5 分钟仍用旧部门列表。key 应含 userId+deptId+scope;ClearCache(userId) 需清掉该用户新旧两种键。
问题 7(P2):菜单 DataScope 默认 0 会覆盖成「全部」
列注释是 -1=使用角色默认,枚举默认却是 0=全部。SetMenu 在 >=0 时覆盖角色。新建/未配置菜单应保持 -1,不要让未配置变成全部。不必把「继承」加进角色下拉枚举。
建议改动
角色.Biz.cs — Insert 未赋值才写默认 DataScope
DataScopeModule.cs — OnValid 失败不放行
DataScopeContext.cs — 缓存键与 ClearCache
DataScopeHelper — 部门仅本人≡本部门;IUserScope 注释
用户.Biz.cs / 部门.Biz.cs / 日志.Biz.cs — 接口 + 拦截器
DataScopeTests.cs — 见下方验收
Cube 会自己:CreateWhere 合并 GetFilter、拆除仅本人 DataPermission、给 Cube 程序集内 Token 等挂 IUserScope。
验收(XCode 单测)
- 普通角色
DataScope=全部,Update 后仍为全部
- Insert 未赋 DataScope 时仍有 Type 默认值
- 仅本人上下文,拦截器拒绝改他人 IDataScope 数据
- User:本部门滤
DepartmentID,仅本人滤 ID
- Log:本部门仍滤
CreateUserID
- Department:仅本人滤
ID=当前部门,不是 -1
- 同一用户更换
DepartmentID 后部门列表立即更新(或 ClearCache 后必新)
背景
XCode 已具备数据范围模型:
DataScopes(全部=0 … 自定义=4)、Role.DataScope/DataDepartmentIds/ViewSensitive,以及DataScopeContext、DataScopeHelper.GetFilter/CanAccess、DataScopeInterceptor。NewLife.Cube WebAPI版本( 前后端分离 ) 希望行级权限唯一跟角色
DataScope走。当前 Cube 只能用[DataPermission(null, "ID={#userId}")]做成「非系统仅本人」,忽略DataScope。要把行权接到GetFilter,下列问题必须在 XCode 修:Cube 无法跨程序集给User/Department/Log补 partial 接口,也无法挡住Role.Valid在Insert/Update时把0改写成「本部门」。消费方已锁定:
IDataScope/IUserScope/IDepartmentScope的实体自动按 DataScope 过滤。IUserScope、无部门列的表(日志等):本部门/自定义不要 join 用户表放大成同事数据。DataScope存成全部(0)。IFieldScope脱敏由 Cube 调用现有MaskSensitiveFields。问题 1(P0):
Role.Valid把DataScope==0当成未设置文件:
XCode/Membership/角色.Biz.cs(约 133–142 行)DataScopes.全部 == 0。普通角色保存「全部」时,entity.Valid会改成「本部门」或「本部门及下级」。Cube 控制器无法覆盖(Save 会再跑一遍 Valid)。期望: 仅 Insert 且 DataScope 不在脏数据中 时按
Type填默认;Update 或已显式赋值时,0就是全部。问题 2(P0):拦截器校验失败仍
return true文件:
XCode/Membership/DataScopeModule.csOnValid(约 52–79 行)无权时
throw InvalidOperationException,被 catch 写日志后return true。挂上拦截器后,越权写入仍成功。期望:
return false或继续抛出。无上下文时保持不校验。问题 3(P0):内置实体未挂载,
GetFilter无效IDataScope+ FieldProvider,无DataScopeInterceptorAdd<DataScopeInterceptor>()ITenantScopeIDepartmentScope(DepartmentId→ID)+ FieldProvider + 拦截器CreateUserIDIUserScope显式映射 +GetUserField() => _.CreateUserID+ 拦截器问题 4(P1):仅
IDepartmentScope+ 仅本人 → 空表仅本人时AccessibleDepartmentIds为空数组,BuildDepartmentFilter变成Equal(-1);CanAccess也对空数组返回 false。部门表「一行一个部门」时,仅本人/本部门应为ID = 当前用户.DepartmentID。不要改IDataScope(User)仅本人走 UserId 的语义。问题 5(P1):纯
IUserScope保持按用户过滤非全部时
userField.Equal(当前用户)请保持,并写进注释:无部门列时本部门不会变成同事可见。问题 6(P1):缓存键没有
DepartmentIDDataScope:{userId}:{scope}导致调岗后最多 5 分钟仍用旧部门列表。key 应含userId+deptId+scope;ClearCache(userId)需清掉该用户新旧两种键。问题 7(P2):菜单 DataScope 默认 0 会覆盖成「全部」
列注释是
-1=使用角色默认,枚举默认却是 0=全部。SetMenu在>=0时覆盖角色。新建/未配置菜单应保持 -1,不要让未配置变成全部。不必把「继承」加进角色下拉枚举。建议改动
角色.Biz.cs— Insert 未赋值才写默认 DataScopeDataScopeModule.cs— OnValid 失败不放行DataScopeContext.cs— 缓存键与 ClearCacheDataScopeHelper— 部门仅本人≡本部门;IUserScope 注释用户.Biz.cs/部门.Biz.cs/日志.Biz.cs— 接口 + 拦截器DataScopeTests.cs— 见下方验收Cube 会自己:
CreateWhere合并GetFilter、拆除仅本人DataPermission、给 Cube 程序集内 Token 等挂IUserScope。验收(XCode 单测)
DataScope=全部,Update 后仍为全部DepartmentID,仅本人滤IDCreateUserIDID=当前部门,不是-1DepartmentID后部门列表立即更新(或 ClearCache 后必新)