Files
alpenwerk-hr/app/(app)/layout.tsx
Andrei Laas c6cff9656e
Some checks failed
CI / Lint, Typen, Tests, Build (push) Failing after 5m27s
CI / Migrationen auf leerer Datenbank (push) Successful in 10m3s
Passwort-Anmeldung: Provider, Formulare, drei Zustaende der Shell
2026-09-08 16:51:14 +02:00

45 lines
1.9 KiB
TypeScript

import { redirect } from "next/navigation";
import type { ReactNode } from "react";
import { HireWizardProvider } from "@/components/hire/HireWizardContext";
import { AppShell } from "@/components/shell/AppShell";
import { currentUserId } from "@/lib/auth/session";
import { withUser } from "@/lib/db";
import { loadShellData } from "@/lib/shell-data";
export default async function AppLayout({ children }: { children: ReactNode }) {
const userId = await currentUserId();
if (!userId) redirect("/login");
// Alles in *einer* Transaktion, weil nur dort der Sitzungskontext gilt —
// und damit nebenbei auf einem einheitlichen Lesestand. Was dabei in wie
// vielen Rundreisen gelesen wird, steht in lib/shell-data.ts.
const ergebnis = await withUser(userId, (tx) => loadShellData(tx, userId));
// Hier — und nicht im Proxy — fällt diese Entscheidung: der Proxy hat keine
// Datenbankverbindung. Sie wird bei jedem Aufbau frisch gestellt, eine
// entzogene Freischaltung wirkt also sofort statt erst mit dem nächsten
// Sitzungstoken.
//
// Beide Umleitungen sind Bedienkomfort, keine Absicherung: wer sie umgeht,
// bekommt trotzdem keine Zeile, weil die RLS-Policies dieselbe Frage stellen
// (is_hr_user()). Ohne sie stünde die Person nur vor einer leeren Anwendung
// und wüsste nicht, warum.
if (ergebnis.status === "passwort_wechseln") redirect("/passwort-aendern");
// Ohne den Grund in der Adresse stünde die Person vor einer wortlosen
// Anmeldeseite und versuchte es endlos erneut.
if (ergebnis.status === "kein_zugang") redirect("/login?error=no_hr_access");
const data = ergebnis.daten;
const userLabel = data.profile.full_name || data.profile.email || "";
return (
<HireWizardProvider openPositions={data.openPositions} locations={data.locations} drafts={data.drafts}>
<AppShell userLabel={userLabel} openNotes={data.openNotes}>
{children}
</AppShell>
</HireWizardProvider>
);
}