Skip to content
Usuario

Sessions

Administracion global de sesiones

Sesiones activas

Para que sirve esta pantalla

/super-admin/sessions permite consultar sesiones del sistema y cerrar sesiones de forma administrativa. Sirve para reaccionar ante accesos no deseados, sesiones antiguas, usuarios que cambiaron de rol, soporte operativo o incidentes de seguridad.

Esta pantalla no usa el endpoint legacy /api/auth/forze-close. Usa endpoints Super Admin protegidos por Token.Auth y requireRole(‘super_admin’).

RutaFrontend/super-admin/sessions
ComponenteVista principalActiveSessions.vue
EndpointListadoGET /api/super-admin/sessions

Proceso al cargar la pantalla

  1. El router entra a /super-admin/sessions con meta.role = ‘super_admin’.
  2. El layout Super Admin muestra el item Sesiones activas.
  3. ActiveSessions.vue ejecuta mounted().
  4. Primero carga negocios para el filtro con GET /api/super-admin/businesses?page=1&pageSize=100.
  5. Despues carga sesiones con GET /api/super-admin/sessions.
  6. El backend valida token, sesion activa si aplica y rol super_admin.
  7. El DAO consulta session, login, rol y business.
  8. La vista pinta tabla, paginacion, filtros y acciones disponibles.

Filtros, paginacion y ordenamiento

ControlParametroQue haceNotas
Buscar sesionsearchBusca por id de sesion, nombre, correo, id de login, rol o negocio.Usa debounce de 450 ms antes de consultar backend.
NegociobusinessIdFiltra sesiones asociadas a un negocio.El filtro se carga desde el listado de negocios Super Admin.
RolroleFiltra por codigo de rol.Opciones visibles: super_admin, admin, business_admin, doctor, assistant, reception, receptionist.
EstadoactivePermite ver activas, inactivas o todas.Por defecto la UI usa true.
Por paginapageSizeCambia tamano de pagina.Opciones: 10, 20, 50, 100.
OrdensortBy, sortDirOrdena server-side por columnas permitidas.Whitelist: created_at, updated_at, active, last, user_name, email, role, business_name.

Columnas de la tabla: que significa cada una

ColumnaFuenteSignificado operativoComo interpretarla
Usuariologin.nameNombre de la cuenta de acceso.No es paciente. Es usuario del sistema.
Correologin.emailCorreo de la cuenta.Sirve para identificar al usuario antes de cerrar sesiones.
Rolrol.codeRol tecnico/operativo del usuario.Ayuda a distinguir super_admin, admin tenant, doctor o auxiliar.
Negociobusiness.nameTenant asociado al usuario.Super Admin puede aparecer sin negocio.
Activasession.activeIndica si la sesion esta activa en backend.Si es false, no deberia permitir operar con sesiones activas obligatorias.
Ultimasession.lastMarca la sesion vigente principal del usuario.El middleware exige active = 1 y last = 1.
Iniciosession.created_atFecha de creacion de la sesion.Permite detectar sesiones antiguas.
Actualizacionsession.updated_atUltimo cambio de la sesion.Cambia al cerrar o actualizar la sesion.
Cierre forzadosession.forze_atFecha de cierre administrativo.Si esta vacia, no hay cierre forzado registrado.
Forzada porsession.forze_byUsuario Super Admin que forzo el cierre.Sirve para trazabilidad operativa.
AccionesUI + endpoints Super AdminCerrar una sesion o todas las sesiones del usuario.No se muestran acciones para sesion propia ni para sesiones cerradas.

Boton: Cerrar sesion

Cierra una sesion especifica. La UI abre un modal de confirmacion y llama:

PATCH /api/super-admin/sessions/:id/close

En frontend, confirmCloseSession() llama DASuperAdminService.closeSession(session.id_session). En backend, la ruta llama SuperAdminController.closeSession y despues SuperAdminDao.closeSession.

Boton: Cerrar sesiones del usuario

Cierra todas las sesiones activas del usuario seleccionado. Requiere escribir exactamente CERRAR antes de confirmar.

PATCH /api/super-admin/users/:id/close-sessions

En frontend, confirmCloseUserSessions() llama DASuperAdminService.closeUserSessions(idLogin). En backend, la ruta llama SuperAdminController.closeUserSessions y luego SuperAdminDao.closeUserSessions.

SQL de listado de sesiones

El listado une sesiones con usuarios, roles y negocios. No consulta pacientes, expedientes, recetas, citas clinicas, tratamientos ni odontograma.

SELECT
  s.id_session,
  s.active,
  s.last,
  s.created_at,
  s.updated_at,
  s.forze_at,
  s.forze_by,
  l.id_login,
  l.name AS user_name,
  l.email,
  r.code AS role,
  b.id_business,
  b.name AS business_name
FROM `session` s
INNER JOIN login l ON l.id_login = s.id_login
LEFT JOIN rol r ON r.id_rol = l.id_rol
LEFT JOIN business b ON b.id_business = l.id_business
WHERE ...filtros seguros...
ORDER BY ...columna permitida...
LIMIT :_limit OFFSET :_offset;

Que cambia en base de datos al cerrar una sesion

El cierre de una sesion especifica marca esa sesion como inactiva y tambien invalida refresh tokens activos del usuario. Esto es importante: aunque el boton cierre una sesion puntual, el backend apaga los refresh tokens activos del usuario para evitar que pueda emitir nuevos access tokens con una sesion cerrada.

UPDATE `session`
 SET active = 0,
     last = 0,
     forze_by = :actor_login_id,
     forze_at = NOW(),
     updated_by = :actor_login_id,
     updated_at = NOW()
WHERE id_session = :id_session;

UPDATE refresh_token
 SET last = 0
WHERE id_login = :id_login
 AND last = 1;

Que cambia al cerrar todas las sesiones de un usuario

El cierre masivo busca todas las sesiones activas del usuario, las marca como cerradas y apaga sus refresh tokens activos. No borra usuario, negocio ni datos.

UPDATE `session`
 SET active = 0,
     last = 0,
     forze_by = :actor_login_id,
     forze_at = NOW(),
     updated_by = :actor_login_id,
     updated_at = NOW()
WHERE id_login = :id_login
 AND active = 1;

UPDATE refresh_token
 SET last = 0
WHERE id_login = :id_login
 AND last = 1;

Como se refleja en el usuario

EscenarioCon REQUIRE_ACTIVE_SESSION=trueCon REQUIRE_ACTIVE_SESSION=falseRefresh token
Usuario con access token vigenteEl siguiente request protegido falla porque la sesion ya no esta activa.El access token puede seguir funcionando hasta expirar.No puede renovar si su refresh activo fue apagado.
Usuario con “mantener sesion”Queda fuera en el siguiente request y no puede refrescar token.Puede conservar access token hasta expiracion, pero no renovar.refresh_token.last = 0.
Usuario sin “mantener sesion”Queda fuera en el siguiente request protegido.Access token vive hasta expiracion.No tenia refresh token util que renovar.
Sesion ya cerradaNo se muestra boton; aparece como cerrada.No se muestra boton; aparece como cerrada.Debe estar invalidado si fue cierre forzado.

Validacion de sesion activa en cada request

Cuando REQUIRE_ACTIVE_SESSION=true, el middleware awaitHandlerFactory revisa que el JWT tenga id_login e id_session. Luego consulta SessionDao.checkActiveSession(). Solo permite continuar si existe una fila en session con active = 1 y last = 1.

SELECT id_session
FROM `session`
WHERE id_login = :id_login
 AND id_session = :id_session
 AND active = 1
 AND last = 1
LIMIT 1;

Duracion de sesion y access token

La duracion del access token se configura con JWT_EXPIRES_IN en src/config/security.js y se aplica desde src/config/jwt.js. En produccion controlada se usa JWT_EXPIRES_IN=3600, equivalente a 1 hora. Si no se configura, el default del codigo es 60000.

Cerrar una sesion no cambia la fecha interna del JWT ya emitido; lo que hace efectivo el cierre inmediato es REQUIRE_ACTIVE_SESSION=true, porque obliga a validar la sesion en base de datos en cada request protegido.

Auditoria de cierres

AccionEventoMetadata segura
Cerrar una sesionSUPER_ADMIN_SESSION_CLOSEScope de invalidacion refresh y razon super_admin_close_session.
Cerrar sesiones de usuarioSUPER_ADMIN_USER_SESSIONS_CLOSEIDs de sesiones cerradas, scope refresh y razon super_admin_close_user_sessions.

La auditoria no debe guardar passwords, hashes, tokens, refresh tokens ni datos clinicos. Los cierres tampoco borran negocio, usuario ni informacion clinica.

Diagrama de cierre de sesion

flowchart TD
A[Super Admin pulsa Cerrar sesion] --> B[Modal de confirmacion]
B --> C[PATCH /api/super-admin/sessions/:id/close]
C --> D[Token.Auth]
D --> E[requireRole super_admin]
E --> F[SuperAdminController.closeSession]
F --> G[SuperAdminDao.closeSession]
G --> H{Es sesion propia?}
H -- Si --> I[403: no permitido]
H -- No --> J[UPDATE session active=0 last=0]
J --> K[UPDATE refresh_token last=0]
K --> L[Auditoria SUPER_ADMIN_SESSION_CLOSE]
L --> M[Frontend refresca tabla]
M --> N[Usuario afectado falla en siguiente request si REQUIRE_ACTIVE_SESSION=true]

Diagrama de cierre de sesiones del usuario

flowchart TD
A[Super Admin pulsa Cerrar sesiones del usuario] --> B[Debe escribir CERRAR]
B --> C[PATCH /api/super-admin/users/:id/close-sessions]
C --> D[Token.Auth + requireRole super_admin]
D --> E[SuperAdminController.closeUserSessions]
E --> F[SuperAdminDao.closeUserSessions]
F --> G{Es el propio usuario?}
G -- Si --> H[403: no permitido]
G -- No --> I[Buscar usuario]
I --> J[Buscar sesiones activas]
J --> K[UPDATE session active=0 last=0 WHERE id_login]
K --> L[UPDATE refresh_token last=0 WHERE id_login]
L --> M[Auditoria SUPER_ADMIN_USER_SESSIONS_CLOSE]
M --> N[Frontend refresca tabla]