From 9667ebc83d7cf310deda1d4cf75306fb91ee7cfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Omar=20S=C3=A1nchez=20Pizarro?= Date: Wed, 21 Jan 2026 10:31:38 +0100 Subject: [PATCH] activity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Omar Sánchez Pizarro --- KEEPALIVE_SYSTEM.md | 324 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 324 insertions(+) create mode 100644 KEEPALIVE_SYSTEM.md diff --git a/KEEPALIVE_SYSTEM.md b/KEEPALIVE_SYSTEM.md new file mode 100644 index 0000000..0b762a4 --- /dev/null +++ b/KEEPALIVE_SYSTEM.md @@ -0,0 +1,324 @@ +# Sistema de Keepalive y Seguimiento de Usuarios Activos + +## 📝 Descripción + +El sistema de keepalive permite rastrear en tiempo real qué usuarios están activos y cuándo fue su última actividad. Utiliza el WebSocket existente para mantener una conexión persistente y enviar heartbeats periódicos. + +## 🎯 Características + +### Backend + +1. **WebSocket con Heartbeat** + - Envío automático de ping cada 60 segundos + - Detección de conexiones inactivas + - Cierre automático de conexiones sin respuesta + +2. **Seguimiento de Actividad** + - Registro de última actividad en sesiones + - Estado activo/inactivo por usuario + - Timeout de inactividad: 5 minutos + +3. **Base de Datos** + - Campo `lastActivity` en sesiones + - Campo `isActive` para marcar usuarios conectados + - Índices optimizados para consultas rápidas + +4. **Endpoints** + - `GET /api/users/active` - Obtener usuarios activos en tiempo real + - `GET /api/admin/sessions` - Obtener todas las sesiones con estado de actividad + - Ambos requieren autenticación (el segundo requiere rol admin) + +### Frontend + +1. **Heartbeat Automático** + - Envío de heartbeat cada 30 segundos + - Respuesta automática a pings del servidor + +2. **Detección de Actividad** + - Seguimiento de clicks, teclas, scroll y movimientos del ratón + - Throttling de 10 segundos para no sobrecargar el servidor + - Envío automático de eventos de actividad + +3. **Componente de Usuarios Activos** + - Lista de usuarios conectados en tiempo real + - Indicadores de estado (activo/inactivo) + - Actualización automática cada 30 segundos + - Actualización en tiempo real vía WebSocket + +## 🚀 Uso + +### Ver Usuarios Activos + +Los administradores pueden ver los usuarios activos en: +- **Dashboard principal** - Componente "Usuarios Activos" en la parte superior +- **Vista de Sesiones** - `/sessions` - Muestra todas las sesiones con estado de conexión +- **Endpoint API**: `GET /api/users/active` + +### Ver Estado de Sesiones + +La vista de **Sesiones** (`/sessions`) ahora muestra información detallada sobre el estado de cada sesión: + +**Estadísticas mejoradas:** +- Total de sesiones +- Sesiones válidas (no expiradas) +- 🟢 Sesiones conectadas (con actividad reciente < 5 min) +- 🟡 Sesiones inactivas (válidas pero sin actividad) +- 🔴 Sesiones expiradas +- Usuarios únicos + +**Por cada sesión:** +- Estado de validez: ✅ Válida / 🔴 Expirada +- Estado de conexión: 🟢 Conectado / 🟡 Inactivo +- Última actividad (relativa y absoluta) +- Información del dispositivo +- Token y fechas de creación/expiración + +### Estructura de Respuesta + +**GET /api/users/active:** +```json +{ + "activeUsers": [ + { + "username": "admin", + "role": "admin", + "status": "active", + "lastActivity": "2026-01-21T10:30:00.000Z", + "connectedViaWebSocket": true + }, + { + "username": "user1", + "role": "user", + "status": "inactive", + "lastActivity": "2026-01-21T10:25:00.000Z", + "connectedViaWebSocket": false, + "deviceInfo": { + "browser": "Chrome", + "os": "Windows" + } + } + ], + "total": 2, + "timestamp": "2026-01-21T10:35:00.000Z" +} +``` + +**GET /api/admin/sessions:** +```json +{ + "sessions": [ + { + "token": "abc123...", + "username": "admin", + "fingerprint": "xyz...", + "deviceInfo": { + "browser": "Chrome", + "browserVersion": "120.0", + "os": "Linux", + "ip": "192.168.1.100" + }, + "createdAt": "2026-01-21T09:00:00.000Z", + "expiresAt": "2026-01-22T09:00:00.000Z", + "lastActivity": "2026-01-21T10:30:00.000Z", + "isActive": true, + "isExpired": false + } + ], + "stats": { + "total": 10, + "active": 8, + "expired": 2, + "connected": 5, + "inactive": 3, + "byUser": { + "admin": 3, + "user1": 2 + } + } +} +``` + +## 🔧 Configuración + +### Timeouts y Intervalos + +**Backend** (`web/backend/services/websocket.js`): +```javascript +// Tiempo de inactividad para marcar como inactivo (5 minutos) +const INACTIVE_TIMEOUT = 5 * 60 * 1000; + +// Intervalo para limpiar conexiones inactivas (1 minuto) +const CLEANUP_INTERVAL = 60 * 1000; +``` + +**Frontend** (`web/dashboard/src/App.vue`): +```javascript +// Heartbeat cada 30 segundos +heartbeatInterval = setInterval(() => { ... }, 30000); + +// Throttle de actividad: 10 segundos +activityThrottleTimeout = setTimeout(() => { ... }, 10000); +``` + +## 📊 Estados de Usuario + +1. **Active** (Activo) + - Usuario conectado vía WebSocket + - Actividad reciente (< 5 minutos) + - Indicador verde + +2. **Inactive** (Inactivo) + - Usuario conectado pero sin actividad reciente (> 5 minutos) + - Indicador amarillo + +3. **Offline** (Desconectado) + - Sin conexión WebSocket + - No aparece en la lista de usuarios activos + +## 🔄 Flujo de Datos + +### Conexión WebSocket + +``` +Cliente conecta → Servidor valida token → Actualiza lastActivity + ↓ +Servidor envía confirmación de conexión + ↓ +Cliente inicia heartbeat cada 30s + ↓ +Servidor responde con pong + ↓ +Se actualiza lastActivity en DB +``` + +### Eventos de Usuario + +``` +Usuario interactúa (click, tecla, etc.) + ↓ +Cliente envía evento de actividad (throttled) + ↓ +Servidor actualiza lastActivity + ↓ +Broadcast de cambio de estado a otros usuarios +``` + +### Desconexión + +``` +Cliente cierra conexión o timeout + ↓ +Servidor marca isActive = false en DB + ↓ +Broadcast de estado offline a otros usuarios +``` + +## 🎨 Componente ActiveUsers + +Ubicación: `web/dashboard/src/components/ActiveUsers.vue` + +### Props + +Ninguna (componente standalone) + +### Eventos Escuchados + +- `user-status-change` - Cambios de estado de usuarios vía WebSocket + +### Características + +- **Actualización automática**: cada 30 segundos +- **Actualización en tiempo real**: vía eventos WebSocket +- **Indicadores visuales**: + - 🟢 Verde: usuario activo + - 🟡 Amarillo: usuario inactivo + - 📶 Icono de señal: conectado vía WebSocket +- **Badges de rol**: admin/user +- **Timestamp relativo**: "hace X minutos" + +## 🔐 Seguridad + +- Solo usuarios autenticados pueden ver usuarios activos +- El token se valida en cada conexión WebSocket +- Las sesiones expiran automáticamente según configuración +- Los heartbeats mantienen la sesión activa + +## 📈 Escalabilidad + +El sistema está diseñado para manejar múltiples usuarios concurrentes: + +1. **Throttling de actividad**: evita spam de eventos +2. **Índices en MongoDB**: consultas optimizadas +3. **Limpieza periódica**: cierre de conexiones inactivas +4. **TTL en sesiones**: eliminación automática de sesiones expiradas + +## 🐛 Debugging + +Para ver logs de WebSocket en la consola del navegador: + +```javascript +// En la consola del navegador +localStorage.setItem('debug', 'websocket'); +``` + +Logs del servidor: +``` +Cliente WebSocket conectado: username (role) +Cliente WebSocket desconectado: username +Usuario inactivo detectado: username +Cerrando conexión inactiva: username +``` + +## 🖥️ Vista de Sesiones Mejorada + +La vista de Sesiones (`/sessions`) ahora incluye información completa sobre el estado de actividad: + +### Estadísticas Ampliadas + +``` +┌─────────────────────────────────────────────────────────┐ +│ [Total: 10] [Válidas: 8] [🟢 Conectadas: 5] │ +│ [🟡 Inactivas: 3] [🔴 Expiradas: 2] [Usuarios: 3] │ +└─────────────────────────────────────────────────────────┘ +``` + +### Tabla de Sesiones + +Cada fila muestra: +- **Usuario**: nombre del usuario +- **Dispositivo**: navegador, OS, IP +- **Última Actividad**: tiempo relativo (ej: "Hace 2 minutos") + timestamp exacto +- **Token**: primeros 16 caracteres +- **Creada**: timestamp de creación +- **Expira**: timestamp de expiración +- **Estado**: doble indicador + - ✅ Válida / 🔴 Expirada + - 🟢 Conectado / 🟡 Inactivo (solo si válida) +- **Acciones**: botón para eliminar sesión + +### Diferencias de Estado + +**✅ Válida + 🟢 Conectado:** +- Sesión no expirada +- Usuario con actividad reciente (< 5 minutos) +- Probablemente conectado vía WebSocket + +**✅ Válida + 🟡 Inactivo:** +- Sesión no expirada +- Usuario sin actividad reciente (> 5 minutos) +- WebSocket desconectado o usuario inactivo + +**🔴 Expirada:** +- Sesión pasada la fecha de expiración +- Se eliminará automáticamente por TTL de MongoDB +- No se puede eliminar manualmente (botón deshabilitado) + +## 📝 Notas Adicionales + +- El sistema es compatible con múltiples pestañas/dispositivos por usuario +- Cada conexión WebSocket se rastrea independientemente +- Los heartbeats se reinician automáticamente si se reconecta +- La actividad del usuario se detecta de forma pasiva (no intrusiva) +- La vista de Sesiones se actualiza manualmente (botón "🔄 Actualizar") +- Los usuarios activos se actualizan automáticamente cada 30 segundos +