+20
-13
@@ -13,7 +13,12 @@ function isPublicPath(pathname: string) {
|
|||||||
// Public pages
|
// Public pages
|
||||||
if (pathname === "/") return true;
|
if (pathname === "/") return true;
|
||||||
if (pathname === "/login") return true;
|
if (pathname === "/login") return true;
|
||||||
|
if (pathname === "/tos") return true;
|
||||||
|
if (pathname === "/privacy") return true;
|
||||||
|
if (pathname === "/beta") return true;
|
||||||
|
if (pathname.startsWith("/beta/")) return true;
|
||||||
if (pathname.startsWith("/auth")) return true;
|
if (pathname.startsWith("/auth")) return true;
|
||||||
|
if (pathname.startsWith("/api/auth")) return true;
|
||||||
|
|
||||||
// Static / framework assets
|
// Static / framework assets
|
||||||
if (pathname.startsWith("/_next")) return true;
|
if (pathname.startsWith("/_next")) return true;
|
||||||
@@ -27,6 +32,17 @@ function isPublicPath(pathname: string) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isProtectedLaunchPath(pathname: string) {
|
||||||
|
return (
|
||||||
|
pathname === "/builder" ||
|
||||||
|
pathname.startsWith("/builder/") ||
|
||||||
|
pathname === "/builds" ||
|
||||||
|
pathname.startsWith("/builds/") ||
|
||||||
|
pathname === "/vault" ||
|
||||||
|
pathname.startsWith("/vault/")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function middleware(req: NextRequest) {
|
export function middleware(req: NextRequest) {
|
||||||
const { pathname } = req.nextUrl;
|
const { pathname } = req.nextUrl;
|
||||||
const token = req.cookies.get("session_token")?.value;
|
const token = req.cookies.get("session_token")?.value;
|
||||||
@@ -36,18 +52,9 @@ export function middleware(req: NextRequest) {
|
|||||||
// Set LAUNCH_ONLY_ROOT=true in your Docker compose.
|
// Set LAUNCH_ONLY_ROOT=true in your Docker compose.
|
||||||
const launchOnlyRoot = process.env.LAUNCH_ONLY_ROOT === "true";
|
const launchOnlyRoot = process.env.LAUNCH_ONLY_ROOT === "true";
|
||||||
|
|
||||||
// If we're in "launch only" mode, anonymous users can ONLY see public paths.
|
// In "launch only" mode, anonymous users are blocked only from gated app areas.
|
||||||
// Everything else (including /builder) gets bounced.
|
if (launchOnlyRoot && !isLoggedIn && isProtectedLaunchPath(pathname)) {
|
||||||
if (launchOnlyRoot && !isLoggedIn && !isPublicPath(pathname)) {
|
return redirectToLogin(req);
|
||||||
// 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 ---
|
// --- Protected API routes ---
|
||||||
@@ -81,4 +88,4 @@ export const config = {
|
|||||||
matcher: [
|
matcher: [
|
||||||
"/((?!_next/static|_next/image|favicon.ico|robots.txt|sitemap.xml).*)",
|
"/((?!_next/static|_next/image|favicon.ico|robots.txt|sitemap.xml).*)",
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user