WuYongJie f646b71813
Some checks failed
CI Check / check (push) Has been cancelled
chore: 初始化本地仓库并同步最近改动
2025-11-18 17:50:16 +08:00

111 lines
3.9 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server'
import { getServerSession } from 'next-auth'
import { authOptions } from '@/lib/auth'
import { prisma } from '@/lib/prisma'
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 })
}
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 })
}
}