/** * Sistema de sessão usando Redis * Armazena informações de sessão do usuário */ import { getRedisClient } from "./index"; const SESSION_PREFIX = "session:"; const USER_SESSION_PREFIX = "user_session:"; const SESSION_TTL = 60 * 60 * 24 * 7; // 7 dias (mesmo que refresh token) export interface SessionTierInfo { subscriptionTierId: number | null; subscriptionTierSlug: string | null; subscriptionTierName: string | null; subscriptionTierLevel: number | null; } export interface SessionData { userId: number; username: string; email: string; accessToken: string; createdAt: number; subscriptionTierId: number | null; subscriptionTierSlug: string | null; subscriptionTierName: string | null; subscriptionTierLevel: number | null; } /** * Cria ou atualiza uma sessão */ export async function setSession( sessionId: string, data: SessionData, ): Promise { try { const client = getRedisClient(); if (!client.isOpen) { await client.connect(); } const key = `${SESSION_PREFIX}${sessionId}`; await client.setEx(key, SESSION_TTL, JSON.stringify(data)); // Também armazenar referência por userId para invalidar todas as sessões const userKey = `${USER_SESSION_PREFIX}${data.userId}`; await client.sAdd(userKey, sessionId); await client.expire(userKey, SESSION_TTL); } catch (error) { console.error("❌ Erro ao criar sessão:", error); throw error; } } /** * Obtém dados de uma sessão */ export async function getSession( sessionId: string, ): Promise { try { const client = getRedisClient(); if (!client.isOpen) { await client.connect(); } const key = `${SESSION_PREFIX}${sessionId}`; const data = await client.get(key); if (!data) { return null; } return JSON.parse(data) as SessionData; } catch (error) { console.error("❌ Erro ao obter sessão:", error); return null; } } /** * Remove uma sessão */ export async function deleteSession(sessionId: string): Promise { try { const client = getRedisClient(); if (!client.isOpen) { await client.connect(); } const key = `${SESSION_PREFIX}${sessionId}`; const data = await client.get(key); if (data) { const sessionData = JSON.parse(data) as SessionData; const userKey = `${USER_SESSION_PREFIX}${sessionData.userId}`; await client.sRem(userKey, sessionId); } await client.del(key); } catch (error) { console.error("❌ Erro ao remover sessão:", error); throw error; } } /** * Remove todas as sessões de um usuário */ export async function deleteAllUserSessions(userId: number): Promise { try { const client = getRedisClient(); if (!client.isOpen) { await client.connect(); } const userKey = `${USER_SESSION_PREFIX}${userId}`; const sessionIds = await client.sMembers(userKey); if (sessionIds.length > 0) { const keys = sessionIds.map((id) => `${SESSION_PREFIX}${id}`); await client.del(keys); await client.del(userKey); } } catch (error) { console.error("❌ Erro ao remover todas as sessões do usuário:", error); throw error; } } /** * Atualiza TTL de uma sessão */ export async function refreshSession(sessionId: string): Promise { try { const client = getRedisClient(); if (!client.isOpen) { await client.connect(); } const key = `${SESSION_PREFIX}${sessionId}`; const exists = await client.exists(key); if (exists) { await client.expire(key, SESSION_TTL); } } catch (error) { console.error("❌ Erro ao atualizar TTL da sessão:", error); throw error; } }