50 lines
2.3 KiB
TypeScript
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>
|
|
);
|
|
}
|