7.3 KiB
7.3 KiB
脚手架审计整改清单
状态标记:
⬜ 待处理·🔶 需讨论·✅ 已决定·✔ 已完成顺序按批次(P0 安全堵漏 → P1 RBAC 闭环 → P2 会话加固 → P3 工程化契约)推进,序号即处理顺序,可调。
P0 安全越权堵漏
- C1 跨租户越权 —— Tenant 表无租户过滤,任意租户超管可管全平台租户。✔ 已完成:
super_admin=平台超管(保留)、tenant_super_admin=租户顶层(保留),tenant:*仅平台租户可授予(constants.ts + roles.service 保留码校验 + 平台级权限剥离) - H1 软删与唯一约束冲突 —— 删后无法重建同名 → P2002 → 500。✔ 已完成:方案 B(BaseCrudService.softRemove 改名回收
#id,按列长截断)+ P2002→409 - H2 删除角色不清理关联与缓存 —— user_role/role_resource/role_org 残留,聚合不校验已删角色。✔ 已完成:removeRole 级联清理 + 清缓存 + 保留角色禁删 + resolveAuth 过滤已删角色
- H3 权限聚合缺 status 过滤 —— 停用资源仍被授权。✔ 已完成:resolveAuth 资源查询补
status='enabled' - H4 用户停用/删除后旧 token 仍可用 —— 守卫不查用户状态,缓存 TTL=7 天。✔ 已完成:方案 A(tokenVersion)+ JwtAuthGuard 每请求校验 + Redis 用户状态缓存
- H5 重置密码不吊销会话 —— refresh token 不撤销。✔ 已完成:并入 H4,resetPassword/停用/删除 → invalidateSessions(tokenVersion++ + 删 refresh + 清缓存)
- H6 角色资源树半选回显导致权限放大 —— 半选父节点被持久化 + 回显级联全选。✔ 已完成:只保存叶子键
getCheckedKeys(true)+ 回显setCheckedKeys(assigned, true) - H10 401 自动刷新无限循环 —— login/refresh 自身 401 也进刷新重放。✔ 已完成:
_retry标记 + 排除 login/refresh + 失败 reject - H11 data_scope self 语义错误 —— self 等同本部门;详情接口无数据权限。✔ 已完成:self 按 userId 过滤 + 详情 assertCanView 403
- H13 seed 幂等副作用 —— 重跑重置管理员密码/启用账号。✔ 已完成:update 分支剥离 password/status
- M1 日志脱敏不含 phone/email —— 违反 spec 安全红线。✔ 已完成:mask.ts 补充 phone/mobile/email
- M6 JWT 密钥默认兜底值 —— 生产忘配置即可伪造 token。✔ 已完成:缺失/生产弱密钥直接拒绝启动
- M8 pageSize 无上限 —— 可拉全表。✔ 已完成:
@Max(200) - M9 DTO 枚举缺校验 —— status 裸
@IsString。✔ 已完成:全 DTO 加@IsIn(UserStatus/CommonStatus/DataScope/ResourceType) - M10 Prisma 错误未映射 —— P2002/P2025 原文泄漏且 500。✔ 已完成:P2002→409、P2025→404、未知异常不泄漏内部细节
- M11 assignResources 非事务 + 不校验 + :id 语义混淆 —— ✔ 已完成:事务化 + 角色存在性校验(:id 实为 roleCode,已注释说明)
- M22 super_admin 可被租户自建 —— ✔ 已完成:并入 C1,
RESERVED_ROLE_CODES校验(super_admin / tenant_super_admin) - M4 组织树可成环 —— collectDescendants 死循环。✔ 已完成:create/update 防环校验 + collectDescendants visited 集合
P1 RBAC 闭环
- H7 用户-角色分配缺失 —— 无端点/DTO/UI。✔ 已完成:
GET/PUT /users/:id/roles+ DTO + 前端分配角色表单 + 用户页入口 - H9 按钮级权限未实现 —— 无下发接口/指令,导出按钮不存在。✔ 核心已完成:
/auth/permissions下发 + permission store +v-permission指令 + ty-crud 权限过滤 + 用户页导出演示(role/audit/login-log 3 个导出按钮为同模式,待补) - M18 前端无路由级权限过滤 + 403 页 —— ✔ 已完成:路由守卫按可访问菜单 path 过滤 + 403 页(/403)
- M21 数据权限覆盖面过窄 —— 仅用户列表。✔ 已完成(方案 A):组织树按可见部门过滤 + 审计/登录日志按操作人部门过滤;角色/字典/配置保持租户级
- H8 注册/忘记密码是假功能 —— mock 假成功。✔ 已完成:注册真实化(POST /auth/register),注册/忘记密码默认隐藏(showRegister/showForgetPassword=false,fork 可开启)
- M17 租户 onboarding 断裂 —— 新建租户不可用、删除留孤儿。✔ 已完成:initTenant 模板(根组织+tenant_super_admin+管理员+资源+字典+授权)+ 删除级联清理;顺带修复 BaseCrudService tenant 大小写注入 bug
- 新增 用户自助修改密码/个人资料 —— 缺失清单。✔ 已完成:PATCH /auth/me/password(校验原密码 + 吊销其它会话)+ 顶栏「修改密码」入口
P2 会话与安全加固
- M5 登录安全基线缺失 —— 无锁定/后端验证码/密码策略。✔ 已完成:失败锁定(5 次/15 分钟)+ 密码长度策略(验证码后置)
- M7 Swagger 无鉴权 + CORS 全开 + 无 helmet/限流 —— ✔ 已完成:helmet + CORS 白名单(CORS_ORIGIN)+ Swagger 仅非生产 + @nestjs/throttler 限流
- M12 RefreshToken 哈希未校验 + 无清理 —— ✔ 已完成:refresh 校验 tokenHash(清理并入 L8)
- M14 401 强退后 authStore 失真 —— ✔ 已完成:auth store 增 reset,handler 同步清空
- M15 dictStore loaded 守卫无法刷新 —— ✔ 已完成:fetch 加 force 参数,字典页增删改后 force 刷新
- M20 登录租户写死 touyun —— ✔ 已完成:登录按用户名自动探测租户,多租户返回候选由前端弹窗选择
- M3 created_by 全项目零写入 —— ✔ 已完成:BaseCrudService.create 注入 createdBy
- L5 登出审计 username 写 null —— ✔ 已完成:按 userId 回查真实 username
- L7 useRequest loading 竞态 + ty-crud 重复请求 —— ✔ 已完成:useRequest 请求序号防竞态 + ty-crud 搜索/重置去重
- L8 审计/登录日志、refresh_token 无清理任务 —— ✔ 已完成:@nestjs/schedule 定时清理(过期 token + 90 天前日志)
P3 工程化契约
- H12 e2e 必然失败 + 无业务测试 —— 方案:修 e2e + 补核心链路用例
- M2 时间字段 ISO vs Unix 毫秒 —— ✔ 已完成:API 层统一 Unix 毫秒(TransformInterceptor 递归转换 + 前端类型 number)
- M16 vite
olldownOptions拼写错误 —— 方案:改rolldownOptions - M19 前端 .env/.env.dev 入库 + .env.example 带像真密码 —— 方案:gitignore + 模板脱敏
- L1 模板残留/无 LICENSE/stats.html 入库 —— 方案:清理 + 补 LICENSE
- L2 启动 console.log 噪音 —— 方案:移除
- L3 docs/requirements 空目录 + config/menu.ts 死代码 —— 方案:清理
- L4 README 克隆命令与子模块风格不一致 —— 方案:统一
- L6 ty-crud 取消确认 rejection 未捕获 —— 方案:catch
- L9 @nestjs/mau 非常规依赖 —— 方案:核实来源/用途
- L10 无 CI/Dockerfile/compose 部署编排 —— 方案:补 CI + 部署物料
- 新增 spec 覆盖补全 —— users/roles/orgs/tenants/configs 与前端多页无 spec 锚点。方案:补主 spec