import { auth } from '@/auth'; import { NextResponse } from 'next/server'; const protectedApiPrefixes = ['/api/products', '/api/organizations', '/api/users']; const superAdminOnlyRoutes = ['/dashboard/workspaces', '/dashboard/administration/setup']; const organizationAdminRoutes = ['/dashboard/users', '/dashboard/workspaces/team']; interface BootstrapStatusResponse { initialized: boolean; } function isBootstrapAllowedPath(pathname: string) { return ( pathname === '/administration/setup' || pathname.startsWith('/api/auth/') || pathname.startsWith('/api/setup/bootstrap/') || pathname === '/api/setup/templates' ); } async function getBootstrapInitialized(origin: string): Promise { try { const response = await fetch(new URL('/api/setup/bootstrap/status', origin), { cache: 'no-store', headers: { 'x-setup-proxy-check': '1' } }); if (!response.ok) return null; const payload = (await response.json()) as BootstrapStatusResponse; return payload.initialized; } catch { return null; } } export default auth(async (req) => { const pathname = req.nextUrl.pathname; const bootstrapAllowedPath = isBootstrapAllowedPath(pathname); if (bootstrapAllowedPath) { return NextResponse.next(); } const isInitialized = await getBootstrapInitialized(req.nextUrl.origin); if (isInitialized === false) { if (pathname.startsWith('/api/')) { return NextResponse.json( { message: 'System setup is required before this API is available.', redirectTo: '/administration/setup' }, { status: 503 } ); } return NextResponse.redirect(new URL('/administration/setup', req.nextUrl.origin)); } const isDashboardRoute = pathname.startsWith('/dashboard'); const isProtectedApiRoute = protectedApiPrefixes.some((prefix) => pathname.startsWith(prefix)); const user = req.auth?.user; const isSignedIn = Boolean(user); const isSuperAdmin = user?.systemRole === 'super_admin'; const isOrganizationAdmin = isSuperAdmin || Boolean( user?.activeOrganizationId && (user.activeMembershipRole === 'admin' || user.activePermissions?.includes('users:manage')) ); if (!isSignedIn && (isDashboardRoute || isProtectedApiRoute)) { if (isProtectedApiRoute) { return NextResponse.json({ message: 'Unauthorized' }, { status: 401 }); } const signInUrl = new URL('/auth/sign-in', req.nextUrl.origin); signInUrl.searchParams.set('callbackUrl', `${pathname}${req.nextUrl.search}`); return NextResponse.redirect(signInUrl); } if (isSignedIn && superAdminOnlyRoutes.some((prefix) => pathname.startsWith(prefix)) && !isSuperAdmin) { return NextResponse.redirect(new URL('/dashboard', req.nextUrl.origin)); } if (isSignedIn && organizationAdminRoutes.some((prefix) => pathname.startsWith(prefix)) && !isOrganizationAdmin) { return NextResponse.redirect(new URL('/dashboard', req.nextUrl.origin)); } return NextResponse.next(); }); export const config = { matcher: [ '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)' ] };