+1
-1
@@ -2,7 +2,7 @@
|
||||
NEXT_PUBLIC_API_BASE_URL=http://battlbuilder-api:8080
|
||||
|
||||
# Middleware to limited site to only root page
|
||||
NEXT_PUBLIC_LAUNCH_ONLY_ROOT=true
|
||||
LAUNCH_ONLY_ROOT=true
|
||||
|
||||
NEXT_PUBLIC_SHORTLINK_BASE_URL=https://battl.build
|
||||
|
||||
|
||||
+56
-15
@@ -2,42 +2,83 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import type { NextRequest } from "next/server";
|
||||
|
||||
function redirectToLogin(req: NextRequest) {
|
||||
const url = req.nextUrl.clone();
|
||||
url.pathname = "/login";
|
||||
url.searchParams.set("next", req.nextUrl.pathname);
|
||||
return NextResponse.redirect(url);
|
||||
}
|
||||
|
||||
function isPublicPath(pathname: string) {
|
||||
// Public pages
|
||||
if (pathname === "/") return true;
|
||||
if (pathname === "/login") return true;
|
||||
if (pathname.startsWith("/auth")) return true;
|
||||
|
||||
// Static / framework assets
|
||||
if (pathname.startsWith("/_next")) return true;
|
||||
if (pathname === "/favicon.ico") return true;
|
||||
if (pathname === "/robots.txt") return true;
|
||||
if (pathname === "/sitemap.xml") return true;
|
||||
|
||||
// Health / misc APIs you may want public
|
||||
if (pathname === "/api/health") return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function middleware(req: NextRequest) {
|
||||
const { pathname } = req.nextUrl;
|
||||
const token = req.cookies.get("session_token")?.value;
|
||||
const isLoggedIn = Boolean(token);
|
||||
|
||||
// Protect admin API routes
|
||||
// IMPORTANT: Use a server-only env var for middleware behavior.
|
||||
// Set LAUNCH_ONLY_ROOT=true in your Docker compose.
|
||||
const launchOnlyRoot = process.env.LAUNCH_ONLY_ROOT === "true";
|
||||
|
||||
// If we're in "launch only" mode, anonymous users can ONLY see public paths.
|
||||
// Everything else (including /builder) gets bounced.
|
||||
if (launchOnlyRoot && !isLoggedIn && !isPublicPath(pathname)) {
|
||||
// For API requests, return 401 instead of redirecting
|
||||
if (pathname.startsWith("/api/")) {
|
||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
}
|
||||
|
||||
// For pages, redirect to home (keeps the landing page experience)
|
||||
const url = req.nextUrl.clone();
|
||||
url.pathname = "/";
|
||||
return NextResponse.redirect(url);
|
||||
}
|
||||
|
||||
// --- Protected API routes ---
|
||||
if (pathname.startsWith("/api/admin")) {
|
||||
if (!token) {
|
||||
if (!isLoggedIn) {
|
||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
}
|
||||
}
|
||||
|
||||
// Protect builds API routes
|
||||
if (pathname.startsWith("/api/builds")) {
|
||||
if (!token) {
|
||||
if (!isLoggedIn) {
|
||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
}
|
||||
}
|
||||
|
||||
// Protect admin pages
|
||||
// --- Protected pages ---
|
||||
if (pathname.startsWith("/admin")) {
|
||||
if (!token) {
|
||||
const url = req.nextUrl.clone();
|
||||
url.pathname = "/login";
|
||||
url.searchParams.set("next", pathname);
|
||||
return NextResponse.redirect(url);
|
||||
}
|
||||
if (!isLoggedIn) return redirectToLogin(req);
|
||||
}
|
||||
|
||||
// Protect the builder UI
|
||||
if (pathname === "/builder" || pathname.startsWith("/builder/")) {
|
||||
if (!isLoggedIn) return redirectToLogin(req);
|
||||
}
|
||||
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
||||
export const config = {
|
||||
// Run middleware for all application routes, but avoid static assets.
|
||||
matcher: [
|
||||
"/api/admin/:path*",
|
||||
"/api/builds",
|
||||
"/api/builds/:path+",
|
||||
"/admin/:path*",
|
||||
"/((?!_next/static|_next/image|favicon.ico|robots.txt|sitemap.xml).*)",
|
||||
],
|
||||
};
|
||||
Reference in New Issue
Block a user