syncova-policies/app/api/users/[id]/route.ts
Weapie 265ca8ac38
All checks were successful
Container-Image bauen und veröffentlichen / build-and-push (push) Successful in 5m15s
Improve accessibility and access controls; verify production and database recovery
2026-09-14 11:44:41 +02:00

52 lines
3.2 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server'
import { getAdminSession } from '@/lib/require-admin'
import { prisma } from '@/lib/prisma'
import { validateUserInput } from '@/lib/user-validation'
import bcrypt from 'bcryptjs'
import type { Prisma } from '@prisma/client'
async function mutate(request: NextRequest, params: Promise<{ id: string }>, remove: boolean) {
const session = await getAdminSession()
if (!session) return NextResponse.json({ error: 'Nicht autorisiert' }, { status: 401 })
if (session.user.role !== 'SUPER_ADMIN') return NextResponse.json({ error: 'Nur Super-Admins dürfen Benutzer verwalten.' }, { status: 403 })
const raw = (await params).id
if (!/^[1-9]\d*$/.test(raw) || !Number.isSafeInteger(Number(raw))) return NextResponse.json({ error: 'Ungültige ID' }, { status: 400 })
const id = Number(raw)
try {
const data = remove ? {} : await request.json()
const error = remove ? null : validateUserInput(data, false)
if (error) return NextResponse.json({ error }, { status: 400 })
if (remove && id === Number(session.user.id)) return NextResponse.json({ error: 'Sie können sich nicht selbst löschen.' }, { status: 400 })
const update: Prisma.UserUpdateInput = {}
if (data.email !== undefined) update.email = data.email.trim().toLowerCase()
if (data.name !== undefined) update.name = data.name?.trim() || null
if (data.role !== undefined) update.role = data.role
if (data.isActive !== undefined) update.isActive = data.isActive
if (data.password) update.password = await bcrypt.hash(data.password, 12)
const result = await prisma.$transaction(async tx => {
const user = await tx.user.findUnique({ where: { id } })
if (!user) return { status: 404, body: { error: 'Benutzer nicht gefunden.' } }
const demote = remove || (data.role !== undefined && data.role !== 'SUPER_ADMIN') || data.isActive === false
if (user.isActive && user.role === 'SUPER_ADMIN' && demote &&
await tx.user.count({ where: { role: 'SUPER_ADMIN', isActive: true } }) <= 1) {
return { status: 400, body: { error: 'Mindestens ein aktiver Super-Admin muss erhalten bleiben.' } }
}
if (remove) {
await tx.user.delete({ where: { id } })
return { status: 200, body: { message: 'Benutzer gelöscht.' } }
}
const saved = await tx.user.update({ where: { id }, data: update,
select: { id: true, email: true, name: true, role: true, isActive: true, updatedAt: true } })
return { status: 200, body: saved }
})
return NextResponse.json(result.body, { status: result.status })
} catch (error) {
if (error && typeof error === 'object' && 'code' in error && error.code === 'P2002')
return NextResponse.json({ error: 'Diese E-Mail-Adresse wird bereits verwendet.' }, { status: 409 })
console.error('Benutzerverwaltung fehlgeschlagen', error)
return NextResponse.json({ error: 'Benutzer konnte nicht geändert werden.' }, { status: 500 })
}
}
export async function PUT(request: NextRequest, { params }: { params: Promise<{ id: string }> }) { return mutate(request, params, false) }
export async function DELETE(request: NextRequest, { params }: { params: Promise<{ id: string }> }) { return mutate(request, params, true) }