255 lines
11 KiB
Markdown
255 lines
11 KiB
Markdown
# 角色去硬编码迁移清单
|
|
|
|
> 适用范围:当前项目中所有直接依赖 `super_admin/provincial_admin/admin/common/developer` 的权限判断
|
|
> 文档定位:从“问题分析”进入“逐文件迁移清单”,指导研发按优先级拆改。
|
|
|
|
---
|
|
|
|
## 1. 迁移目标
|
|
|
|
本清单的目标不是把所有“角色”这个概念删掉,而是把“用角色名直接判断能力”的写法替换成下面三类正规来源:
|
|
|
|
1. `permission_key`
|
|
2. `effective_scope`
|
|
3. `module policy / capability snapshot`
|
|
|
|
保留角色本身作为“授权载体”,但不再让角色名直接主导业务逻辑。
|
|
|
|
---
|
|
|
|
## 2. 问题类型定义
|
|
|
|
为方便排期,先统一问题类型。
|
|
|
|
| 类型 | 含义 |
|
|
| --- | --- |
|
|
| `CTX` | 服务层上下文派生硬编码 |
|
|
| `ACT` | 服务层动作放行硬编码 |
|
|
| `UI` | 前端按钮/编辑态硬编码 |
|
|
| `GUARD` | 前端路由、guard、fallback、role mapping 硬编码 |
|
|
| `COMPAT` | 兼容层短期保留但必须收缩的旧逻辑 |
|
|
|
|
---
|
|
|
|
## 3. 后端迁移清单
|
|
|
|
## 3.1 P0:必须最先处理
|
|
|
|
| 文件 | 当前写法 | 问题类型 | 替换目标 | 优先级 | 风险 | 影响范围 |
|
|
| --- | --- | --- | --- | --- | --- | --- |
|
|
| `fastapi_modules/fastapi_leaudit/services/impl/ragDatasetServiceImpl.py` | 多处 `UserRole in ('provincial_admin','admin','super_admin')` | `ACT` | 改为 `rag:* permission + RagPolicy + effective_scope` | `P0` | 高 | RAG 管理接口、数据集文档接口 |
|
|
| `fastapi_modules/fastapi_leaudit/services/impl/ragChatServiceImpl.py` | `user_role == 'provincial_admin'`、`_app_visible` 角色分支 | `ACT` | 改为 `PUBLIC_MIXED` 策略 | `P0` | 高 | 应用列表、默认应用、聊天入口 |
|
|
| `fastapi_modules/fastapi_leaudit/controllers/ragChatController.py` | 把 `UserRole` 透传给 service | `ACT` | 改为透传 `ScopeContext/CapabilitySnapshot` | `P0` | 中 | 所有 RAG 接口联动 |
|
|
|
|
## 3.2 P1:统一上下文能力层
|
|
|
|
| 文件 | 当前写法 | 问题类型 | 替换目标 | 优先级 | 风险 | 影响范围 |
|
|
| --- | --- | --- | --- | --- | --- | --- |
|
|
| `fastapi_modules/fastapi_leaudit/services/impl/documentServiceImpl.py` | `_getCurrentUserContext()` 中按 `role_key IN (...)` 生成 `is_global/can_manage/is_super_admin` | `CTX` | 改为 `PermissionDecisionService` | `P1` | 高 | 文档列表、详情、附件、确认、删除 |
|
|
| `fastapi_modules/fastapi_leaudit/services/impl/govdocServiceImpl.py` | 通过 `is_global/can_manage` 控制 `region/created_by` | `CTX` | 改为 `GovdocPolicy` | `P1` | 高 | 公文详情、run、报告、下载 |
|
|
| `fastapi_modules/fastapi_leaudit/services/impl/usageStatsServiceImpl.py` | `_getCurrentUserContext` 中 `role_key IN (...)` 派生范围 | `CTX` | 改为 `UsageStatsPolicy` | `P1` | 中高 | 概览、趋势、明细 |
|
|
| `fastapi_modules/fastapi_leaudit/services/impl/contractTemplateServiceImpl.py` | `is_global/can_manage/is_area_admin` 依赖角色名 | `CTX` | 改为 `ContractTemplatePolicy` | `P1` | 中 | 模板列表、搜索、创建、删除 |
|
|
| `fastapi_modules/fastapi_leaudit/services/impl/rbacAdminServiceImpl.py` | `bool_or(r.role_key IN (...))` 派生管理能力 | `CTX` | 改为 `RbacAdminPolicy + rbac permission` | `P1` | 高 | 用户列表、组织树、角色分配 |
|
|
| `fastapi_modules/fastapi_leaudit/services/impl/homeServiceImpl.py` | `role_key = 'super_admin' => bypass_area` | `CTX` | 改为首页能力快照 | `P1` | 中 | 首页入口可见性 |
|
|
|
|
## 3.3 P2:默认角色与兼容角色清理
|
|
|
|
| 文件 | 当前写法 | 问题类型 | 替换目标 | 优先级 | 风险 | 影响范围 |
|
|
| --- | --- | --- | --- | --- | --- | --- |
|
|
| `fastapi_modules/fastapi_leaudit/services/impl/authServiceImpl.py` | 用户无角色时自动补 `common`;回退主角色 `common` | `COMPAT` | 保留默认角色机制,但从业务能力判断中剥离“common 特权假设” | `P2` | 中 | 登录、初始化用户 |
|
|
| `fastapi_modules/fastapi_leaudit/services/impl/rbacServiceImpl.py` | `roleBucket = "admin" if any(role in {...}) else "common"` | `COMPAT` | 仅短期保留在菜单兼容层,逐步删除角色桶映射 | `P2` | 高 | 路由树、菜单 fallback |
|
|
| `fastapi_modules/fastapi_leaudit/services/impl/rbacServiceImpl.py` | 静态蓝图 `_COMPAT_ROUTE_BLUEPRINTS` 以 `admin/common` 分桶 | `COMPAT` | 改为数据库路由兜底,不认角色桶 | `P2` | 中高 | 前端菜单 |
|
|
|
|
---
|
|
|
|
## 4. 前端迁移清单
|
|
|
|
## 4.1 P0:直接影响权限感知
|
|
|
|
| 文件 | 当前写法 | 问题类型 | 替换目标 | 优先级 | 风险 | 影响范围 |
|
|
| --- | --- | --- | --- | --- | --- | --- |
|
|
| `legal-platform-frontend/components/dify-dataset-manager/index.tsx` | `provincial_admin/super_admin/admin` 决定 `canEditDataset` | `UI` | 改为读 `rag` 能力或 permission_map | `P0` | 高 | RAG 编辑按钮、详情编辑态 |
|
|
| `legal-platform-frontend/hooks/use-area-dataset-config.ts` | `roleCanManageDataset = provincial_admin/super_admin/admin` | `UI` | 改为纯 permission 决策 | `P0` | 高 | 知识库配置页全部操作 |
|
|
| `legal-platform-frontend/components/dify-dataset-manager/area-dataset-config.tsx` | `isProvincialAdmin`、非省级自动填地区 | `UI` | 改为根据 `effective_scope` 与 `allowed_areas` 决定 | `P0` | 中高 | 地区选择器、创建编辑表单 |
|
|
|
|
## 4.2 P1:菜单与路由层
|
|
|
|
| 文件 | 当前写法 | 问题类型 | 替换目标 | 优先级 | 风险 | 影响范围 |
|
|
| --- | --- | --- | --- | --- | --- | --- |
|
|
| `legal-platform-frontend/lib/auth/user-routes.ts` | 静态 `FALLBACK_MENU_DATA.admin/common` | `GUARD` | 收敛为数据库路由兜底,不做角色桶映射 | `P1` | 高 | 主菜单 |
|
|
| `legal-platform-frontend/lib/api/legacy/auth/user-routes.ts` | `mapUserRoleToRoleKey()` 中 `provincial_admin -> admin`、`developer -> admin` | `GUARD` | 删除角色映射,直接使用后端返回路由与权限 | `P1` | 高 | 菜单缓存、路由授权 |
|
|
| `legal-platform-frontend/components/layout/Sidebar.tsx` | 按 `userRole` 拉路由、写 `localStorage.user_role` | `GUARD` | 改为按登录态和后端返回能力渲染 | `P1` | 中高 | 侧边栏菜单、权限 map |
|
|
| `legal-platform-frontend/lib/auth/cross-checking-access.ts` | `provincial_admin` 自动补 `省局` area 候选 | `GUARD` | 改为服务端返回 `allowed_areas` | `P1` | 中 | 交叉评查入口展示 |
|
|
| `legal-platform-frontend/lib/auth/guard.ts` | `developer/provincial_admin` 白名单进入设置页 | `GUARD` | 改为检查后台管理权限 | `P1` | 高 | 设置页访问 |
|
|
|
|
## 4.3 P2:页面级残留
|
|
|
|
| 文件 | 当前写法 | 问题类型 | 替换目标 | 优先级 | 风险 | 影响范围 |
|
|
| --- | --- | --- | --- | --- | --- | --- |
|
|
| `legal-platform-frontend/app/(audit)/contract-template/list/ContractTemplateListClient.tsx` | `currentUser.role === "admin"` 才能上传 | `UI` | 改为 `contract_template:create:write` | `P2` | 中高 | 合同模板上传入口 |
|
|
| `legal-platform-frontend/app/(audit)/role-permissions/RolePermissionsClient.tsx` | `provincial_admin` 禁删、`coreRoles = ['provincial_admin','admin','common']`、`setIsCityAdmin(userRole==='admin')` | `UI/COMPAT` | 保留系统角色保护逻辑,但与角色名硬编码解耦 | `P2` | 中高 | 角色权限管理页 |
|
|
| `legal-platform-frontend/hooks/usePermission.tsx` | 默认 `userRole = common`,大量消费 `localStorage.user_role` | `COMPAT` | 保留兼容字段,但新增能力快照来源,逐步弱化角色中心地位 | `P2` | 中 | 多页面基础权限钩子 |
|
|
| `legal-platform-frontend/components/layout/Layout.tsx` | 默认 `userRole = developer`,回退读取本地角色 | `COMPAT` | 改为显式会话能力初始化 | `P2` | 中 | 全局布局 |
|
|
|
|
---
|
|
|
|
## 5. 接口影响面清单
|
|
|
|
角色去硬编码不会只影响代码写法,还会影响接口行为。
|
|
|
|
## 5.1 后端接口影响
|
|
|
|
| 模块 | 受影响接口 |
|
|
| --- | --- |
|
|
| RAG | `/v3/rag/apps`、`/v3/rag/apps/default`、`/v3/rag/datasets/admin*`、`/v3/rag/datasets/{id}*` |
|
|
| 文档 | `/documents/list`、`/documents/{id}`、`/documents/status`、`/v3/review-points/*` |
|
|
| 公文 | `/govdoc/documents*`、`/govdoc/runs/*`、`/govdoc/documents/{id}/original` |
|
|
| 统计 | `/v3/usage-stats/*` |
|
|
| RBAC | `/v3/rbac/users*`、`/v3/rbac/roles/{id}/users`、`/v3/rbac/users/{id}/roles*` |
|
|
| 合同模板 | `/v3/contract-templates*` |
|
|
| 首页 | 首页入口模块加载逻辑 |
|
|
|
|
## 5.2 前端受影响页面
|
|
|
|
| 页面/模块 | 受影响点 |
|
|
| --- | --- |
|
|
| 侧边栏菜单 | 路由来源、权限 map 来源 |
|
|
| 知识库管理页 | 可编辑、可创建、地区选择范围 |
|
|
| 合同模板页 | 上传按钮、删除按钮 |
|
|
| 设置页 | 进入 guard |
|
|
| 交叉评查入口 | 是否显示入口模块 |
|
|
| 角色权限管理页 | 系统角色保护、核心角色展示逻辑 |
|
|
|
|
---
|
|
|
|
## 6. 推荐替换模式
|
|
|
|
## 6.1 后端替换模式
|
|
|
|
不推荐:
|
|
|
|
```python
|
|
if user_role in ("provincial_admin", "admin", "super_admin"):
|
|
...
|
|
```
|
|
|
|
推荐:
|
|
|
|
```python
|
|
decision = await permissionDecisionService.decide(
|
|
ScopeContext(
|
|
user_id=current_user_id,
|
|
permission_key="rag:dataset:update",
|
|
module="rag",
|
|
resource_id=dataset_id,
|
|
)
|
|
)
|
|
if not decision.allowed:
|
|
raise Forbidden()
|
|
```
|
|
|
|
## 6.2 前端替换模式
|
|
|
|
不推荐:
|
|
|
|
```ts
|
|
const canUpload = currentUser.role === "admin";
|
|
```
|
|
|
|
推荐:
|
|
|
|
```ts
|
|
const canUpload = hasPermission("contract_template:create:write");
|
|
```
|
|
|
|
或者:
|
|
|
|
```ts
|
|
const canManageDataset = capability.rag?.manage === true;
|
|
```
|
|
|
|
---
|
|
|
|
## 7. 兼容策略
|
|
|
|
并不是所有角色相关代码都要同一天删除。
|
|
|
|
建议分 3 类处理:
|
|
|
|
1. `立即删除`
|
|
- 服务层动作白名单
|
|
- 前端页面按钮直接按角色判断
|
|
2. `先替换后删除`
|
|
- `is_global/can_manage/bypass_area`
|
|
3. `短期保留但冻结`
|
|
- 路由 fallback
|
|
- 本地 `user_role` 兼容字段
|
|
|
|
“冻结”的意思是:
|
|
|
|
- 不再新增依赖
|
|
- 只允许向统一能力来源迁移
|
|
|
|
---
|
|
|
|
## 8. 风险说明
|
|
|
|
## 8.1 最大风险
|
|
|
|
如果只改后端,不改前端,会出现:
|
|
|
|
- 后端已经可用,但前端按钮还不显示
|
|
- 菜单还按旧角色展示
|
|
- 用户误以为权限失效
|
|
|
|
如果只改前端,不改后端,会出现:
|
|
|
|
- 前端展示放开
|
|
- 后端仍按旧角色拒绝
|
|
- 联调体验极差
|
|
|
|
## 8.2 第二风险
|
|
|
|
去硬编码后,如果没有统一能力快照,前端容易又发明一套新的本地推断规则。
|
|
|
|
所以必须同步提供:
|
|
|
|
- `/auth/me` 扩展能力
|
|
- 或专门的当前用户能力接口
|
|
|
|
---
|
|
|
|
## 9. 推荐执行顺序
|
|
|
|
建议按下面顺序推进:
|
|
|
|
1. `ragDatasetServiceImpl.py`
|
|
2. `ragChatServiceImpl.py`
|
|
3. RAG 前端 3 个文件
|
|
4. `documentServiceImpl.py`
|
|
5. `govdocServiceImpl.py`
|
|
6. `usageStatsServiceImpl.py`
|
|
7. `rbacAdminServiceImpl.py`
|
|
8. `contractTemplateServiceImpl.py`
|
|
9. `homeServiceImpl.py`
|
|
10. 菜单/guard/fallback 前端文件
|
|
|
|
原因:
|
|
|
|
- 先打掉最明显的双轨冲突
|
|
- 再统一高风险数据域
|
|
- 最后收口前端兼容层
|
|
|
|
---
|
|
|
|
## 10. 完成判定
|
|
|
|
角色去硬编码完成,不是指仓库里再也没有 `admin` 字符串,而是指:
|
|
|
|
1. 角色名不再直接决定业务动作是否允许
|
|
2. 角色名不再直接决定数据边界
|
|
3. 前端不再用角色名推断核心按钮与菜单
|
|
4. 新增自定义角色时,不需要全仓库搜角色名改逻辑
|
|
|
|
只有达到这 4 条,才算真正完成迁移。
|