diff --git a/server/api/admin/users/[id].put.ts b/server/api/admin/users/[id].put.ts index 2d2e38f..2f5884c 100644 --- a/server/api/admin/users/[id].put.ts +++ b/server/api/admin/users/[id].put.ts @@ -55,12 +55,37 @@ export default defineEventHandler(async (event) => { const currentLevel = getRoleLevel(user.role) const targetLevel = getRoleLevel(targetUser.role) - // 1. 禁止修改系统初始超级管理员 (ID: 1) + /* + * 系统初始超级管理员(ID=1,登录名 admin)的处理 —— 第 90 轮按站长要求放宽。 + * + * 原来这里是"一律禁止修改"(403 无法修改系统初始超级管理员), + * 结果是连它的**显示名都改不了**(站长想把界面上的 admin 改成自己的名字)。 + * 现在按"哪些能改、哪些必须锁死"拆开: + * · 允许:姓名(显示名)、年级、班级、状态; + * · 锁死:**登录名必须保持 admin** —— 那是 admin/admin123 的应急登录通道,改了就没了; + * · 锁死:角色不能动(不能把自己降权,否则没人能管站点); + * · 锁死:密码不在这里改(避免被其它管理员顺手重置)。 + */ if (targetUser.id === 1) { - throw createError({ - statusCode: 403, - statusMessage: '无法修改系统初始超级管理员' - }) + const nextUsername = String(username || '').trim() + if (nextUsername && nextUsername !== targetUser.username) { + throw createError({ + statusCode: 400, + statusMessage: '初始超级管理员的登录名必须保持 admin(应急登录通道,改了就无法用它登录)' + }) + } + if (role && role !== targetUser.role) { + throw createError({ + statusCode: 403, + statusMessage: '不能修改初始超级管理员的角色' + }) + } + if (password) { + throw createError({ + statusCode: 403, + statusMessage: '不能在用户管理中重置初始超级管理员的密码(请用它登录后在「设置」里自行修改)' + }) + } } // 2. 禁止对自身进行任何用户管理操作(包括角色、资料、状态、密码等) diff --git a/server/api/admin/users/[id]/promote-super.post.ts b/server/api/admin/users/[id]/promote-super.post.ts new file mode 100644 index 0000000..c9f9013 --- /dev/null +++ b/server/api/admin/users/[id]/promote-super.post.ts @@ -0,0 +1,66 @@ +import { eq } from 'drizzle-orm' +import { db } from '~/drizzle/db' +import { users } from '~/drizzle/schema' +import { getRoleLevel } from '~~/server/utils/permissions' + +/** + * 把某个账号**提升为超级管理员**(第 90 轮新增)。 + * + * 为什么单独开一个接口,而不是放开 `[id].put.ts` 的 role 字段: + * 那里面 `canChangeRoleOf()` **明确禁止**把任何人提升为 SUPER_ADMIN + * (报错原文:"超级管理员不能将目标用户提升为 SUPER_ADMIN"), + * 而且用户管理的角色下拉也**故意不给** SUPER_ADMIN 选项(网页版同样如此)。 + * 站长的诉求是"用我自己绑了微信的中文账号做日常管理",所以要给一条**显式、可审计**的通道: + * 单独接口 + 前端二次确认,而不是把通用编辑接口的口子放大。 + * + * 权限:只有 SUPER_ADMIN 能调;不能提升自己(已经是了);不能对已经是超管的账号重复提升。 + * 注意:初始超级管理员(ID=1)本身就是 SUPER_ADMIN,会命中"已经是超级管理员"。 + */ +export default defineEventHandler(async (event) => { + const user = event.context.user + if (!user) { + throw createError({ statusCode: 401, message: '未登录' }) + } + if (user.role !== 'SUPER_ADMIN') { + throw createError({ statusCode: 403, message: '仅超级管理员可以提升其他账号为超级管理员' }) + } + + const userId = Number(getRouterParam(event, 'id')) + if (!userId || Number.isNaN(userId)) { + throw createError({ statusCode: 400, message: '无效的用户ID' }) + } + if (userId === user.id) { + throw createError({ statusCode: 400, message: '你自己已经是超级管理员了' }) + } + + const rows = await db.select().from(users).where(eq(users.id, userId)).limit(1) + if (rows.length === 0) { + throw createError({ statusCode: 404, message: '用户不存在' }) + } + const target = rows[0] + + if (target.role === 'SUPER_ADMIN') { + throw createError({ statusCode: 400, message: `「${target.name || target.username}」已经是超级管理员` }) + } + // 只允许"向上提升",不允许借此降权(降权仍走通用编辑接口) + if (getRoleLevel(target.role) > getRoleLevel('SUPER_ADMIN')) { + throw createError({ statusCode: 400, message: '目标账号角色异常,无法提升' }) + } + + await db.update(users).set({ role: 'SUPER_ADMIN' }).where(eq(users.id, userId)) + + // 角色变了 → 清掉它的认证缓存,避免旧权限继续生效 + try { + const { cache } = await import('~~/server/utils/cache-helpers') + await cache.delete(`auth:user:${userId}`) + } catch { + // 清缓存失败不影响提升结果 + } + + console.log(`[Users] ${user.username} 把 ${target.username}(#${userId}) 提升为 SUPER_ADMIN`) + return { + success: true, + message: `已把「${target.name || target.username}」提升为超级管理员`, + user: { id: target.id, name: target.name, username: target.username, role: 'SUPER_ADMIN' } + } +})