fix: support soft-delete user uniqueness in tools

This commit is contained in:
hectorzhao
2026-07-26 13:14:46 +08:00
parent 2ce682c3fc
commit 059b38e8fe
3 changed files with 56 additions and 43 deletions
+1
View File
@@ -2488,4 +2488,5 @@ git diff --check
- 手机号码基础校验放宽为`^1\d{10}$`,不依赖号段更新。客户端/HTTP混合批次逐号码把非法号码、平台黑名单和企业应用黑名单记为`submit_failed/rejected`且金额0,合法号码照常冻结、入队;CMPP混合多目的提交对被拦截号码生成平台`REJECTD`失败回执,合法号码继续处理。 - 手机号码基础校验放宽为`^1\d{10}$`,不依赖号段更新。客户端/HTTP混合批次逐号码把非法号码、平台黑名单和企业应用黑名单记为`submit_failed/rejected`且金额0,合法号码照常冻结、入队;CMPP混合多目的提交对被拦截号码生成平台`REJECTD`失败回执,合法号码继续处理。
- 短信审核页只返回待人工审核及人工处理记录,自动放行/拒绝不再混入;号码数量恢复设计基线的查看入口,真实接口仅返回手机号、归属地、运营商和短信状态并支持服务端搜索/分页。 - 短信审核页只返回待人工审核及人工处理记录,自动放行/拒绝不再混入;号码数量恢复设计基线的查看入口,真实接口仅返回手机号、归属地、运营商和短信状态并支持服务端搜索/分页。
- 新待审核短信同步保存`reviewTaskId`,审核决定同时按短信直连和批次`riskTaskId`查找,修复审核任务已通过而短信仍`pending_review`。遵照要求不改写现存历史异常数据、不补发历史短信。 - 新待审核短信同步保存`reviewTaskId`,审核决定同时按短信直连和批次`riskTaskId`查找,修复审核任务已通过而短信仍`pending_review`。遵照要求不改写现存历史异常数据、不补发历史短信。
- 用户登录标识改为“仅未删除记录唯一”后,部署管理员初始化与真实环境冒烟脚本同步从`username`唯一`upsert`改为先查询未删除用户、再按主键更新或创建,避免迁移后Prisma拒绝旧的唯一查询。
- 发布前门禁阶段结果:Prisma format/generate/validate通过;风险审核+发送链定向2 suites / 108 tests通过,随后补充应用覆盖、号码分页与逐号码拦截用例;API全量26 suites / 338 tests、API TypeScript build、前端TypeScript/Vite生产构建、Gateway `go test ./...`/`go vet ./...`、依赖安全门禁通过。API保留既有Redis不可用容错告警与`--forceExit`提示,前端保留约1.95MB单chunk/584.70KB gzip提示。 - 发布前门禁阶段结果:Prisma format/generate/validate通过;风险审核+发送链定向2 suites / 108 tests通过,随后补充应用覆盖、号码分页与逐号码拦截用例;API全量26 suites / 338 tests、API TypeScript build、前端TypeScript/Vite生产构建、Gateway `go test ./...`/`go vet ./...`、依赖安全门禁通过。API保留既有Redis不可用容错告警与`--forceExit`提示,前端保留约1.95MB单chunk/584.70KB gzip提示。
+27 -21
View File
@@ -19,7 +19,9 @@ function hashPassword(value) {
} }
async function main() { async function main() {
const existingUser = await prisma.user.findUnique({ where: { username } }); const existingUser = await prisma.user.findFirst({
where: { username, deletedAt: null },
});
const createPassword = configuredPassword || randomBytes(18).toString('base64url'); const createPassword = configuredPassword || randomBytes(18).toString('base64url');
const updatePassword = configuredPassword; const updatePassword = configuredPassword;
const role = await prisma.role.upsert({ const role = await prisma.role.upsert({
@@ -27,26 +29,30 @@ async function main() {
update: { name: '平台管理员', scope: 'platform' }, update: { name: '平台管理员', scope: 'platform' },
create: { code: 'platform_admin', name: '平台管理员', scope: 'platform' }, create: { code: 'platform_admin', name: '平台管理员', scope: 'platform' },
}); });
const user = await prisma.user.upsert({ const userData = {
where: { username }, email,
update: { displayName: '生产平台管理员',
email, ...(updatePassword ? { passwordHash: hashPassword(updatePassword) } : {}),
displayName: '生产平台管理员', status: 'active',
...(updatePassword ? { passwordHash: hashPassword(updatePassword) } : {}), failedLoginCount: 0,
status: 'active', lockedUntil: null,
failedLoginCount: 0, deletedAt: null,
lockedUntil: null, tenantId: null,
deletedAt: null, };
tenantId: null, const user = existingUser
}, ? await prisma.user.update({
create: { where: { id: existingUser.id },
username, data: userData,
email, })
displayName: '生产平台管理员', : await prisma.user.create({
passwordHash: hashPassword(createPassword), data: {
status: 'active', username,
}, email,
}); displayName: '生产平台管理员',
passwordHash: hashPassword(createPassword),
status: 'active',
},
});
await prisma.userRole.upsert({ await prisma.userRole.upsert({
where: { userId_roleId: { userId: user.id, roleId: role.id } }, where: { userId_roleId: { userId: user.id, roleId: role.id } },
update: {}, update: {},
+28 -22
View File
@@ -25,29 +25,35 @@ async function ensureSmokeData() {
create: { code: tenantCode, name: 'Smoke Test Enterprise', status: 'active' }, create: { code: tenantCode, name: 'Smoke Test Enterprise', status: 'active' },
}); });
const user = await prisma.user.upsert({ const existingUser = await prisma.user.findFirst({
where: { username }, where: { username, deletedAt: null },
update: {
tenantId: tenant.id,
email,
phone,
displayName: 'Smoke Client Admin',
passwordHash: hashPassword(password),
status: 'active',
failedLoginCount: 0,
lockedUntil: null,
deletedAt: null,
},
create: {
tenantId: tenant.id,
username,
email,
phone,
displayName: 'Smoke Client Admin',
passwordHash: hashPassword(password),
status: 'active',
},
}); });
const user = existingUser
? await prisma.user.update({
where: { id: existingUser.id },
data: {
tenantId: tenant.id,
email,
phone,
displayName: 'Smoke Client Admin',
passwordHash: hashPassword(password),
status: 'active',
failedLoginCount: 0,
lockedUntil: null,
deletedAt: null,
},
})
: await prisma.user.create({
data: {
tenantId: tenant.id,
username,
email,
phone,
displayName: 'Smoke Client Admin',
passwordHash: hashPassword(password),
status: 'active',
},
});
const enterpriseAdminRole = await prisma.role.upsert({ const enterpriseAdminRole = await prisma.role.upsert({
where: { code: 'enterprise_admin' }, where: { code: 'enterprise_admin' },