50 lines
1.7 KiB
TypeScript
50 lines
1.7 KiB
TypeScript
import createIntlMiddleware from "next-intl/middleware";
|
|
import { auth } from "@/lib/auth";
|
|
import { NextResponse } from "next/server";
|
|
import type { NextRequest } from "next/server";
|
|
import { routing } from "@/i18n/routing";
|
|
|
|
const intlMiddleware = createIntlMiddleware(routing);
|
|
|
|
const publicPaths = ["/login", "/register", "/api/auth", "/api/register"];
|
|
|
|
function isPublicPath(pathname: string): boolean {
|
|
// Strip locale prefix for comparison
|
|
const stripped = pathname.replace(/^\/(de|fr|it|en)/, "") || "/";
|
|
return (
|
|
publicPaths.some((p) => stripped === p || stripped.startsWith(`${p}/`)) ||
|
|
pathname.startsWith("/api/auth") ||
|
|
pathname.startsWith("/api/register")
|
|
);
|
|
}
|
|
|
|
export default async function middleware(request: NextRequest) {
|
|
const { pathname } = request.nextUrl;
|
|
|
|
// NextAuth API routes and register API pass through directly
|
|
if (pathname.startsWith("/api/auth") || pathname.startsWith("/api/register")) {
|
|
return NextResponse.next();
|
|
}
|
|
|
|
// Auth guard for protected paths
|
|
if (!isPublicPath(pathname)) {
|
|
const session = await auth();
|
|
if (!session) {
|
|
const loginUrl = new URL("/login", request.url);
|
|
loginUrl.searchParams.set("callbackUrl", pathname);
|
|
return NextResponse.redirect(loginUrl);
|
|
}
|
|
}
|
|
|
|
return intlMiddleware(request);
|
|
}
|
|
|
|
export const config = {
|
|
// Excludes _next/* internal routes, the favicon, api routes, AND any
|
|
// path containing a dot (covers all static files served from public/,
|
|
// e.g. /threema/qr_code_AIAGENT.png). Without the dot exclusion, the
|
|
// i18n middleware prepends the locale ("/en/threema/qr_code_AIAGENT.png")
|
|
// and the file is not found.
|
|
matcher: ["/((?!_next|favicon.ico|api|.*\\..*).*)"],
|
|
};
|