2026-06-03 18:41:52 +08:00

167 lines
5.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { NextRequest, NextResponse } from 'next/server'
import { getServerSession } from 'next-auth'
import { authOptions } from '@/lib/auth'
import { prisma } from '@/lib/prisma'
import { planDepartmentScopeWithPaidCore } from '@/lib/license'
// 统一更新用户信息;历史素材作者名只允许最高权限账号显式同步。
export async function POST(req: NextRequest) {
try {
const session = await getServerSession(authOptions)
if (!session || (session.user as any)?.role !== 'ADMIN') {
return NextResponse.json(
{ error: '权限不足' },
{ status: 403 }
)
}
const { userId, username, department, role, isActive, canDownload, syncMaterialAuthorName } = await req.json()
if (!userId) {
return NextResponse.json(
{ error: '缺少用户ID' },
{ status: 400 }
)
}
// 获取当前登录用户信息
const currentUser = await prisma.user.findUnique({
where: { id: (session.user as any).id },
select: { id: true, managedDepartment: true }
}) as any
if (!currentUser) {
return NextResponse.json(
{ error: '当前用户不存在' },
{ status: 404 }
)
}
// 获取当前用户的完整信息(包括 isSuperAdmin)
const currentUserFull = await prisma.user.findUnique({
where: { id: (session.user as any).id },
}) as any
// 获取更新前的用户信息
const oldUser = await prisma.user.findUnique({
where: { id: userId },
select: {
id: true,
username: true,
department: true
}
})
if (!oldUser) {
return NextResponse.json(
{ error: '用户不存在' },
{ status: 404 }
)
}
// 获取目标用户的完整信息(包括 isSuperAdmin)
const targetUserFull = await prisma.user.findUnique({
where: { id: userId },
}) as any
// 权限检查:只有最高权限账号或目标用户所属部门的管理员可以编辑
if (!currentUserFull?.isSuperAdmin) {
// 如果是部门管理员,只能编辑自己管理的部门下的用户
if (currentUser.managedDepartment) {
const departments = await prisma.department.findMany({ select: { name: true } })
const scopePlan = await planDepartmentScopeWithPaidCore({
scopeDepartment: currentUser.managedDepartment,
targetDepartment: oldUser.department,
departments,
})
if (!scopePlan.valid || !scopePlan.withinScope) {
return NextResponse.json(
{ error: '权限不足:只能编辑自己管理的部门树范围内的用户' },
{ status: 403 }
)
}
} else {
// 没有管理部门的管理员不能编辑任何人
return NextResponse.json(
{ error: '权限不足' },
{ status: 403 }
)
}
}
// 最高权限账号不能被非最高权限账号编辑
if (targetUserFull?.isSuperAdmin && !currentUserFull?.isSuperAdmin) {
return NextResponse.json(
{ error: '权限不足:不能编辑最高权限账号' },
{ status: 403 }
)
}
const hasProtectedPermissionFields =
role !== undefined ||
(department !== undefined && (department || '') !== (oldUser.department || '')) ||
isActive !== undefined ||
canDownload !== undefined
if (!currentUserFull?.isSuperAdmin && hasProtectedPermissionFields) {
return NextResponse.json(
{ error: '权限不足:只有最高权限账号可以修改角色、部门、启用状态或下载权限' },
{ status: 403 }
)
}
// 构建更新数据
const updateData: any = {}
if (username !== undefined) updateData.username = username
if (department !== undefined) updateData.department = department || ''
if (role !== undefined) updateData.role = role
if (isActive !== undefined) updateData.isActive = isActive
if (canDownload !== undefined) updateData.canDownload = canDownload
const shouldSyncMaterialAuthorName =
Boolean(syncMaterialAuthorName) &&
Boolean(currentUserFull?.isSuperAdmin) &&
username !== undefined &&
username !== oldUser.username
// 使用事务更新用户;历史素材作者名同步仅限最高权限账号显式触发。
const result = await prisma.$transaction(async (tx) => {
// 更新用户信息
const updatedUser = await tx.user.update({
where: { id: userId },
data: updateData,
})
if (shouldSyncMaterialAuthorName) {
await tx.material.updateMany({
where: { userId: userId },
data: { authorName: username },
})
}
return updatedUser
})
console.log('[Update User] Success:', {
userId: result.id,
username: result.username,
department: result.department,
materialsUpdated: shouldSyncMaterialAuthorName
})
return NextResponse.json({
success: true,
user: result,
materialsUpdated: shouldSyncMaterialAuthorName
})
} catch (error) {
console.error('[Update User] Error:', error)
return NextResponse.json(
{ error: '更新用户失败' },
{ status: 500 }
)
}
}