7.8 KiB
线索域数据隔离在既有数据范围机制上的落地
Type: grilling Status: blocked Blocked by: 产品确认(权限与数据可见性-PRD.md)
Question
三类角色(销售/部门负责人/超管)对线索、公海池的可见范围与操作权差异极大,全域横切。需定清如何用既有机制(DataScopeEnum + DataScopeInterceptor + SysRoleDataScope + ADR-0018 按模块可配)表达,而非新建机制。
需在本 ticket 定清:
- 线索模块暴露的权限点(
clue:*)清单:公海查看/领取/关注、我的线索 CRUD、线索管理(分配/合并/删除/导入导出)、线索设置(公海池 CRUD/导入导出)分别对应哪些权限点。参考 crm-dict 的dict:*做法。 - 数据范围维度:线索的数据范围按什么过滤?
- 销售:SELF(仅本人领取的线索)+ 可见本部门/本团队公海线索;
- 部门负责人:DEPT / DEPT_AND_CHILD(本部门全部公海+私海);
- 超管:ALL。
- 这四档能否直接套
DataScopeEnum?公海线索"按公海池归属部门过滤" vs 私海线索"按领取人所属部门过滤",是不是两条不同的数据范围规则?
- 公海池(crm-rule 侧)的数据范围:部门负责人只见本部门池、超管全见——同样套
DataScopeEnum还是另有规则。 - ADR-0018 的"按模块可配"如何应用于 crm-lead / crm-rule:这两个模块是否各自注册为一个可配数据范围模块。
产出:权限点清单 + 数据范围规则表(角色 × 视图 × 过滤维度),写入 ## Answer。为四视图列表 ticket 和公海池实体 ticket 提供隔离规则。
已 grill 定稿的核心模型(数据隔离两层叠加)
最终 WHERE = 第一层业务过滤 AND 第二层数据范围,分工如下:
第一层 —— 业务过滤(service 显式 SQL,定"哪个视图")
- "我的线索" =
owner_id = 当前用户 AND status IN (…) - "我的关注" =
id IN (当前用户关注表) - "线索公海" =
status = 待领取 AND 公海池 ∈ 当前用户够得着的池 - "线索管理" = 治理视图,业务条件按筛选项
- "仅本人"的收窄完全靠第一层
owner_id = 我,不依赖第二层。
第二层 —— 数据范围(DataScopeInterceptor 自动 AND,按角色档位)
- lead 表只挂一个
@DataScope(module = "lead", deptColumn = "dept_id"),只按dept_id做部门档兜底,不使用 owner 列(owner 过滤下放到第一层)。 - 档位折算(既有机制):销售 → DEPT(本部门,默认;可由管理员按 ADR-0008 调宽,需用户复核是否要放到全平台);部门负责人 → DEPT_AND_CHILD(本部门及下属);超管 → ALL。
dept_id存"公海池的归属部门":待领取线索也有 dept_id(=其所属公海池的归属部门),第二层dept_id IN 本部门集才能正确圈出"本部门的公海线索";已领取线索的 dept_id 仍取所属池归属部门(不随领取人主部门变动——见下 Open question [I])。
这样为什么不冲突
三视图查同一张 lead 表,第二层注入的都是同一角色档位的 dept_id IN(...)(或 ALL 不注入),不打架;"我的 vs 公海"的区分完全由第一层业务条件承担。撞不到"一表两列"的机制上限。
已 grill 定稿(I / K 收口)
- [I] 线索
dept_id恒定、永不变动(选 I-1)。依据:销售只能领取他所属部门公海池里的线索,故领取人与池必同部门。领取前 dept_id=池归属部门,领取后即使不改也恰等于领取人部门——两种做法结果一致,取简单:dept_id恒等于所属公海池归属部门,全生命周期不改。 - [K] 公海池表也做数据范围隔离,且复用
lead模块(选 K-1 + K-1a)。部门负责人只能管本部门池、超管管全部;crm-rule 侧池表挂@DataScope(module="lead", deptColumn="...池归属部门列"),与线索共用同一档数据范围配置(池归属部门 = 线索 dept_id,业务上同源,无需分开配)。
Open questions(已全部收口)
- [J] 接口/按钮点位候选清单 — 已以“可被管控点位候选清单”形式产出(见下方 J 段)。
已 grill 定稿:权限模型(两套正交机制)
线索域的访问控制 = 两套彼此正交、机制不同的东西,spec 必须分开写:
机制一:功能权限 = present-then-enforce(运行期配置驱动,非硬编码)
- 由权限点管理录入才控制;未录入即放行(不是代码里预定义固定清单)。
- 每个权限点录两样:权限编码(= 前端按钮编码,控按钮显隐)+ API URL(= 后端接口权限,控接口调用)。
- 因此 05 不产出硬编码权限编码表,而产出 crm-lead / crm-rule 对外暴露的"可被管控点位"候选:接口 URL 清单 + 关键前端按钮点位,供管理员按需录入权限点管理。想控哪个录哪个。
机制二:数据范围 = 代码强制、始终生效(与权限点配不配无关)
@DataScope(module="lead")+DataScopeInterceptor注入,always-on。- 档位:销售 DEPT(本部门)、部门负责人 DEPT_AND_CHILD、超管 ALL;公海池表复用
lead模块(K-1a)。 - 不受"该操作有没有配功能权限点"影响——即使某按钮没被纳管,数据范围过滤照样生效。
两者关系:功能权限管"这个按钮/接口能不能用(配了才管)";数据范围管"能作用到哪些行(代码恒管)"。二者 AND 叠加,互不替代。
J:可被管控点位候选清单(供权限点管理录入,非硬编码)
按原型三角色 × 操作矩阵整理的候选点位(管理员择需录入;此处仅为"有哪些点位可纳管"的备选表,不是运行期一定生效的清单):
crm-lead 接口/按钮候选:公海查看·领取·关注、我的线索 查看·新增·编辑·导入·导出、反馈(含暂存/文件)、转商机、释放、关注/取关、线索管理页访问、分配/批量分配、线索合并、单条/批量删除、管理侧导入·导出、回收任意私海线索、激活失效线索(状态机 F2)。
crm-rule 接口/按钮候选(公海池配置):线索设置-公海池 查看·新增·编辑·删除·导入导出。
原型里"部门负责人只管本部门/超管管全部"这类部门收窄由机制二(数据范围)自动完成,不靠功能权限点表达。编码格式(前端按钮编码 + API URL)在权限点管理录入时给定,spec 不预置固定编码串。
【挂起】可见性模型升级为三机制 — 等产品确认
原"两层 AND"模型无法表达"拉人进团队成员/设协作人即越过部门天花板"。已升级为三机制,产出对齐稿 权限与数据可见性-PRD.md:
- 功能权限(present-then-enforce)
- 数据可见范围(按模块四档天花板,多角色取最宽)—既有
- 行级授权(通行证,越过天花板)—新增跨模块通用能力
组合: 能否看到某数据 = 页面业务条件 AND (落在数据可见范围 OR 已被行级授权)
行级授权=crm-auth/crm-base机制增强(超线索边界,需独立ticket): 通用表 sys_row_grant + 拦截器 OR/EXISTS 注入 + @DataScope声明授权来源翻译。建模难点(粒度不一致): 商机=按单条授权; 线索池负责人/协作人=按池(动态集合)授权。resource_type记"授权对象类型"(可≠被查数据类型),查询时翻译授权对象→可见数据(直接/间接)。
待产品确认(挂起)
- [PRD-1]行级授权触发动作清单是否完整
- [PRD-2]被授权者权限边界(只读/可操作,是否分级)
- [PRD-3]移除授权即时失效确认
- [D]线索是否存在跨部门逐条指派(决定要不要resource_type=lead直接授权通道)
- [E]池负责人/协作人授权范围(仅池内线索/兼池配置可管)