diff --git a/server/api/admin/users/[id].put.ts b/server/api/admin/users/[id].put.ts index 9825c1b..f65cf5b 100644 --- a/server/api/admin/users/[id].put.ts +++ b/server/api/admin/users/[id].put.ts @@ -109,12 +109,29 @@ export default defineEventHandler(async (event) => { } } - // 2. 禁止对自身进行任何用户管理操作(包括角色、资料、状态、密码等) + /* + * 2. 自己改自己:**只允许改姓名(显示名)**,其余一律禁止。 + * + * 站长要在「用户管理」里把 admin 的显示名改成自己的名字(登录名仍是 admin), + * 原来这里是"自己一律不能改",于是他只看到「禁止在用户管理中修改自己的账户」。 + * 放宽到"只有姓名变了、其它字段一个都没动"是安全的:改不了角色/状态/密码/账号名, + * 也提不了权,只是换个显示名而已(等价于个人资料页改名字)。 + */ if (String(userId) === String(user.id)) { - throw createError({ - statusCode: 400, - statusMessage: '禁止在用户管理中修改自己的账户' - }) + const gradeChanged = String(grade || '').trim() !== String(targetUser.grade || '').trim() + const classChanged = String(userClass || '').trim() !== String(targetUser.class || '').trim() + const statusChanged = + !!status && String(status).toLowerCase() !== String(targetUser.status || '').toLowerCase() + const roleChanged = !!role && role !== targetUser.role + const onlyNameChanged = + nameChanged && !usernameChanged && !gradeChanged && !classChanged && !statusChanged && !roleChanged && !password + + if (!onlyNameChanged) { + throw createError({ + statusCode: 400, + statusMessage: '禁止在用户管理中修改自己的账户(自己只能改「姓名」,其它请到「设置」里操作)' + }) + } } // 3. 非超级管理员必须严格高于目标角色级别 @@ -144,7 +161,16 @@ export default defineEventHandler(async (event) => { // 角色权限控制(统一使用 canChangeRoleOf 语义化检查) let validRole = targetUser.role if (role && role !== targetUser.role) { - if (!canChangeRoleOf(user, targetUser, role)) { + /* + * 站长要求用户编辑表单的角色下拉里要有「技术运维」(SUPER_ADMIN)。 + * 原 canChangeRoleOf() 一律禁止提升为 SUPER_ADMIN(网页版也这么设计), + * 这里对**超级管理员**放开这一条:只有超管能把别人提升为超管,且目标不能是初始账号(ID=1,它本来就是)。 + * 效果与 POST /api/admin/users/{id}/promote-super 一致,两条路都可用。 + */ + const allowPromoteBySuper = + user.role === 'SUPER_ADMIN' && role === 'SUPER_ADMIN' && targetUser.id !== 1 + + if (!allowPromoteBySuper && !canChangeRoleOf(user, targetUser, role)) { throw createError({ statusCode: 403, statusMessage: user.role === 'SUPER_ADMIN'