lovife
|
8480f431ba
|
feat(user): 账号管理(CRUD、Excel 导入、改密)并修掉 5 处缺陷
后端补齐 /users 全套(列表/新增/修改/软删/启停/重置密码/批量导入)与
PUT /auth/password;前端加「组织与账号 → 账号管理」一屏(左组织树 + 右列表、
新增编辑弹窗、导入体检报告、初始密码只显示一次的强确认)。
验收:e2e-m0-user.py 55/55;e2e-m0.py 回归 36/36;typecheck 0 错、build 通过。
账号管理页已在浏览器肉眼确认(首屏与切页均可见、数据与分页正确)。
本轮修掉的 5 个真问题 —— 都不是功能没做完,而是做完了但错的:
1) 学校租户也发放 PLATFORM_ADMIN 角色行
学校管理员在新增账号时传 roleCodes=[PLATFORM_ADMIN] 就能造出带
tenant:manage 的账号,而 /tenants 只校验权限码、不校验是否真在平台租户下
→ 任何学校管理员都能开通租户、拉全平台租户列表(租户级越权到平台级)。
RoleProvisioner 不再给非平台租户发该角色行 + 服务端按租户白名单校验。
2) UserUpsertReq.username 的 @NotBlank 对修改也生效
PUT /users/{id} 永远返回 40001,且明细只说存在阻断性校验问题,
看不出是登录名 —— 改账号功能整体不可用。去掉该注解,
必填性改由 UserService.create 判定。
3) Main.vue 的 <transition appear>
首次渲染被当成一次过渡,元素被加上 zoom-fade-enter-from(opacity:0)后
永不清理 → DOM 内容齐全、接口数据正常、文字可选中,但整块内容区肉眼不可见。
极易误判成页面没渲染而往路由/接口方向排查。去掉 appear。
4) assertAnotherAdminExists 在停用/删除路径上不可达
能调这两个接口的人自己必然是活跃管理员,所以除目标外还有管理员恒成立;
而真正会锁死租户的路径 —— 把管理员改成普通角色(目标可以是操作者自己)——
当时没有拦。补 losingAdminRole() + UserMapper.countAdminRoles(),
并在方法注释里写明哪条路径真生效、哪条只是防御性的。
5) sys_user.user_type 有两套互相冲突的枚举
DDL/实体注释写「1教师/管理员 2填报人(学生) 3社会人员」,而权威契约
(03-接口设计 §2.7)与 BuiltinRole.UserType 是
「1平台运营 2学校管理员 3班主任 4学生」—— 2 和 3 完全错位。
后果:userType=3(班主任,最高频的账号)被当成社会人员(二期)直接拒掉,
建班主任账号会失败;前端还把学校管理员显示成填报人(学生)。
改法:后端从角色反推用户类型再比对;新增 V3 迁移更正库注释
(V1 已应用不能改,Flyway 会校验 checksum);更正 PRD 与 schema DDL 的同一行;
前端「用户类型」从手选改为由角色推导,从根上消除矛盾组合;
E2E 加 3 条回归断言锁住这个语义。
顺带修掉:
· components/index.ts 里 6 个指向已删组件的悬空导出(构建不报错、用到才炸)
· tsconfig 的 lib 停在 ES2020 而代码用了 Array.prototype.at
· 两处 .at() 的空值风险(useBreakpoint / useTabsStore)
· dashboard 的 userStore.menus 拼错,导致平台判断恒为 false
· http.ts 里两个永不命中的错误码常量
· 账号列表的 fixed 列缺 :scroll 配置,会浮在其它列上面
· .gitignore 补 __pycache__
新增脚本:
· scripts/e2e-m0-user.py 账号管理 55 项验收(含越权与自锁的负向断言)
· scripts/dev-clean-test-users.py 清理 E2E 残留的测试账号
|
2026-09-28 22:25:01 +08:00 |
|
lovife
|
9d7a8ca845
|
feat(m0): 后端骨架 + 账号体系(M0 验收 36/36 通过)
技术栈(已在 4.1.1 上实测跑通,非纸面选型)
Java 21 + Spring Boot 4.1.1 + MyBatis-Plus 3.5.17(boot4) + PostgreSQL 16.15
+ Redis 7 + Flyway 12.4 + springdoc 3.1.1;前端定 Vue 3 + Element Plus + uni-app
交付内容
M0-01 基础设施 deploy/docker-compose.yml(PG + Redis + MinIO,容器名与端口避让本机既有项目)
M0-02 后端骨架 xt-common + xt-server;统一响应 / 全局异常 / 58 个错误码 /
多租户拦截 / 软删除 / 字段自动填充 / AES-GCM / HMAC 索引 / RSA / JWT
M0-05 租户 开通租户(一次完成建租户 + 发 6 个内置角色 + 建首个管理员)、列表、详情
M0-06 组织 CRUD + 组织树 + ancestor_path 自动维护 + 占用校验
M0-07 PC 登录 RSA 解密 + 图形验证码 + 失败锁定 + 等时比较防账号枚举 + 审计日志
M0-08 登出/当前用户 Token 黑名单(存 SHA-256,TTL 到自然过期)
M0-01 数据库 Flyway 2 个迁移 → 26 张表(20 业务 + 5 标准 + 1 迁移记录)
安全姿态
· 租户拦截器【默认拒绝】:匿名请求触及租户表直接抛 40101,不做「不加条件放行」
· 权限码定义在代码里(PermissionDef / BuiltinRole),不建 sys_permission 表,杜绝前后端漂移
· 匿名接口只靠 @PublicApi 放行,不做路径白名单,避免两套机制各说各话
· 账号不存在时也跑一次 BCrypt(假哈希),拉平响应时间防枚举
· 登录密码 RSA 传输,防止网关/APM 把明文密码记进日志
脚本
scripts/sync-ddl.py 文档 DDL → Flyway 迁移,带 --check 防漂移
scripts/e2e-m0.py M0 验收 36 项,可进 CI
scripts/verify-docs.py 文档一致性(接口数【逐节】核对、错误码、跨文档数字、表格列数)
scripts/dev-login.py RSA 加密登录助手
scripts/dev-clean-e2e.py 清理 E2E 测试数据
文档修正(实测暴露,非人工审查)
· DDL 缺陷:sys_tenant.contact_phone / sys_user.phone / collect_roster.phone
原 varchar(20) 按明文长度建,装不下 AES-GCM 密文(约 52 字符),改 varchar(128)(PRD V2.4)
· 错误码 40007b/40007c 带字母后缀与「code 为数字」的约定冲突,规范化为 40071/40072
· 07-开发实施计划 新增 §9 版本兼容踩坑记录(10 条实录)与 §10 M0 完成情况
|
2026-09-28 17:28:21 +08:00 |
|
lovife
|
63aec55329
|
docs: 产品文档与交互原型(P1-P7 交付物)
一期范围:学校收集 + 自主认定(4 类材料全部有实测样本)
- 主 PRD 190KB:125 条 FR / 21 条 VAL / 20 张表 DDL / 121 个接口
- 功能逻辑卷 88KB:不含代码模块
- 接口设计 116KB:58 个错误码 / 12 个 VO
- 核心模块设计:M1 命名 / M2 压缩 / M3 识别 / M4 门禁 / M5 校验 / M6 导出
- 开发任务拆解:100 任务 / 387 人日 / 15 周
- 验收测试清单:36 条 Golden 断言 / 111 条功能验收
- PostgreSQL DDL:已在 PG 16.15 实测零错误
- 交互原型 31 屏:学生端 11 / 班主任端 9 / 管理端 11
|
2026-09-28 16:19:19 +08:00 |
|