import { WebSocketServer } from 'ws'; import { getDB, getSession, getUser, deleteSession as deleteSessionFromDB } from './mongodb.js'; let wss = null; // Duración de la sesión en milisegundos (24 horas) const SESSION_DURATION = 24 * 60 * 60 * 1000; // Inicializar WebSocket Server export function initWebSocket(server) { wss = new WebSocketServer({ server, path: '/ws' }); wss.on('connection', async (ws, req) => { // Extraer token de los query parameters const url = new URL(req.url, `http://${req.headers.host}`); const token = url.searchParams.get('token'); if (!token) { console.log('Intento de conexión WebSocket sin token'); ws.close(1008, 'Token requerido'); return; } // Validar token try { const db = getDB(); if (!db) { console.error('MongoDB no disponible para validar WebSocket'); ws.close(1011, 'Servicio no disponible'); return; } // Verificar token en MongoDB const session = await getSession(token); if (!session) { console.log('Intento de conexión WebSocket con token inválido'); ws.close(1008, 'Token inválido'); return; } // Verificar que la sesión no haya expirado if (session.expiresAt && new Date(session.expiresAt) < new Date()) { await deleteSessionFromDB(token); console.log('Intento de conexión WebSocket con sesión expirada'); ws.close(1008, 'Sesión expirada'); return; } // Verificar que el usuario aún existe const user = await getUser(session.username); if (!user) { // Eliminar sesión si el usuario ya no existe await deleteSessionFromDB(token); console.log('Intento de conexión WebSocket con usuario inexistente'); ws.close(1008, 'Usuario no encontrado'); return; } // 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 - almacenar información del usuario en el websocket ws.user = { username: session.username, role: user.role || 'user', token: token }; console.log(`Cliente WebSocket conectado: ${session.username} (${user.role || 'user'})`); } catch (error) { console.error('Error validando token WebSocket:', error); ws.close(1011, 'Error de autenticación'); return; } ws.on('close', () => { if (ws.user) { console.log(`Cliente WebSocket desconectado: ${ws.user.username}`); } else { console.log('Cliente WebSocket desconectado'); } }); ws.on('error', (error) => { console.error('Error WebSocket:', error); }); }); return wss; } // Broadcast a todos los clientes WebSocket export function broadcast(data) { if (!wss) return; wss.clients.forEach((client) => { if (client.readyState === 1) { // WebSocket.OPEN client.send(JSON.stringify(data)); } }); } // Obtener instancia del WebSocket Server export function getWebSocketServer() { return wss; }