Files
gutscheintracker/app/api/users/[id]/route.ts
T

71 lines
4.0 KiB
TypeScript

import { NextRequest, NextResponse } from "next/server";
import { getDb } from "@/lib/db";
import { getViewer } from "@/lib/viewer";
/** Nutzer zuordnen/entfernen (nur Server-Admin). */
export async function PATCH(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
const viewer = await getViewer();
if (!viewer || viewer.role !== "admin") return NextResponse.json({ error: "forbidden" }, { status: 403 });
const { id } = await params;
const numId = Number(id);
if (!Number.isInteger(numId)) return NextResponse.json({ error: "not found" }, { status: 404 });
const db = getDb();
const target = await db.user.findUnique({ where: { id: numId }, include: { membership: true } });
if (!target) return NextResponse.json({ error: "not found" }, { status: 404 });
const body = await req.json().catch(() => ({}));
const hasHousehold = body.householdId !== undefined && body.householdId !== null;
if (!hasHousehold) {
if (target.membership) await db.householdMember.delete({ where: { userId: numId } });
return NextResponse.json({ ok: true, householdId: null });
}
const hid = Number(body.householdId);
if (!Number.isInteger(hid) || !(await db.household.findUnique({ where: { id: hid } }))) {
return NextResponse.json({ errors: ["householdId"] }, { status: 400 });
}
if (target.membership && target.membership.householdId !== hid) {
return NextResponse.json({ errors: ["householdId"], message: "Nutzer ist bereits einem anderen Haushalt zugeordnet." }, { status: 409 });
}
const householdRole = body.householdRole === "admin" ? "admin" : "member";
await db.householdMember.upsert({
where: { userId: numId },
create: { householdId: hid, userId: numId, role: householdRole },
update: { householdId: hid, role: householdRole },
});
return NextResponse.json({ ok: true, householdId: hid });
}
/** Nutzer löschen (nur Server-Admin). Private Daten werden entfernt, gemeinsame Bestände bleiben erhalten. */
export async function DELETE(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
const viewer = await getViewer();
if (!viewer || viewer.role !== "admin") return NextResponse.json({ error: "forbidden" }, { status: 403 });
const { id } = await params;
const numId = Number(id);
if (!Number.isInteger(numId)) return NextResponse.json({ error: "not found" }, { status: 404 });
if (numId === viewer.id) {
return NextResponse.json({ errors: ["id"], message: "Das eigene Konto kann nicht gelöscht werden." }, { status: 400 });
}
const db = getDb();
const target = await db.user.findUnique({ where: { id: numId } });
if (!target) return NextResponse.json({ error: "not found" }, { status: 404 });
if (target.role === "admin") {
const admins = await db.user.count({ where: { role: "admin" } });
if (admins <= 1) {
return NextResponse.json({ errors: ["id"], message: "Der letzte Admin kann nicht gelöscht werden." }, { status: 400 });
}
}
const privateVoucherIds = (await db.voucher.findMany({ where: { ownerId: numId, householdId: null }, select: { id: true } })).map((v) => v.id);
const privateContactIds = (await db.contact.findMany({ where: { ownerId: numId, householdId: null }, select: { id: true } })).map((c) => c.id);
await db.$transaction([
db.notificationLog.deleteMany({ where: { rule: { voucher: { id: { in: privateVoucherIds } } } } }),
db.reminderRule.deleteMany({ where: { voucherId: { in: privateVoucherIds } } }),
db.voucherContact.deleteMany({ where: { OR: [{ voucherId: { in: privateVoucherIds } }, { contactId: { in: privateContactIds } }] } }),
db.voucher.deleteMany({ where: { id: { in: privateVoucherIds } } }),
db.contact.deleteMany({ where: { id: { in: privateContactIds } } }),
db.voucher.updateMany({ where: { ownerId: numId }, data: { ownerId: viewer.id } }),
db.contact.updateMany({ where: { ownerId: numId }, data: { ownerId: viewer.id } }),
db.householdMember.deleteMany({ where: { userId: numId } }),
db.user.delete({ where: { id: numId } }),
]);
return NextResponse.json({ ok: true });
}