115 lines
4.1 KiB
TypeScript
115 lines
4.1 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
|
import { getServerSession } from 'next-auth'
|
|
import { authOptions } from '@/lib/auth'
|
|
import { prisma } from '@/lib/prisma'
|
|
import { isCurrentSuperAdmin } from '@/lib/admin-permissions'
|
|
|
|
function buildParentMap(users: Array<{ id: string; parentId: string | null }>) {
|
|
const map = new Map<string, string | null>()
|
|
users.forEach((u) => map.set(u.id, u.parentId))
|
|
return map
|
|
}
|
|
|
|
function isAncestor(ancestorId: string, nodeId: string, parentMap: Map<string, string | null>) {
|
|
let current: string | null | undefined = nodeId
|
|
while (current) {
|
|
if (current === ancestorId) return true
|
|
current = parentMap.get(current) ?? null
|
|
}
|
|
return false
|
|
}
|
|
|
|
export async function POST(req: NextRequest) {
|
|
try {
|
|
const session = await getServerSession(authOptions)
|
|
const sessionUser = session?.user as any
|
|
if (!session || sessionUser?.role !== 'ADMIN') {
|
|
return NextResponse.json({ error: '无权限' }, { status: 403 })
|
|
}
|
|
if (!(await isCurrentSuperAdmin(session))) {
|
|
return NextResponse.json({ error: '权限不足:只有最高权限账号可以调整用户层级' }, { status: 403 })
|
|
}
|
|
|
|
const { userId, parentId } = await req.json()
|
|
if (!userId) {
|
|
return NextResponse.json({ error: '缺少 userId' }, { status: 400 })
|
|
}
|
|
if (parentId && typeof parentId !== 'string') {
|
|
return NextResponse.json({ error: 'parentId 参数无效' }, { status: 400 })
|
|
}
|
|
if (userId === parentId) {
|
|
return NextResponse.json({ error: '不能将用户设置为自己的上级' }, { status: 400 })
|
|
}
|
|
|
|
const [currentUser, targetUser] = await Promise.all([
|
|
prisma.user.findUnique({
|
|
where: { id: sessionUser.id },
|
|
select: { id: true, isSuperAdmin: true },
|
|
}),
|
|
prisma.user.findUnique({
|
|
where: { id: userId },
|
|
select: { id: true, parentId: true, isSuperAdmin: true },
|
|
}),
|
|
])
|
|
|
|
if (!currentUser) {
|
|
return NextResponse.json({ error: '当前用户不存在' }, { status: 404 })
|
|
}
|
|
if (!targetUser) {
|
|
return NextResponse.json({ error: '用户不存在' }, { status: 404 })
|
|
}
|
|
|
|
if (targetUser.isSuperAdmin && !currentUser.isSuperAdmin) {
|
|
return NextResponse.json({ error: '无权限调整最高权限账号' }, { status: 403 })
|
|
}
|
|
|
|
let parentUser: { id: string; parentId: string | null; isSuperAdmin: boolean } | null = null
|
|
if (parentId) {
|
|
parentUser = await prisma.user.findUnique({
|
|
where: { id: parentId },
|
|
select: { id: true, parentId: true, isSuperAdmin: true },
|
|
})
|
|
if (!parentUser) {
|
|
return NextResponse.json({ error: '新的上级不存在' }, { status: 404 })
|
|
}
|
|
}
|
|
|
|
const allUsers = await prisma.user.findMany({
|
|
select: { id: true, parentId: true },
|
|
})
|
|
const parentMap = buildParentMap(allUsers)
|
|
|
|
if (parentId && isAncestor(targetUser.id, parentId, parentMap)) {
|
|
return NextResponse.json({ error: '不能将用户的下级设置为其上级,避免形成循环' }, { status: 400 })
|
|
}
|
|
|
|
if (!currentUser.isSuperAdmin) {
|
|
if (!isAncestor(currentUser.id, targetUser.id, parentMap)) {
|
|
return NextResponse.json({ error: '只能调整自己分支内的下属' }, { status: 403 })
|
|
}
|
|
if (!parentId) {
|
|
return NextResponse.json({ error: '不能将下属提升为顶层,请选择本分支内的上级' }, { status: 403 })
|
|
}
|
|
if (!isAncestor(currentUser.id, parentId, parentMap) && parentId !== currentUser.id) {
|
|
return NextResponse.json({ error: '不能跨分支调整下属' }, { status: 403 })
|
|
}
|
|
if (parentUser?.isSuperAdmin) {
|
|
return NextResponse.json({ error: '不能将下属挂载到最高权限账号' }, { status: 403 })
|
|
}
|
|
}
|
|
|
|
const updated = await prisma.user.update({
|
|
where: { id: userId },
|
|
data: { parentId: parentId ?? null },
|
|
select: { id: true, parentId: true },
|
|
})
|
|
|
|
return NextResponse.json({ success: true, userId: updated.id, parentId: updated.parentId })
|
|
} catch (e) {
|
|
console.error('Update hierarchy error:', e)
|
|
return NextResponse.json({ error: '更新失败' }, { status: 500 })
|
|
}
|
|
}
|
|
|
|
|