Files
basic-erp/apps/api
GeorgeandClaude Sonnet 5.5 079cedbaed feat(api): login web con sesiones, guard global y freno a fuerza bruta
- POST /api/auth/login (U_WEB_USER/U_WEB_PASS de EmployeesInfo), logout y me.
- Token opaco (32 bytes) en Authorization: Bearer; una sesión por usuario,
  timeout deslizante configurable (SESSION_TIMEOUT_MINUTES, 30 por defecto).
- AuthGuard global con @Public(); /health/sap ahora exige sesión.
- Usuario inexistente y contraseña errónea devuelven el mismo mensaje;
  comparación en tiempo constante; filtro OData escapado; se rechazan
  U_WEB_USER duplicados.
- LoginAttemptsService: 429 tras 5 fallos por usuario o 20 por IP (15 min).
- Tests unitarios y e2e con SAP simulado.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-13 18:38:11 -05:00
..

api

Backend NestJS (ESM) del ERP base. Proxy hacia SAP Business One Service Layer.

cp .env.example .env
npm run start:dev      # http://localhost:3000/api/health
npm test               # unitarios
npm run test:e2e       # e2e
npm run lint

Configuración: src/config/env.schema.ts valida el .env al arrancar (zod); si algo es inválido, el proceso no inicia.

Nota: instalar dependencias con npm 11 (npx npm@11 install); npm 10 falla al resolver peers con TypeScript 6.

Autenticación

Login web contra EmployeesInfo (U_WEB_USER / U_WEB_PASS); el backend usa la sesión SAP compartida. Guard global: todo /api/* exige Authorization: Bearer <token> salvo rutas @Public().

Endpoint Descripción
POST /api/auth/login {username, password} Devuelve {token, user, company}
GET /api/auth/me Usuario de la sesión
POST /api/auth/logout Cierra la sesión (204)
  • Una sesión por usuario (un nuevo login invalida el token anterior); timeout deslizante SESSION_TIMEOUT_MINUTES (30).
  • Tras 5 fallos por usuario (o 20 por IP) en 15 min responde 429.
  • Sesiones en memoria: ejecutar un solo proceso.
curl -s -H 'Content-Type: application/json' -d '{"username":"USUARIO","password":"CLAVE"}' localhost:3000/api/auth/login