fix(admin): cascade delete user tokens; test invite cleanup
This commit is contained in:
@@ -86,6 +86,28 @@ ok(tSet.body?.ok === true, 'attachment_set_thumb 回填缩略图', tSet.body);
|
||||
const tGet = await api(A, 'POST', '/api/attachment_thumb', { id: rawUp.b?.data?.item?.id }, T);
|
||||
ok(tGet.body?.data?.data_b64 === Buffer.from('RAWSUMB').toString('base64'), 'attachment_thumb 读回 raw 缩略图', tGet.body);
|
||||
|
||||
// ---- admin 用户删除级联 ----
|
||||
const invDel = await api(A, 'POST', '/admin/invites/generate', { count: 1 }, T);
|
||||
const delCode = invDel.body?.data?.codes?.[0];
|
||||
const regDel = await api(A, 'POST', '/auth/register', { username: 'deltgt', password: 'password123', invite_code: delCode });
|
||||
ok(regDel.status === 200, 'deltgt 注册', regDel.body);
|
||||
const usersBefore = await api(A, 'GET', '/admin/users', undefined, T);
|
||||
const delUser = usersBefore.body?.data?.users?.find((u) => u.username === 'deltgt');
|
||||
ok(!!delUser, 'deltgt 出现在用户列表', delUser);
|
||||
const selfUser = usersBefore.body?.data?.users?.find((u) => u.username === 'demo');
|
||||
const selfDel = await api(A, 'POST', '/admin/users/delete', { user_id: selfUser.id }, T);
|
||||
ok(selfDel.status !== 200, '不能删除自己(高危保护)', selfDel.status);
|
||||
const delResp = await api(A, 'POST', '/admin/users/delete', { user_id: delUser.id }, T);
|
||||
ok(delResp.status === 200, 'admin_user_delete 断言:删除成功', delResp.body);
|
||||
const usersAfter = await api(A, 'GET', '/admin/users', undefined, T);
|
||||
ok(!usersAfter.body?.data?.users?.some((u) => u.username === 'deltgt'), 'deltgt 已从列表移除');
|
||||
ok(!fs.existsSync(path.join(dataA, 'users', delUser.id + '.db')), '用户库文件已删除');
|
||||
ok(!fs.existsSync(path.join(dataA, 'users', String(delUser.id))), '用户附件目录已删除');
|
||||
// 清理测试邀请码,恢复邀请码计数
|
||||
const delInv = await api(A, 'GET', '/admin/invites', undefined, T);
|
||||
const invRow = delInv.body?.data?.invites?.find((i) => i.code === delCode);
|
||||
if (invRow) { await api(A, 'POST', '/admin/invites/delete', { id: invRow.id }, T); }
|
||||
|
||||
// 个人信息:upsert → get 往返
|
||||
const profileContent = { info: { name: '张三', school: '重庆城市科技学院', major: '网络工程' }, resume: { selfIntro: '热爱安全研究' } };
|
||||
const pUp = await api(A, 'POST', '/api/profile_upsert', { content: profileContent }, T);
|
||||
|
||||
@@ -180,7 +180,7 @@ const server = http.createServer(async (req, res) => {
|
||||
// 用户删除:高危操作,级联清理(图床文件 → 用户库 → 附件目录 → 认证数据)
|
||||
if (req.method === 'POST' && route === '/admin/users/delete') {
|
||||
const body = await readJson(req);
|
||||
const uid = Number(body.user_id);
|
||||
const uid = String(body.user_id ?? '').trim();
|
||||
const target = db.prepare('SELECT id, username, is_admin FROM users WHERE id=?').get(uid);
|
||||
if (!target) return send(404, false, '用户不存在');
|
||||
if (target.id === auth.user_id) return send(400, false, '不能删除当前登录的账号自己');
|
||||
@@ -208,6 +208,7 @@ const server = http.createServer(async (req, res) => {
|
||||
// 认证库级联清理
|
||||
db.exec('BEGIN');
|
||||
try {
|
||||
db.prepare('DELETE FROM tokens WHERE user_id=?').run(target.id);
|
||||
db.prepare('DELETE FROM current WHERE user_id=?').run(target.id);
|
||||
db.prepare('DELETE FROM attachments WHERE user_id=?').run(target.id);
|
||||
db.prepare('DELETE FROM devices WHERE user_id=?').run(target.id);
|
||||
|
||||
Reference in New Issue
Block a user