- 新增财务菜单与应收应付、充值记录、账户流水页面及路由 - 组织管理改为左右分栏,优化左侧树层级展示与选中交互 - 角色权限分配改为列表形式,支持各级菜单独立勾选 - 我的订单工具栏按钮样式与独立 loading 交互优化 Co-authored-by: Cursor <cursoragent@cursor.com>
1049 lines
40 KiB
Markdown
1049 lines
40 KiB
Markdown
# 多维度组合数据权限设计方案 PRD
|
||
|
||
## 文档基础信息
|
||
|
||
| 项目 | 内容 |
|
||
| ---- | ---- |
|
||
| 文档名称 | 多维度交集式数据权限标准方案 |
|
||
| 适用系统 | OMS 业务系统 + RBAC 管理端 |
|
||
| 关联文档 | [`rbac系统设计-060801.md`](./rbac系统设计-060801.md)、[`oms系统设计-050801.md`](./oms系统设计-050801.md) |
|
||
| 权限架构 | **身份认证** → **功能权限(RBAC PermissionCode)** → **数据权限(本方案)**,三层解耦 |
|
||
| 版本 | V1.2 |
|
||
| 设计目标 | 在现有 RBAC 功能权限之上,为**内部用户**补齐多维数据过滤;与客户门户 **CustomerId 硬隔离** 并存、互不替代 |
|
||
|
||
---
|
||
|
||
## 导读:与 RBAC / OMS 的分工
|
||
|
||
### 三层权限模型
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ 身份认证(Authentication) │
|
||
│ JWT:sub(GUID) + mapId(INT) + loginType(0内部/1客户) │
|
||
│ 详见 rbac §4 │
|
||
├─────────────────────────────────────────────────────────────┤
|
||
│ 功能权限(Authorization · 能做什么) │
|
||
│ 用户角色 → role_permission → PermissionCode 并集 P │
|
||
│ 控制:菜单、按钮、API 是否可调用 │
|
||
│ 详见 rbac §5 │
|
||
├─────────────────────────────────────────────────────────────┤
|
||
│ 数据权限(Data Scope · 能看到哪些行) ← 本文 │
|
||
│ 五维交集过滤,仅后端注入查询条件 │
|
||
│ 控制:列表/详情/导出/统计 返回的数据行范围 │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
**关键原则**:
|
||
|
||
1. 有 `Track.Orders.Query` 功能权限,不代表能看全部订单;还须通过数据权限过滤。
|
||
2. 数据权限**不能**替代功能权限;二者 AND 关系:**先鉴权码、再滤数据**。
|
||
3. **客户门户(`loginType=1`)不走本文五维模型**,走 OMS 既有 **CustomerId 硬隔离**(见 oms §4.4.0、`OmsSessionHelper`)。
|
||
4. **内部用户(`loginType=0`)** 才启用本文多维数据权限;超管白名单豁免。
|
||
|
||
### 双登录主体与数据隔离策略
|
||
|
||
| 主体 | JWT `loginType` | 数据隔离机制 | 配置入口 |
|
||
| ---- | --------------- | ------------ | -------- |
|
||
| **客户 / 子客户** | 1 | `CustomerId = effectiveCustomerId`(会话解析,不可绕过) | 无需数据权限配置;子客户功能范围由 RBAC 专属角色 `CustomerSub_{userId}` 控制 |
|
||
| **内部用户** | 0 | 本文五维交集 + 可选 `CustomerId` 等业务维度 | RBAC 管理端「数据权限」Tab / 权限模板 |
|
||
| **超级管理员** | 0 | 角色 `Code=Admin` → **跳过全部数据维度** | 内置,不可关闭 |
|
||
|
||
### 双 ID 对齐(必须与 RBAC 一致)
|
||
|
||
| 标识 | 类型 | 数据权限表 / 业务表用法 |
|
||
| ---- | ---- | ------------------------ |
|
||
| `user.Id` | CHAR(36) GUID | **数据权限配置表** 外键 `UserId`;组织权限 `OrganizationId` |
|
||
| `user.userid` | INT 自增 | JWT Claim **`mapId`**;OMS 审计字段 **`CreateUserId` / `UpdateUserId`** |
|
||
| `organization.Id` | CHAR(36) GUID | 组织维度过滤;**禁止**使用自增 bigint 作为 org_id |
|
||
| `t_customer.Id` | BIGINT | OMS 业务 **`CustomerId`**;销售负责范围过滤时的业务键 |
|
||
|
||
> **修正(相对 V1.0)**:V1.0 中 `user_id bigint`、`org_id bigint` 与现网 RBAC 不一致,统一改为 GUID;OMS 侧负责人仍用 `CreateUserId`(INT mapId)。
|
||
|
||
---
|
||
|
||
## 一、需求概述
|
||
|
||
### 1.1 业务痛点
|
||
|
||
原有仅依靠 `user.OrganizationId`(单组织归属)+ 管理员无过滤(`ResolveListCustomerIdAsync` 返回 null)存在以下问题:
|
||
|
||
1. 同部门不同岗位(销售 vs 客服 vs 财务)数据可见范围无法区分;
|
||
2. 产品、运营、总部职能岗需要**跨分公司**查看指定产品线/区域数据;
|
||
3. 营收、客户隐私、成本等敏感字段无法独立管控与脱敏;
|
||
4. 不支持时间、金额、单据状态等**岗位级**动态范围限制;
|
||
5. 临时授权无时效回收;内部用户查单/查客无审计追溯;
|
||
6. 客户门户已有 CustomerId 隔离,但**运营后台**仍「登录即全量」,与合规要求不符。
|
||
|
||
### 1.2 核心设计原则
|
||
|
||
1. **功能权限与数据权限解耦**(见导读三层模型)。
|
||
2. **多维度取交集**(内部用户):
|
||
```
|
||
可见数据 = 组织过滤 ∩ 数据范围 ∩ 业务标签 ∩ 密级 ∩ 自定义条件
|
||
```
|
||
3. **密级最高优先级**:无密级权限的行直接过滤;有权限但字段级敏感则**脱敏展示**(仍返回行)。
|
||
4. **最小权限原则**:新建内部用户默认**无扩展数据权限**(仅组织默认范围,见 §2.1.4);须管理员分配或套用模板。
|
||
5. **超级管理员白名单**:角色 `Admin` 跳过五维过滤。
|
||
6. **后端唯一可信**:全部过滤在 Service/Repository 层注入;前端不做数据拦截。
|
||
7. **分模块接入**:订单、客户、充值、渠道配置等按 `DataResourceCode` 注册,统一走 `IDataScopeApplier`。
|
||
|
||
### 1.3 五大权限控制维度(仅内部用户)
|
||
|
||
| 维度 | 回答的问题 | 典型 OMS 落点 |
|
||
| ---- | ---------- | ------------- |
|
||
| 1. 组织 | 哪个分公司/部门的数据? | 订单扩展字段 `OrganizationId`;客户列表按销售组织 |
|
||
| 2. 数据范围 | 本人 / 本组 / 本部门 / 组织树 / 全局? | `CreateUserId`、`t_customer.Salesman` |
|
||
| 3. 业务标签 | 哪条产品线/区域/KPI 分区? | 销售产品、KPI 分区、客户分组 `CustomerGroup` |
|
||
| 4. 数据密级 | 能否看机密/绝密字段? | 费用明细、成本、利润、客户手机号 |
|
||
| 5. 自定义过滤 | 时间/金额/状态等附加条件? | 本年度订单、金额>1万、排除作废 |
|
||
|
||
---
|
||
|
||
## 二、详细功能需求
|
||
|
||
### 2.1 维度 1:组织数据权限
|
||
|
||
#### 2.1.1 组织架构模型(对齐 RBAC `organization`)
|
||
|
||
复用 RBAC 组织树,**不另建组织主数据**:
|
||
|
||
```
|
||
公司 → 事业部 → 分公司 → 部门 → 小组
|
||
```
|
||
|
||
| RBAC 字段 | 说明 |
|
||
| --------- | ---- |
|
||
| `organization.Id` | GUID,数据权限过滤键 |
|
||
| `organization.ParentId` | 树形父节点 |
|
||
| `organization.Type` | `OrganizationType`:1/2/3(与 RBAC 枚举一致) |
|
||
| `user.OrganizationId` | 用户**主归属**组织,作默认数据范围起点 |
|
||
|
||
#### 2.1.2 组织权限范围枚举
|
||
|
||
| 编码 | 名称 | 规则说明 |
|
||
| ---- | ---- | -------- |
|
||
| 1 | 仅本级组织 | 仅 `OrganizationId = 授权组织`,不含下级 |
|
||
| 2 | 本级 + 所有下级 | 授权组织及其子树(管理岗默认) |
|
||
|
||
#### 2.1.3 业务规则
|
||
|
||
1. 平级组织默认互相隔离;
|
||
2. 支持**一人多组织**授权(多条 `user_org_perm`);
|
||
3. 支持**跨组织白名单**(总部财务、审计勾选多个分公司);
|
||
4. 用户主归属 `user.OrganizationId` 在未单独配置时,作为**默认组织范围**(本级+下级)。
|
||
|
||
#### 2.1.4 与 OMS 业务表映射
|
||
|
||
| 业务实体 | 组织字段策略 | 说明 |
|
||
| -------- | ------------ | ---- |
|
||
| `t_order` | **新增** `OrganizationId CHAR(36) NULL` | 创建时取自客户归属组织或操作人主组织;历史数据可批量回填 |
|
||
| `t_customer` | **新增** `OrganizationId CHAR(36) NULL` | 客户归属销售组织;与 `Salesman` 联动维护 |
|
||
| `t_recharge_record` | 继承 `CustomerId → t_customer.OrganizationId` | 查询时 JOIN,不必冗余 |
|
||
| 渠道/系统主数据 | 默认**不受组织维限制** | 通过功能权限 + 密级控制;若需按组织隔离再扩展 |
|
||
|
||
### 2.2 维度 2:角色数据范围
|
||
|
||
#### 2.2.1 数据范围枚举
|
||
|
||
| 编码 | 名称 | SQL 语义(以订单为例) |
|
||
| ---- | ---- | ---------------------- |
|
||
| 1 | 个人级 | `CreateUserId = 当前 mapId` 或 `t_customer.Salesman = 当前用户账号` |
|
||
| 2 | 小组级 | 同 `user.OrganizationId` 且组织 Type=小组 的全体 mapId |
|
||
| 3 | 部门级 | 同部门组织子树内所有用户的 mapId |
|
||
| 4 | 组织树级 | 以授权组织为根的子树内全部数据 |
|
||
| 5 | 全局级 | 不追加负责人过滤(仍受组织/业务/密级/自定义约束) |
|
||
|
||
#### 2.2.2 与 RBAC 角色的关系
|
||
|
||
| 配置方式 | 优先级 | 说明 |
|
||
| -------- | ------ | ---- |
|
||
| **角色级默认** `role_data_scope` | 低 | 角色绑定数据范围,用户继承其所有角色的**最大值**(取最宽) |
|
||
| **用户级覆盖** `user_data_scope` | 高 | 显式配置则覆盖角色默认 |
|
||
|
||
> 示例:用户同时有「销售专员」(个人级) 和「销售主管」(部门级) 两角色 → 有效范围为 **部门级**(取 max)。
|
||
|
||
#### 2.2.3 OMS 业务配套字段
|
||
|
||
| 字段 | 表 | 用途 |
|
||
| ---- | -- | ---- |
|
||
| `CreateUserId` | 各 OMS 业务表 | INT,= `user.userid`;个人级过滤 |
|
||
| `Salesman` | `t_customer` | VARCHAR,可与 `user.Account` 对应;销售看自己的客户 |
|
||
| `CustomerService` | `t_customer` | 客服负责范围(可选启用) |
|
||
| `CustomerId` | `t_order` 等 | 先按客户归属,再按客户负责人收窄 |
|
||
|
||
**内部用户查订单推荐链路**:
|
||
|
||
```
|
||
t_order
|
||
→ CustomerId → t_customer(Salesman / OrganizationId)
|
||
→ CreateUserId(下单操作人)
|
||
按 data_scope 选用 CreateUserId 或 Salesman 或组织子树
|
||
```
|
||
|
||
### 2.3 维度 3:业务维度权限(跨组织)
|
||
|
||
#### 2.3.1 业务分类类型(OMS 落地)
|
||
|
||
| biz_type 编码 | 名称 | OMS 数据源 |
|
||
| ------------- | ---- | ---------- |
|
||
| `product_line` | 产品线 | `t_sales_product` / 产品分类 |
|
||
| `kpi_area` | KPI 分区 | `t_kpi_area` |
|
||
| `customer_group` | 客户分层 | `t_customer.CustomerGroup`(0 普通,1~5 VIP) |
|
||
| `warehouse` | 仓库 | `t_warehouse_address.Id` |
|
||
| `region` | 区域 | 字典或 KPI 分区上级(可扩展) |
|
||
|
||
#### 2.3.2 控制规则
|
||
|
||
1. 独立于组织架构,支持多选;**OR** 语义:命中任一已授权标签即可;
|
||
2. 与组织维度 **AND**:须同时满足组织范围 **且** 业务标签;
|
||
3. 用户未配置任何业务标签 = **不限制业务标签**(与 V1.0「无标签=无权限」不同,避免过度收紧;若需强制可 per-module 配置 `RequireBizTag=true`);
|
||
4. 业务表映射:
|
||
|
||
| 表 | 过滤字段 |
|
||
| -- | -------- |
|
||
| `t_order` | `ProductCode` → 产品 → 产品线;`ConsigneeCountry` + KPI 分区 |
|
||
| `t_customer` | `CustomerGroup` |
|
||
| 渠道配置 | 直接按产品/分区 Id |
|
||
|
||
### 2.4 维度 4:数据密级权限(行级 + 字段级)
|
||
|
||
#### 2.4.1 密级分级
|
||
|
||
| 编码 | 名称 | 典型数据 |
|
||
| ---- | ---- | -------- |
|
||
| 1 | 公开级 | 运单号、状态、路由 |
|
||
| 2 | 内部级 | 应收费用、客户名称 |
|
||
| 3 | 机密级 | 应付/成本、毛利、完整地址 |
|
||
| 4 | 绝密级 | 手机号、身份证、银行信息、完整利润 |
|
||
|
||
#### 2.4.2 两级控制
|
||
|
||
| 级别 | 行为 |
|
||
| ---- | ---- |
|
||
| **行级** | `secret_level` 高于用户授权 → **整行不返回** |
|
||
| **字段级** | 行可见但字段密级超限 → **脱敏**(如 `138****1234`),接口仍 200 |
|
||
|
||
#### 2.4.3 业务表字段
|
||
|
||
| 表 | 策略 |
|
||
| -- | ---- |
|
||
| `t_order` | 表级默认密级 2;`t_order_fee` 应付行密级 3 |
|
||
| `t_customer` | 表级密级 3;Phone/Email 字段密级 4 |
|
||
| `t_recharge_record` | 密级 3(含金额) |
|
||
|
||
新增通用字段(按需,非全表强制):
|
||
|
||
- `SecretLevel TINYINT NOT NULL DEFAULT 2`
|
||
|
||
### 2.5 维度 5:自定义行过滤条件
|
||
|
||
#### 2.5.1 支持的条件类型
|
||
|
||
| 类型 | 示例 | 适用表 |
|
||
| ---- | ---- | ------ |
|
||
| 时间 | 本年度、近 3 个月、自定义区间 | `t_order.CreateTime` |
|
||
| 数值 | 应收合计 > 10000 | `t_order_fee` 聚合 |
|
||
| 枚举 | `OrderStatus IN (...)` | `t_order` |
|
||
| 渠道 | 指定 `ProductCode` / `ChannelCode` | `t_order` |
|
||
|
||
#### 2.5.2 安全实现
|
||
|
||
1. 可视化表单 → AST → SqlSugar 表达式,**禁止**管理员输入原生 SQL;
|
||
2. 按 `DataResourceCode`(如 `Order`、`Customer`、`Recharge`)区分规则;
|
||
3. 条件仅 **AND** 追加到交集结果,不改变业务接口原有筛选参数语义。
|
||
|
||
### 2.6 特殊权限:临时数据权限
|
||
|
||
| 项 | 说明 |
|
||
| -- | ---- |
|
||
| 场景 | 审计、跨部门对账、临时顶岗 |
|
||
| 配置 | 关联用户 GUID、全套五维副本、生效/过期时间 |
|
||
| 存储 | 各 `user_*_perm` 表 `ExpireTime` 非空;或独立 `user_data_perm_grant` 快照 |
|
||
| 生效 | `EffectiveTime <= NOW() < ExpireTime` 的记录参与计算;过期自动失效 |
|
||
| 审计 | 标记 `IsTemporary=1`;访问日志单独索引 |
|
||
|
||
### 2.7 权限模板
|
||
|
||
预设岗位模板,一键写入角色或用户的数据权限配置:
|
||
|
||
| 模板 | 组织 | 数据范围 | 业务 | 密级 |
|
||
| ---- | ---- | -------- | ---- | ---- |
|
||
| 普通销售 | 主归属、仅本级 | 个人级 | 指定产品线 | 1、2 |
|
||
| 销售主管 | 本级+下级 | 部门级 | 全部产品线 | 1、2、3 |
|
||
| 分公司经理 | 本级+下级 | 组织树级 | 全部 | 1、2、3 |
|
||
| 总部产品经理 | 多组织白名单 | 全局级 | 单一产品线 | 1、2 |
|
||
| 财务专员 | 本级+下级 | 组织树级 | 全部 | 含 3、4(字段脱敏策略另配) |
|
||
| 客服专员 | 本级 | 个人级 | — | 1、2(客户手机号脱敏) |
|
||
|
||
支持自定义模板 CRUD;模板可绑定 RBAC **角色 Code**,新用户分配角色时自动继承。
|
||
|
||
---
|
||
|
||
## 三、后端核心权限计算逻辑
|
||
|
||
### 3.1 通用计算公式
|
||
|
||
记当前内部用户有效配置(已合并多角色、已过滤过期临时授权):
|
||
|
||
- `OrgFilter`:组织维度 SQL 条件
|
||
- `ScopeFilter`:数据范围条件
|
||
- `BizFilter`:业务标签条件(空配置 = 恒真)
|
||
- `SecretFilter`:密级条件
|
||
- `CustomFilter`:自定义条件
|
||
|
||
**最终查询条件**:
|
||
|
||
```
|
||
WHERE IsDeleted = 0
|
||
AND (Admin ? TRUE : (
|
||
OrgFilter
|
||
AND ScopeFilter
|
||
AND BizFilter
|
||
AND SecretFilter
|
||
AND CustomFilter
|
||
))
|
||
AND <业务接口原有筛选>
|
||
```
|
||
|
||
**伪代码**:
|
||
|
||
```csharp
|
||
async Task<Expression<Func<T, bool>>> BuildDataScopeAsync<T>(
|
||
DataResourceCode resource,
|
||
ICurrentUser user)
|
||
{
|
||
if (user.IsInRole("Admin")) return _ => true;
|
||
if (OmsSessionHelper.IsCustomerLogin(user))
|
||
throw new InvalidOperationException("客户门户走 CustomerId 隔离");
|
||
|
||
var ctx = await _dataPermCache.GetOrLoadAsync(user.Id); // GUID
|
||
var parts = new List<Expression<Func<T, bool>>>();
|
||
|
||
parts.Add(BuildOrgFilter<T>(ctx, resource));
|
||
parts.Add(BuildScopeFilter<T>(ctx, user.GetId<int>(), resource));
|
||
parts.Add(BuildBizFilter<T>(ctx, resource));
|
||
parts.Add(BuildSecretFilter<T>(ctx));
|
||
parts.Add(BuildCustomFilter<T>(ctx, resource));
|
||
|
||
return parts.Aggregate((a, b) => a.And(b));
|
||
}
|
||
```
|
||
|
||
### 3.2 超级管理员豁免
|
||
|
||
满足任一条件跳过五维过滤:
|
||
|
||
1. 用户角色包含 `Code = Admin`(RBAC 种子超管);
|
||
2. 或显式 `user.IsSuperAdmin = 1`(扩展字段,可选)。
|
||
|
||
仍受 **功能权限码** 约束(若无 `Track.Orders.Query` 仍不可调用接口)。
|
||
|
||
### 3.3 与客户门户的并存规则
|
||
|
||
**同一套路由 `/admin/order/*`(服务内 `/order/*`)**,不按门户拆 URL;在 `OrderService` 入口按 `loginType` 分支:
|
||
|
||
| loginType | 隔离方式 |
|
||
| --------- | -------- |
|
||
| 1 客户 | `OmsSessionHelper` → `CustomerId = effectiveCustomerId` |
|
||
| 0 内部 + Admin | 不加五维 |
|
||
| 0 内部 + 非 Admin | `DataScopeApplier` 五维交集 |
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
A["POST /admin/order/list"] --> B{loginType?}
|
||
B -->|1 客户| C[CustomerId 硬隔离]
|
||
B -->|0 内部| D{Admin?}
|
||
D -->|是| E[无五维过滤]
|
||
D -->|否| F[DataScopeApplier]
|
||
C --> G[查询]
|
||
E --> G
|
||
F --> G
|
||
```
|
||
|
||
### 3.4 演算示例
|
||
|
||
**用户**:华南分公司销售经理(非 Admin)
|
||
|
||
| 维度 | 配置 |
|
||
| ---- | ---- |
|
||
| 组织 | 华南分公司,本级+下级 |
|
||
| 数据范围 | 组织树级 |
|
||
| 业务 | 线上零售产品线 |
|
||
| 密级 | 1、2、3 |
|
||
| 自定义 | 2026 年、已付款 |
|
||
|
||
**订单列表 SQL 语义**:
|
||
|
||
```sql
|
||
WHERE t_order.IsDeleted = 0
|
||
AND t_order.OrganizationId IN (华南分公司子树 GUID 列表)
|
||
AND t_order.ProductCode IN (线上零售产品 Code 列表)
|
||
AND t_order.SecretLevel <= 3
|
||
AND YEAR(t_order.CreateTime) = 2026
|
||
AND t_order.OrderStatus = 'pendingPayment' -- 已付款态按业务枚举调整
|
||
-- 不含 CustomerId 全量;内部运营后台不按单客户隔离
|
||
```
|
||
|
||
---
|
||
|
||
## 四、数据库设计
|
||
|
||
> RBAC 库(EF)与 OMS 库(SqlSugar)可同实例不同表;**数据权限配置表建议放 RBAC 库**,与 `user`/`role`/`organization` 同库 FK。
|
||
|
||
### 4.1 用户组织权限 `user_org_perm`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| ---- | ---- | ---- |
|
||
| Id | CHAR(36) | PK |
|
||
| UserId | CHAR(36) | FK → `user.Id` |
|
||
| OrganizationId | CHAR(36) | FK → `organization.Id` |
|
||
| OrgScope | TINYINT | 1 仅本级 / 2 本级+下级 |
|
||
| EffectiveTime | DATETIME | 生效时间,默认创建时 |
|
||
| ExpireTime | DATETIME | NULL=永久 |
|
||
| IsTemporary | TINYINT | 0/1 |
|
||
| CreateTime | DATETIME | |
|
||
|
||
### 4.2 角色 / 用户数据范围
|
||
|
||
**`role_data_scope`**
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| ---- | ---- | ---- |
|
||
| Id | CHAR(36) | PK |
|
||
| RoleId | CHAR(36) | FK → `role.Id` |
|
||
| DataScope | TINYINT | 1~5 |
|
||
| DataResourceCode | VARCHAR(32) | 可选,空=全局默认 |
|
||
|
||
**`user_data_scope`**(用户级覆盖)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| ---- | ---- | ---- |
|
||
| Id | CHAR(36) | PK |
|
||
| UserId | CHAR(36) | FK → `user.Id` |
|
||
| DataScope | TINYINT | 1~5 |
|
||
| DataResourceCode | VARCHAR(32) | 可选 |
|
||
|
||
### 4.3 用户业务维度 `user_biz_perm`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| ---- | ---- | ---- |
|
||
| Id | CHAR(36) | PK |
|
||
| UserId | CHAR(36) | |
|
||
| BizType | VARCHAR(32) | product_line / kpi_area / customer_group / warehouse |
|
||
| BizId | VARCHAR(64) | 业务主键(兼容 GUID 与 INT 字符串) |
|
||
| ExpireTime | DATETIME | 可空 |
|
||
|
||
### 4.4 用户密级 `user_secret_perm`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| ---- | ---- | ---- |
|
||
| Id | CHAR(36) | PK |
|
||
| UserId | CHAR(36) | |
|
||
| SecretLevel | TINYINT | 1~4 |
|
||
| DataResourceCode | VARCHAR(32) | 可选,按模块细分 |
|
||
|
||
### 4.5 用户自定义过滤 `user_filter_rule`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| ---- | ---- | ---- |
|
||
| Id | CHAR(36) | PK |
|
||
| UserId | CHAR(36) | |
|
||
| DataResourceCode | VARCHAR(32) | Order / Customer / Recharge |
|
||
| FilterContent | JSON | 前端配置 AST |
|
||
| FilterHash | VARCHAR(64) | 内容哈希,便于缓存失效 |
|
||
| CreateTime | DATETIME | |
|
||
|
||
> **不再存储 `filter_snippet` 原生 SQL 文本**;运行时由 AST 生成表达式,避免 SQL 注入与方言耦合。
|
||
|
||
### 4.6 权限模板 `data_perm_template` / `data_perm_template_item`
|
||
|
||
模板头 + 明细行(`DimensionType` + `ItemContent` JSON),支持绑定 `RoleCode`。完整 DDL 见 **§十三** 与 `sql/install_data_permission.sql`。
|
||
|
||
**角色级五维表**(与用户对偶,供模板套用与角色继承):
|
||
|
||
- `role_org_perm` · `role_data_scope` · `role_biz_perm` · `role_secret_perm` · `role_filter_rule`
|
||
|
||
### 4.7 数据权限审计 `data_perm_access_log`
|
||
|
||
| 字段 | 说明 |
|
||
| ---- | ---- |
|
||
| UserId、DataResourceCode、ApiPath | 谁访问了什么 |
|
||
| AppliedScopeJson | 本次生效的五维快照 |
|
||
| QueryTime、RowCount | 性能与合规 |
|
||
|
||
### 4.8 OMS 业务表扩展(分期)
|
||
|
||
| 阶段 | 表 | 新增字段 |
|
||
| ---- | -- | -------- |
|
||
| P1 | `t_customer` | `OrganizationId CHAR(36)` |
|
||
| P1 | `t_order` | `OrganizationId CHAR(36)`、`SecretLevel TINYINT DEFAULT 2` |
|
||
| P2 | `t_order_fee` | 应付行 `SecretLevel`、字段级脱敏配置 |
|
||
| P2 | `t_recharge_record` | `SecretLevel` |
|
||
|
||
**不强制**全表统一 `biz_type/biz_id/owner_user_id`;改用 OMS 已有字段 + JOIN 映射(见 §2.3、§2.2.3)。
|
||
|
||
---
|
||
|
||
## 五、接口与执行流程
|
||
|
||
### 5.1 服务组件
|
||
|
||
| 组件 | 职责 |
|
||
| ---- | ---- |
|
||
| `IDataPermissionRepository` | 读配置表 |
|
||
| `IDataScopeContextFactory` | 合并角色+用户配置 → `DataScopeContext` |
|
||
| `IDataScopeApplier` | 按 `DataResourceCode` 注入 SqlSugar `Queryable` |
|
||
| `IFieldMaskingService` | 密级字段脱敏 |
|
||
| `DataPermissionCache` | Redis:`data_perm:{userGuid}`,TTL 30min |
|
||
|
||
### 5.2 请求链路
|
||
|
||
1. JWT 校验 → 解析 `sub`(GUID)、`mapId`、`loginType`;
|
||
2. `[Authorize(Permission = "...")]` 功能权限校验(RBAC 完善后启用);
|
||
3. `loginType=1` → `OmsSessionHelper` CustomerId 分支;
|
||
4. `loginType=0` → 加载 `DataScopeContext` → Applier 注入条件;
|
||
5. 查询结果 → `IFieldMaskingService` 按密级脱敏;
|
||
6. 写 `data_perm_access_log`(异步,可采样)。
|
||
|
||
### 5.3 权限变更与缓存
|
||
|
||
| 事件 | 动作 |
|
||
| ---- | ---- |
|
||
| 用户数据权限 CRUD | 删除 `data_perm:{userId}` |
|
||
| 用户角色变更 | 同上 |
|
||
| 组织树移动 | 批量失效该组织下用户缓存 |
|
||
| 模板绑定角色更新 | 失效该角色所有用户 |
|
||
|
||
### 5.4 管理端 API(建议前缀 `/rbac/data-perm/*`)
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
| ---- | ---- | ---- |
|
||
| GET | `/rbac/data-perm/get-by-user` | 查询用户五维配置 |
|
||
| PUT | `/rbac/data-perm/save-user` | 保存用户五维 |
|
||
| GET | `/rbac/data-perm/template/list` | 模板列表 |
|
||
| POST | `/rbac/data-perm/template/apply` | 模板套用到用户/角色 |
|
||
| GET | `/rbac/data-perm/access-log` | 审计分页 |
|
||
|
||
权限码建议:`Rbac.DataPerm.Query`、`Rbac.DataPerm.Update`(在 `PermissionDefinitionProvider` 注册)。
|
||
|
||
### 5.5 登录响应扩展(可选)
|
||
|
||
`GET /rbac/auth/get-current-user` 增加只读摘要(不含 SQL):
|
||
|
||
```json
|
||
{
|
||
"dataScopeSummary": {
|
||
"isAdmin": false,
|
||
"orgNames": ["华南分公司"],
|
||
"dataScope": 4,
|
||
"secretLevels": [1, 2, 3]
|
||
}
|
||
}
|
||
```
|
||
|
||
供前端展示「当前数据范围」提示,**不可替代**后端过滤。
|
||
|
||
---
|
||
|
||
## 六、分模块接入清单(OMS)
|
||
|
||
| DataResourceCode | 服务 | 主表 | 组织字段 | 范围字段 | 备注 |
|
||
| ---------------- | ---- | ---- | -------- | -------- | ---- |
|
||
| `Order` | `OrderService` | `t_order` | OrganizationId | CreateUserId + Customer.Salesman | 同 `/admin/order/list`,内部用户走 Applier |
|
||
| `Customer` | `CustomerService` | `t_customer` | OrganizationId | Salesman / CustomerService | `/customer/list` 内部查询 |
|
||
| `Recharge` | `RechargeService` | `t_recharge_record` | via Customer | CreateUserId | 审核列表 |
|
||
| `ChannelProduct` | `SalesProductService` | `t_sales_product` | — | 业务标签 product_line | 配置类,密级偏低 |
|
||
| `Xhs` | `Xhs*Service` | 各 t_xhs_* | — | CustomerId(已有) | 内部用户走五维;客户走 Xhs CustomerId |
|
||
|
||
**客户门户模块**(`/admin/order/*`、Xhs 客户侧):**不接入**五维 Applier,保持现有 `OmsSessionHelper`。
|
||
|
||
---
|
||
|
||
## 七、前端功能需求
|
||
|
||
### 7.1 用户数据权限编辑(`/system/users` 或 RBAC 用户详情)
|
||
|
||
- Tab:组织 / 数据范围 / 业务标签 / 密级 / 自定义过滤;
|
||
- 组织树勾选:复用 `GET /rbac/organization/get-tree`;
|
||
- 权限模板一键填充;
|
||
- 临时权限:EffectiveTime + ExpireTime。
|
||
|
||
### 7.2 权限模板管理
|
||
|
||
- CRUD + 绑定 RoleCode;
|
||
- 预览「有效 SQL 语义」只读说明(不给 SQL 编辑)。
|
||
|
||
### 7.3 权限审计日志
|
||
|
||
- TablePro:用户、模块、时间、AppliedScopeJson 展开;
|
||
- 导出 Excel。
|
||
|
||
### 7.4 密级与脱敏配置
|
||
|
||
- 维护 `DataResourceCode + 字段名 → SecretLevel` 映射表;
|
||
- 与接口响应 DTO 字段对齐。
|
||
|
||
### 7.5 前端约束
|
||
|
||
- `hasPermission()` 恢复真实校验(rbac §9.4)后,按钮与数据范围提示分离;
|
||
- **禁止**前端按组织/密级过滤列表数据。
|
||
|
||
---
|
||
|
||
## 八、非功能性需求
|
||
|
||
| 类别 | 要求 |
|
||
| ---- | ---- |
|
||
| 安全 | 后端过滤;AST 白名单运算符;字段脱敏;临时权限强制过期 |
|
||
| 性能 | Redis 缓存 Context;`(OrganizationId, CreateTime)`、`(CustomerId)` 索引 |
|
||
| 扩展 | 新模块注册 `DataResourceCode` + Applier 策略类 |
|
||
| 易用 | 模板 + 角色继承;组织树可视化 |
|
||
| 审计 | 权限变更日志 + 访问采样日志 |
|
||
|
||
---
|
||
|
||
## 九、典型岗位配置示例
|
||
|
||
### 示例 1:普通销售(内部)
|
||
|
||
- 组织:主归属销售部,仅本级
|
||
- 数据范围:个人级(Salesman = 本人账号)
|
||
- 业务:负责产品线
|
||
- 密级:1、2
|
||
- 接口:`Track.Orders.Query` + 五维过滤
|
||
|
||
### 示例 2:分公司销售经理
|
||
|
||
- 组织:本分公司,本级+下级
|
||
- 数据范围:组织树级
|
||
- 业务:全部产品线
|
||
- 密级:1、2、3
|
||
- 自定义:本年度
|
||
|
||
### 示例 3:总部产品经理(跨组织)
|
||
|
||
- 组织:多分公司白名单
|
||
- 数据范围:全局级
|
||
- 业务:单一产品线
|
||
- 密级:1、2
|
||
|
||
### 示例 4:客户主账号(门户)
|
||
|
||
- **不配置五维**
|
||
- `loginType=1`,`CustomerId` 硬隔离
|
||
- 功能权限:角色 `Customer` + 分配的 PermissionCode
|
||
|
||
### 示例 5:子客户
|
||
|
||
- **不配置五维**
|
||
- 订单归属主客户 `CustomerId`(推荐策略,oms §1.4)
|
||
- 功能权限:角色 `CustomerSub_{userId}` ⊆ 主客户权限
|
||
|
||
### 示例 6:超级管理员
|
||
|
||
- 角色 `Admin`:跳过五维
|
||
- 仍配置功能权限码(默认全开)
|
||
|
||
---
|
||
|
||
## 十、实施分期
|
||
|
||
| 阶段 | 内容 | 依赖 |
|
||
| ---- | ---- | ---- |
|
||
| **P0** | `OrderService` 同路由按 `loginType` 分支;内部非 Admin 接 `DataScopeApplier`(替换管理员无过滤) | 无路由变更 |
|
||
| **P1** | 建 RBAC 数据权限表;`OrganizationId` 落库客户/订单;组织+数据范围两维;Order/Customer 接入 | RBAC 迁移 |
|
||
| **P2** | 业务标签、密级、字段脱敏 | 产品/KPI 主数据 |
|
||
| **P3** | 自定义过滤 AST、临时权限、审计页 | P1 稳定 |
|
||
| **P4** | 权限模板与角色联动;`[Authorize(Permission)]` 全量启用 | RBAC 包升级 |
|
||
|
||
---
|
||
|
||
## 十一、与现有实现的差异对照
|
||
|
||
| 项 | 本文目标 | 当前 oms0414-back |
|
||
| -- | -------- | ----------------- |
|
||
| 客户门户隔离 | CustomerId 强制 | ✅ `OmsSessionHelper` 已实现 |
|
||
| 内部用户查订单 | 五维过滤 | ⚠️ `ResolveListCustomerIdAsync` 管理员返回 null,**无过滤** |
|
||
| 组织主数据 | 复用 RBAC `organization` | ✅ 已有,未用于数据过滤 |
|
||
| 功能权限 | PermissionCode + 数据权限 | ⚠️ 细粒度 Permission 拦截待实现 |
|
||
| 用户 ID | GUID 配置 + INT 审计 | ✅ 与 RBAC 一致 |
|
||
|
||
---
|
||
|
||
## 十二、交付说明
|
||
|
||
1. 本文档与 **`rbac系统设计-060801.md`**、**`oms系统设计-050801.md`** 配套使用,冲突时以**双登录主体分工**(导读)为准;
|
||
2. 建表 SQL 见 **`oms0414-back/sql/install_data_permission.sql`**、**`migrate_oms_data_permission_columns.sql`**;
|
||
3. 新业务模块在 §六 注册 `DataResourceCode` 后接入 `IDataScopeApplier`;
|
||
4. 客户门户 **禁止** 接入五维 Applier,继续用 `CustomerId` 隔离;
|
||
5. V1.0 中「所有业务表统一五字段」改为 **分期扩展 + 字段映射**,降低 OMS 全表改造风险。
|
||
|
||
---
|
||
|
||
## 十三、表结构详设
|
||
|
||
### 13.1 ER 关系
|
||
|
||
```mermaid
|
||
erDiagram
|
||
user ||--o{ user_org_perm : has
|
||
user ||--o{ user_data_scope : has
|
||
user ||--o{ user_biz_perm : has
|
||
user ||--o{ user_secret_perm : has
|
||
user ||--o{ user_filter_rule : has
|
||
role ||--o{ role_org_perm : has
|
||
role ||--o{ role_data_scope : has
|
||
role ||--o{ role_biz_perm : has
|
||
role ||--o{ role_secret_perm : has
|
||
role ||--o{ role_filter_rule : has
|
||
organization ||--o{ user_org_perm : scoped
|
||
data_perm_template ||--o{ data_perm_template_item : contains
|
||
data_resource ||--o{ data_perm_field_mask : masks
|
||
```
|
||
|
||
### 13.2 表清单
|
||
|
||
| 表名 | 库 | 说明 |
|
||
| ---- | -- | ---- |
|
||
| `user_org_perm` | RBAC | 用户组织权限 |
|
||
| `role_org_perm` | RBAC | 角色组织权限 |
|
||
| `user_data_scope` | RBAC | 用户数据范围(覆盖角色) |
|
||
| `role_data_scope` | RBAC | 角色数据范围 |
|
||
| `user_biz_perm` | RBAC | 用户业务标签 |
|
||
| `role_biz_perm` | RBAC | 角色业务标签 |
|
||
| `user_secret_perm` | RBAC | 用户密级 |
|
||
| `role_secret_perm` | RBAC | 角色密级 |
|
||
| `user_filter_rule` | RBAC | 用户自定义过滤 AST |
|
||
| `role_filter_rule` | RBAC | 角色自定义过滤 AST |
|
||
| `data_resource` | RBAC | 模块注册(Order/Customer…) |
|
||
| `data_perm_field_mask` | RBAC | 字段脱敏规则 |
|
||
| `data_perm_template` | RBAC | 权限模板头 |
|
||
| `data_perm_template_item` | RBAC | 模板明细 |
|
||
| `data_perm_change_log` | RBAC | 配置变更审计 |
|
||
| `data_perm_access_log` | RBAC | 访问审计(采样) |
|
||
| `t_customer.OrganizationId` | OMS | P1 扩展 |
|
||
| `t_order.OrganizationId/SecretLevel` | OMS | P1 扩展 |
|
||
|
||
### 13.3 有效权限合并规则(运行时唯一标准)
|
||
|
||
> **配置页**(`get-by-user`)展示库表原值;**运行时**(`get-effective` / 列表过滤)按下表合并。二者不可混用。
|
||
|
||
| 维度 | 角色侧 | 用户直配 | 合并算法 | 空配置默认 |
|
||
| ---- | ------ | -------- | -------- | ---------- |
|
||
| 组织 | 多角色 **UNION** | **UNION** 到角色结果 | 展开子树后 `OrganizationId IN (...)` | 无任一条时回退 `user.OrganizationId`(scope=2) |
|
||
| 数据范围 | 多角色取 **MAX** | **按资源覆盖**角色结果 | 见 §14.1 步骤 5 | 无配置 → **Personal(1)** |
|
||
| 业务标签 | 多角色 **UNION** | **UNION** | 同类型 `bizId` 并集;有过滤则 `OR` 命中 | **空=不限制** |
|
||
| 密级 | **UNION** | **UNION** | `SecretLevel IN (授权集合)` | 无配置 → **[1,2]**(公开+内部) |
|
||
| 自定义过滤 | 多规则 **AND** | **AND** | AST 逐条 AND | 无规则 → 恒真 |
|
||
|
||
**过期**:运行时排除 `EffectiveTime > NOW()` 或 `ExpireTime <= NOW()` 的行。
|
||
**Admin**:角色 `Code=Admin` → 跳过五维,但仍走功能 PermissionCode。
|
||
**客户**:`loginType=1` → 不算五维,走 `CustomerId`(与本文无关)。
|
||
|
||
### 13.4 枚举常量
|
||
|
||
**OrgScope**
|
||
|
||
| 值 | 名称 |
|
||
| -- | ---- |
|
||
| 1 | SelfOnly |
|
||
| 2 | SelfAndChildren |
|
||
|
||
**DataScope**
|
||
|
||
| 值 | 名称 | 说明 |
|
||
| -- | ---- | ---- |
|
||
| 1 | Personal | `CreateUserId=mapId` 或 `Salesman=Account` |
|
||
| 2 | Team | 同小组组织下用户 |
|
||
| 3 | Department | 同部门子树 |
|
||
| 4 | OrgTree | 授权组织子树 |
|
||
| 5 | Global | 不追加负责人条件 |
|
||
|
||
**BizType**
|
||
|
||
| 值 | OMS 映射 |
|
||
| -- | -------- |
|
||
| `product_line` | `t_sales_product` 分类 / ProductCode 前缀 |
|
||
| `kpi_area` | `t_kpi_area.Id` |
|
||
| `customer_group` | `t_customer.CustomerGroup` |
|
||
| `warehouse` | `t_warehouse_address.Id` / `t_order.WarehouseId` |
|
||
| `region` | 字典扩展 |
|
||
|
||
**SecretLevel**
|
||
|
||
| 值 | 名称 |
|
||
| -- | ---- |
|
||
| 1 | Public |
|
||
| 2 | Internal |
|
||
| 3 | Confidential |
|
||
| 4 | TopSecret |
|
||
|
||
**DataResourceCode**(见 `data_resource.Code`)
|
||
|
||
`Order` · `Customer` · `Recharge` · `ChannelProduct` · `Xhs`
|
||
|
||
**Filter AST 运算符**(白名单)
|
||
|
||
`eq` · `ne` · `in` · `notIn` · `gt` · `gte` · `lt` · `lte` · `between` · `like` · `isNull` · `isNotNull`
|
||
|
||
**Filter AST 示例**
|
||
|
||
```json
|
||
{
|
||
"logic": "and",
|
||
"conditions": [
|
||
{ "field": "CreateTime", "op": "between", "value": ["2026-01-01", "2026-12-31"] },
|
||
{ "field": "OrderStatus", "op": "in", "value": ["pendingPayment", "pendingShip"] },
|
||
{ "field": "DeclaredSum", "op": "gte", "value": 10000 }
|
||
]
|
||
}
|
||
```
|
||
|
||
**模板 ItemContent 按 DimensionType**
|
||
|
||
| DimensionType | JSON 结构 |
|
||
| ------------- | --------- |
|
||
| `org` | `{ "organizationId": "guid", "orgScope": 2 }` |
|
||
| `data_scope` | `{ "dataScope": 3, "dataResourceCode": "Order" }` |
|
||
| `biz` | `{ "bizType": "product_line", "bizId": "US_AIR", "bizName": "美线空运" }` |
|
||
| `secret` | `{ "secretLevels": [1,2,3], "dataResourceCode": null }` |
|
||
| `filter` | `{ "dataResourceCode": "Order", "filterContent": { ...AST } }` |
|
||
|
||
---
|
||
|
||
## 十四、接口与核心逻辑详设
|
||
|
||
> 路由 `/rbac/data-perm/*`;分页 `{ total, items }`;写操作单事务、软删旧行+插新行。
|
||
|
||
### 14.0 产品决策(已确认)
|
||
|
||
| # | 决策 | 结论 |
|
||
| - | ---- | ---- |
|
||
| 1 | 订单路由 | **不分离**;`/admin/order/*` 内按 `loginType` 分支 |
|
||
| 2 | 新员工默认 dataScope | **Personal(1)** |
|
||
| 3 | 改自己的数据权限 | **禁止**(403) |
|
||
| 4 | 模板批量套用 | **部分失败继续**,返回 `failures[]` |
|
||
| 5 | access-log 自动写入 | **P1 不做**;前端审计页已预留 |
|
||
|
||
### 14.0.1 前端页面(oms0414)
|
||
|
||
| 路由 | 组件 | 说明 |
|
||
| ---- | ---- | ---- |
|
||
| `/system/dataPerm/users` | `views/system/dataPerm/users/index.vue` | 用户列表 + 五维配置抽屉 |
|
||
| `/system/dataPerm/templates` | `views/system/dataPerm/templates/index.vue` | 模板 CRUD + 批量套用 |
|
||
| `/system/dataPerm/audit` | `views/system/dataPerm/audit/index.vue` | 变更日志 / 访问日志 Tab |
|
||
|
||
API 客户端:`src/api/rbac/data-perm.ts`(后端未就绪时会 404,页面已 catch)。
|
||
|
||
---
|
||
|
||
### 14.1 三个核心类(必须先实现)
|
||
|
||
| 类 | 职责 |
|
||
| -- | ---- |
|
||
| `EffectiveScopeBuilder` | 角色+用户+默认 → `DataScopeContext` |
|
||
| `DataScopeApplier` | Context → SqlSugar 条件(`/order/list` 等) |
|
||
| `FilterAstValidator` | 校验/编译 filterContent |
|
||
|
||
```csharp
|
||
record DataScopeContext {
|
||
bool IsAdmin;
|
||
Guid UserId; int MapId; string Account;
|
||
string DataResourceCode;
|
||
IReadOnlySet<Guid> OrganizationIds;
|
||
int DataScope; // 1~5
|
||
IReadOnlyList<int> ResolvedOwnerIds; // Team/Dept 预解析 mapId
|
||
IReadOnlyDictionary<string, string[]> BizFilters; // null=不限制
|
||
IReadOnlySet<int> SecretLevels;
|
||
IReadOnlyList<CompiledFilter> CustomFilters;
|
||
}
|
||
```
|
||
|
||
缓存:`data_perm:ctx:{userId}:{resourceCode}` TTL 30min;配置变更 DEL 该 user 全部 ctx。
|
||
|
||
---
|
||
|
||
### 14.2 运行时合并规则
|
||
|
||
| 维度 | 算法 |
|
||
| ---- | ---- |
|
||
| 组织 | `role_org_perm` ∪ `user_org_perm` → OrgScope 展开子树 → `IN`;全无 → `user.OrganizationId`(scope=2) |
|
||
| 数据范围 | 用户专码 > 用户全局 > 角色专码 MAX > 角色全局 MAX;全无 → **Personal(1)** |
|
||
| 业务 | 并集;**空=不限制** |
|
||
| 密级 | 并集;空 → **[1,2]** |
|
||
| 自定义 | 全部 **AND** |
|
||
| 过期 | 运行时排除;`get-by-user` 编辑页仍展示过期行并标 `isExpired` |
|
||
|
||
**`get-by-user`** 仅 user_* 直配;**`get-effective-by-user`** 走 Builder 合并结果。
|
||
|
||
---
|
||
|
||
### 14.3 `EffectiveScopeBuilder.BuildAsync`
|
||
|
||
入参:`userId`, `dataResourceCode`(如 `Order`)
|
||
|
||
1. 查 user,不存在 → 404
|
||
2. 角色含 `Admin` → `{ IsAdmin=true }`
|
||
3. 组织:role∪user 行 → FilterEffective → 展开子树 → `OrganizationIds`
|
||
4. 数据范围:用户专码/全局优先,否则角色 MAX,否则 1
|
||
5. 业务:role∪user → 分组;空 → null
|
||
6. 密级:并集;空 → [1,2]
|
||
7. 过滤:role∪user 同 resource → Compile → AND
|
||
8. dataScope∈{2,3} 时预解析 `ResolvedOwnerIds`;无 `user.OrganizationId` → 业务异常
|
||
|
||
---
|
||
|
||
### 14.4 `DataScopeApplier`(`/admin/order/*` 同路由)
|
||
|
||
在 `OrderService` 列表/详情/导出等读路径入口:
|
||
|
||
1. `loginType=1` → 仅 `CustomerId`(现有 `OmsSessionHelper`)
|
||
2. `loginType=0` + Admin → 不加五维
|
||
3. `loginType=0` + 非 Admin → `BuildAsync(currentUser, "Order")` 后:
|
||
- `OrganizationId IN ctx.OrganizationIds`
|
||
- `SecretLevel IN ctx.SecretLevels`
|
||
- BizFilters 按注册表翻译
|
||
- dataScope:Personal → `CreateUserId=mapId OR Salesman=Account`;Team/Dept → `CreateUserId IN ResolvedOwnerIds`;OrgTree/Global → 不加 Owner
|
||
- CustomFilters AND
|
||
4. DTO 映射阶段 `FieldMaskingService` 脱敏
|
||
5. **P1 不写 access-log**
|
||
|
||
---
|
||
|
||
### 14.5 HTTP 共性
|
||
|
||
- 鉴权:Bearer + PermissionCode
|
||
- 可配置主体:内部用户;纯 Customer/CustomerSub → save 拒绝
|
||
- **`save-user`:`targetUserId == 操作者 userId` → 403「不能修改自己的数据权限」**
|
||
- 双库:RBAC EF + OMS SqlSugar(`biz-options` 读 OMS)
|
||
|
||
---
|
||
|
||
### 14.6 接口逐步逻辑
|
||
|
||
#### `GET /meta` — `Rbac.DataPerm.Query`
|
||
|
||
代码常量枚举 + `data_resource` 表 + 每 resource 的 `filterableFields` 字典;不读当前用户权限。
|
||
|
||
#### `GET /biz-options` — Query
|
||
|
||
`bizType` 必填。分支:`product_line`→`t_sales_product`;`kpi_area`→`t_kpi_area`;`customer_group`→0~5 常量;`warehouse`→`t_warehouse_address`。keyword 模糊分页。
|
||
|
||
#### `GET /get-by-user` — Query `userId`
|
||
|
||
查 user + 五张 `user_*`(IsDeleted=0,含过期);纯客户 → 400;JOIN 组织名;**不调 Builder**。
|
||
|
||
#### `GET /get-effective-by-user` — Query `userId`, `dataResourceCode`
|
||
|
||
`BuildAsync` → 组织名 → `summaryText`;Admin 短路。
|
||
|
||
#### `PUT /save-user` — Query `userId`
|
||
|
||
校验(组织启用、枚举、去重、AST、**禁止 self-edit**)→ 事务:软删旧 user_* → 插新 → change_log → 失效缓存 → 返回 get-by-user。
|
||
|
||
#### `GET/PUT get-by-role / save-role`
|
||
|
||
对称读写 `role_*`;save-role 后失效该角色所有 user 的 ctx 缓存。
|
||
|
||
#### 模板 `list/get/create/update/delete`
|
||
|
||
create/update 校验 item JSON Schema;内置模板不可删、不可改 code。
|
||
|
||
#### `POST /template/apply`
|
||
|
||
加载模板 → `PermBundle`;foreach targetId:失败则 **failures+=reason, continue**(部分失败继续);replace/merge 规则:org/biz/secret Union,scope Max,filter 追加 AND;调内部 save;返回 `{ successCount, failures[] }`。
|
||
|
||
#### `field-mask/list|save`
|
||
|
||
按 resource 全量覆盖脱敏规则。
|
||
|
||
#### `change-log/list`
|
||
|
||
配置变更只读分页(**P1 必做**)。
|
||
|
||
#### `access-log/list`
|
||
|
||
只读分页;**P1 无自动写入**,表结构预留。
|
||
|
||
#### `POST /invalidate-cache`
|
||
|
||
运维 DEL Redis ctx。
|
||
|
||
#### `get-current-user` 扩展
|
||
|
||
`loginType=1` → null;Admin → summary;否则 Builder 仅取 summaryText + secretLevels。
|
||
|
||
---
|
||
|
||
### 14.7 路径速查
|
||
|
||
| 方法 | 路径 | PermissionCode |
|
||
| ---- | ---- | -------------- |
|
||
| GET | `/rbac/data-perm/meta` | Rbac.DataPerm.Query |
|
||
| GET | `/rbac/data-perm/biz-options` | Rbac.DataPerm.Query |
|
||
| GET | `/rbac/data-perm/get-by-user` | Rbac.DataPerm.Query |
|
||
| GET | `/rbac/data-perm/get-effective-by-user` | Rbac.DataPerm.Query |
|
||
| PUT | `/rbac/data-perm/save-user` | Rbac.DataPerm.Update |
|
||
| GET | `/rbac/data-perm/get-by-role` | Rbac.DataPerm.Query |
|
||
| PUT | `/rbac/data-perm/save-role` | Rbac.DataPerm.Update |
|
||
| GET | `/rbac/data-perm/template/list` | Rbac.DataPerm.Template |
|
||
| GET | `/rbac/data-perm/template/get` | Rbac.DataPerm.Template |
|
||
| POST | `/rbac/data-perm/template/create` | Rbac.DataPerm.Template |
|
||
| PUT | `/rbac/data-perm/template/update` | Rbac.DataPerm.Template |
|
||
| DELETE | `/rbac/data-perm/template/delete` | Rbac.DataPerm.Template |
|
||
| POST | `/rbac/data-perm/template/apply` | Rbac.DataPerm.Update |
|
||
| GET | `/rbac/data-perm/field-mask/list` | Rbac.DataPerm.Query |
|
||
| PUT | `/rbac/data-perm/field-mask/save` | Rbac.DataPerm.Update |
|
||
| GET | `/rbac/data-perm/change-log/list` | Rbac.DataPerm.Audit |
|
||
| GET | `/rbac/data-perm/access-log/list` | Rbac.DataPerm.Audit |
|
||
| POST | `/rbac/data-perm/invalidate-cache` | Rbac.DataPerm.Update |
|
||
|
||
### 14.8 权限码
|
||
|
||
`Rbac.DataPerm` · `.Query` · `.Update` · `.Template` · `.Audit`
|
||
|
||
### 14.9 错误码补充
|
||
|
||
| 场景 | 消息 |
|
||
| ---- | ---- |
|
||
| 修改自己的数据权限 | 不能修改自己的数据权限 |
|
||
| 纯客户账号 save | 客户账号不支持数据权限配置 |
|
||
| template apply 单条失败 | 记入 failures[].reason,不中断批次 |
|
||
|
||
### 14.10 实施顺序
|
||
|
||
1. EffectiveScopeBuilder + 单测
|
||
2. meta / get-by-user / get-effective
|
||
3. save-user / save-role + change-log
|
||
4. Applier 接入 `/order/list`(同路由 loginType 分支)
|
||
5. template / biz-options
|
||
6. field-mask;(access-log 写入 Phase 2)
|
||
|
||
### 14.11 JSON 契约摘要
|
||
|
||
**UserDataPermDto**:userId、orgPerms[]、dataScopes[]、bizPerms[]、secretPerms[]、filterRules[](含 isExpired)。
|
||
|
||
**SaveUserDataPermInput**:同上五数组,全量覆盖;缺省数组=清空该维。
|
||
|
||
**EffectiveDataScopeDto**:isAdmin、organizationIds[]、dataScope、secretLevels[]、bizFilters[]、summaryText。
|
||
|
||
**template/apply 响应**:`{ successCount, failures: [{ targetId, reason }] }`。
|
||
|
||
---
|
||
|
||
## 十五、SQL 执行顺序
|
||
|
||
```bash
|
||
# 1. RBAC 数据权限表 + 种子
|
||
mysql ... < sql/install_data_permission.sql
|
||
|
||
# 2. OMS 业务表扩展列
|
||
mysql ... < sql/migrate_oms_data_permission_columns.sql
|
||
|
||
# 3. 菜单与 Admin 权限码
|
||
mysql ... < sql/seed_data_perm_rbac_menu.sql
|
||
```
|
||
|
||
> `PermissionDefinitionProvider` 中注册 §14.9 权限码后,需重新分配角色或执行 seed 脚本。
|