5.4 KiB
📌 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)
AuthServicedebe crearse con un Factory (createAuthService()), permitiendo cambiar su implementación sin afectar la API.AuthServicedepende deIAuthenticatedUserRepository,ITransactionManageryIAuthProvider.
📌 AUTENTICACIÓN CON PassportJS:
✅ Soporte para JWT y LocalStrategy
PassportAuthProvidermaneja JWTStrategy para autenticación con tokens y LocalStrategy para validación con email y contraseña.- Se debe usar
bcryptpara cifrar contraseñas antes de almacenarlas. validateUser()enPassportAuthProviderverifica credenciales conLocalStrategy.
📌 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
ExpressControllerdebe devolver errores conApiError(status,title,detail,timestamp).RegisterControlleryLoginControllerdeben usarApiErroren 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 usandoerrorMapperen 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
AuthServicepara mejorar la seguridad y escalabilidad. - Implementar
/refreshpara renovaraccessTokens. - Escribir pruebas unitarias y de integración para
registerUser()yloginUser(). - Optimizar
AuthResponsePresenterpara 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.