import { NextRequest, NextResponse } from "next/server" import { getCookieCache } from "better-auth/cookies" // Rotas públicas explícitas (não autenticadas) // Permite handshake de máquina sem sessão prévia para criar a sessão de máquina. const PUBLIC_PATHS = [/^\/login$/, /^\/machines\/handshake$/] // Rotas somente admin const ADMIN_ONLY_PATHS = [/^\/admin(?:$|\/)/] const APP_HOME = "/dashboard" export async function middleware(request: NextRequest) { const { pathname, search } = request.nextUrl if (PUBLIC_PATHS.some((pattern) => pattern.test(pathname))) return NextResponse.next() const session = await getCookieCache(request) if (!session?.user) { const hasSessionCookie = Boolean(request.cookies.get("better-auth.session-token")) const hasRefreshCookie = Boolean(request.cookies.get("better-auth.refresh-token")) || Boolean(request.cookies.get("better-auth.refresh-token-v2")) if (hasSessionCookie || hasRefreshCookie) { const refreshed = await attemptSessionRefresh(request) if (refreshed) { return refreshed } } const redirectUrl = new URL("/login", request.url) redirectUrl.searchParams.set("callbackUrl", pathname + search) return NextResponse.redirect(redirectUrl) } const role = (session.user as { role?: string })?.role?.toLowerCase() ?? "agent" const isAdmin = role === "admin" // Em desenvolvimento, evitamos bloquear rotas admin por possíveis diferenças // de cache de cookie/sessão entre dev server e middleware. Em produção, aplica o gate. if ( process.env.NODE_ENV === "production" && !isAdmin && ADMIN_ONLY_PATHS.some((pattern) => pattern.test(pathname)) ) { return NextResponse.redirect(new URL(APP_HOME, request.url)) } return NextResponse.next() } export const config = { runtime: "nodejs", // Evita executar para assets e imagens estáticas matcher: ["/((?!api|_next/static|_next/image|favicon.ico|icon.png).*)"], } async function attemptSessionRefresh(request: NextRequest): Promise { try { const refreshUrl = new URL("/api/auth/get-session", request.url) const response = await fetch(refreshUrl, { method: "GET", headers: { cookie: request.headers.get("cookie") ?? "", }, }) if (!response.ok) { return null } const data = await response.json().catch(() => null) if (!data?.user) { return null } const redirect = NextResponse.redirect(request.nextUrl) const setCookieHeaders = typeof response.headers.raw === "function" ? response.headers.raw()["set-cookie"] ?? [] : [] if (setCookieHeaders.length === 0) { const single = response.headers.get("set-cookie") if (single) setCookieHeaders.push(single) } for (const cookie of setCookieHeaders) { redirect.headers.append("set-cookie", cookie) } return redirect } catch { return null } }