Files
2025-11-11 03:08:36 -03:00

154 lines
3.6 KiB
TypeScript

/**
* 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<void> {
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<SessionData | null> {
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<void> {
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<void> {
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<void> {
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;
}
}