import Link from "next/link";
import Image from "next/image";
import { redirect } from "next/navigation";
import { getTranslations } from "next-intl/server";
import {
LayoutDashboard,
Boxes,
GitBranch,
ShieldAlert,
ClipboardCheck,
KanbanSquare,
Siren,
BookOpenText,
MessagesSquare,
Network,
FolderCheck,
Truck,
LineChart,
Search,
Settings,
} from "lucide-react";
import { auth, signOut } from "@/server/auth";
import { dbForTenant } from "@/server/db";
import { hasPermission } from "@/server/rbac";
import { HREF_TO_MODULE } from "@/lib/modules";
import { Button } from "@/components/ui/button";
import { NavLink } from "@/components/nav-link";
export default async function AppLayout({
children,
}: Readonly<{ children: React.ReactNode }>) {
const session = await auth();
if (!session?.user) redirect("/login");
// Kontostatus (autoritativ aus DB, nicht aus dem JWT): deaktivierte Nutzer werden
// abgemeldet, ein offener Passwortwechsel wird erzwungen (Force-Change).
const account = await dbForTenant(session.user.tenantId).user.findUnique({
where: { id: session.user.id },
select: { status: true, mustChangePassword: true },
});
if (!account || account.status !== "ACTIVE") {
return (
Konto deaktiviert
Ihr Zugang wurde deaktiviert. Bitte wenden Sie sich an Ihre Administration.
);
}
if (account.mustChangePassword) redirect("/change-password");
const t = await getTranslations("nav");
const tc = await getTranslations("common");
const nav = [
{ href: "/dashboard", label: t("dashboard"), icon: LayoutDashboard, enabled: true },
{ href: "/assets", label: t("assets"), icon: Boxes, enabled: true },
{ href: "/processes", label: t("bia"), icon: GitBranch, enabled: true },
{ href: "/risks", label: t("risks"), icon: ShieldAlert, enabled: true },
{ href: "/soa", label: t("soa"), icon: ClipboardCheck, enabled: false },
{ href: "/measures", label: t("measures"), icon: KanbanSquare, enabled: true },
{ href: "/incidents", label: t("incidents"), icon: Siren, enabled: false },
{ href: "/policies", label: t("policies"), icon: BookOpenText, enabled: true },
{ href: "/chat", label: t("chat"), icon: MessagesSquare, enabled: false },
{ href: "/dependencies", label: t("dependencies"), icon: Network, enabled: true },
{ href: "/evidence", label: t("evidence"), icon: FolderCheck, enabled: false },
{ href: "/suppliers", label: t("suppliers"), icon: Truck, enabled: true },
{ href: "/review", label: t("review"), icon: LineChart, enabled: false },
];
// Modul-Gating: deaktivierte Module werden ausgeblendet (§3.4)
const moduleRows = await dbForTenant(session.user.tenantId).tenantModule.findMany();
const disabledModules = new Set(moduleRows.filter((m) => !m.enabled).map((m) => m.moduleKey));
const moduleEnabled = (href: string) => {
const key = HREF_TO_MODULE[href];
return !key || !disabledModules.has(key);
};
const visibleNav = nav.filter((item) => !item.enabled || moduleEnabled(item.href));
const canManageTenant = hasPermission(session, "tenant:manage");
const initials = (session.user.name ?? "?")
.split(/\s+/)
.map((p) => p[0])
.slice(0, 2)
.join("")
.toUpperCase();
async function logout() {
"use server";
await signOut({ redirectTo: "/login" });
}
return (
);
}