feat: allow administrator deletion and remove icon source field
This commit is contained in:
1 parent
a5f1236d44
commit
2db0c75498
18 files changed
+367
-27
No files matched your search
@@ -13,10 +13,14 @@ ADMIN_PASSWORD=admin
|
||||
|
||||
后台接口:`GET /api/admin/users?limit=50&offset=0`、`POST /api/admin/users`、`PATCH /api/admin/users/:id`。列表完整分页,仅返回账号身份、角色、状态和创建时间;不返回哈希、会话令牌或财务数据。角色为 `admin`、`user`、`readonly`。管理动作在事务内重查管理员权限;禁止修改自身角色或封禁自己,并保留可用管理员。
|
||||
|
||||
删除原管理员:先创建或设置另一位管理员,使用新管理员登录并完成首次改密,然后在后台原管理员所在行点击“删除管理员”。输入被删除账号名称和当前管理员密码后确认。`DELETE /api/admin/users/:id` 仅支持删除其他管理员;后端在事务中重查操作人权限、密码是否变化、被删除用户名和剩余管理员状态。至少保留另一位未封禁且完成改密的管理员,不允许删除自己。删除不可撤销,会级联清理该账号财务数据、会话和 MCP 授权,并删除私有图标;已发布共享图标保留。仍有其他管理员时,重启不会重新创建默认 admin。
|
||||
|
||||
角色/封禁状态变化会删除该用户全部会话、撤销 MCP/PAT/OAuth 授权、取消待确认草稿和已批准待兑换授权。解封不会恢复旧令牌。密码修改也会撤销既有 MCP 授权。HTTP 与 MCP 后端都会检查封禁、首次改密和只读权限;只读用户可管理自己的登录密码及只读连接,无法提交财务写入、草稿或确认业务操作。管理员仍遵循原有财务数据用户隔离。
|
||||
|
||||
验证:前后端类型检查、网页生产构建、53 项单元测试,以及使用临时 MySQL 库和独立 API 的管理员与现有业务/MCP/OAuth 回归。当前数据库已应用新增迁移;本机网页验证默认管理员首次登录展示强制改密页,未替用户设置新密码。
|
||||
|
||||
追加验证:新管理员首次改密后删除原 admin 成功,用户名确认或密码错误时拒绝,普通用户和未改密管理员无权删除,禁止删除当前管理员。被删除用户的持仓、历史、私有图标和授权被清理,共享图标保留,新管理员仍可使用后台;再次初始化不会重建原账号。图标表通过 `20261005150000_remove_icon_source` 移除 source,接口、前端类型和图标初始化脚本同步调整,现有 ZIP v9 图标格式保持一致。53 项单元测试与 29 项隔离回归通过。
|
||||
|
||||
运行隔离回归:在仓库根目录执行 `pnpm --filter @worthpath/api test:isolated`。测试库名使用随机 `wp_test_` 前缀,API 使用随机本机端口;完成或失败后清理自己创建的服务和数据库。管理员测试只在该隔离流程中运行,避免修改真实管理员。
|
||||
|
||||
已有迁移目录 `005_account_icons`、`006_navigation_transfers`、`007_notes_display` 排在初始迁移之前,因此原有 `migrate deploy` 从空库初始化会失败。本次未重命名历史迁移。隔离测试用当前 Prisma 模型建立临时库,再移除本次字段并执行新增 SQL 来验证增量迁移;现有库迁移正常。全新部署仍需要单独修复历史迁移顺序。
|
||||
@@ -32,7 +32,7 @@ Revision 保存按业务日期生效的绝对金额,每次金额更新新增
|
||||
|
||||
## 账户图标模块
|
||||
|
||||
Icon 存储 name、ownerId、shared、SHA-256、规范静态 PNG 的 MediumBlob 和可选公开来源;Position.iconId 外键 SetNull,多个账户共享同一图片。所有图标接口使用已验证身份,读取/检索/赋值均限定 shared=true 或 ownerId=当前用户,响应不返回 ownerId。个人上传默认私有;共享发布须中文名称和明确公开确认。拒绝 SVG、动图、损坏图片、超限像素/文件,重编码移除元数据。内置图标固定 ID 追加初始化;在线请求不会发送用户财务数据。
|
||||
Icon 存储 name、ownerId、shared、SHA-256 和规范静态 PNG 的 MediumBlob,不存储 source;内置图标来源保留在资源清单中。Position.iconId 外键 SetNull,多个账户共享同一图片。所有图标接口使用已验证身份,读取/检索/赋值均限定 shared=true 或 ownerId=当前用户,响应不返回 ownerId。个人上传默认私有;共享发布须中文名称和明确公开确认。拒绝 SVG、动图、损坏图片、超限像素/文件,重编码移除元数据。内置图标固定 ID 追加初始化;在线请求不会发送用户财务数据。
|
||||
|
||||
当前备份要求完整 icons 数组,ZIP v9 将图标内容放入 icons.json;内容校验和解码在导入事务前完成,图标在事务内以当前用户私有范围重建,账户关联重映射。清空删除私有图标,公开共享图标不因发布者清空而消失。用户删除时图标 ownerId SetNull,不影响他人已引用的公共图标。
|
||||
|
||||
|
||||
+22
-12
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"tableCount": 17,
|
||||
"columnCount": 161,
|
||||
"columnCount": 163,
|
||||
"tables": [
|
||||
{
|
||||
"TABLE_NAME": "_prisma_migrations",
|
||||
@@ -397,11 +397,6 @@
|
||||
"COLUMN_NAME": "data",
|
||||
"COLUMN_COMMENT": "规范化静态 PNG 图片二进制"
|
||||
},
|
||||
{
|
||||
"TABLE_NAME": "icon",
|
||||
"COLUMN_NAME": "source",
|
||||
"COLUMN_COMMENT": "可选公开来源网址"
|
||||
},
|
||||
{
|
||||
"TABLE_NAME": "icon",
|
||||
"COLUMN_NAME": "createdAt",
|
||||
@@ -552,6 +547,16 @@
|
||||
"COLUMN_NAME": "metalCostPerGram",
|
||||
"COLUMN_COMMENT": "买入时每克实物成本,原币;空值表示不计算盈亏"
|
||||
},
|
||||
{
|
||||
"TABLE_NAME": "position",
|
||||
"COLUMN_NAME": "lastRepaymentMonth",
|
||||
"COLUMN_COMMENT": "最后手动标记已完成还款的业务月份,UTC+8 YYYY-MM;空表示未标记"
|
||||
},
|
||||
{
|
||||
"TABLE_NAME": "position",
|
||||
"COLUMN_NAME": "lastBookedDate",
|
||||
"COLUMN_COMMENT": "最后手动标记已完成记账的业务日期,UTC+8 YYYY-MM-DD;空表示未标记"
|
||||
},
|
||||
{
|
||||
"TABLE_NAME": "positionlink",
|
||||
"COLUMN_NAME": "id",
|
||||
@@ -868,14 +873,19 @@
|
||||
"COLUMN_COMMENT": "独立资产是否参与资产总览和净资产轨迹"
|
||||
},
|
||||
{
|
||||
"TABLE_NAME": "position",
|
||||
"COLUMN_NAME": "lastRepaymentMonth",
|
||||
"COLUMN_COMMENT": "最后手动标记已完成还款的业务月份,UTC+8 YYYY-MM;空表示未标记"
|
||||
"TABLE_NAME": "user",
|
||||
"COLUMN_NAME": "role",
|
||||
"COLUMN_COMMENT": "系统权限:admin、user 或 readonly;管理员不能查看其他用户财务数据"
|
||||
},
|
||||
{
|
||||
"TABLE_NAME": "position",
|
||||
"COLUMN_NAME": "lastBookedDate",
|
||||
"COLUMN_COMMENT": "最后手动标记已完成记账的业务日期,UTC+8 YYYY-MM-DD;空表示未标记"
|
||||
"TABLE_NAME": "user",
|
||||
"COLUMN_NAME": "banned",
|
||||
"COLUMN_COMMENT": "封禁后禁止登录和使用已有会话、MCP 授权"
|
||||
},
|
||||
{
|
||||
"TABLE_NAME": "user",
|
||||
"COLUMN_NAME": "mustChangePassword",
|
||||
"COLUMN_COMMENT": "首次登录必须设置新的强密码"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in new issue
Block a user