feat(auth): 移除多角色体验账号直登,仅保留微信手机号授权登录
- 登录页删除体验账号卡片、切换按钮与全部 demo 登录/失败回退逻辑,微信授权失败只提示重试 - completeLogin 只接受服务端签发的 token,禁止无 token 的假登录 - 删除 /api/auth/demo-accounts、/api/auth/demo-login、loadDemoAccounts 与客户端 API - 停止种子 demo_accounts 配置并清理历史配置行;117 套件/763 用例全绿;线上接口已 404
这个提交包含在:
@@ -1352,22 +1352,9 @@ async function seedInitialDataIfEmpty(conn: any): Promise<void> {
|
||||
`, [mapLocationConfigVal]);
|
||||
}
|
||||
|
||||
// 体验账号(演示/评审):账号清单与展示文案全部落库,小程序端不再写死
|
||||
const demoAccountsVal = JSON.stringify({
|
||||
enabled: true,
|
||||
accounts: [
|
||||
{ userId: 1001, roleTag: 'host', roleDesc: '房主/局长', desc: '余额充足 · 发起项目制/AA组局' },
|
||||
{ userId: 2001, roleTag: 'buyer', roleDesc: '普通买家', desc: '搭子报名 · 预约陪伴 · 核销码签到' },
|
||||
{ userId: 2006, roleTag: 'expert', roleDesc: '金牌陪伴师', desc: '工作台接单 · 雷达抢单 · 现场核销' }
|
||||
],
|
||||
remark: '体验账号:仅此处配置的账号可走「体验登录」获取真实会话 token;清空 accounts 即关闭体验登录'
|
||||
});
|
||||
if (!existingKeys.has('demo_accounts')) {
|
||||
await conn.query(`
|
||||
INSERT INTO platform_configs (config_key, name, value_json, description, status)
|
||||
VALUES ('demo_accounts', '体验账号配置', ?, '演示/评审用体验账号清单(含展示文案),关闭时清空 accounts', 1)
|
||||
`, [demoAccountsVal]);
|
||||
}
|
||||
// 体验账号直登已下线:清理历史配置,避免残留测试账号清单
|
||||
await conn.query("DELETE FROM platform_configs WHERE config_key = 'demo_accounts'");
|
||||
|
||||
if (existingKeys.has('platform_protocol')) {
|
||||
const [protoRows]: any = await conn.query("SELECT value_json FROM platform_configs WHERE config_key = 'platform_protocol'");
|
||||
if (protoRows && protoRows.length > 0) {
|
||||
|
||||
@@ -3090,88 +3090,6 @@ app.post('/api/auth/wechat-phone', async (req: Request, res: Response) => {
|
||||
}
|
||||
});
|
||||
|
||||
// ===== 体验账号(演示/评审):清单与文案全部来自 DB 配置,小程序端不再写死 =====
|
||||
async function loadDemoAccounts(): Promise<Array<{ userId: number; roleTag: string; roleDesc: string; desc: string }>> {
|
||||
try {
|
||||
const record = await repo.getPlatformConfigByKey('demo_accounts');
|
||||
const value = (record && record.valueJson) || {};
|
||||
if (value.enabled === false) return [];
|
||||
const accounts = Array.isArray(value.accounts) ? value.accounts : [];
|
||||
return accounts
|
||||
.map((a: any) => ({
|
||||
userId: Number(a.userId) || 0,
|
||||
roleTag: String(a.roleTag || ''),
|
||||
roleDesc: String(a.roleDesc || ''),
|
||||
desc: String(a.desc || ''),
|
||||
}))
|
||||
.filter((a: any) => a.userId > 0)
|
||||
.slice(0, 10);
|
||||
} catch (e) {
|
||||
logServerError('loadDemoAccounts', e);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
app.get('/api/auth/demo-accounts', async (_req: Request, res: Response) => {
|
||||
try {
|
||||
const accounts = await loadDemoAccounts();
|
||||
const list = [];
|
||||
for (const acc of accounts) {
|
||||
const u: any = await repo.getUserById(acc.userId);
|
||||
if (!u) continue;
|
||||
if (u.status === '已封禁' || u.status === '封禁') continue;
|
||||
list.push({
|
||||
userId: u.id,
|
||||
nickname: u.nickname || `用户${u.id}`,
|
||||
avatar: u.avatar || '',
|
||||
roleTag: acc.roleTag,
|
||||
roleDesc: acc.roleDesc,
|
||||
desc: acc.desc,
|
||||
});
|
||||
}
|
||||
res.json({ code: 20000, data: list });
|
||||
} catch (err: any) {
|
||||
res.status(500).json({ code: 50000, message: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
// 体验登录:只对 DB 配置内的账号签发真实 token,避免"无 token 的假登录"造成的 401/身份错配
|
||||
app.post('/api/auth/demo-login', rateLimit({ name: 'demo_login', windowMs: 60 * 1000, max: 20, key: rateWriteKey }), async (req: Request, res: Response) => {
|
||||
try {
|
||||
const userId = Number(req.body?.userId) || 0;
|
||||
const accounts = await loadDemoAccounts();
|
||||
if (!accounts.some((a) => a.userId === userId)) {
|
||||
return res.status(403).json({ code: 40300, message: '该账号未开启体验登录' });
|
||||
}
|
||||
const user: any = await repo.getUserById(userId);
|
||||
if (!user) {
|
||||
return res.status(404).json({ code: 40400, message: '体验账号不存在或已被清理' });
|
||||
}
|
||||
if (user.status === '已封禁' || user.status === '封禁') {
|
||||
return res.status(403).json({ code: 40300, message: '该体验账号已被封禁' });
|
||||
}
|
||||
const token = signUserToken(user.id);
|
||||
res.json({
|
||||
code: 20000,
|
||||
data: {
|
||||
userId: user.id,
|
||||
user: {
|
||||
id: user.id,
|
||||
nickname: user.nickname,
|
||||
avatar: user.avatar,
|
||||
gender: user.gender,
|
||||
phone: user.phone,
|
||||
},
|
||||
userToken: token,
|
||||
token,
|
||||
},
|
||||
message: '体验登录成功',
|
||||
});
|
||||
} catch (err: any) {
|
||||
res.status(500).json({ code: 50000, message: err.message || '体验登录异常' });
|
||||
}
|
||||
});
|
||||
|
||||
// 微信小程序 JSAPI 统一下单预支付接口 (支持真实商户号配置与沙盒收银台无缝切换)
|
||||
app.post('/api/pay/wechat/prepay', rateLimit({ name: 'prepay', windowMs: 60 * 1000, max: 30, key: rateWriteKey }), async (req: Request, res: Response) => {
|
||||
try {
|
||||
|
||||
在新工单中引用
屏蔽一个用户