mongodb
Signed-off-by: Omar Sánchez Pizarro <omar.sanchez@pistacero.net>
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import crypto from 'crypto';
|
||||
import { getRedisClient } from '../services/redis.js';
|
||||
import { getDB, getSession, deleteSession as deleteSessionFromDB, deleteUserSessions as deleteUserSessionsFromDB, getUser } from '../services/mongodb.js';
|
||||
|
||||
// Duración de la sesión en segundos (24 horas)
|
||||
const SESSION_DURATION = 24 * 60 * 60;
|
||||
// Duración de la sesión en milisegundos (24 horas)
|
||||
const SESSION_DURATION = 24 * 60 * 60 * 1000;
|
||||
|
||||
// Generar token seguro
|
||||
function generateToken() {
|
||||
@@ -11,10 +11,10 @@ function generateToken() {
|
||||
|
||||
// Autenticación por token Middleware
|
||||
export async function authMiddleware(req, res, next) {
|
||||
const redisClient = getRedisClient();
|
||||
const db = getDB();
|
||||
|
||||
if (!redisClient) {
|
||||
return res.status(500).json({ error: 'Redis no está disponible. La autenticación requiere Redis.' });
|
||||
if (!db) {
|
||||
return res.status(500).json({ error: 'MongoDB no está disponible. La autenticación requiere MongoDB.' });
|
||||
}
|
||||
|
||||
const authHeader = req.headers.authorization;
|
||||
@@ -30,32 +30,41 @@ export async function authMiddleware(req, res, next) {
|
||||
}
|
||||
|
||||
try {
|
||||
// Verificar token en Redis
|
||||
const sessionKey = `session:${token}`;
|
||||
const sessionData = await redisClient.get(sessionKey);
|
||||
// Verificar token en MongoDB
|
||||
const session = await getSession(token);
|
||||
|
||||
if (!sessionData) {
|
||||
if (!session) {
|
||||
return res.status(401).json({ error: 'Invalid token', message: 'Token inválido o sesión expirada' });
|
||||
}
|
||||
|
||||
// Parsear datos de sesión
|
||||
const session = JSON.parse(sessionData);
|
||||
// Verificar que la sesión no haya expirado
|
||||
if (session.expiresAt && new Date(session.expiresAt) < new Date()) {
|
||||
await deleteSessionFromDB(token);
|
||||
return res.status(401).json({ error: 'Invalid token', message: 'Sesión expirada' });
|
||||
}
|
||||
|
||||
// Verificar que el usuario aún existe
|
||||
const userKey = `user:${session.username}`;
|
||||
const userExists = await redisClient.exists(userKey);
|
||||
const user = await getUser(session.username);
|
||||
|
||||
if (!userExists) {
|
||||
if (!user) {
|
||||
// Eliminar sesión si el usuario ya no existe
|
||||
await redisClient.del(sessionKey);
|
||||
await deleteSessionFromDB(token);
|
||||
return res.status(401).json({ error: 'Invalid token', message: 'Usuario no encontrado' });
|
||||
}
|
||||
|
||||
// Actualizar TTL de la sesión (refresh)
|
||||
await redisClient.expire(sessionKey, SESSION_DURATION);
|
||||
// Actualizar expiración de la sesión (refresh)
|
||||
const sessionsCollection = db.collection('sessions');
|
||||
const newExpiresAt = new Date(Date.now() + SESSION_DURATION);
|
||||
await sessionsCollection.updateOne(
|
||||
{ token },
|
||||
{ $set: { expiresAt: newExpiresAt } }
|
||||
);
|
||||
|
||||
// Autenticación exitosa
|
||||
req.user = { username: session.username };
|
||||
// Autenticación exitosa - incluir rol en req.user
|
||||
req.user = {
|
||||
username: session.username,
|
||||
role: user.role || 'user' // Por defecto 'user' si no tiene rol
|
||||
};
|
||||
req.token = token;
|
||||
next();
|
||||
} catch (error) {
|
||||
@@ -69,35 +78,14 @@ export const basicAuthMiddleware = authMiddleware;
|
||||
|
||||
// Función para crear sesión
|
||||
export async function createSession(username) {
|
||||
const redisClient = getRedisClient();
|
||||
if (!redisClient) {
|
||||
throw new Error('Redis no está disponible');
|
||||
}
|
||||
|
||||
const token = generateToken();
|
||||
const sessionKey = `session:${token}`;
|
||||
const sessionData = {
|
||||
username,
|
||||
createdAt: new Date().toISOString(),
|
||||
};
|
||||
|
||||
// Almacenar sesión en Redis con TTL
|
||||
await redisClient.setEx(sessionKey, SESSION_DURATION, JSON.stringify(sessionData));
|
||||
|
||||
return token;
|
||||
const { createSession: createSessionInDB } = await import('../services/mongodb.js');
|
||||
return await createSessionInDB(username);
|
||||
}
|
||||
|
||||
// Función para invalidar sesión
|
||||
export async function invalidateSession(token) {
|
||||
const redisClient = getRedisClient();
|
||||
if (!redisClient) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const sessionKey = `session:${token}`;
|
||||
await redisClient.del(sessionKey);
|
||||
return true;
|
||||
return await deleteSessionFromDB(token);
|
||||
} catch (error) {
|
||||
console.error('Error invalidando sesión:', error);
|
||||
return false;
|
||||
@@ -106,31 +94,11 @@ export async function invalidateSession(token) {
|
||||
|
||||
// Función para invalidar todas las sesiones de un usuario
|
||||
export async function invalidateUserSessions(username) {
|
||||
const redisClient = getRedisClient();
|
||||
if (!redisClient) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// Buscar todas las sesiones del usuario
|
||||
const keys = await redisClient.keys('session:*');
|
||||
let count = 0;
|
||||
|
||||
for (const key of keys) {
|
||||
const sessionData = await redisClient.get(key);
|
||||
if (sessionData) {
|
||||
const session = JSON.parse(sessionData);
|
||||
if (session.username === username) {
|
||||
await redisClient.del(key);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
return await deleteUserSessionsFromDB(username);
|
||||
} catch (error) {
|
||||
console.error('Error invalidando sesiones del usuario:', error);
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user