Repository navigation
Conversation
|
Warning Rate limit exceeded
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 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 configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughSe 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. ChangesPassword Reset Feature
Sequence DiagramsequenceDiagram
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 }
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutos Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (2)
prisma/migrations/20260520124718_add_password_reset_token/migration.sql (1)
2-3: ⚡ Quick winAgregar í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 winDefiní
@@indexen 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
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (10)
package.jsonprisma/migrations/20260520124718_add_password_reset_token/migration.sqlprisma/schema.prismasrc/lib/email.service.jssrc/modules/users/users/controllers/users.controllers.jssrc/modules/users/users/routes/users.routes.jssrc/modules/users/users/services/users.services.jstests/e2e/stores.test.jstests/unit/commerce/store-status.test.jstests/unit/users/password-reset.test.js
|



OM-516:
Summary by CodeRabbit