# RBAC 角色体系 + 部门管理员 + 权限申请审批 实现计划 > 状态:**待用户确认**(未开始编码) > 创建日期:2026-08-14 > 关联:基于 v2.0 技术方案,叠加多角色与权限工作流 --- ## 一、需求重述与澄清 ### 1.1 用户原始需求 1. **两类管理员角色**: - 超级管理员(SUPER_ADMIN):系统级,所有文档所有操作 - 部门管理员(DEPT_ADMIN):管理"被授权部门"的文档与人员,对其他部门不可见 2. **超级管理员职责**: - 把"部门 X 的管理权"授予某些用户(即设置某人为部门 X 的管理员) - 拥有所有文档的所有操作权限(已是现状) 3. **部门管理员默认权限**: - 对**所管理部门**的所有文档:所有操作权限 - 对**其他部门**文档:无权限 - 可对所辖部门人员做"细粒度权限划分" 4. **普通用户默认权限**: - 仅能查看**本部门管理的**所有文档 - 不能查看其他部门文档 - 部门管理员与超级管理员都可对他做细粒度授权 ### 1.2 待澄清的歧义点(确认计划时一并说明,便于修正) | # | 歧义点 | 我的默认解读(如不符请告知) | |---|---|---| | Q1 | "本部门管理的所有文档"——文档当前**不直接挂部门**,只有 `category_id` 与 `created_by` | 默认引入"**文档所属部门 = 创建者所在部门**"语义;同时保留文档级 ACL(`doc_permission`)覆盖细粒度授权 | | Q2 | 部门管理员能否管理子部门文档?(如机关 → 作战部,作战部管理员能否看机关文档?反之呢?) | 默认 **部门管理员 = 所管理部门及其所有后代部门**(与现有"组织祖先链"语义一致)。部门管理员**不能**管理祖先部门 | | Q3 | "权限申请"流程:用户向谁申请?申请什么? | 默认指**普通用户向上级/管理员申请具体文档或文档分类的额外权限**,由部门管理员/超管审批;审批通过后落 `doc_permission` 表 | | Q4 | 部门管理员之间是否平级?一个部门能否有多个管理员? | 默认**一对多**(一个部门可有多位管理员,权限等价),与现有"用户 × 组织"模型契合 | | Q5 | "细粒度权限划分"的粒度:模块级 / 文档级 / 字段级? | 默认**文档级**(沿用现有 `doc_permission` 表的 5 个 canXxx),不引入字段级 | | Q6 | 部门管理员能否创建/删除本部门用户? | 默认**可以管理本部门及下级部门的用户**(增删改、重置密码),但不能改其他部门用户 | | Q7 | 部门管理员能否创建子部门? | 默认**不能**(组织结构由超管维护),仅可对所辖部门的"文档/用户/权限"做管理 | > ⚠️ 请逐项确认("Q1✓ Q2 改为..."等),歧义点会影响后续表结构与 API 设计。 --- ## 二、总体架构设计 ### 2.1 角色模型选型:保留 `role_code` 列,新增"部门管理员授权表" **为什么不引入完整 RBAC(Role/Permission/RolePermission/UserRole 多对多)?** - 现系统 `RoleCode` 是写死枚举、`allowedModules` 静态映射,已被 JWT、装饰器、前端门控、f6Scope 静态测试等多处依赖;改为多对多会引发大爆炸。 - 需求**只有三种角色**(超管/部门管理员/普通用户),不需要"自定义角色"能力。 - 文档级细粒度已由 `doc_permission` 完整覆盖,不需要再做"角色 × 权限点矩阵"。 **结论**:在 `sys_user.role_code` 枚举中加一档 `DEPT_ADMIN`,用一张 `sys_dept_admin`(用户 × 组织)关联表表达"谁管哪些部门"。 ### 2.2 文档归属语义:新增 `organization_id` 列 `Document` 当前**没有组织归属字段**,要实现"本部门文档"必须新增: - `doc_document.organization_id`:默认取**创建者所属组织**(上传时自动填充) - 历史数据回填脚本:按 `created_by → user.organization_id` 推导 ### 2.3 数据范围(Data Scope)三层模型 | 角色 | 文档范围 | 用户管理范围 | |---|---|---| | SUPER_ADMIN(即 `ADMIN`) | 全部 | 全部 | | DEPT_ADMIN | 所管理部门**及后代**的文档 + 显式 ACL 授权 | 所管理部门**及后代**的用户 | | USER | 仅显式 ACL 授权 + `visibility_type=ALL_AUTHENTICATED` | 仅自己 | > "本部门文档"对普通用户可见 = 文档 `organization_id` ∈ 用户所属组织的祖先链时,普通用户享有 VIEW 权限。 ### 2.4 权限申请工作流 ``` 普通用户/部门管理员 ──提交申请──► 待审批 │ │ │ ├── 部门管理员审批(仅本部门申请) │ └── 超级管理员审批(任意申请) │ ▼ 通过 → 落 doc_permission 表 驳回 → 标记驳回理由 ``` 申请单要素:申请人、目标文档(或分类)、申请动作(view/download/edit 等)、申请理由、审批人、状态、审批意见。 --- ## 三、现状调研(已完成) ### 3.1 后端已有基础 | 维度 | 现状 | |------|------| | **组织树** | `Organization` 已是层级模型(`parent_id` + `org_path`),CRUD + 软删 + 乐观锁齐全,已有"祖先链"和"后代遍历"工具函数 | | **用户生命周期** | 建改删/重置密码/禁用/自我保护、最后管理员保护、`auth_version` 主动失效机制完备 | | **二角色体系** | `RoleCode.USER / RoleCode.ADMIN`(`backend/dms/common/enums.py:8-10`),CHECK 约束(`backend/dms/models/user.py:18-21`) | | **文档级 ACL** | `doc_permission` 表 + `evaluate_plan_access` 统一判定入口(`backend/dms/services/authorization_service.py:101-158`)+ 全量差异保存 + 子方案动态继承主案 + 附件通过主案传递 | | **三种可见性策略** | `ALL_AUTHENTICATED / ORGANIZATION / CUSTOM`(`backend/dms/models/document.py:149-153`) | | **审计基础设施** | 22 种动作 + 8 种目标类型,`business_audit` 辅助函数统一落表 | ### 3.2 后端关键缺口 1. **无 DEPT_ADMIN 角色**:`role_code` CHECK 限制为 `('USER', 'ADMIN')` 2. **无"用户 × 组织"管理员授权表** 3. **`Document` 无组织归属字段**:无法表达"本部门文档" 4. **无数据范围中间态**:列表查询对 ADMIN 一律全量、对 USER 一律按 ACL 过滤,无 DEPT_ADMIN 中间档 5. **无权限申请/审批端点** 6. **审计 CHECK 约束**:若新增 `ASSIGN_DEPT_ADMIN / GRANT_DEPT_ADMIN` 等动作,需扩展 CHECK(0004 已有先例) ### 3.3 前端已有基础 | 维度 | 现状 | |------|------| | **认证** | 完整的登录/退出/会话恢复,`tokenStore` 区分 sessionStorage/localStorage | | **组织管理 UI** | 完整 CRUD(树形、关键词、排序、状态、parent 校验防环)`DirectoryPage.tsx:217-487` | | **用户管理 UI** | 完整 CRUD + 重置密码 + 组织树筛选(含下级)+ 分页 `DirectoryPage.tsx:763-1271` | | **文档级 ACL UI** | 完整的 `F6PermissionModal`:三档 visibility + 组织/人员主体 + 5 个布尔动作 + 子案继承 | | **模块级导航门控** | `allowedModules` 驱动导航条 + `isPageAllowed` 拦截跳转 | | **角色枚举** | 仅 `USER` / `ADMIN` 两档(`frontend/src/shared/api/enums.ts:1-5`) | ### 3.4 前端关键缺口 1. **无 DEPT_ADMIN 角色**:`RoleCode` 仅 USER/ADMIN 2. **无部门管理员概念**:`OrganizationNode` 无 `managerId`、`UserSummary` 无 `managedOrgIds` 3. **无"我的申请/待我审批"页面**:不存在 `features/requests/` 或 `features/approvals/` 4. **无权限申请 API 客户端** 5. **角色门控写死在 App.tsx**:`App.tsx:2986-3014` 三处 `roleCode === RoleCode.ADMIN` 硬编码 6. **双重门控耦合**:导航按 `allowedModules`、路由按 `roleCode`,必须同步 7. **`f6Scope.test.ts:23` 静态断言脆弱**:用 `readFileSync` 做字符串匹配,新增角色门控时需更新 --- ## 四、实现阶段(共 6 阶段,建议按顺序) ### 阶段 1:数据库迁移 `0006_rbac_dept_admin` **新建文件**:`backend/migrations/versions/0006_rbac_dept_admin.py` **变更项**: 1. `sys_user.role_code` CHECK 扩展为 `('USER', 'ADMIN', 'DEPT_ADMIN')` 2. 新建 `sys_dept_admin` 表: ```sql CREATE TABLE sys_dept_admin ( id BIGINT PK, user_id BIGINT NOT NULL, -- FK sys_user organization_id BIGINT NOT NULL, -- FK sys_organization granted_by BIGINT NOT NULL, -- FK sys_user (授予人) granted_at DATETIME NOT NULL, row_version INT NOT NULL DEFAULT 0, created_at/updated_at/created_by/updated_by + is_deleted/deleted_at (mixin), UNIQUE(user_id, organization_id, active_marker), CHECK (user_id <> organization_id) -- 防呆 ) ``` 3. `doc_document` 加列 `organization_id BIGINT NULL` + 冗余 `organization_name` + 索引 `ix_doc_document_org_active` 4. `sys_audit_log.action_type` CHECK 扩展:`ASSIGN_DEPT_ADMIN / REVOKE_DEPT_ADMIN / SUBMIT_ACCESS_REQUEST / APPROVE_ACCESS_REQUEST / REJECT_ACCESS_REQUEST` 5. `sys_audit_log.target_type` CHECK 扩展:`DEPT_ADMIN_GRANT / ACCESS_REQUEST` 6. 新建 `doc_access_request` 表(权限申请单): ```sql CREATE TABLE doc_access_request ( id BIGINT PK, requester_id BIGINT NOT NULL, -- FK sys_user document_id BIGINT NULL, -- 申请具体文档 category_id BIGINT NULL, -- 申请某分类下所有文档(与 document_id 互斥) requested_actions VARCHAR(64) NOT NULL, -- "VIEW,DOWNLOAD" 逗号分隔 reason TEXT NOT NULL, status VARCHAR(16) NOT NULL, -- PENDING/APPROVED/REJECTED/CANCELLED approver_id BIGINT NULL, approver_comment TEXT NULL, approved_actions VARCHAR(64) NULL, -- 审批通过的实际动作(可缩减) submitted_at DATETIME NOT NULL, decided_at DATETIME NULL, row_version INT NOT NULL DEFAULT 0, ... (mixin) CHECK (status IN ('PENDING','APPROVED','REJECTED','CANCELLED')), CHECK ((document_id IS NULL) <> (category_id IS NULL)) -- 二选一 ) ``` 7. 历史数据回填:`UPDATE doc_document d JOIN sys_user u ON u.id = d.created_by SET d.organization_id = u.organization_id WHERE d.organization_id IS NULL` **验证**:`alembic upgrade head` + 回滚脚本 `downgrade()` 完整。 **复杂度**:中(约束较多但都是 ADD COLUMN / CREATE TABLE) --- ### 阶段 2:后端模型与服务层 **新建** `backend/dms/models/dept_admin.py`: - `DeptAdminGrant` ORM 模型(继承 `BusinessTableMixin`) **新建** `backend/dms/models/access_request.py`: - `AccessRequest` ORM 模型,含 `requested_actions` / `approved_actions` 的 list 序列化辅助方法 **修改** `backend/dms/models/document.py`: - 加 `organization_id` + `organization_name` 列 + relationship **修改** `backend/dms/models/user.py` + `backend/dms/common/enums.py:8-10`: - `RoleCode` 加 `DEPT_ADMIN` **新建** `backend/dms/services/dept_admin_service.py`: - `list_grants(user_id=None, org_id=None)` — 查询授权 - `grant(user_id, org_id, granted_by)` — 新增授权(含自环检测、组织存在性、用户角色升级到 DEPT_ADMIN) - `revoke(grant_id, row_version, revoked_by)` — 撤销授权(撤销后若用户无其他授权则降级回 USER) - `managed_org_ids(user_id)` — 返回用户管理的全部 org_id(含后代) - `is_dept_admin_of(user_id, org_id)` — 判定 **新建** `backend/dms/services/access_request_service.py`: - `submit(requester_id, payload)` — 提交申请(不允许申请自己已有权限的) - `list_for_approver(approver_id, status, page)` — 待我审批列表(按数据范围过滤) - `list_for_requester(requester_id, status, page)` — 我的申请 - `approve(request_id, approver_id, payload)` — 通过(落 `doc_permission`,发审计) - `reject(request_id, approver_id, payload)` — 驳回 **修改** `backend/dms/services/authorization_service.py`(核心改造): - `evaluate_plan_access` 新增分支: - SUPER_ADMIN → 放行(已存在) - **DEPT_ADMIN** → 若文档 `organization_id` ∈ 用户的 `managed_org_ids`(含后代)→ 放行 - USER → 若文档 `organization_id` == 用户 `organization_id` 且 status=PUBLISHED → VIEW 放行("本部门文档默认可见") - `plan_allowed_actions` 同步扩展返回值 **修改** `backend/dms/services/document_query_service.py:318`: - `list_documents` 增加 DEPT_ADMIN 分支:`WHERE doc.organization_id IN (managed_org_ids ∪ descendants)` **修改** `backend/dms/services/user_service.py:142`: - `list_users` 增加 DEPT_ADMIN 分支:仅能查询所辖部门的用户 **修改** `backend/dms/services/user_service.py:35-43`: - `ALLOWED_MODULES` 字典:DEPT_ADMIN 看到 `DOCUMENT_BROWSER / ORGANIZATION_USER_MANAGEMENT / AUDIT_LOG`(不含 BACKEND_MANAGEMENT) **修改** `backend/dms/services/document_mutation_service.py`: - 上传文档时自动填充 `organization_id = creator.organization_id` - DEPT_ADMIN 可在所辖部门内 CRUD,USER 不可创建(维持现状) **复杂度**:**高**(authorization_service 是核心路径,改造需配套单测) --- ### 阶段 3:API 端点 **新建** `backend/dms/api/v1/dept_admin.py`: - `GET /api/v1/dept-admins?userId=&orgId=` — 列表(仅 ADMIN) - `POST /api/v1/dept-admins` — 授予(仅 ADMIN) - `DELETE /api/v1/dept-admins/?rowVersion=` — 撤销(仅 ADMIN) **新建** `backend/dms/api/v1/access_requests.py`: - `POST /api/v1/access-requests` — 提交(任意已认证用户) - `GET /api/v1/access-requests/mine?status=&page=` — 我的申请 - `GET /api/v1/access-requests/pending?page=` — 待我审批 - `POST /api/v1/access-requests//approve` — 通过 - `POST /api/v1/access-requests//reject` — 驳回 - `POST /api/v1/access-requests//cancel` — 取消(仅本人 + PENDING) **修改** `backend/dms/security/decorators.py`: - 新增 `@dept_admin_or_admin_required` 装饰器 - 或更通用的 `@require_data_scope(resource_type)` 检查 **修改** `backend/dms/api/v1/organizations.py` 与 `users.py`: - 把 `@admin_required` 调整为:列表查询允许 DEPT_ADMIN 但结果按 scope 过滤;写操作仍限 ADMIN **修改** `backend/dms/api/v1/users.py:68-77` `/users/me`: - 在 `user_summary` 中增加 `managedOrgIds: Id[]` 字段(仅 DEPT_ADMIN 非空) **修改** `backend/dms/security/jwt_tokens.py`: - claims 增加 `managedOrgIds`(避免每次请求都查表),或仅在 `/me` 返回 **复杂度**:中 --- ### 阶段 4:前端类型与 API 客户端 **修改** `frontend/src/shared/api/enums.ts`: - `RoleCode` 加 `DEPT_ADMIN` - 新增 `AccessRequestStatus`(PENDING/APPROVED/REJECTED/CANCELLED) - `AuditActionType` 加 5 项(前端枚举与后端同步) **修改** `frontend/src/features/auth/authTypes.ts`: - `UserSummary` 加 `managedOrgIds: Id[]`(默认空数组) **修改** `frontend/src/features/auth/authApi.test.ts` + `authSession.test.ts` + `directoryApi.test.ts`: - mock 数据补 `managedOrgIds: []` **新建** `frontend/src/features/dept-admin/deptAdminTypes.ts`: - `DeptAdminGrant / DeptAdminGrantListQuery / DeptAdminGrantRequest` **新建** `frontend/src/features/dept-admin/deptAdminApi.ts`: - list / grant / revoke **新建** `frontend/src/features/access-requests/requestTypes.ts`: - `AccessRequest / AccessRequestCreateRequest / AccessRequestApproveRequest / AccessRequestStatus` **新建** `frontend/src/features/access-requests/requestApi.ts`: - submit / listMine / listPending / approve / reject / cancel **修改** `frontend/src/features/auth/authSession.ts`: - `AuthenticatedPage` 加 `"requests"` - `AllowedModule` 加 `ACCESS_REQUEST` - `MODULE_PAGES` / `MODULE_ORDER` 同步映射 **复杂度**:中 --- ### 阶段 5:前端页面与组件 **修改** `frontend/src/app/App.tsx:2986-3014`: - **关键**:把 `roleCode === RoleCode.ADMIN` 抽象为 `` 组件 - 同步更新 `f6Scope.test.ts:23` 静态断言(改为允许 `DEPT_ADMIN` 但仍禁止与 `BIND_ATTACHMENT` 共现) **修改** `frontend/src/features/directory/DirectoryPage.tsx`: - 角色下拉从 `Object.values(RoleCode)` 改为字典枚举 + 中文标签 - DEPT_ADMIN 登录时:左侧组织树**仅显示所辖部门及下级**,右侧用户表同范围过滤 - 新增"部门管理员授权"面板:超管可见,UI 为"用户 × 组织"矩阵 / 双向 Picker **修改** `frontend/src/features/directory/DirectoryPage.tsx:1430-1435`(UserEditorModal): - DEPT_ADMIN 创建用户时 `organizationId` 下拉限制为所辖部门 **新建** `frontend/src/features/access-requests/RequestsPage.tsx`: - 顶部 Tab:我的申请 / 待我审批 - 我的申请:列表 + "新建申请"按钮(弹窗选文档/分类 + 动作复选 + 理由) - 待我审批:列表 + 通过/驳回按钮(驳回必填意见,通过可缩减动作集) **新建** `frontend/src/features/access-requests/RequestEditorModal.tsx`: - 选目标:从可见文档列表 / 从分类树挑选 - 动作复选:5 个 canXxx - 理由文本域 **修改** `frontend/src/app/App.tsx` 路由: - 加 `{page === "requests" && }` **修改** `frontend/src/shared/api/enums.ts:60-69` AllowedAction**保持不变**(申请单用同一套动作) **复杂度**:**高**(DirectoryPage 1700 行,需小心改造;新增 RequestsPage 全新页面) --- ### 阶段 6:单元测试 & 端到端验证 **后端**: - `backend/tests/dms/test_dept_admin.py` — 授权/撤销/角色升级降级/自环 - `backend/tests/dms/test_access_request_workflow.py` — 提交/审批/落表/状态机 - `backend/tests/dms/test_authorization_dept_admin.py` — 数据范围三层模型 - `backend/tests/dms/test_user_scope_dept_admin.py` — 用户列表 scope 过滤 **前端**: - `deptAdminApi.test.ts` / `requestApi.test.ts` — 类型守卫 + 端点契约 - `directoryTypes.test.ts` / `authSession.test.ts` — 已有测试补字段 - 新建 `appScope.test.ts` 扩展断言:`requests` 页面门控按 RBAC 三档角色 **手动验收**(用户参与): 1. 超管授予 A 为部门 X 管理员 → A 登录看到 X 及其子部门 2. A 创建用户 B(仅能在 X 范围内选组织)→ B 默认只能看 X 的文档 3. B 提交"对文档 D 的下载权限申请" → A 审批通过 → B 可下载 D 4. A 给 B 配置"文档 E 仅查看" → B 无法下载 E 5. 超管撤销 A 的部门管理员授权 → A 降级为 USER,所有扩展权限失效 **复杂度**:中 --- ## 五、依赖项 - 无新外部依赖(不引入 Redis/Celery 等) - 复用现有:Argon2 / JWT / SQLAlchemy / Alembic / Vitest / pytest - 审批流不引入工作流引擎,用状态机足够 --- ## 六、风险与缓解 | 风险 | 等级 | 缓解 | |---|---|---| | **R1: `evaluate_plan_access` 改造引入性能回归**(每条文档都查 managed_org_ids) | 高 | 在 `dept_admin_service` 加内存缓存(请求级),或把 managed_org_ids 拍平成 IN 子句一次查出 | | **R2: 文档归属语义变更影响历史数据** | 高 | 迁移脚本必须回填 `organization_id`;回填逻辑:`SELECT d.id, u.organization_id FROM doc_document d JOIN sys_user u ON u.id = d.created_by WHERE d.organization_id IS NULL` | | **R3: 普通用户"本部门可见"语义与现有 `visibility_type=ORGANIZATION` 冲突**(语义重叠) | 中 | 保留 `visibility_type` 做显式授权;新增的"本部门默认可见"独立判定,两者**取并集**。文档落库时统一两者语义 | | **R4: JWT claims 加 managedOrgIds 后撤销授权无法实时生效** | 中 | 撤销时 `User.auth_version += 1` 强制 token 失效(已有机制) | | **R5: 前端 f6Scope.test.ts:23 静态断言脆弱** | 中 | 同步更新断言内容,增加 DEPT_ADMIN 白名单 | | **R6: 已有 mock 数据 265 个测试用例可能因类型新增字段大面积破坏** | 中 | 阶段 2 完成后立即跑全量测试,预期破坏点 5-8 处,按文件批量补字段 | | **R7: 部门管理员与"挂载附件 / 配置文档权限"功能交叉** | 中 | DEPT_ADMIN 在所辖范围内享有 `BIND_ATTACHMENT / CONFIG_PERMISSION`(沿用文档级 `allowed_actions` 动态计算,无需新增字段) | | **R8: `App.tsx` 3000+ 行 + DirectoryPage 1700 行**,改造易引入回归 | 中 | 拆分 `` 抽象 + 不动既有功能分支,仅扩展角色判定集 | --- ## 七、工作量估算 | 阶段 | 后端 | 前端 | 测试 | 合计 | |---|---|---|---|---| | 1. 迁移 | 2h | - | 0.5h | 2.5h | | 2. 模型与服务 | 5h | - | 2h | 7h | | 3. API | 3h | - | 1h | 4h | | 4. 前端类型与 API | - | 2h | 1h | 3h | | 5. 前端页面 | - | 6h | 1.5h | 7.5h | | 6. 测试与验收 | - | - | 3h | 3h | | **总计** | **10h** | **8h** | **9h** | **27h** | **整体复杂度**:**高**(核心授权路径改造 + 新增完整工作流) --- ## 八、待用户确认事项 请逐项回复,确认后才开始编码: 1. **歧义点 Q1–Q7** 是否需要调整? 2. **角色模型选型**:同意"保留 `role_code` 列 + 新增 `sys_dept_admin` 关联表"还是希望走完整 RBAC(自定义角色 + 权限点矩阵)? 3. **权限申请工作流**是否需要?还是仅需"管理员直接配置权限",跳过申请审批? 4. **`App.tsx` 拆分**:是否同意在改造同时把 `` 抽出来(小幅重构)?还是希望本次保持最小改动不重构? 5. **阶段顺序**:是否同意按 阶段1→6 顺序推进?或希望先做某个阶段验证后再继续? --- ## 九、关键文件锚点(便于后续实现时直接跳转) ### 后端 | 路径 | 说明 | |---|---| | `backend/dms/common/enums.py:8-10` | `RoleCode` 枚举(加 DEPT_ADMIN) | | `backend/dms/common/enums.py:13-17` | `AllowedModule` 静态枚举 | | `backend/dms/common/enums.py:68-75` | `AllowedAction` 文档级动作 | | `backend/dms/models/user.py:15-78` | `User` 模型 | | `backend/dms/models/organization.py:22-65` | `Organization` 模型 | | `backend/dms/models/document.py:25-215` | `Document` 模型(加 organization_id) | | `backend/dms/models/permission.py:23-87` | `doc_permission` 表 | | `backend/dms/services/authorization_service.py:101-158` | `evaluate_plan_access` 核心授权逻辑 | | `backend/dms/services/authorization_service.py:161-217` | `plan_allowed_actions` / `attachment_allowed_actions` | | `backend/dms/services/document_query_service.py:318-389` | `list_documents` Python 层过滤 | | `backend/dms/services/user_service.py:35-43` | `ALLOWED_MODULES` 字典 | | `backend/dms/services/user_service.py:142-181` | `list_users` | | `backend/dms/services/permission_service.py:286-420` | `save_permissions` 全量差异保存 | | `backend/dms/api/v1/users.py:68-77` | `/users/me` 端点 | | `backend/dms/api/v1/organizations.py` | 组织端点 | | `backend/dms/security/decorators.py:77-84` | `admin_required` 装饰器 | | `backend/dms/security/jwt_tokens.py:34-43` | `issue_access_token` claims | | `backend/migrations/versions/0005_category_flat_mode.py` | 最新迁移版本(下一版应为 0006) | ### 前端 | 路径 | 说明 | |---|---| | `frontend/src/shared/api/enums.ts:1-5` | `RoleCode` | | `frontend/src/shared/api/enums.ts:7-13` | `AllowedModule` | | `frontend/src/shared/api/enums.ts:60-69` | `AllowedAction` | | `frontend/src/features/auth/authTypes.ts:21-35` | `UserSummary` | | `frontend/src/features/auth/authSession.ts:9-55` | `AuthenticatedPage` / `MODULE_PAGES` / `getNavigationItems` | | `frontend/src/features/auth/__tests__/authApi.test.ts:10-28` | user mock(需补字段) | | `frontend/src/features/auth/__tests__/authSession.test.ts:29-43` | user mock(需补字段) | | `frontend/src/features/directory/directoryTypes.ts:13-23` | `OrganizationNode` | | `frontend/src/features/directory/DirectoryPage.tsx:113-115` | 角色下拉硬编码(需扩展) | | `frontend/src/features/directory/DirectoryPage.tsx:1430-1435` | `UserEditorModal` 角色选择 | | `frontend/src/features/permissions/permissionTypes.ts:9-44` | 文档级 ACL 类型 | | `frontend/src/features/permissions/PermissionModal.tsx:138-533` | F6 文档权限弹窗 | | `frontend/src/app/App.tsx:107` | `Page` 类型 | | `frontend/src/app/App.tsx:2986-3014` | 角色门控三处(需抽象) | | `frontend/src/features/permissions/__tests__/f6Scope.test.ts:23` | 静态断言(需更新) | --- **文档结束。等待用户确认后再启动阶段 1 编码。**