feat: autorregistro con verificacion de correo + aprobacion, superadmin y SMTP
- POST /api/auth/register: primer usuario del sistema -> superadmin con sesion directa (bootstrap, sin correo ni aprobacion); los siguientes quedan pending_verification y reciben un correo con enlace de un solo uso (24h). - GET /api/auth/verify-email: pasa a pending_approval y notifica in-app a los admin/superadmin activos. - admin/superadmin aprueban (POST /api/users/:id/approve, eligen rol y departamento) o rechazan (POST /api/users/:id/reject, borra y audita el email) desde Organizacion -> Usuarios (nuevo badge de estado + acciones). - login() da mensaje especifico segun el status de la cuenta en vez del generico "credenciales invalidas". - Recuperacion de clave (forgot/reset-password): respuesta siempre generica, token de 1 hora de un solo uso. - Nuevo modulo settings: SMTP configurable SOLO por superadmin desde Configuracion -> Correo (SMTP); clave cifrada AES-256-GCM (ENCRYPTION_KEY) en la tabla system_settings, nunca expuesta por la API. sendMail() degrada a modo dev (loguea en vez de enviar) si no hay SMTP configurado, y nunca deja que un fallo de envio tumbe al que lo llama. - Migracion 002_registration_and_smtp.sql: rol superadmin, columnas de ciclo de vida en users (status, tokens), tabla system_settings, y promueve al usuario mas antiguo del sistema a superadmin. - Fix: React.StrictMode disparaba el efecto de VerifyEmailPage dos veces; la segunda llamada (token ya consumido) mostraba "enlace invalido" pese a que la verificacion ya habia funcionado. Se agrega una guarda por token. - Fix (deuda tecnica v1.0.0): se reordena el montaje de rutas en app.js — subtasksRoutes (mount generico en /api) va al final, para no interceptar con su requireAuth interno una request sin token dirigida a un router mas especifico registrado despues. - Documentacion actualizada: AGENTS.md, SPEC.md, API.md, BASE_DE_DATOS.md, CONFIGURACION.md, ESTADO.md, CHANGELOG.md. Version 1.1.0. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
# ESTADO — project.linkedcorp.net
|
||||
|
||||
Ultima actualizacion: 2026-09-06
|
||||
Fase actual: **En produccion** (`https://project.linkedcorp.net`, v1.0.0). MVP fase 1 operativo.
|
||||
Fase actual: **En produccion** (`https://project.linkedcorp.net`, v1.1.0). MVP fase 1 operativo +
|
||||
autorregistro/aprobacion/SMTP.
|
||||
|
||||
## Como retomar
|
||||
|
||||
@@ -63,6 +64,41 @@ Fase actual: **En produccion** (`https://project.linkedcorp.net`, v1.0.0). MVP f
|
||||
higiene de `DEPLOY_WEB.md`) — bloqueado por el clasificador de auto-mode del agente durante el
|
||||
deploy; requiere ejecutarlo a mano o con autorizacion explicita la proxima vez.
|
||||
|
||||
### Autorregistro, aprobación, superadmin y SMTP (2026-09-06)
|
||||
|
||||
- Migración `002_registration_and_smtp.sql`: rol `superadmin`, columnas de ciclo de vida en `users`
|
||||
(`status`, tokens de verificación/recuperación), tabla `system_settings`. El usuario más antiguo
|
||||
(id=1, creado por `create-admin.js` antes de este feature) se promovió solo a `superadmin`.
|
||||
- `POST /api/auth/register`: primer usuario del sistema → `superadmin` con sesión directa
|
||||
(bootstrap); los siguientes → `pending_verification`, correo con enlace de un solo uso (24h).
|
||||
- `GET /api/auth/verify-email` → `pending_approval` + notificación in-app a `admin`/`superadmin`.
|
||||
- `admin`/`superadmin` aprueban (`POST /api/users/:id/approve`, eligen rol/departamento) o rechazan
|
||||
(`POST /api/users/:id/reject`, borra y audita el email) desde Organización → Usuarios (nuevo badge
|
||||
de estado + acciones de fila).
|
||||
- `login()` da mensaje específico según `status` (pendiente de verificar / pendiente de aprobar)
|
||||
en vez del genérico "credenciales inválidas".
|
||||
- Recuperación de clave (`/olvide-clave` → `/restablecer-clave`): respuesta siempre genérica, token
|
||||
de 1 hora de un solo uso.
|
||||
- SMTP configurable desde Configuración → Correo (SMTP), **solo superadmin** (oculto para el resto);
|
||||
clave cifrada AES-256-GCM (`ENCRYPTION_KEY`) en `system_settings`, nunca expuesta por la API.
|
||||
`sendMail()` degrada a modo dev (loguea en vez de enviar) si no hay SMTP configurado, y nunca deja
|
||||
que un fallo de envío tumbe al que lo llama (crítico para `forgot-password`, que debe responder
|
||||
genérico siempre).
|
||||
- Bug real corregido: `React.StrictMode` disparaba el efecto de `VerifyEmailPage` dos veces; la
|
||||
segunda llamada (token ya consumido) mostraba "enlace inválido" pese a que la verificación había
|
||||
funcionado. Se agregó una guarda por token ya solicitado.
|
||||
- Deuda técnica de la v1.0.0 resuelta de paso: se reordenó el montaje de rutas en `app.js` —
|
||||
`subtasksRoutes` (mount genérico en `/api`) ahora va al final, así ya no intercepta con su
|
||||
`requireAuth` interno una request sin token dirigida a un router más específico (`/api/settings`,
|
||||
etc.) registrado después.
|
||||
- Verificado end-to-end en dev con Playwright: registro → correo logueado (modo dev) → login
|
||||
rechazado (pendiente de verificar) → verificar correo → login rechazado (pendiente de aprobar) →
|
||||
aprobar desde Usuarios → login exitoso → recuperar clave → login con clave nueva → panel SMTP
|
||||
visible solo para superadmin. Sin errores de consola.
|
||||
- **Pendiente**: desplegar esta versión a producción (migración `002` sobre `.32` + redeploy de
|
||||
ambos servicios) — ver `DEPLOY_WEB.md`. El superadmin de producción deberá cargar el SMTP real
|
||||
desde la UI cuando lo tenga; hasta entonces el sistema sigue en modo dev (logueando enlaces).
|
||||
|
||||
## Pendiente (fase 2, sin comprometer lo ya construido)
|
||||
|
||||
- Riesgos e Incidencias como modulos propios (hoy: `risk_level` simple en el proyecto).
|
||||
@@ -87,14 +123,12 @@ Fase actual: **En produccion** (`https://project.linkedcorp.net`, v1.0.0). MVP f
|
||||
(roles/prioridades/estados/tipos) cuando `NODE_ENV=production`; los departamentos y usuarios de
|
||||
ejemplo (TI/Finanzas/RRHH/Comercial, admin con clave=usuario) son SOLO de dev. El admin real de
|
||||
produccion se crea con `create-admin.js` (clave fuerte generada, nunca clave=usuario).
|
||||
- Autorregistro con doble candado (correo + aprobacion admin) — decision explicita del usuario,
|
||||
revierte la regla inicial "sin autosuscripcion". El primer usuario del sistema es `superadmin`
|
||||
automatico; el resto pasa por verificacion + aprobacion. SMTP vive en BD (cifrado), configurable
|
||||
solo por el superadmin desde la UI, no en `.env`.
|
||||
|
||||
## Deuda tecnica
|
||||
|
||||
- `npm audit`: 3 vulnerabilidades moderadas en `qs`/`body-parser`, transitivas de Express 4.x (sin
|
||||
fix no-breaking disponible al 2026-09-06). No critico; revisar cuando Express publique el fix.
|
||||
- Ruteo backend: `app.use('/api', subtasksRoutes)` actua como catch-all de cualquier `/api/*` no
|
||||
matcheado por un mount mas especifico registrado antes; una request SIN token a una ruta
|
||||
inexistente bajo `/api` devuelve 401 "No autenticado" en vez de 404. No afecta ninguna ruta real
|
||||
de la app (todas requieren auth de todos modos) — deteccion: `curl .../api/health` (esa ruta no
|
||||
existe bajo `/api`, solo en la raiz `/health`). Prolijidad pendiente para fase 2: montar
|
||||
`subtasksRoutes` bajo un prefijo mas especifico.
|
||||
|
||||
Reference in New Issue
Block a user