Harden authentication, tenant isolation and security boundaries

This commit is contained in:
t.indorf
2026-10-09 22:49:55 +02:00
parent ec3f4f933d
commit 656ada80bd
71 changed files with 3107 additions and 1200 deletions
+21 -13
View File
@@ -10,6 +10,7 @@ import {
getChildBirthdateRange,
parseDateInput,
} from "@/lib/child-birthdate";
import { serializableTransaction } from "@/lib/transaction";
import { prisma } from "@/lib/prisma";
// Telefonnummern: führendes "+" optional, dann Ziffern, Leerzeichen, Bindestriche,
@@ -118,14 +119,18 @@ export async function createMyChild(rawPayload: unknown) {
}
try {
await prisma.child.create({
data: {
kitaId: session.user.kitaId,
familyId: session.user.familyId,
firstName: parsed.data.firstName,
lastName: parsed.data.lastName,
dateOfBirth: parseDateInput(parsed.data.dateOfBirth),
},
await serializableTransaction(async tx => {
const count = await tx.child.count({ where: { kitaId: session.user.kitaId, familyId: session.user.familyId! } });
if (count >= 20) throw new Error("Household child limit reached");
await tx.child.create({
data: {
kitaId: session.user.kitaId,
familyId: session.user.familyId!,
firstName: parsed.data.firstName,
lastName: parsed.data.lastName,
dateOfBirth: parseDateInput(parsed.data.dateOfBirth),
},
});
});
revalidatePath("/dashboard/profil");
@@ -158,10 +163,11 @@ export async function createMyFamily(rawPayload: unknown) {
},
});
await tx.user.update({
where: { id: session.user.id },
const attached = await tx.user.updateMany({
where: { id: session.user.id, kitaId: session.user.kitaId, familyId: null, disabledAt: null, sessionVersion: session.user.sessionVersion },
data: { familyId: family.id },
});
if (attached.count !== 1) throw new Error("Account already assigned or revoked");
});
revalidatePath("/dashboard/profil");
@@ -170,7 +176,9 @@ export async function createMyFamily(rawPayload: unknown) {
revalidatePath("/dashboard");
return { success: true };
} catch (error) {
console.error("Fehler beim Anlegen des eigenen Haushalts:", error);
if (!(error instanceof Error && error.message === "Account already assigned or revoked")) {
console.error("Fehler beim Anlegen des eigenen Haushalts:", error);
}
return { error: "Der Haushalt konnte nicht angelegt werden." };
}
}
@@ -239,7 +247,7 @@ export async function updateMyChild(childId: string, rawPayload: unknown) {
}
await prisma.child.update({
where: { id: childId },
where: { id: childId, kitaId: session.user.kitaId, familyId: session.user.familyId! },
data: {
firstName: parsed.data.firstName,
lastName: parsed.data.lastName,
@@ -271,7 +279,7 @@ export async function deleteMyChild(childId: string) {
}
await prisma.child.delete({
where: { id: childId },
where: { id: childId, kitaId: session.user.kitaId, familyId: session.user.familyId! },
});
revalidatePath("/dashboard/profil");