Consola de administración
Usuarios, cuentas, correo, marca, extensiones, seguridad, auditoría y retención.
En esta página
La consola de administración (/admin) concentra en un solo lugar el control de usuarios, cuentas vinculadas, correo, marca, extensiones, seguridad, auditoría y retención de tu instancia. La antigua URL /admin/dashboard redirige a /admin.
Quién puede entrar#
- Gestor del dominio: el manager del backend que es *dueño* del dominio de esta instancia (
TOP_DOMAIN). Entra por/admin/login. Un manager ajeno (el alta de managers es abierta) recibe 403. - Usuario administrador: un usuario de la app con su correo en
ADMIN_EMAILSy sesión con MFA (salvoMFA_ENFORCE_ADMIN=false). - Sin sesión se responde 401; con sesión pero sin rol, propiedad o MFA, 403. Todas las rutas
/api/admin/**pasan por el mismo guardia (requireAdmin), limitan la tasa de peticiones y auditan las acciones sensibles.
El rol de administrador no se edita desde la consola
Ser administrador depende de la variable ADMIN_EMAILS (entorno del servidor), a propósito: así nadie puede escalar privilegios desde la interfaz o la base de datos. La ficha de usuario muestra el rol en solo lectura; para cambiarlo edita la variable y redespliega.
Navegación#
- Barra lateral por secciones (en móvil, un cajón) y migas de pan.
- Búsqueda global: pulsa
/(o Ctrl/Cmd+K) y escribe para saltar a un usuario, una extensión o un ajuste (contraseña, MFA, clave de firma, lista de supresión, DNS...). Flechas para moverte, Intro para abrir, Esc para cerrar. - Cabecera: dominio activo, estado del sistema (base de datos, backend compartido, límite de peticiones) y menú del perfil (idioma, volver al correo, cerrar sesión).
- Las pantallas con cambios sin guardar piden confirmación antes de salir.
Secciones#
| Sección | Ruta | Qué hace |
|---|---|---|
| Resumen | /admin | Usuarios activos y altas, correo enviado/recibido en 24 h, rebotes y quejas, cola de Elixir, almacenamiento de adjuntos, extensiones con errores, MFA de administradores y aviso de modo heredado |
| Usuarios | /admin/users | Tabla con búsqueda, filtros (estado, rol, MFA, cuenta Google), orden, paginación y selección masiva; ficha con sesiones activas (revocar una o todas), restablecer MFA, deshabilitar/habilitar, contraseña temporal o cambio forzado, alta de usuarios y exportación CSV |
| Cuentas vinculadas | /admin/accounts | Cuentas OAuth por usuario con estado del token (sin mostrarlo), integraciones que la usan, desvincular y pedir reconexión |
| Correo | /admin/mail | Métricas agregadas (nunca contenido), cuotas por hora, lista de supresión (ver/quitar), cola de programados, estado de los webhooks y salud DNS (SPF, DKIM, DMARC) |
| Dominio y marca | /admin/domain | Editor de tema y landing |
| Extensiones | /admin/extensions | Catálogo, instalar/desinstalar, activar/desactivar, versión, permisos, credenciales, estado y último error |
| Seguridad | /admin/security | Comprobaciones de MFA, sesión, configuración presente y eventos de seguridad recientes |
| Auditoría | /admin/audit | Visor de eventos con filtros, paginación y exportación CSV; valores enmascarados |
| Retención y almacenamiento | /admin/retention | Políticas editables (spam, papelera, raw, auditoría), simular o ejecutar ahora y uso de almacenamiento |
| Spam y remitentes | /admin/spam | Nivel de filtrado (presets, umbral, acción por banda, pesos por familia, vista previa), listas de bloqueados y permitidos con CSV, correos externos (política y whitelist), registro de decisiones sin contenido, probador de señales y estadísticas. Detalle en Filtro de spam y remitentes |
| Mi perfil | /admin/profile | Contraseña (12+), MFA y códigos de recuperación, sesiones propias, clave de firma del dominio y preferencias (idioma, tema, densidad) |
Usuarios: cómo se modela el estado#
La tabla User no cambia. El estado administrativo vive en tablas aditivas que crea npm run db:ensure: UserAdminState (deshabilitado, cambio de contraseña pendiente, último acceso), UserSession (registro de sesiones emitidas, para poder listarlas) y AdminSetting (políticas editables). Un usuario deshabilitado no puede iniciar sesión y sus sesiones vigentes dejan de valer (se sube tokenVersion).
- Restablecer MFA: exige escribir el correo del usuario; cierra sus sesiones y queda auditado. Si es administrador deberá enrolar MFA de nuevo en su próximo acceso.
- Contraseña: no se muestra ninguna contraseña existente. "Contraseña temporal" genera una, la muestra una sola vez, marca el cambio obligatorio y cierra sesiones. "Forzar cambio" solo marca el cambio: el login redirige a
/security?force=1. - Límite: no hay correo de recuperación de contraseña en el sistema, por eso no existe el enlace de un solo uso.
Privacidad#
La consola nunca muestra asuntos, cuerpos ni adjuntos. Correo solo expone conteos y metadatos; la única lista con direcciones es la de supresión (hace falta para poder quitarlas). Las credenciales de extensiones, los tokens OAuth y los hashes nunca salen del servidor.
API de la consola#
| Ruta | Uso |
|---|---|
GET /api/admin/me · system · search · overview | Armazón: quién eres, estado del sistema, búsqueda de usuarios, tarjetas del resumen |
/api/admin/users (+ [id], bulk, export) | Listar/crear, detalle, deshabilitar, MFA, sesiones, contraseña, acciones masivas y CSV |
/api/admin/accounts | Cuentas vinculadas |
/api/admin/mail/* | Métricas, supresión, webhooks, DNS |
/api/admin/extensions/* | Catálogo, instaladas, activar, orden, estado, prueba, credenciales |
/api/admin/audit (+ export) · security/status | Auditoría y seguridad |
/api/admin/retention/* | Políticas, ejecución y almacenamiento (/api/admin/retention sigue sirviendo al cron con CRON_SECRET) |
/api/admin/profile/* · domain-key | Perfil del administrador y clave de firma |
Todas devuelven Cache-Control: no-store, validan con zod, acotan la paginación (máx. 100 por página) y usan SQL parametrizado tolerante a tablas ausentes. Detalles de la firma de dominio en API del backend y firma.
Límites conocidos#
- El estado del token de una cuenta vinculada se deriva de las fechas y de la presencia de tokens; no se pregunta al proveedor (no se sabe si Google lo revocó hasta usarlo).
- Las sesiones solo se listan desde que se despliega el registro
UserSession: las anteriores siguen válidas pero no aparecen. - El cambio de contraseña forzado se aplica en el redirect del login, no con un bloqueo de servidor en cada ruta.
- Sin clave de firma registrada la instancia funciona en modo heredado (soportado, con privilegios reducidos en el backend); regístrala en Mi perfil para pasar a peticiones firmadas.