# 租户与角色权限关系真实案例说明 > 适用范围:`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. 最终理解公式 后续看所有业务模块,都可以套下面这条公式: `最终是否允许 = 角色权限通过` 并且 `目标租户开放该业务` 并且 `目标租户允许承载该类数据` 并且 `当前用户数据范围允许访问该租户/该资源` 只要按这个公式看,就不会再把“角色权限”和“租户配置”混成一件事。