Skip to content

Om 516 - #164

Merged
leoAchu16 merged 4 commits into
devfrom
OM-516
May 20, 2026
Merged

Om 516#164
leoAchu16 merged 4 commits into
devfrom
OM-516

Conversation

@SebaKisser

@SebaKisser SebaKisser commented May 20, 2026 •

Copy link
Copy Markdown
Collaborator

OM-516:

  • Campos de reset token en schema
  • Instalacion de nodemailer
  • Servicios de forgot y rest password
  • Controladores y rutas en users para forgot y reset password
  • email.service.js que contiene el cuerpo del correo con el enlace

Summary by CodeRabbit

  • New Features
    • Sistema integral de recuperación de contraseña: Los usuarios pueden solicitar restablecimiento mediante correo electrónico, validar el enlace de recuperación segura recibido y actualizar su contraseña fácilmente. Incluye protección con tokens de corta duración para máxima seguridad de la cuenta.

Review Change Stack

* Campos de reset token en schema
* Instalacion de nodemailer
* Servicios de forgot y rest password
* Controladores y rutas en users para forgot y reset password
* email.service.js que contiene el cuerpo del correo con el enlace
@coderabbitai

coderabbitai Bot commented May 20, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@SebaKisser has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 38 minutes and 57 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9f9bd556-94c8-4bbf-a5cb-276d07d3b682

📥 Commits

Reviewing files that changed from the base of the PR and between 6cf8396 and 0c1a6a3.

📒 Files selected for processing (4)
  • src/modules/users/users/controllers/users.controllers.js
  • src/modules/users/users/routes/users.routes.js
  • src/modules/users/users/services/users.services.js
  • tests/unit/users/password-reset.test.js
📝 Walkthrough

Walkthrough

Se implementa un flujo completo de recuperación de contraseña mediante la adición de esquema de base de datos, servicio de email nodemailer, lógica de generación y validación de tokens, tres endpoints API públicos, y cobertura comprehensiva de tests para los servicios principales.

Changes

Password Reset Feature

Layer / File(s) Summary
Database schema and dependencies
package.json, prisma/migrations/20260520124718_add_password_reset_token/migration.sql, prisma/schema.prisma
Se agrega dependencia nodemailer, se crean columnas password_reset_token y password_reset_token_expires en tabla Users mediante migración SQL, y se actualizan los tipos del schema Prisma.
Email service infrastructure
src/lib/email.service.js
Se configura transporter nodemailer con variables de entorno (host, puerto, credenciales) y se implementa función sendPasswordResetEmail que construye URLs de reset y envía mensajes HTML con enlaces válidos.
Core password reset services
src/modules/users/users/services/users.services.js
Se implementan requestPasswordResetService (genera token y envía email), validateResetTokenService (verifica existencia y vigencia) y resetPasswordService (valida longitud mínima, hashea y persiste contraseña nueva).
Controllers and routes
src/modules/users/users/controllers/users.controllers.js, src/modules/users/users/routes/users.routes.js
Se agregan controladores requestPasswordReset, validateResetToken y resetPassword con validaciones de parámetros; se mapean a rutas públicas POST /forgot-password, GET /validate-reset-token/:token y POST /reset-password.
Comprehensive test suite
tests/unit/users/password-reset.test.js, tests/e2e/stores.test.js, tests/unit/commerce/store-status.test.js
Se agrega suite unit cubriendo validaciones, casos exitosos y lógica de expiración para los tres servicios; se actualizan mocks en tests existentes para soportar nuevas consultas de BD.

Sequence Diagram

sequenceDiagram
  participant User
  participant Controller
  participant Service
  participant Prisma as DB (Prisma)
  participant Email

  User->>Controller: POST /forgot-password { email }
  Controller->>Service: requestPasswordResetService(email)
  Service->>Prisma: users.findFirst (email normalizado)
  Prisma-->>Service: usuario activo encontrado
  Service->>Service: generar token con crypto
  Service->>Prisma: users.update (token + expiry)
  Prisma-->>Service: actualizado
  Service->>Email: sendPasswordResetEmail(email, token)
  Email-->>User: email enviado
  Service-->>Controller: { success }

  User->>Controller: GET /validate-reset-token/:token
  Controller->>Service: validateResetTokenService(token)
  Service->>Prisma: users.findFirst (token vigente)
  Prisma-->>Service: { valid: true } o null
  Service-->>Controller: { valid: true }

  User->>Controller: POST /reset-password { token, newPassword }
  Controller->>Service: resetPasswordService(token, newPassword)
  Service->>Prisma: users.findFirst (token vigente)
  Prisma-->>Service: usuario encontrado
  Service->>Service: bcrypt.hash(newPassword)
  Service->>Prisma: users.update (password_hash, limpia token/expiry)
  Prisma-->>Service: actualizado
  Service-->>Controller: { success }
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutos

Suggested reviewers

  • CrisNAC
  • leoAchu16
  • Andoumeda

Poem

🐰 Un token vuela con el viento,
Email que lleva salvación,
Hash que resguarda el momento,
Nueva contraseña en acción.
Los tests verifican sin falta,
El reset se alza y exalta! 🔐

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning El título 'Om 516' es una referencia a un ticket/issue pero no describe el cambio principal del pull request, que es la implementación de funcionalidad de recuperación de contraseña. Cambiar el título a algo más descriptivo como 'Implementar funcionalidad de recuperación de contraseña' o 'Agregar flujo de forgot password y reset password'.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch OM-516

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (2)
prisma/migrations/20260520124718_add_password_reset_token/migration.sql (1)

2-3: ⚡ Quick win

Agregar índice para lookup de token de reset.

Las búsquedas por token/expiración van a ser frecuentes en este flujo; sin índice, escalan mal. Recomendado agregar índice (idealmente parcial WHERE password_reset_token IS NOT NULL) en esta migración.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@prisma/migrations/20260520124718_add_password_reset_token/migration.sql`
around lines 2 - 3, Agregar un índice para acelerar búsquedas por
token/expiración en la tabla "Users": crea un índice (idealmente parcial) sobre
la columna password_reset_token con la condición WHERE password_reset_token IS
NOT NULL; opcionalmente hazlo como índice compuesto incluyendo
password_reset_token_expires si las consultas filtran por ambas columnas.
Actualiza la migración que añade las columnas ("password_reset_token" y
"password_reset_token_expires") para crear este índice después de agregar las
columnas y asegúrate de nombrar el índice de forma clara (por ejemplo usando
password_reset_token_idx).
prisma/schema.prisma (1)

27-30: ⚡ Quick win

Definí @@index en Prisma para los campos de reset token.

En Line 27–30 faltan índices en el modelo para acompañar las consultas por token y expiración; conviene declararlos en el schema además de la migración SQL.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@prisma/schema.prisma` around lines 27 - 30, Agrega índices en el modelo que
contiene los campos password_reset_token y password_reset_token_expires: dentro
del modelo (el que declara password_reset_token) añade
@@index([password_reset_token]) y/o @@index([password_reset_token,
password_reset_token_expires]) según las consultas que uses para buscar tokens
expirados; luego vuelve a generar la migración con Prisma (por ejemplo prisma
migrate dev) para que la definición del esquema y la migración SQL estén
sincronizadas.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/modules/users/users/controllers/users.controllers.js`:
- Around line 155-156: En validateResetToken, el fallback para errores
inesperados usa 400; cámbialo a 500 para que los errores del servidor no se
marquen como client errors: en la sección que calcula statusCode (actualmente
"const statusCode = error.statusCode || error.status || 400") reemplaza el 400
por 500 y conserva el resto (error.statusCode / error.status), asegurándote de
que la respuesta siga usando res.status(statusCode).json({ success: false,
message: error.message }).

In `@src/modules/users/users/routes/users.routes.js`:
- Line 20: La ruta expone el token en la URL; cambia la definición
router.get("/validate-reset-token/:token", validateResetToken) por una ruta
POST: router.post("/validate-reset-token", validateResetToken) y adapta el
handler validateResetToken para leer el token desde req.body.token en lugar de
req.params.token; asegúrate de que el middleware de parseo de JSON esté activado
(body-parser/express.json) y actualiza cualquier llamada, tests o documentación
que consuman la antigua ruta GET.

In `@src/modules/users/users/services/users.services.js`:
- Around line 429-437: Actualmente se persiste el token raw (variable token) en
la columna password_reset_token mediante prisma.users.update; cambia esto para
guardar únicamente un hash del token (p. ej. usando
crypto.createHash('sha256').update(token).digest('hex')) y deja
password_reset_token_expires igual, luego envía el token raw al usuario. En las
rutas/métodos que validan el token (los bloques donde se consultan/comparan el
token recibo — las consultas posteriores alrededor de las comprobaciones en las
líneas 450–451 y 475–476) aplica el mismo hashing al token entrante antes de
comparar con password_reset_token en la DB. Asegúrate de usar la misma función
de hashing y formato (hex) en ambos lugares y no almacenar nunca el token en
texto plano.
- Around line 473-495: Current code has a TOCTOU: it does
prisma.users.findFirst(...) to validate token then prisma.users.update(...)
which allows two concurrent requests to both pass; fix by performing a single
atomic update that includes the token and expiry guards in the WHERE (e.g., use
prisma.users.updateMany with where: { password_reset_token: token,
password_reset_token_expires: { gt: new Date() }, status: true } and data: {
password_hash, password_reset_token: null, password_reset_token_expires: null
}), compute password_hash before the update, then check the returned count (or
affected rows) and throw the same 400 error if no rows were updated; remove the
separate prisma.users.findFirst/id_user usage.

---

Nitpick comments:
In `@prisma/migrations/20260520124718_add_password_reset_token/migration.sql`:
- Around line 2-3: Agregar un índice para acelerar búsquedas por
token/expiración en la tabla "Users": crea un índice (idealmente parcial) sobre
la columna password_reset_token con la condición WHERE password_reset_token IS
NOT NULL; opcionalmente hazlo como índice compuesto incluyendo
password_reset_token_expires si las consultas filtran por ambas columnas.
Actualiza la migración que añade las columnas ("password_reset_token" y
"password_reset_token_expires") para crear este índice después de agregar las
columnas y asegúrate de nombrar el índice de forma clara (por ejemplo usando
password_reset_token_idx).

In `@prisma/schema.prisma`:
- Around line 27-30: Agrega índices en el modelo que contiene los campos
password_reset_token y password_reset_token_expires: dentro del modelo (el que
declara password_reset_token) añade @@index([password_reset_token]) y/o
@@index([password_reset_token, password_reset_token_expires]) según las
consultas que uses para buscar tokens expirados; luego vuelve a generar la
migración con Prisma (por ejemplo prisma migrate dev) para que la definición del
esquema y la migración SQL estén sincronizadas.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6f5c2c30-4446-4794-bc72-cd1d578a7eef

📥 Commits

Reviewing files that changed from the base of the PR and between ed626be and 6cf8396.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (10)
  • package.json
  • prisma/migrations/20260520124718_add_password_reset_token/migration.sql
  • prisma/schema.prisma
  • src/lib/email.service.js
  • src/modules/users/users/controllers/users.controllers.js
  • src/modules/users/users/routes/users.routes.js
  • src/modules/users/users/services/users.services.js
  • tests/e2e/stores.test.js
  • tests/unit/commerce/store-status.test.js
  • tests/unit/users/password-reset.test.js

Comment thread src/modules/users/users/controllers/users.controllers.js Outdated
Comment thread src/modules/users/users/routes/users.routes.js Outdated
Comment thread src/modules/users/users/services/users.services.js
Comment thread src/modules/users/users/services/users.services.js Outdated
@sonarqubecloud

Copy link
Copy Markdown

@leoAchu16
leoAchu16 merged commit fd96fce into dev May 20, 2026
4 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request May 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants