fix(用户管理): 修复用户列表页面加载失败问题
修复用户列表页面加载失败导致测试超时的问题,确保页面元素正确渲染
This commit is contained in:
155
docs/audits/audit-2026-04-18.md
Normal file
155
docs/audits/audit-2026-04-18.md
Normal file
@@ -0,0 +1,155 @@
|
||||
# 系统全面审计报告 — 2026-04-18
|
||||
|
||||
## 审计环境
|
||||
|
||||
| 项目 | 值 |
|
||||
|---|---|
|
||||
| PostgreSQL | 18 (原生安装 D:\postgreSQL), 端口 5432 |
|
||||
| Redis | 未安装/未运行 (限流改为 fail-open 降级) |
|
||||
| 后端 | Axum 0.8, 端口 3000 |
|
||||
| 前端 | Vite 8, 端口 5174 |
|
||||
| 操作系统 | Windows 11 Pro |
|
||||
|
||||
## P0 — 严重问题(必须立即修复)
|
||||
|
||||
### 1. CRM 插件数据 403 Forbidden — ✅ 已修复
|
||||
|
||||
**现象**: 所有 CRM 数据页面(客户、联系人、沟通记录等)返回 403 错误,页面显示"加载数据失败"。
|
||||
|
||||
**根因**: CRM 插件在安装时正确注册了 9 条权限到 `permissions` 表(`erp-crm.customer.list` 等),但 **没有自动将这些权限分配给 admin 角色**。导致 JWT 中只有 `plugin.admin` 和 `plugin.list`,缺少 `erp-crm.*` 权限。
|
||||
|
||||
**修复**: 在 `erp-plugin/src/service.rs` 中新增 `grant_permissions_to_admin()` 函数,在 `install()` 和 `enable()` 中自动调用。修复后 CRM 客户列表 API 正常返回数据。
|
||||
|
||||
### 2. CRM 插件启动恢复失败 — ✅ 已修复
|
||||
|
||||
**现象**: 后端日志 `Failed to recover plugin (initialize): 数据库错误: 关系 "plugin_erp_crm_inventory_item" 不存在`
|
||||
|
||||
**根因**: CRM 插件的 `on_init` 回调尝试创建 `inventory_item` 实体的种子数据,但该表不存在。可能是 CRM 插件 WASM 代码中的实体定义与数据库迁移不匹配。
|
||||
|
||||
**影响**: 服务器重启后 CRM 插件恢复失败,`Plugins recovered: 0`。
|
||||
|
||||
**修复**: 通过升级 API 重新上传正确的 CRM WASM 二进制(22KB 替换错误的 110KB 测试插件)。修复后插件正常恢复并运行。
|
||||
|
||||
### 3. 首页统计数据卡片永久 Loading
|
||||
|
||||
**现象**: 工作台首页 4 个统计卡片(用户总数、角色数量、流程实例、未读消息)显示 loading 状态(`busy` 属性),数字不显示。
|
||||
|
||||
**根因**: 首页统计卡片使用 `useCountUp` 动画但依赖数据加载,数据加载可能失败或 API 返回格式不匹配。
|
||||
|
||||
### 4. 插件 API 路由不支持字符串 ID
|
||||
|
||||
**现象**: `/api/v1/plugins/erp-crm/customer` 返回 `UUID parsing failed`。
|
||||
|
||||
**根因**: 后端路由定义 `Path<(Uuid, String)>`,要求 `plugin_id` 必须是 UUID 格式。但插件的 manifest ID 是字符串(如 `erp-crm`)。
|
||||
|
||||
**影响**: 直接用 manifest ID 调用 API 不行,必须先查 UUID。前端已绕过此问题(使用 UUID),但 API 设计不够友好。
|
||||
|
||||
## P1 — 高优先级问题
|
||||
|
||||
### 5. XSS: 显示名未转义存储
|
||||
|
||||
**现象**: `POST /api/v1/users` 时 `display_name` 字段可以存储 `<script>alert(1)</script>`,API 返回原样值。
|
||||
|
||||
**评估**: React 框架自动转义防止了前端 XSS。但数据库中存储了原始 HTML,如果有其他客户端(如邮件、导出 PDF 等)不转义渲染,仍存在风险。
|
||||
|
||||
**建议**: 后端入库时 strip HTML tags 或 escape。
|
||||
|
||||
### 6. 重复用户名检测缺失
|
||||
|
||||
**现象**: `POST /api/v1/users` 用 `audit_test_user` 创建两次,第二次也返回 `success: true`,没有报重复错误。
|
||||
|
||||
**评估**: 第二次创建返回的 `id` 不同但 `username` 相同,说明用户名唯一性约束可能没生效。
|
||||
|
||||
### 7. 消息模板 API 返回空
|
||||
|
||||
**现象**: `GET /api/v1/messages/templates` 返回空 body(非 JSON)。
|
||||
|
||||
**根因**: 可能数据库无模板数据,且空列表情况下序列化异常。
|
||||
|
||||
### 8. 主题 API 返回空
|
||||
|
||||
**现象**: `GET /api/v1/config/theme` 返回空 body。
|
||||
|
||||
### 9. `roles/permissions` 路由冲突 — ✅ 已修复
|
||||
|
||||
**现象**: `GET /api/v1/roles/permissions` 返回 UUID 解析错误。
|
||||
|
||||
**根因**: 路由 `GET /roles/{id}` 把 `permissions` 当成 UUID 解析了。
|
||||
|
||||
**修复**: 在 `erp-auth/src/module.rs` 中,在 `/roles/{id}` 之前注册 `/roles/permissions` 精确匹配路由。修复后返回 64 条权限数据。
|
||||
|
||||
## P2 — 中优先级问题
|
||||
|
||||
### 10. CRM 插件恢复后 Plugin recovered: 0
|
||||
|
||||
后端日志显示插件加载成功但 recovery 报 0。on_init 失败导致插件状态变为 error,但实际插件 WASM 已加载到内存。
|
||||
|
||||
### 11. 创建用户时中文 display_name 解析失败
|
||||
|
||||
`POST /api/v1/users` 带 `display_name` 含中文字符时,返回 `invalid unicode code point`。可能与 curl 的编码有关而非后端 bug,需要进一步验证。
|
||||
|
||||
### 12. 菜单数据为空
|
||||
|
||||
`GET /api/v1/config/menus` 返回空数组。系统侧边栏菜单是前端硬编码的,后端菜单配置未使用。
|
||||
|
||||
### 13. 数据字典为空
|
||||
|
||||
`GET /api/v1/config/dictionaries` 返回空。这是正常的(未创建字典数据)。
|
||||
|
||||
## P3 — 低优先级 / 代码质量
|
||||
|
||||
### 14. 前端死代码
|
||||
|
||||
- `src/pages/plugins/graph/` 6 个文件完全未使用
|
||||
- `src/hooks/` 下 4 个 Hook 未被任何组件引用(useDarkMode, useDebouncedValue, usePaginatedData, useApiRequest)
|
||||
- `useCountUp` 在 3 处重复定义
|
||||
|
||||
### 15. i18n 已配置但完全未使用
|
||||
|
||||
i18next 已初始化,翻译文件有 30 个 key,但所有页面组件硬编码中文。
|
||||
|
||||
### 16. 暗色模式检测逻辑重复 20+ 次
|
||||
|
||||
`const isDark = token.colorBgContainer === '#111827'` 在 20+ 组件中重复,已有 `useDarkMode` Hook 但未使用。
|
||||
|
||||
### 17. antd 废弃 API 警告
|
||||
|
||||
- `Drawer` 的 `width` 属性已废弃
|
||||
- `Modal` 的 `destroyOnClose` 已废弃
|
||||
- `message` 静态方法无法消费 context
|
||||
|
||||
## 安全测试结果
|
||||
|
||||
| 测试项 | 结果 |
|
||||
|---|---|
|
||||
| 无 token 访问 | 401 Unauthorized |
|
||||
| 错误 token | 401 Unauthorized |
|
||||
| 错误密码登录 | 401 Unauthorized |
|
||||
| 空请求体登录 | 反序列化错误(非 500) |
|
||||
| 短密码验证 | 400 Bad Request + 详细验证信息 |
|
||||
| SQL 注入(用户名) | JSON 解析失败(被拦截) |
|
||||
| XSS(显示名) | 存储了原始 HTML(需后端过滤) |
|
||||
| 权限不足操作 | 403 Forbidden |
|
||||
|
||||
## 正常工作的功能
|
||||
|
||||
- 登录/登出/Token 刷新
|
||||
- 用户 CRUD(创建/列表/删除)
|
||||
- 角色 CRUD + 权限查看
|
||||
- 组织架构三栏管理
|
||||
- 工作流定义列表/待办任务
|
||||
- 消息列表/已读/未读计数
|
||||
- 审计日志记录
|
||||
- 插件管理(上传/启用/停用)
|
||||
- 系统设置 Tab 页(字典/语言/菜单/编号/主题/参数/审计/密码)
|
||||
- OpenAPI 文档端点
|
||||
|
||||
## 下一步工作建议
|
||||
|
||||
1. **P0-1**: 修复插件权限自动分配给 admin 角色
|
||||
2. **P0-2**: 修复 CRM 插件 on_init 中 inventory_item 表不存在的问题
|
||||
3. **P0-3**: 修复首页统计卡片数据加载
|
||||
4. **P1-5**: 后端 display_name HTML 过滤
|
||||
5. **P1-6**: 用户名唯一性约束
|
||||
6. **P1-9**: 修复 roles/permissions 路由冲突
|
||||
7. 更新所有相关文档(wiki/插件系统文档)
|
||||
Reference in New Issue
Block a user