Files
archivdms/middleware.ts
T
patrick 9a24ea29e1 FDN-01: repository & projektgerüst
Git-Repository für bestehenden archivdms-Code initialisiert, Branch-/Commit-Konvention (feature/<ticket>-<slug>-Branches, Ticket-Prefix in Commit-Nachricht) etabliert.
2026-08-11 21:27:53 +02:00

53 lines
2.0 KiB
TypeScript

import { NextRequest, NextResponse } from "next/server";
// Cookie name mirrors internal/api/server.go's sessionCookieName constant.
const SESSION_COOKIE = "archivdms_session";
// Routes that must stay reachable without a session cookie.
//
// "/public" covers BOTH the human-facing external share page
// (/public/share/[token]) AND the /public/api/* proxy that next.config.ts
// rewrites to the backend's unauthenticated /public/* endpoints. Without this
// exemption the share link would bounce to /login and be useless.
const PUBLIC_PATHS = ["/login", "/public"];
/**
* Fast UX gate: only checks whether the session cookie is present, not
* whether the JWT inside it is still valid. Real validation happens on
* every backend API call (internal/api/server.go authMiddleware) — this
* middleware exists purely to avoid a flash of protected UI before a
* redirect to /login when there's obviously no session at all.
*/
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
const isPublic = PUBLIC_PATHS.some(
(p) => pathname === p || pathname.startsWith(`${p}/`)
);
const hasSession = Boolean(request.cookies.get(SESSION_COOKIE)?.value);
if (!hasSession && !isPublic) {
const loginUrl = new URL("/login", request.url);
loginUrl.searchParams.set("next", pathname);
return NextResponse.redirect(loginUrl);
}
if (hasSession && pathname === "/login") {
return NextResponse.redirect(new URL("/documents", request.url));
}
return NextResponse.next();
}
export const config = {
matcher: [
// Only guard page navigations. /api/* is excluded on purpose: those
// requests are rewritten straight through to the Go backend (see
// next.config.ts), which does its own full JWT validation via
// authMiddleware — gating them here as well would just break
// unauthenticated calls like POST /api/auth/login.
"/((?!api|_next/static|_next/image|favicon.ico|.*\\.(?:png|jpg|jpeg|svg|webp|ico)$).*)",
],
};