You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

7.8 KiB

线索域数据隔离在既有数据范围机制上的落地

Type: grilling Status: blocked Blocked by: 产品确认(权限与数据可见性-PRD.md)

Question

三类角色(销售/部门负责人/超管)对线索、公海池的可见范围与操作权差异极大,全域横切。需定清如何用既有机制(DataScopeEnum + DataScopeInterceptor + SysRoleDataScope + ADR-0018 按模块可配)表达,而非新建机制。

需在本 ticket 定清:

  1. 线索模块暴露的权限点clue:*)清单:公海查看/领取/关注、我的线索 CRUD、线索管理(分配/合并/删除/导入导出)、线索设置(公海池 CRUD/导入导出)分别对应哪些权限点。参考 crm-dict 的 dict:* 做法。
  2. 数据范围维度:线索的数据范围按什么过滤?
    • 销售:SELF(仅本人领取的线索)+ 可见本部门/本团队公海线索;
    • 部门负责人:DEPT / DEPT_AND_CHILD(本部门全部公海+私海);
    • 超管:ALL。
    • 这四档能否直接套 DataScopeEnum?公海线索"按公海池归属部门过滤" vs 私海线索"按领取人所属部门过滤",是不是两条不同的数据范围规则?
  3. 公海池(crm-rule 侧)的数据范围:部门负责人只见本部门池、超管全见——同样套 DataScopeEnum 还是另有规则。
  4. 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

  1. 功能权限(present-then-enforce)
  2. 数据可见范围(按模块四档天花板,多角色取最宽)—既有
  3. 行级授权(通行证,越过天花板)—新增跨模块通用能力

组合: 能否看到某数据 = 页面业务条件 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]池负责人/协作人授权范围(仅池内线索/兼池配置可管)