import createIntlMiddleware from 'next-intl/middleware'; import { routing } from './i18n/routing'; import type { NextRequest } from 'next/server'; import { NextResponse } from 'next/server'; import { getToken } from 'next-auth/jwt'; const protectedRoutes: Record = { '/example': ['ad'], }; const intlMiddleware = createIntlMiddleware(routing); export default async function middleware(req: NextRequest) { const pathname = req.nextUrl.pathname; const segments = pathname.split('/'); const locale = segments[1]; const pathWithoutLocale = '/' + segments.slice(2).join('/'); const matchedRoute = Object.keys(protectedRoutes).find((route) => { return ( pathWithoutLocale === route || pathWithoutLocale.startsWith(route + '/') ); }); // Short-circuit: skip token fetch entirely for public routes if (!matchedRoute) { return intlMiddleware(req); } const token = await getToken({ req, secret: process.env.NEXTAUTH_SECRET }); if (!token) { const url = req.nextUrl.clone(); url.pathname = '/api/auth/signin'; url.searchParams.set('callbackUrl', pathname); return NextResponse.redirect(url); } const requiredRoles = protectedRoutes[matchedRoute]; if (requiredRoles.length > 0) { const userRoles = token.roles ?? []; const hasRole = requiredRoles.some((role) => userRoles.includes(role)); if (!hasRole) { const url = req.nextUrl.clone(); url.pathname = `/${locale}/403`; return NextResponse.redirect(url); } } return intlMiddleware(req); } export const config = { matcher: ['/((?!api|trpc|_next|_vercel|.*\\..*).*)'], };