added splash page
This commit is contained in:
parent
41614a96cd
commit
6abe450f1d
2 changed files with 66 additions and 141 deletions
|
|
@ -5,7 +5,11 @@ import { NextResponse, NextRequest } from "next/server";
|
|||
* Public pages that should remain reachable without being signed in.
|
||||
* Everything else is considered protected (including most /api/*).
|
||||
*/
|
||||
const PUBLIC_PAGES = new Set<string>(["/auth/sign-in", "/auth/sign-up"]);
|
||||
const PUBLIC_PAGES = new Set<string>([
|
||||
"/", // ← splash page is public
|
||||
"/auth/sign-in",
|
||||
"/auth/sign-up",
|
||||
]);
|
||||
|
||||
/**
|
||||
* API paths that are explicitly allowed without auth.
|
||||
|
|
@ -17,8 +21,7 @@ import { NextResponse, NextRequest } from "next/server";
|
|||
];
|
||||
|
||||
/** Directus base (used to remotely validate the token after restarts). */
|
||||
const DIRECTUS =
|
||||
(process.env.NEXT_PUBLIC_API_BASE_URL || process.env.DIRECTUS_URL || "").replace(/\/$/, "");
|
||||
const DIRECTUS = (process.env.NEXT_PUBLIC_API_BASE_URL || process.env.DIRECTUS_URL || "").replace(/\/$/, "");
|
||||
|
||||
/** Helper: does the path start with any prefix in a list? */
|
||||
function startsWithAny(pathname: string, prefixes: string[]) {
|
||||
|
|
@ -47,22 +50,32 @@ import { NextResponse, NextRequest } from "next/server";
|
|||
}
|
||||
}
|
||||
|
||||
/** Build redirect to /auth/sign-in?reauth=1&next=<original>, and clear auth markers. */
|
||||
function kickToSignIn(req: NextRequest) {
|
||||
/**
|
||||
* Build redirect to /auth/sign-in?next=<original>.
|
||||
* Only set reauth=1 (and clear cookies) when opts.reauth === true.
|
||||
*/
|
||||
function kickToSignIn(req: NextRequest, opts?: { reauth?: boolean }) {
|
||||
const wantReauth = !!opts?.reauth;
|
||||
|
||||
const orig = new URL(req.url);
|
||||
const next = orig.pathname + (orig.search || "");
|
||||
|
||||
const url = new URL(req.url);
|
||||
url.pathname = "/auth/sign-in";
|
||||
url.search = "";
|
||||
url.searchParams.set("reauth", "1");
|
||||
if (wantReauth) url.searchParams.set("reauth", "1");
|
||||
url.searchParams.set("next", next);
|
||||
|
||||
const res = NextResponse.redirect(url);
|
||||
// Clear tokens so the very next /auth/* request is truly unauthenticated
|
||||
res.cookies.set("ma_at", "", { maxAge: 0, path: "/" });
|
||||
res.cookies.set("ma_v", "", { maxAge: 0, path: "/" }); // throttle marker
|
||||
// If you also use a refresh token, clear it here too:
|
||||
// res.cookies.set("ma_rt", "", { maxAge: 0, path: "/" });
|
||||
|
||||
// Only clear auth markers in true re-auth scenarios
|
||||
if (wantReauth) {
|
||||
res.cookies.set("ma_at", "", { maxAge: 0, path: "/" });
|
||||
res.cookies.set("ma_v", "", { maxAge: 0, path: "/" }); // throttle marker
|
||||
// If you also use a refresh token, clear it here too:
|
||||
// res.cookies.set("ma_rt", "", { maxAge: 0, path: "/" });
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -90,9 +103,9 @@ import { NextResponse, NextRequest } from "next/server";
|
|||
isAuthRoute &&
|
||||
(url.searchParams.get("reauth") === "1" || url.searchParams.get("force") === "1");
|
||||
|
||||
// If unauthenticated and the route is protected, send to sign-in (with next + reauth)
|
||||
// If unauthenticated and the route is protected, send to sign-in WITHOUT reauth
|
||||
if (!token && isProtected) {
|
||||
return kickToSignIn(req);
|
||||
return kickToSignIn(req, { reauth: false });
|
||||
}
|
||||
|
||||
// If we have a token, perform local expiry check.
|
||||
|
|
@ -100,8 +113,7 @@ import { NextResponse, NextRequest } from "next/server";
|
|||
const exp = jwtExp(token);
|
||||
const expired = !exp || exp * 1000 <= Date.now();
|
||||
|
||||
// If it's an auth route and token looks valid, keep your existing UX:
|
||||
// bounce away from auth pages — unless this is a forced reauth.
|
||||
// If it's an auth route and token looks valid, bounce away from auth pages — unless this is a forced reauth.
|
||||
if (isAuthRoute && !expired && !forceAuth) {
|
||||
url.pathname = "/portal";
|
||||
url.search = "";
|
||||
|
|
@ -111,7 +123,8 @@ import { NextResponse, NextRequest } from "next/server";
|
|||
// If protected route: enforce validity
|
||||
if (isProtected) {
|
||||
if (expired) {
|
||||
return kickToSignIn(req);
|
||||
// True reauth
|
||||
return kickToSignIn(req, { reauth: true });
|
||||
}
|
||||
|
||||
// ── Throttled remote validation (catches server restarts / revoked tokens)
|
||||
|
|
@ -131,8 +144,8 @@ import { NextResponse, NextRequest } from "next/server";
|
|||
});
|
||||
|
||||
if (!r.ok) {
|
||||
// Token no longer valid on the server → force re-auth, carry next
|
||||
return kickToSignIn(req);
|
||||
// Token no longer valid on the server → true reauth, carry next
|
||||
return kickToSignIn(req, { reauth: true });
|
||||
}
|
||||
|
||||
// Cache the success for ~1 minute to avoid hammering Directus
|
||||
|
|
@ -146,7 +159,7 @@ import { NextResponse, NextRequest } from "next/server";
|
|||
return res;
|
||||
} catch {
|
||||
// If Directus is unreachable, be conservative and require re-auth
|
||||
return kickToSignIn(req);
|
||||
return kickToSignIn(req, { reauth: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -213,7 +226,7 @@ import { NextResponse, NextRequest } from "next/server";
|
|||
}
|
||||
|
||||
function isPublicPath(pathname: string): boolean {
|
||||
// 1) Public pages (auth screens)
|
||||
// 1) Public pages (root splash & auth screens)
|
||||
if (PUBLIC_PAGES.has(pathname)) return true;
|
||||
|
||||
// 2) Static assets / internals
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue