import { cookies } from "next/headers"; import { type NextRequest, NextResponse } from "next/server"; import { verifyAccessToken } from "@/lib/auth/jwt"; import { getMainCharacter } from "@/lib/prisma/queries/characters"; import { getDefaultSubscriptionTier, getSubscriptionTierById, } from "@/lib/prisma/queries/subscription-tiers"; import { getUserById } from "@/lib/prisma/queries/users"; import { deleteSession, getSession, refreshSession, setSession, } from "@/lib/redis/session"; import { secureLogger } from "@/lib/secure-logger"; /** * GET /api/auth/session * Verifica e retorna dados da sessão atual */ export async function GET(_request: NextRequest) { try { // Buscar sessionId do cookie const cookieStore = await cookies(); const sessionId = cookieStore.get("sessionId")?.value; if (!sessionId) { return NextResponse.json( { success: false, authenticated: false, error: "Nenhuma sessão encontrada", }, { status: 401 }, ); } // Buscar sessão no Redis let session = await getSession(sessionId); if (!session) { // Limpar cookie se sessão não existe const response = NextResponse.json( { success: false, authenticated: false, error: "Sessão expirada ou inválida", }, { status: 401 }, ); response.cookies.delete("sessionId"); return response; } // Verificar se o access token ainda é válido const tokenPayload = verifyAccessToken(session.accessToken); if (!tokenPayload) { // Token expirado - remover sessão await deleteSession(sessionId); const response = NextResponse.json( { success: false, authenticated: false, error: "Token expirado", }, { status: 401 }, ); response.cookies.delete("sessionId"); return response; } let tierInfo: { subscription_tier_id: number | null; name: string | null; slug: string | null; level: number | null; } | null = { subscription_tier_id: session.subscriptionTierId, name: session.subscriptionTierName, slug: session.subscriptionTierSlug, level: session.subscriptionTierLevel, }; if ( tierInfo.subscription_tier_id === undefined || tierInfo.subscription_tier_id === null || tierInfo.slug === null ) { const dbUser = await getUserById(session.userId); const fetchedTier = dbUser?.subscription_tier ? await getSubscriptionTierById( dbUser.subscription_tier.subscription_tier_id, ) : await getDefaultSubscriptionTier(); tierInfo = fetchedTier ? { subscription_tier_id: fetchedTier.subscription_tier_id, name: fetchedTier.name, slug: fetchedTier.slug, level: fetchedTier.level, } : { subscription_tier_id: null, name: null, slug: null, level: null, }; session = { ...session, subscriptionTierId: tierInfo.subscription_tier_id, subscriptionTierName: tierInfo.name, subscriptionTierSlug: tierInfo.slug, subscriptionTierLevel: tierInfo.level, }; await setSession(sessionId, session); } // Atualizar TTL da sessão await refreshSession(sessionId); // Buscar personagem principal do usuário const mainCharacter = await getMainCharacter(session.userId); return NextResponse.json( { success: true, authenticated: true, user: { userId: session.userId, username: session.username, email: session.email, characterName: mainCharacter?.character_name || null, subscriptionTier: tierInfo ? { id: tierInfo.subscription_tier_id, name: tierInfo.name, slug: tierInfo.slug, level: tierInfo.level, } : null, }, }, { status: 200 }, ); } catch (error) { secureLogger.error("❌ Erro ao verificar sessão", { error: error instanceof Error ? error.message : "Erro desconhecido", stack: error instanceof Error ? error.stack : undefined, timestamp: new Date().toISOString(), }); return NextResponse.json( { success: false, authenticated: false, error: error instanceof Error ? error.message : "Erro interno", }, { status: 500 }, ); } } /** * DELETE /api/auth/session * Encerra a sessão atual */ export async function DELETE(_request: NextRequest) { try { const cookieStore = await cookies(); const sessionId = cookieStore.get("sessionId")?.value; if (sessionId) { await deleteSession(sessionId); } const response = NextResponse.json( { success: true, message: "Sessão encerrada", }, { status: 200 }, ); response.cookies.delete("sessionId"); return response; } catch (error) { secureLogger.error("❌ Erro ao encerrar sessão", { error: error instanceof Error ? error.message : "Erro desconhecido", timestamp: new Date().toISOString(), }); return NextResponse.json( { success: false, error: error instanceof Error ? error.message : "Erro interno", }, { status: 500 }, ); } }