Files
minecraft-account-manager/apps/web/src/app/admin/(console)/layout.tsx
T
dmg b7c0083647
CI / validate (push) Successful in 5m20s
Release / release (push) Successful in 6m56s
feat(portal): add SSR operations and exclusive groups
2026-08-01 19:21:23 -04:00

50 lines
2.3 KiB
TypeScript

import type { ReactNode } from "react";
import Link from "next/link";
import { redirect } from "next/navigation";
import { getClientIp } from "@minecraft-account-manager/network";
import { recordEvent } from "@minecraft-account-manager/database";
import { headers } from "next/headers";
import { getServerSession } from "next-auth";
import { AdminSignOutButton } from "@/components/admin-sign-out-button";
import { adminAuthOptions, requiredAdminRole } from "@/lib/auth/admin-auth";
import { db } from "@/lib/database";
export const dynamic = "force-dynamic";
export default async function AdminConsoleLayout({ children }: { children: ReactNode }) {
const session = await getServerSession(adminAuthOptions);
if (!session) redirect("/admin/login");
const roles = (session.user as typeof session.user & { roles?: string[] })?.roles ?? [];
if (!roles.includes(requiredAdminRole)) redirect("/admin/login?error=forbidden");
const requestHeaders = await headers();
const ipAddress = getClientIp(requestHeaders, process.env.TRUST_PROXY === "true");
await recordEvent(db, {
type: "games.minecraft.account-manager.ui.accessed",
source: "/web/admin",
subject: "admin-console",
ipAddress: ipAddress ?? undefined,
data: { adminEmail: session.user?.email ?? null },
});
return (
<div className="min-h-screen bg-canvas text-ink">
<header className="border-b border-line bg-panel">
<div className="mx-auto flex max-w-6xl flex-wrap items-center gap-5 px-6 py-5">
<Link className="font-display text-sm font-black uppercase tracking-[0.2em]" href="/admin">SoMC Portal / Ops</Link>
<nav aria-label="Administrator" className="ml-auto flex flex-wrap gap-5 font-mono text-[10px] font-bold uppercase tracking-widest">
<Link className="hover:text-accent" href="/admin">Dashboard</Link>
<Link className="hover:text-accent" href="/admin/settings">Settings</Link>
<Link className="hover:text-accent" href="/admin/users">Users</Link>
<Link className="hover:text-accent" href="/admin/groups">Groups</Link>
<Link className="hover:text-accent" href="/admin/events">Events</Link>
</nav>
<AdminSignOutButton />
</div>
</header>
{children}
</div>
);
}