diff --git a/app/admin/layout.tsx b/app/admin/layout.tsx index 804a4ff..f7db1ea 100644 --- a/app/admin/layout.tsx +++ b/app/admin/layout.tsx @@ -1,7 +1,10 @@ "use client"; + import type React from "react"; -import { useState } from "react"; +import { useEffect, useMemo, useState } from "react"; +import { usePathname, useRouter } from "next/navigation"; import AdminLeftNavigation from "@/components/AdminLeftNavigation"; +import { useAuth } from "@/context/AuthContext"; import { LayoutDashboard, Download, @@ -15,113 +18,96 @@ import { } from "lucide-react"; const navItems = [ - { - label: "Dashboard", - href: "/admin", - icon: , - }, - { - label: "Imports", - href: "/admin/import-status", - icon: , - }, - { - label: "Mappings", - href: "/admin/mapping", - icon: , - }, - { - label: "Products", - href: "/admin/products", - icon: , - }, - { - label: "Merchants", - href: "/admin/merchants", - icon: , - }, - { - label: "Platforms", - href: "/admin/platforms", - icon: , - }, - { - label: "Enrichment", - href: "/admin/enrichment", - icon: , - }, - { - label: "Users", - href: "/admin/users", - icon: , - }, - { - label: "Settings", - href: "/admin/settings", - icon: , - }, - { - label: "List Emails", - href: "/admin/email", - icon: , - }, - { - label: "Send a Email", - href: "/admin/email/send", - icon: , - }, - + { label: "Dashboard", href: "/admin", icon: }, + { label: "Imports", href: "/admin/import-status", icon: }, + { label: "Mappings", href: "/admin/mapping", icon: }, + { label: "Products", href: "/admin/products", icon: }, + { label: "Merchants", href: "/admin/merchants", icon: }, + { label: "Platforms", href: "/admin/platforms", icon: }, + { label: "Enrichment", href: "/admin/enrichment", icon: }, + { label: "Users", href: "/admin/users", icon: }, + { label: "Settings", href: "/admin/settings", icon: }, + { label: "List Emails", href: "/admin/email", icon: }, + { label: "Send an Email", href: "/admin/email/send", icon: }, ]; -// ... existing code ... -// ADMIN CHECK FOR LOGIN -// const { user, loading } = useAuth(); - -// if (!loading && user?.role !== "ADMIN") { -// redirect("/"); // or /login -// } - export default function AdminLayout({ - children, - }: { + children, +}: { children: React.ReactNode; }) { const [collapsed, setCollapsed] = useState(false); + const { user, loading } = useAuth(); + + const router = useRouter(); + const pathname = usePathname(); + + // Where to send people back after login + const next = useMemo( + () => encodeURIComponent(pathname || "/admin"), + [pathname] + ); + + /** + * ✅ AUTH GUARD + * Redirects happen in useEffect (NOT during render) + */ + useEffect(() => { + if (loading) return; + + // Not logged in + if (!user) { + router.replace(`/login?next=${next}`); + return; + } + + // Logged in but not admin + if (user.role !== "ADMIN") { + router.replace("/"); + } + }, [loading, user, router, next]); + + // While loading OR redirecting, render nothing + if (loading) return null; + if (!user) return null; + if (user.role !== "ADMIN") return null; return ( -
- setCollapsed((v) => !v)} - /> +
+ setCollapsed((v) => !v)} + items={navItems} + /> - {/* Main column */} -
- {/* Top bar */} -
-
-

- Admin -

-

- Battl Builders Control Panel -

-
-
+ {/* Main column */} +
+ {/* Top bar */} +
+
+

+ Admin +

+

+ Battl Builders Control Panel +

+
+ +
Internal • v0.1 -
- ADMIN -
+
+ ADMIN
-
+
+
- {/* Content */} -
- {children} -
-
+ {/* Content */} +
+ {children} +
+
); } \ No newline at end of file diff --git a/app/api/auth/session/route.ts b/app/api/auth/session/route.ts new file mode 100644 index 0000000..ec6b25a --- /dev/null +++ b/app/api/auth/session/route.ts @@ -0,0 +1,38 @@ +import { NextResponse } from "next/server"; + +export async function POST(req: Request) { + const { token, role } = await req.json(); + + if (!token) { + return NextResponse.json({ ok: false }, { status: 400 }); + } + + const res = NextResponse.json({ ok: true }); + + // Server-readable, JS-unreadable + res.cookies.set("bb_access_token", token, { + httpOnly: true, + secure: process.env.NODE_ENV === "production", + sameSite: "lax", + path: "/", + }); + + // Optional: for quick middleware role checks (not “secure” by itself) + if (role) { + res.cookies.set("bb_role", role, { + httpOnly: false, + secure: process.env.NODE_ENV === "production", + sameSite: "lax", + path: "/", + }); + } + + return res; +} + +export async function DELETE() { + const res = NextResponse.json({ ok: true }); + res.cookies.set("bb_access_token", "", { path: "/", maxAge: 0 }); + res.cookies.set("bb_role", "", { path: "/", maxAge: 0 }); + return res; +} \ No newline at end of file diff --git a/app/layout.tsx b/app/layout.tsx index 623c225..d9f8f51 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,6 +1,8 @@ // app/layout.tsx import "./globals.css"; import type { ReactNode } from "react"; +import Script from "next/script"; + import { AuthProvider } from "@/context/AuthContext"; import { Banner } from "@/components/Banner"; @@ -38,6 +40,9 @@ export default function RootLayout({ children }: { children: ReactNode }) { {" "} +