Files
leaudit-platform-backend/docs/权限与地区隔离/租户与角色权限关系真实案例说明.md
T

5.4 KiB
Raw Blame History

租户与角色权限关系真实案例说明

适用范围:leaudit-platform 当前 角色权限 + 租户配置 + 数据范围 模型
更新日期:2026-05-20
文档定位:不用抽象术语,直接用真实业务例子说明“租户”和“角色权限配置”到底是什么关系。


1. 先记一句最核心的话

这套系统里有三层控制:

  1. 角色权限
    • 管“这个人能不能做这件事”
  2. 租户配置
    • 管“这件事能不能落到这个租户上”
  3. 数据范围
    • 管“这个人最终能看到哪些租户的数据”

它们是三层,不是一层。


2. 例子 1:入口模块

假设现在有两个租户:

  • MZ = 梅州
  • PUBLIC = 公共资源域

再假设有一个用户 张三

  • 人属于 MZ
  • 角色有:
    • entry_module:create
    • entry_module:update

这时候只能说明一件事:

  • 张三“有权新建和编辑入口模块”

但这还不能直接推出:

  • 张三可以把入口模块挂到任何租户上

还要再看租户配置。

如果租户配置是:

  • MZ.feature_keys 包含 home.entry_module
  • MZ.can_host_entry_module = true
  • PUBLIC.feature_keys 包含 home.entry_module
  • PUBLIC.can_host_entry_module = false

那么结果就是:

  1. 张三可以进入入口模块管理页
  2. 张三可以新建入口模块
  3. 张三可以把模块挂到 MZ
  4. 张三不能把模块挂到 PUBLIC

为什么?

  • 因为权限页只给了他“操作资格”
  • PUBLIC 没开放“可承载入口模块”

所以这里的判断链路是:

  1. 先看角色权限:能不能新建
  2. 再看租户承载能力:这个租户能不能被选
  3. 最后才允许落库

3. 例子 2:文档上传

假设用户 李四

  • 属于 HZ
  • 角色里有 documents:upload:create

这说明:

  • 李四“可以上传文档”

但如果 HZ 这个租户配置是:

  • feature_keys 没有 documents.upload
  • 或者 can_host_documents = false

那么正确行为应该是:

  1. 李四即使有上传权限
  2. HZ 这个租户也不应该作为文档归属租户被使用
  3. 页面可能不显示上传入口,或者后端直接拒绝

也就是说:

  • 有权限 不等于 这个租户允许承载这类业务

4. 例子 3:知识库

假设用户 王五

  • 属于 MZ
  • 角色里有 rag:dataset:manage

这说明:

  • 王五可以管理知识库

但是否能给 SZ 租户建知识库,还要看:

  • SZ.feature_keys 是否开启了 rag.dataset
  • SZ.can_host_rag 是否为 true

如果:

  • SZ 没开 rag.dataset

那就算王五权限再高,也不应该把知识库业务落到 SZ

这里要理解:

  • rag:dataset:manage 是“人有能力操作”
  • feature_keys / can_host_rag 是“租户有没有资格承载这个业务”

5. 例子 4:公共资源域 PUBLIC

这个最容易混。

假设 PUBLIC 用来放:

  • 公共模板
  • 公共规则
  • 公共知识库底座
  • 公共入口模块

PUBLIC 的意义是:

  • 这是一个“共享资源归属地”
  • 不是谁都能随便改的地方

比如用户 赵六

  • 属于 MZ
  • 角色只有 document:read

那他可能可以看到 PUBLIC 下的一些共享资源,
但如果没有 document:update 或更高权限:

  • 他也不能改 PUBLIC 的资源

所以:

  • PUBLIC 决定资源归属偏共享
  • 角色权限 决定你能不能动这份共享资源

6. 例子 5:为什么角色权限页和租户页看起来都在管“入口模块/文档/知识库”

因为它们问的不是同一个问题。

角色权限页在问:

  • 这个用户能不能进入这个模块?
  • 能不能新增、编辑、删除?

租户页在问:

  • 这个租户开不开这个业务?
  • 这个租户能不能承载这类数据?

可以把它理解成:

  • 角色权限 = 驾照
  • 租户能力 = 哪些路允许走
  • 数据范围 = 你今天实际能开到哪些区域

只有驾照,没有开通道路,不行。
只有道路开放,没有驾照,也不行。


7. 一个完整串联例子

假设你要“给梅州上线一个新的首页入口模块”。

要同时满足下面 6 件事:

  1. 当前操作人有权限
    • 例如有 entry_module:create
  2. MZ 租户开放了入口模块业务
    • feature_keys 包含 home.entry_module
  3. MZ 允许承载入口模块
    • can_host_entry_module = true
  4. 当前人数据范围允许操作这个租户
    • 不是只能管自己部门,却跑去配别的租户
  5. 首页用户属于 MZ
    • 登录后解析出 tenant_code = MZ
  6. 首页读取时,模块租户关系里包含 MZ

最后结果才是:

  • 后台能配置
  • 前台能看到
  • 数据不会挂错租户

8. 一句话收口

比如“入口模块”这个词,在系统里其实对应 3 个不同问题:

  1. 角色权限
    • 你能不能配入口模块
  2. 租户配置
    • 这个租户开不开入口模块
    • 这个租户能不能承载入口模块
  3. 数据范围
    • 你能不能看到或操作这个租户下的入口模块

这三件事少一件都不成立。


9. 最终理解公式

后续看所有业务模块,都可以套下面这条公式:

最终是否允许 = 角色权限通过

并且

目标租户开放该业务

并且

目标租户允许承载该类数据

并且

当前用户数据范围允许访问该租户/该资源

只要按这个公式看,就不会再把“角色权限”和“租户配置”混成一件事。