import bcrypt from "bcryptjs"; import crypto from "crypto"; import { NextResponse } from "next/server"; import { prisma } from "../../../lib/prisma"; import { requireSession } from "../../../lib/auth-helpers"; import { sendMail } from "../../../lib/mailer"; import { getEmailVerificationRequired } from "../../../lib/system-settings"; export async function PATCH(request: Request) { const { session } = await requireSession(); if (!session) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } const body = await request.json(); const { currentPassword, newPassword, newEmail } = body || {}; const normalizedEmail = newEmail ? String(newEmail).trim().toLowerCase() : ""; if (!currentPassword) { return NextResponse.json( { error: "Aktuelles Passwort erforderlich." }, { status: 400 } ); } const user = await prisma.user.findUnique({ where: { email: session.user?.email || "" } }); if (!user) { return NextResponse.json({ error: "User nicht gefunden." }, { status: 404 }); } const valid = await bcrypt.compare(currentPassword, user.passwordHash); if (!valid) { return NextResponse.json({ error: "Passwort ungültig." }, { status: 401 }); } const data: { email?: string; passwordHash?: string; emailVerified?: boolean } = {}; let emailVerificationRequired: boolean | null = null; if (normalizedEmail && normalizedEmail !== user.email) { const existing = await prisma.user.findUnique({ where: { email: normalizedEmail } }); if (existing) { return NextResponse.json( { error: "E-Mail bereits vergeben." }, { status: 409 } ); } data.email = normalizedEmail; emailVerificationRequired = await getEmailVerificationRequired(); data.emailVerified = !emailVerificationRequired; } if (newPassword) { data.passwordHash = await bcrypt.hash(newPassword, 10); } if (Object.keys(data).length === 0) { return NextResponse.json({ error: "Keine Änderungen." }, { status: 400 }); } const updated = await prisma.user.update({ where: { id: user.id }, data }); if (data.email) { const verificationRequired = emailVerificationRequired ?? (await getEmailVerificationRequired()); if (!verificationRequired) { return NextResponse.json({ id: updated.id, email: updated.email, changedEmail: true, changedPassword: Boolean(data.passwordHash) }); } const token = crypto.randomUUID(); const expires = new Date(Date.now() + 24 * 60 * 60 * 1000); await prisma.verificationToken.create({ data: { identifier: data.email, token, expires } }); const baseUrl = process.env.NEXTAUTH_URL || "http://localhost:3000"; const verifyUrl = `${baseUrl}/verify/confirm?token=${token}`; await sendMail({ to: data.email, subject: "E-Mail verifizieren", text: `Bitte verifiziere deine E-Mail: ${verifyUrl}` }); } return NextResponse.json({ id: updated.id, email: updated.email, changedEmail: Boolean(data.email), changedPassword: Boolean(data.passwordHash) }); }