Uecko_ERP/docs/prompt-auth.md
2025-06-17 18:18:25 +02:00

5.4 KiB
Raw Permalink Blame History

📌 CONTEXTO DEL PROYECTO: Estoy desarrollando una API en Node.js con TypeScript, Express.js, Sequelize, y Arquitectura Hexagonal (Ports & Adapters) bajo los principios de DDD (Domain-Driven Design) y SOLID.
La API maneja autenticación con PassportJS, soporte para JWT y LocalStrategy, gestión segura de contraseñas con bcrypt, y transformación de respuestas con DTOs (Data Transfer Objects).

📌 PRINCIPIOS Y PATRONES A APLICAR: DDD (Domain-Driven Design):

  • Los agregados encapsulan su estado y exponen solo lo necesario.
  • Cada agregado tiene su propio mapper para conversión entre persistencia y dominio.
  • Repositorios manejan agregados y deben desacoplarse de Sequelize.

SOLID (Principios de Diseño):

  • SRP: Cada clase tiene una única responsabilidad.
  • OCP: El código debe ser fácil de extender sin modificarlo.
  • LSP: Los objetos derivados deben poder sustituir a sus clases base.
  • ISP: Usar interfaces específicas en lugar de dependencias directas.
  • DIP: Usar interfaces (IAuthProvider, ITransactionManager) en lugar de acoplarse a implementaciones concretas.

📌 GESTIÓN DE DEPENDENCIAS: Factory Pattern (createAuthService)

  • AuthService debe crearse con un Factory (createAuthService()), permitiendo cambiar su implementación sin afectar la API.
  • AuthService depende de IAuthenticatedUserRepository, ITransactionManager y IAuthProvider.

📌 AUTENTICACIÓN CON PassportJS: Soporte para JWT y LocalStrategy

  • PassportAuthProvider maneja JWTStrategy para autenticación con tokens y LocalStrategy para validación con email y contraseña.
  • Se debe usar bcrypt para cifrar contraseñas antes de almacenarlas.
  • validateUser() en PassportAuthProvider verifica credenciales con LocalStrategy.

📌 GESTIÓN SEGURA DE CONTRASEÑAS: Uso de bcrypt para cifrado de contraseñas

  • PasswordHash.create() valida la fuerza de la contraseña antes de cifrarla.
  • bcrypt.compare() se usa para validar la contraseña al hacer login.
  • Las contraseñas nunca deben almacenarse en texto plano en la base de datos.

📌 GESTIÓN DE ERRORES: Uso de ApiError para respuestas de error estructuradas

  • ExpressController debe devolver errores con ApiError (status, title, detail, timestamp).
  • RegisterController y LoginController deben usar ApiError en caso de errores (409 Conflict, 401 Unauthorized, 500 Internal Server Error).
  • Se deben capturar errores de Sequelize en BaseRepository (UniqueConstraintError, ConnectionError, TimeoutError).
  • Errores de unicidad (SequelizeUniqueConstraintError) deben ser personalizados según el contexto usando errorMapper en los repositorios.

📌 FLUJO DE LA API /register: 1 Request llega a RegisterController.
2 Valida email, username, password como Value Objects.
3 Llama a AuthService.registerUser().
4 AuthService usa validateUser() para evitar usuarios duplicados.
5 Si el usuario es nuevo, se cifra la contraseña con bcrypt.hash().
6 Se almacena en la BD con AuthenticatedUserRepository.create().
7 Se generan accessToken y refreshToken con PassportAuthProvider.
8 Se responde con los tokens y el userId.

📌 FLUJO DE LA API /login: 1 Request llega a LoginController.
2 Llama a AuthService.loginUser() con email y password.
3 AuthService busca el usuario en AuthenticatedUserRepository.findUserByEmail().
4 Si el usuario existe, compara contraseñas con bcrypt.compare().
5 Si la contraseña es correcta, genera accessToken y refreshToken.
6 Devuelve los tokens en la respuesta.

📌 TRANSFORMACIÓN DE RESPUESTAS: Los Controladores son responsables de la transformación de datos antes de enviarlos.
Se usan Presenters (AuthResponsePresenter) para mapear datos del dominio a DTOs (AuthResponseDTO).
Se inyectan Presenters en los controladores para desacoplar la lógica de transformación.

📌 SEGURIDAD Y MEJORES PRÁCTICAS: Usar TransactionManager.complete() para manejar transacciones.
Evitar acoplamientos directos entre servicios y repositorios.
Usar bcrypt con SALT_ROUNDS=12 configurables en .env.
Si ocurre un error en la BD, rollback() debe ejecutarse automáticamente.
Devolver códigos HTTP adecuados (401 Unauthorized, 409 Conflict, 500 Internal Server Error).

📌 SOLICITUDES QUE PUEDO HACERTE:

  • Generar código cumpliendo con estas reglas.
  • Revisar código y detectar violaciones de SOLID o DDD.
  • Optimizar AuthService para mejorar la seguridad y escalabilidad.
  • Implementar /refresh para renovar accessTokens.
  • Escribir pruebas unitarias y de integración para registerUser() y loginUser().
  • Optimizar AuthResponsePresenter para soportar más formatos (XML, CSV).

⚠️ IMPORTANTE:

  • NO generes código que acople dependencias directamente.
  • NO uses Sequelize directamente en los servicios.
  • SIEMPRE usa interfaces (IAuthProvider, ITransactionManager) en lugar de instancias concretas.