66 lines
2.0 KiB
TypeScript
66 lines
2.0 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { z } from "zod";
|
|
|
|
import { getAppSettings, toApprovalThresholdNumber } from "@/lib/app-settings";
|
|
import { snapshotAppSettings } from "@/lib/audit-snapshots";
|
|
import { createAuditLog } from "@/lib/audit-log";
|
|
import { canManageUsers } from "@/lib/domain";
|
|
import prisma from "@/lib/prisma";
|
|
import { getCurrentViewer } from "@/lib/session";
|
|
|
|
const settingsSchema = z.object({
|
|
approvalThreshold: z.coerce.number().min(0).max(100000)
|
|
});
|
|
|
|
export async function PATCH(request: Request) {
|
|
const viewer = await getCurrentViewer();
|
|
|
|
if (!viewer) {
|
|
return NextResponse.json({ error: "Nicht angemeldet." }, { status: 401 });
|
|
}
|
|
|
|
if (!canManageUsers(viewer.role)) {
|
|
return NextResponse.json({ error: "Nur Vorstand allgemein, AG Orga oder AG Finanzen duerfen Einstellungen aendern." }, { status: 403 });
|
|
}
|
|
|
|
const body = await request.json().catch(() => null);
|
|
const parsed = settingsSchema.safeParse(body);
|
|
|
|
if (!parsed.success) {
|
|
return NextResponse.json({ error: "Bitte eine gueltige Freigabe-Schwelle eingeben." }, { status: 400 });
|
|
}
|
|
|
|
const existingSettings = await getAppSettings();
|
|
const previousSnapshot = snapshotAppSettings(existingSettings);
|
|
|
|
const appSettings = await prisma.appSettings.update({
|
|
where: {
|
|
id: existingSettings.id
|
|
},
|
|
data: {
|
|
approvalThreshold: parsed.data.approvalThreshold
|
|
}
|
|
});
|
|
|
|
await createAuditLog(prisma, {
|
|
actorId: viewer.id,
|
|
action: "settings.update",
|
|
entityType: "settings",
|
|
entityId: appSettings.id,
|
|
entityLabel: "Freigabe-Schwelle",
|
|
summary: `Freigabe-Schwelle wurde auf ${toApprovalThresholdNumber(appSettings.approvalThreshold).toFixed(2)} EUR gesetzt.`,
|
|
metadata: {
|
|
approvalThreshold: toApprovalThresholdNumber(appSettings.approvalThreshold),
|
|
rollback: {
|
|
kind: "settings.update",
|
|
previous: previousSnapshot
|
|
}
|
|
}
|
|
});
|
|
|
|
return NextResponse.json({
|
|
ok: true,
|
|
approvalThreshold: toApprovalThresholdNumber(appSettings.approvalThreshold)
|
|
});
|
|
}
|