2026-05-29 23:29:31 +03:30
|
|
|
import { type NextRequest, NextResponse } from "next/server";
|
2026-05-24 17:37:21 +03:30
|
|
|
import createIntlMiddleware from "next-intl/middleware";
|
|
|
|
|
|
|
|
|
|
import { routing } from "@/i18n/routing";
|
2026-05-29 23:29:31 +03:30
|
|
|
import { ACCESS_TOKEN_COOKIE } from "@/lib/auth/constants";
|
|
|
|
|
import { decodeJwt, isJwtExpired } from "@/lib/auth/jwt";
|
2026-05-24 17:37:21 +03:30
|
|
|
|
|
|
|
|
const handleI18n = createIntlMiddleware(routing);
|
|
|
|
|
|
2026-05-29 23:29:31 +03:30
|
|
|
// Routes that require an authenticated Identity session (optionally /en/-prefixed).
|
|
|
|
|
const PROTECTED = /^\/(?:en\/)?(?:dashboard|studio)(?:\/|$)/;
|
|
|
|
|
|
2026-05-24 17:37:21 +03:30
|
|
|
export async function middleware(request: NextRequest) {
|
2026-05-29 23:29:31 +03:30
|
|
|
// 1. Locale detection / redirect (next-intl)
|
2026-05-24 17:37:21 +03:30
|
|
|
const i18nResponse = handleI18n(request);
|
2026-05-29 23:29:31 +03:30
|
|
|
if (
|
|
|
|
|
i18nResponse.status !== 200 ||
|
|
|
|
|
i18nResponse.headers.has("location")
|
|
|
|
|
) {
|
2026-05-24 17:37:21 +03:30
|
|
|
return i18nResponse;
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-29 23:29:31 +03:30
|
|
|
// 2. Auth guard for protected sections
|
|
|
|
|
const { pathname } = request.nextUrl;
|
|
|
|
|
if (PROTECTED.test(pathname)) {
|
|
|
|
|
const token = request.cookies.get(ACCESS_TOKEN_COOKIE)?.value;
|
|
|
|
|
if (!token || isJwtExpired(decodeJwt(token))) {
|
|
|
|
|
const url = request.nextUrl.clone();
|
|
|
|
|
url.pathname = pathname.startsWith("/en") ? "/en/auth" : "/auth";
|
|
|
|
|
url.searchParams.set("next", pathname);
|
|
|
|
|
return NextResponse.redirect(url);
|
2026-05-24 17:37:21 +03:30
|
|
|
}
|
2026-05-29 23:29:31 +03:30
|
|
|
}
|
2026-05-24 17:37:21 +03:30
|
|
|
|
2026-05-29 23:29:31 +03:30
|
|
|
return i18nResponse;
|
2026-05-24 17:37:21 +03:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const config = {
|
|
|
|
|
// Match all routes except api, _next, static assets
|
|
|
|
|
matcher: [
|
|
|
|
|
"/((?!api|_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)",
|
|
|
|
|
],
|
|
|
|
|
};
|