Skip to content

Conversation

@coratgerl
Copy link
Contributor

@coratgerl coratgerl commented Nov 6, 2025

Issue

Fixes: #9510

  • Add tests
  • Add changes to documentation (guides, repository pages, code comments)

Summary by CodeRabbit

  • New Features

    • Added a beforePasswordResetRequest Cloud Code hook that receives enriched request metadata and supports optional rate-limiting for password-reset requests.
  • Bug Fixes / Improvements

    • Password reset flow now preloads expanded user context, looks up users by token or email, runs the hook before sending reset emails, and enforces the hook for _User accounts.
    • Validation messages updated to mention the new trigger.
  • Tests

    • Expanded coverage for success, blocking errors, file-attached users, non-existent emails, and request-context availability.

@parse-github-assistant
Copy link

I will reformat the title to use the proper commit message syntax.

@parse-github-assistant parse-github-assistant bot changed the title feat: add beforePasswordResetRequest hook feat: Add beforePasswordResetRequest hook Nov 6, 2025
@parse-github-assistant
Copy link

parse-github-assistant bot commented Nov 6, 2025

🚀 Thanks for opening this pull request!

@coratgerl coratgerl changed the title feat: Add beforePasswordResetRequest hook feat: add beforePasswordResetRequest hook Nov 6, 2025
@parseplatformorg
Copy link
Contributor

parseplatformorg commented Nov 6, 2025

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@parse-github-assistant
Copy link

I will reformat the title to use the proper commit message syntax.

@parse-github-assistant parse-github-assistant bot changed the title feat: add beforePasswordResetRequest hook feat: Add beforePasswordResetRequest hook Nov 6, 2025
@coderabbitai
Copy link

coderabbitai bot commented Nov 6, 2025

📝 Walkthrough

Walkthrough

Adds a new beforePasswordResetRequest Cloud trigger API, registers the trigger type, invokes it from UsersRouter during password-reset requests after resolving/inflating the user and expanding attached files, and adds tests covering success, blocking, file-attached users, missing emails, request context, and validation.

Changes

Cohort / File(s) Change Summary
Tests
spec/CloudCode.spec.js
Adds and updates tests for beforePasswordResetRequest: valid flow, blocking behavior (including users with attached files), non-existent email handling, request-object contents (object, headers, ip, installationId, context, config), and updates trigger validation/error-message expectations.
Router / Password Reset Flow
src/Routers/UsersRouter.js
Imports inflate from triggers; handleResetRequest now looks up user by perishable token (with expiry) or by email/username OR query (limits results), sets userResults/userData, sanitizes authData, expands attached files, inflates the user, and invokes beforePasswordResetRequest before sending reset email.
Cloud Code API
src/cloud-code/Parse.Cloud.js
Adds Parse.Cloud.beforePasswordResetRequest(handler, validationHandler) supporting optional class/constructor first arg and optional validationHandler.rateLimit; registers trigger via triggers.addTrigger and conditionally applies a rate limit to POST /requestPasswordReset.
Trigger Types & Request Handling
src/triggers.js
Adds beforePasswordResetRequest to exported Types, updates trigger validation/error messages to include it for _User, and adjusts getRequestObject logic to copy context/config for this trigger.
Manifest
package.json
Listed in manifest block; no functional changes described.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Client
    participant UsersRouter as UsersRouter\n(handleResetRequest)
    participant Triggers as TriggerRegistry
    participant Hook as beforePasswordResetRequest\nHandler
    participant Email as EmailAdapter

    Client->>UsersRouter: POST /requestPasswordReset (email or token)
    UsersRouter->>UsersRouter: Lookup user (token OR email/username)
    UsersRouter->>UsersRouter: Sanitize authData & expand attached files
    UsersRouter->>Triggers: Invoke beforePasswordResetRequest(req with inflated user)
    Triggers->>Hook: Call handler(req)
    alt Handler allows
        Hook-->>Triggers: Return success
        Triggers-->>UsersRouter: Continue flow
        UsersRouter->>Email: sendPasswordResetEmail(user)
        Email-->>Client: 200 OK
    else Handler throws
        Hook-->>Triggers: Throw error
        Triggers-->>UsersRouter: Propagate error
        UsersRouter-->>Client: Error response
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Files meriting extra attention:
    • spec/CloudCode.spec.js — new and modified tests, assertions, and coverage for many scenarios.
    • src/Routers/UsersRouter.js — token vs email lookup branches, expiry checks, OR query logic, inflate/file expansion, and trigger invocation placement.
    • src/cloud-code/Parse.Cloud.js — argument normalization, trigger registration, and optional rate-limit wiring.
    • src/triggers.js — new trigger type and request-object/context copying logic.

Possibly related PRs

Suggested reviewers

  • Moumouls

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding a new beforePasswordResetRequest hook feature.
Description check ✅ Passed The pull request description includes the required issue link and indicates tests and documentation have been added, meeting the template requirements.
Linked Issues check ✅ Passed Code changes implement all requirements: new trigger allows validation before password reset token generation/storage, prevents unnecessary emails to invalid addresses, and enables Cloud Code to block requests by throwing errors [#9510].
Out of Scope Changes check ✅ Passed All changes are directly aligned with adding the beforePasswordResetRequest hook: tests, public API, router implementation, trigger definitions, and documentation updates are all in scope.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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
Copy link

coderabbitai bot commented Nov 6, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@codecov
Copy link

codecov bot commented Nov 6, 2025

Codecov Report

❌ Patch coverage is 96.29630% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 93.07%. Comparing base (c22cb0a) to head (e5b3e09).
⚠️ Report is 3 commits behind head on alpha.

Files with missing lines Patch % Lines
src/cloud-code/Parse.Cloud.js 88.88% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##            alpha    #9906   +/-   ##
=======================================
  Coverage   93.06%   93.07%           
=======================================
  Files         187      187           
  Lines       15253    15275   +22     
  Branches      177      177           
=======================================
+ Hits        14195    14217   +22     
  Misses       1046     1046           
  Partials       12       12           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (5)
src/triggers.js (1)

62-66: Validation updated to restrict to _User — OK; consider throwing Error objects.

Logic is correct; throwing strings matches existing pattern but is brittle. Consider new Parse.Error for future cleanup.

src/Routers/UsersRouter.js (1)

449-474: Minor: reduce variables and narrow scope.

userResults is only used to grab the first element. Simplify to a single const userRecord to reduce cognitive load.

src/cloud-code/Parse.Cloud.js (1)

352-394: Add validator wiring and validate input (parity + future-proofing).

Current implementation mirrors beforeLogin (rateLimit only). If you want validator features (skipWithMasterKey, requireMaster, etc.) or just to validate rateLimit shape, call validateValidator and pass validationHandler to addTrigger.

 ParseCloud.beforePasswordResetRequest = function (handler, validationHandler) {
   let className = '_User';
   if (typeof handler === 'string' || isParseObjectConstructor(handler)) {
     // validation will occur downstream, this is to maintain internal
     // code consistency with the other hook types.
     className = triggers.getClassName(handler);
     handler = arguments[1];
     validationHandler = arguments.length >= 2 ? arguments[2] : null;
   }
-  triggers.addTrigger(triggers.Types.beforePasswordResetRequest, className, handler, Parse.applicationId);
+  validateValidator(validationHandler);
+  triggers.addTrigger(
+    triggers.Types.beforePasswordResetRequest,
+    className,
+    handler,
+    Parse.applicationId,
+    validationHandler
+  );
   if (validationHandler && validationHandler.rateLimit) {
     addRateLimit(
       { requestPath: `/requestPasswordReset`, requestMethods: 'POST', ...validationHandler.rateLimit },
       Parse.applicationId,
       true
     );
   }
 };

Also consider documenting the optional validationHandler param in the JSDoc.

spec/CloudCode.spec.js (2)

3782-3978: Prefer async/await without done in new tests to reduce flakiness.

The new tests use async done => { ...; done(); }. Drop done and rely on async function completion/throws instead. This is the repository’s preferred pattern. Based on learnings.


3800-3816: Add an assertion that password/authData are not exposed to Cloud Code.

After the UsersRouter sanitization fix, add a quick check:

 Parse.Cloud.beforePasswordResetRequest(req => {
   // existing expectations...
+  expect(req.object.get('password')).toBeUndefined();
+  expect(req.object.get('authData')).toBeUndefined();
 });

Helps prevent regressions.

Also applies to: 3836-3859, 3878-3904, 3932-3962

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f27b050 and c354da3.

📒 Files selected for processing (4)
  • spec/CloudCode.spec.js (2 hunks)
  • src/Routers/UsersRouter.js (2 hunks)
  • src/cloud-code/Parse.Cloud.js (1 hunks)
  • src/triggers.js (3 hunks)
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-10-16T19:27:05.311Z
Learnt from: Moumouls
Repo: parse-community/parse-server PR: 9883
File: spec/CloudCodeLogger.spec.js:410-412
Timestamp: 2025-10-16T19:27:05.311Z
Learning: In spec/CloudCodeLogger.spec.js, the test "should log cloud function triggers using the silent log level" (around lines 383-420) is known to be flaky and requires the extra `await new Promise(resolve => setTimeout(resolve, 100))` timeout after awaiting `afterSavePromise` for reliability, even though it may appear redundant.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-08-27T12:33:06.237Z
Learnt from: EmpiDev
Repo: parse-community/parse-server PR: 9770
File: src/triggers.js:467-477
Timestamp: 2025-08-27T12:33:06.237Z
Learning: In the Parse Server codebase, maybeRunAfterFindTrigger is called in production with Parse.Query objects constructed via withJSON(), so the plain object query handling bug only affects tests, not production code paths.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-05-09T09:59:06.289Z
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 9445
File: spec/ParseLiveQuery.spec.js:1340-1375
Timestamp: 2025-05-09T09:59:06.289Z
Learning: Tests in the parse-server repository should use promise-based approaches rather than callback patterns with `done()`. Use a pattern where a Promise is created that resolves when the event occurs, then await that promise.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-05-09T09:59:06.289Z
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 9445
File: spec/ParseLiveQuery.spec.js:1340-1375
Timestamp: 2025-05-09T09:59:06.289Z
Learning: New tests in the parse-server repository should use async/await with promise-based patterns rather than callback patterns with `done()`. The preferred pattern is to create a Promise that resolves when an expected event occurs, then await that Promise.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-05-04T20:41:05.147Z
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 9445
File: spec/ParseLiveQuery.spec.js:1312-1338
Timestamp: 2025-05-04T20:41:05.147Z
Learning: New tests in the parse-server repository should use async/await with promise-based patterns rather than callback patterns with `done()`.

Applied to files:

  • spec/CloudCode.spec.js
🧬 Code graph analysis (3)
src/Routers/UsersRouter.js (1)
src/triggers.js (2)
  • inflate (1002-1008)
  • maybeRunTrigger (895-998)
src/cloud-code/Parse.Cloud.js (2)
src/Routers/CloudCodeRouter.js (1)
  • triggers (4-4)
src/middlewares.js (2)
  • addRateLimit (520-623)
  • addRateLimit (520-623)
spec/CloudCode.spec.js (2)
spec/helper.js (2)
  • Parse (4-4)
  • reconfigureServer (180-214)
src/cloud-code/Parse.Cloud.js (1)
  • emailAdapter (604-604)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
  • GitHub Check: Docker Build
  • GitHub Check: PostgreSQL 18, PostGIS 3.6
  • GitHub Check: PostgreSQL 15, PostGIS 3.5
  • GitHub Check: Node 22
  • GitHub Check: PostgreSQL 17, PostGIS 3.5
  • GitHub Check: PostgreSQL 15, PostGIS 3.4
  • GitHub Check: Node 18
  • GitHub Check: PostgreSQL 16, PostGIS 3.5
  • GitHub Check: MongoDB 6, ReplicaSet
  • GitHub Check: MongoDB 8, ReplicaSet
  • GitHub Check: PostgreSQL 15, PostGIS 3.3
  • GitHub Check: Node 20
  • GitHub Check: MongoDB 7, ReplicaSet
  • GitHub Check: Redis Cache
🔇 Additional comments (2)
src/triggers.js (2)

9-9: New trigger type added correctly.

Entry in Types for beforePasswordResetRequest looks consistent and non-breaking.


291-296: Context exposure includes beforePasswordResetRequest — LGTM.

Request.context now set for this trigger type; aligns with other auth-related hooks.

@mtrezza
Copy link
Member

mtrezza commented Nov 7, 2025

Note that I proposed the name beforePasswordResetRequest to distinguish between the user's request to initiate the reset process (/requestPasswordReset), and the user's form submission (/request_password_reset), which in the future could be named beforePasswordResetSubmission. Let's briefly validate that idea:

  • beforePasswordResetRequest --> user requests email
  • beforePasswordResetSubmission --> user submits form
  • afterPasswordReset --> password reset completed

Maybe this would be more intuitive:

  • beforePasswordResetEmailRequest --> user requests email
  • beforePasswordReset --> user submits form, password reset process is about to start
  • afterPasswordReset --> password reset process completed

Then again, a password reset could be sent via other channels in the future, so maybe we stick with this:

  • beforePasswordResetRequest --> user requests email
  • beforePasswordReset --> user submits form, password reset process is about to start
  • afterPasswordReset --> password reset process completed

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
spec/CloudCode.spec.js (3)

3623-3675: Consider modernizing test pattern

This test correctly validates that afterFind hooks are not triggered during save operations. However, consider converting from async done callback pattern to pure async/await:

Based on learnings

Apply this diff:

-  it('afterFind should not be triggered when saving an object', async () => {
+  it('afterFind should not be triggered when saving an object', async () => {
     let beforeSaves = 0;
     Parse.Cloud.beforeSave('SavingTest', () => {
       beforeSaves++;
     });
     
     // ... rest of test logic ...
     
     expect(beforeSaves).toEqual(3);
     expect(afterSaves).toEqual(3);
     expect(beforeFinds).toEqual(1);
     expect(afterFinds).toEqual(1);
-    done();
   });

3836-3870: Test logic is correct; consider modernizing pattern

The test properly validates that beforePasswordResetRequest runs with a valid user and that the email is sent. However, similar to other tests in this suite, consider removing the done callback and using pure async/await pattern.

Based on learnings


3959-3983: Improve error handling specificity

The try/catch block swallows all errors, which could mask unexpected failures. Consider testing both scenarios explicitly or at least validating the error type when one is thrown.

Apply this diff to make the test more explicit:

   it('should not run beforePasswordResetRequest if email does not exist', async done => {
     let hit = 0;
     const emailAdapter = {
       sendVerificationEmail: () => Promise.resolve(),
       sendPasswordResetEmail: () => {},
       sendMail: () => {},
     };
 
     await reconfigureServer({
       emailAdapter: emailAdapter,
       publicServerURL: 'http://localhost:8378/1',
+      passwordPolicy: {
+        resetPasswordSuccessOnInvalidEmail: true
+      }
     });
 
     Parse.Cloud.beforePasswordResetRequest(req => {
       hit++;
     });
 
-    try {
-      await Parse.User.requestPasswordReset('[email protected]');
-    } catch (e) {
-      // May or may not throw depending on passwordPolicy.resetPasswordSuccessOnInvalidEmail
-    }
+    // Should not throw when resetPasswordSuccessOnInvalidEmail is true
+    await Parse.User.requestPasswordReset('[email protected]');
     expect(hit).toBe(0);
     done();
   });

Alternatively, add a second test for the case where resetPasswordSuccessOnInvalidEmail is false to ensure comprehensive coverage.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2971acf and 8076a65.

📒 Files selected for processing (1)
  • spec/CloudCode.spec.js (3 hunks)
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-10-16T19:27:05.311Z
Learnt from: Moumouls
Repo: parse-community/parse-server PR: 9883
File: spec/CloudCodeLogger.spec.js:410-412
Timestamp: 2025-10-16T19:27:05.311Z
Learning: In spec/CloudCodeLogger.spec.js, the test "should log cloud function triggers using the silent log level" (around lines 383-420) is known to be flaky and requires the extra `await new Promise(resolve => setTimeout(resolve, 100))` timeout after awaiting `afterSavePromise` for reliability, even though it may appear redundant.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-05-04T20:41:05.147Z
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 9445
File: spec/ParseLiveQuery.spec.js:1312-1338
Timestamp: 2025-05-04T20:41:05.147Z
Learning: New tests in the parse-server repository should use async/await with promise-based patterns rather than callback patterns with `done()`.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-08-27T12:33:06.237Z
Learnt from: EmpiDev
Repo: parse-community/parse-server PR: 9770
File: src/triggers.js:467-477
Timestamp: 2025-08-27T12:33:06.237Z
Learning: In the Parse Server codebase, maybeRunAfterFindTrigger is called in production with Parse.Query objects constructed via withJSON(), so the plain object query handling bug only affects tests, not production code paths.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-05-09T09:59:06.289Z
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 9445
File: spec/ParseLiveQuery.spec.js:1340-1375
Timestamp: 2025-05-09T09:59:06.289Z
Learning: Tests in the parse-server repository should use promise-based approaches rather than callback patterns with `done()`. Use a pattern where a Promise is created that resolves when the event occurs, then await that promise.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-05-09T09:59:06.289Z
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 9445
File: spec/ParseLiveQuery.spec.js:1340-1375
Timestamp: 2025-05-09T09:59:06.289Z
Learning: New tests in the parse-server repository should use async/await with promise-based patterns rather than callback patterns with `done()`. The preferred pattern is to create a Promise that resolves when an expected event occurs, then await that Promise.

Applied to files:

  • spec/CloudCode.spec.js
🧬 Code graph analysis (1)
spec/CloudCode.spec.js (1)
spec/helper.js (2)
  • Parse (4-4)
  • reconfigureServer (180-214)
🪛 GitHub Check: Lint
spec/CloudCode.spec.js

[warning] 4034-4034:
More than 2 blank lines not allowed

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Redis Cache
  • GitHub Check: MongoDB 8, ReplicaSet
  • GitHub Check: MongoDB 6, ReplicaSet
  • GitHub Check: Docker Build
  • GitHub Check: Code Analysis (javascript)
🔇 Additional comments (3)
spec/CloudCode.spec.js (3)

3310-3322: LGTM: Trigger validation messages updated correctly

The error messages have been properly updated to include the new beforePasswordResetRequest trigger alongside beforeLogin and afterLogin. The changes are consistent across all validation checks.


3872-3957: LGTM: Blocking behavior well-tested

These tests properly validate that beforePasswordResetRequest can block password reset requests by throwing errors. The inclusion of a test with an attached file is important as it verifies that file expansion occurs before the hook invocation, preventing unnecessary token generation and email sending (as noted in the PR objectives).


3985-4030: LGTM: Request data and class validation tests

These tests properly validate that:

  1. The hook receives all expected request fields (object, headers, ip, installationId, context, config)
  2. Only the _User class is allowed for beforePasswordResetRequest, consistent with other user-authentication triggers

The test patterns match those used for beforeLogin and other triggers, ensuring consistency across the test suite.

@coratgerl
Copy link
Contributor Author

I think beforePasswordResetEmailRequest would be clearer, as it explicitly describes the action (email request). However, if other reset channels (SMS, etc.) are planned for the future, keeping the more generic beforePasswordResetRequest might be a better long-term choice. What do you think?

@coratgerl coratgerl requested a review from mtrezza November 8, 2025 13:51
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
spec/CloudCode.spec.js (1)

4659-4659: Remove extra blank lines.

More than 2 blank lines are not allowed before the new describe block. Please remove the extra blank line to comply with the project's style guidelines.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8076a65 and 659ab5e.

📒 Files selected for processing (1)
  • spec/CloudCode.spec.js (2 hunks)
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-10-16T19:27:05.311Z
Learnt from: Moumouls
Repo: parse-community/parse-server PR: 9883
File: spec/CloudCodeLogger.spec.js:410-412
Timestamp: 2025-10-16T19:27:05.311Z
Learning: In spec/CloudCodeLogger.spec.js, the test "should log cloud function triggers using the silent log level" (around lines 383-420) is known to be flaky and requires the extra `await new Promise(resolve => setTimeout(resolve, 100))` timeout after awaiting `afterSavePromise` for reliability, even though it may appear redundant.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-05-04T20:41:05.147Z
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 9445
File: spec/ParseLiveQuery.spec.js:1312-1338
Timestamp: 2025-05-04T20:41:05.147Z
Learning: New tests in the parse-server repository should use async/await with promise-based patterns rather than callback patterns with `done()`.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-05-09T09:59:06.289Z
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 9445
File: spec/ParseLiveQuery.spec.js:1340-1375
Timestamp: 2025-05-09T09:59:06.289Z
Learning: Tests in the parse-server repository should use promise-based approaches rather than callback patterns with `done()`. Use a pattern where a Promise is created that resolves when the event occurs, then await that promise.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-05-09T09:59:06.289Z
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 9445
File: spec/ParseLiveQuery.spec.js:1340-1375
Timestamp: 2025-05-09T09:59:06.289Z
Learning: New tests in the parse-server repository should use async/await with promise-based patterns rather than callback patterns with `done()`. The preferred pattern is to create a Promise that resolves when an expected event occurs, then await that Promise.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-08-27T12:33:06.237Z
Learnt from: EmpiDev
Repo: parse-community/parse-server PR: 9770
File: src/triggers.js:467-477
Timestamp: 2025-08-27T12:33:06.237Z
Learning: In the Parse Server codebase, maybeRunAfterFindTrigger is called in production with Parse.Query objects constructed via withJSON(), so the plain object query handling bug only affects tests, not production code paths.

Applied to files:

  • spec/CloudCode.spec.js
🧬 Code graph analysis (1)
spec/CloudCode.spec.js (2)
spec/helper.js (2)
  • Parse (4-4)
  • reconfigureServer (180-214)
src/cloud-code/Parse.Cloud.js (1)
  • emailAdapter (604-604)
🔇 Additional comments (1)
spec/CloudCode.spec.js (1)

3310-3322: LGTM!

The trigger validation error messages have been correctly updated to include beforePasswordResetRequest in the list of user-specific triggers. The changes are consistent across all test assertions.

@mtrezza
Copy link
Member

mtrezza commented Nov 8, 2025

@coratgerl Yes, I think if new channel are introduced, we don't want a separate trigger, but just a parameter that indicates the channel for example. So I'd stick with:

  • beforePasswordResetRequest --> user requests reset (via email, phone, etc)
  • beforePasswordReset --> user submits form, password reset process is about to start
  • afterPasswordReset --> password reset process completed

Which is what you currently have, so I think we're good, right?

@coratgerl
Copy link
Contributor Author

Yes seems logic for me

@coratgerl coratgerl requested a review from mtrezza November 19, 2025 08:08
Copy link
Member

@mtrezza mtrezza left a comment

Choose a reason for hiding this comment

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

There are unresolved conversations

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
spec/CloudCode.spec.js (1)

4724-4729: Use fail() instead of throwing an error for clarity.

For consistency with other tests in this file and clearer test failure messages, use fail() instead of throwing a generic error when the operation should have failed.

Apply this diff:

     try {
       await Parse.User.requestPasswordReset('[email protected]');
-      throw new Error('should not have sent password reset email.');
+      fail('should not have sent password reset email.');
     } catch (e) {
       expect(e.message).toBe('password reset blocked');
     }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2a6df76 and 8917926.

📒 Files selected for processing (1)
  • spec/CloudCode.spec.js (2 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 0
File: :0-0
Timestamp: 2025-11-17T15:02:48.786Z
Learning: For Parse Server PRs, always suggest an Angular commit convention PR title that would make a meaningful changelog entry for developers. Update the PR title suggestion on every commit. The format should be: type(scope): description. Common types include feat, fix, perf, refactor, docs, test, chore. The scope should identify the subsystem (e.g., graphql, rest, push, security). The description should be action-oriented and clearly convey the change's impact to developers.
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 0
File: :0-0
Timestamp: 2025-11-08T13:46:04.940Z
Learning: When reviewing Parse Server PRs that add new features, always check whether the feature is documented in the README.md file, though for new Parse Server options this is optional rather than required.
📚 Learning: 2025-10-16T19:27:05.311Z
Learnt from: Moumouls
Repo: parse-community/parse-server PR: 9883
File: spec/CloudCodeLogger.spec.js:410-412
Timestamp: 2025-10-16T19:27:05.311Z
Learning: In spec/CloudCodeLogger.spec.js, the test "should log cloud function triggers using the silent log level" (around lines 383-420) is known to be flaky and requires the extra `await new Promise(resolve => setTimeout(resolve, 100))` timeout after awaiting `afterSavePromise` for reliability, even though it may appear redundant.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-05-04T20:41:05.147Z
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 9445
File: spec/ParseLiveQuery.spec.js:1312-1338
Timestamp: 2025-05-04T20:41:05.147Z
Learning: New tests in the parse-server repository should use async/await with promise-based patterns rather than callback patterns with `done()`.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-05-09T09:59:06.289Z
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 9445
File: spec/ParseLiveQuery.spec.js:1340-1375
Timestamp: 2025-05-09T09:59:06.289Z
Learning: Tests in the parse-server repository should use promise-based approaches rather than callback patterns with `done()`. Use a pattern where a Promise is created that resolves when the event occurs, then await that promise.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-05-09T09:59:06.289Z
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 9445
File: spec/ParseLiveQuery.spec.js:1340-1375
Timestamp: 2025-05-09T09:59:06.289Z
Learning: New tests in the parse-server repository should use async/await with promise-based patterns rather than callback patterns with `done()`. The preferred pattern is to create a Promise that resolves when an expected event occurs, then await that Promise.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-08-27T09:08:34.252Z
Learnt from: EmpiDev
Repo: parse-community/parse-server PR: 9770
File: src/triggers.js:446-454
Timestamp: 2025-08-27T09:08:34.252Z
Learning: When analyzing function signature changes in Parse Server codebase, verify that call sites are actually incorrect before flagging them. Passing tests are a strong indicator that function calls are already properly aligned with new signatures.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-08-27T12:33:06.237Z
Learnt from: EmpiDev
Repo: parse-community/parse-server PR: 9770
File: src/triggers.js:467-477
Timestamp: 2025-08-27T12:33:06.237Z
Learning: In the Parse Server codebase, maybeRunAfterFindTrigger is called in production with Parse.Query objects constructed via withJSON(), so the plain object query handling bug only affects tests, not production code paths.

Applied to files:

  • spec/CloudCode.spec.js
🧬 Code graph analysis (1)
spec/CloudCode.spec.js (1)
spec/helper.js (2)
  • Parse (4-4)
  • reconfigureServer (180-214)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (16)
  • GitHub Check: PostgreSQL 15, PostGIS 3.5
  • GitHub Check: PostgreSQL 18, PostGIS 3.6
  • GitHub Check: PostgreSQL 15, PostGIS 3.4
  • GitHub Check: PostgreSQL 17, PostGIS 3.5
  • GitHub Check: PostgreSQL 16, PostGIS 3.5
  • GitHub Check: MongoDB 7, ReplicaSet
  • GitHub Check: PostgreSQL 15, PostGIS 3.3
  • GitHub Check: Node 20
  • GitHub Check: MongoDB 8, ReplicaSet
  • GitHub Check: Node 22
  • GitHub Check: Node 18
  • GitHub Check: Redis Cache
  • GitHub Check: Code Analysis (javascript)
  • GitHub Check: MongoDB 6, ReplicaSet
  • GitHub Check: Docker Build
  • GitHub Check: Benchmarks
🔇 Additional comments (5)
spec/CloudCode.spec.js (5)

3310-3322: LGTM! Validation messages correctly updated.

The error messages have been properly updated to include beforePasswordResetRequest in the list of triggers that only allow the _User class, maintaining consistency across all validation points.


4661-4694: LGTM! Well-structured test for basic hook flow.

The test properly validates that the beforePasswordResetRequest hook executes with the correct user data and that the email adapter is called as expected.


4734-4755: LGTM! Correctly validates hook behavior for non-existent email.

This test properly ensures the hook doesn't run when an email doesn't exist in the system, which is important for both security (not leaking email existence) and correctness.


4757-4791: LGTM! Comprehensive test for request data availability.

The test properly validates all expected properties in the request object (object, headers, ip, installationId, context, config) and includes a user with an attached file to ensure proper handling of file expansion in the password reset flow.


4793-4807: LGTM! Thorough validation of class restrictions.

The test properly validates that beforePasswordResetRequest can only be registered for the _User class, testing multiple registration patterns to ensure comprehensive coverage.

Signed-off-by: Manuel <[email protected]>
Signed-off-by: Manuel <[email protected]>
Signed-off-by: Manuel <[email protected]>
@coratgerl coratgerl requested a review from mtrezza November 19, 2025 12:52
@coratgerl coratgerl force-pushed the before-password-reset-request branch from 82812d1 to ad8711c Compare November 19, 2025 13:27
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
spec/CloudCode.spec.js (1)

4660-4812: Excellent test coverage with minor optimization opportunity.

The test suite comprehensively covers the beforePasswordResetRequest hook functionality with appropriate use of async/await patterns and correct email domains.

However, in the fourth test (lines 4788-4793), consider combining the user signup and file save operations into a single operation to reduce database writes:

Apply this optimization:

     const user = new Parse.User();
     user.setUsername('testuser2');
     user.setPassword('password');
     user.set('email', '[email protected]');
+    user.set('file', file);
     await user.signUp();
-    await user.save({ file });

This eliminates the redundant save operation while achieving the same result.

Based on learnings

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 82812d1 and ad8711c.

📒 Files selected for processing (1)
  • spec/CloudCode.spec.js (2 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 0
File: :0-0
Timestamp: 2025-11-17T15:02:48.786Z
Learning: For Parse Server PRs, always suggest an Angular commit convention PR title that would make a meaningful changelog entry for developers. Update the PR title suggestion on every commit. The format should be: type(scope): description. Common types include feat, fix, perf, refactor, docs, test, chore. The scope should identify the subsystem (e.g., graphql, rest, push, security). The description should be action-oriented and clearly convey the change's impact to developers.
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 0
File: :0-0
Timestamp: 2025-11-08T13:46:04.940Z
Learning: When reviewing Parse Server PRs that add new features, always check whether the feature is documented in the README.md file, though for new Parse Server options this is optional rather than required.
📚 Learning: 2025-10-16T19:27:05.311Z
Learnt from: Moumouls
Repo: parse-community/parse-server PR: 9883
File: spec/CloudCodeLogger.spec.js:410-412
Timestamp: 2025-10-16T19:27:05.311Z
Learning: In spec/CloudCodeLogger.spec.js, the test "should log cloud function triggers using the silent log level" (around lines 383-420) is known to be flaky and requires the extra `await new Promise(resolve => setTimeout(resolve, 100))` timeout after awaiting `afterSavePromise` for reliability, even though it may appear redundant.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-05-04T20:41:05.147Z
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 9445
File: spec/ParseLiveQuery.spec.js:1312-1338
Timestamp: 2025-05-04T20:41:05.147Z
Learning: New tests in the parse-server repository should use async/await with promise-based patterns rather than callback patterns with `done()`.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-05-09T09:59:06.289Z
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 9445
File: spec/ParseLiveQuery.spec.js:1340-1375
Timestamp: 2025-05-09T09:59:06.289Z
Learning: Tests in the parse-server repository should use promise-based approaches rather than callback patterns with `done()`. Use a pattern where a Promise is created that resolves when the event occurs, then await that promise.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-05-09T09:59:06.289Z
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 9445
File: spec/ParseLiveQuery.spec.js:1340-1375
Timestamp: 2025-05-09T09:59:06.289Z
Learning: New tests in the parse-server repository should use async/await with promise-based patterns rather than callback patterns with `done()`. The preferred pattern is to create a Promise that resolves when an expected event occurs, then await that Promise.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-08-27T09:08:34.252Z
Learnt from: EmpiDev
Repo: parse-community/parse-server PR: 9770
File: src/triggers.js:446-454
Timestamp: 2025-08-27T09:08:34.252Z
Learning: When analyzing function signature changes in Parse Server codebase, verify that call sites are actually incorrect before flagging them. Passing tests are a strong indicator that function calls are already properly aligned with new signatures.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-08-27T12:33:06.237Z
Learnt from: EmpiDev
Repo: parse-community/parse-server PR: 9770
File: src/triggers.js:467-477
Timestamp: 2025-08-27T12:33:06.237Z
Learning: In the Parse Server codebase, maybeRunAfterFindTrigger is called in production with Parse.Query objects constructed via withJSON(), so the plain object query handling bug only affects tests, not production code paths.

Applied to files:

  • spec/CloudCode.spec.js
🧬 Code graph analysis (1)
spec/CloudCode.spec.js (1)
spec/helper.js (2)
  • Parse (4-4)
  • reconfigureServer (180-214)
🔇 Additional comments (1)
spec/CloudCode.spec.js (1)

3310-3322: LGTM!

The updated validation error messages correctly include beforePasswordResetRequest alongside beforeLogin and afterLogin to enforce that only the _User class is allowed for these triggers.

@coratgerl coratgerl requested a review from mtrezza November 19, 2025 13:32
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
spec/CloudCode.spec.js (1)

4660-4812: beforePasswordResetRequest test suite is thorough; consider one extra negative-side-effect assertion

The new beforePasswordResetRequest tests nicely cover:

  • happy path (hook runs, user data resolved, email adapter called),
  • blocking behavior (error thrown, request fails, adapter not called),
  • non-existent email (hook not invoked),
  • full request context (including attached file) on the hook, and
  • _User-only validation for the new trigger, consistent with login hooks.

Functionally and stylistically this looks solid and matches the async/await test guidelines. As an optional hardening step, you could also assert that no password reset token / related state is persisted when the hook throws (to prove DB writes are skipped as intended), but that can be deferred or covered in a more router-focused test if preferred.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ad8711c and e5b3e09.

📒 Files selected for processing (1)
  • spec/CloudCode.spec.js (2 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 0
File: :0-0
Timestamp: 2025-11-17T15:02:48.786Z
Learning: For Parse Server PRs, always suggest an Angular commit convention PR title that would make a meaningful changelog entry for developers. Update the PR title suggestion on every commit. The format should be: type(scope): description. Common types include feat, fix, perf, refactor, docs, test, chore. The scope should identify the subsystem (e.g., graphql, rest, push, security). The description should be action-oriented and clearly convey the change's impact to developers.
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 0
File: :0-0
Timestamp: 2025-11-08T13:46:04.940Z
Learning: When reviewing Parse Server PRs that add new features, always check whether the feature is documented in the README.md file, though for new Parse Server options this is optional rather than required.
📚 Learning: 2025-10-16T19:27:05.311Z
Learnt from: Moumouls
Repo: parse-community/parse-server PR: 9883
File: spec/CloudCodeLogger.spec.js:410-412
Timestamp: 2025-10-16T19:27:05.311Z
Learning: In spec/CloudCodeLogger.spec.js, the test "should log cloud function triggers using the silent log level" (around lines 383-420) is known to be flaky and requires the extra `await new Promise(resolve => setTimeout(resolve, 100))` timeout after awaiting `afterSavePromise` for reliability, even though it may appear redundant.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-05-04T20:41:05.147Z
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 9445
File: spec/ParseLiveQuery.spec.js:1312-1338
Timestamp: 2025-05-04T20:41:05.147Z
Learning: New tests in the parse-server repository should use async/await with promise-based patterns rather than callback patterns with `done()`.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-05-09T09:59:06.289Z
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 9445
File: spec/ParseLiveQuery.spec.js:1340-1375
Timestamp: 2025-05-09T09:59:06.289Z
Learning: Tests in the parse-server repository should use promise-based approaches rather than callback patterns with `done()`. Use a pattern where a Promise is created that resolves when the event occurs, then await that promise.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-05-09T09:59:06.289Z
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 9445
File: spec/ParseLiveQuery.spec.js:1340-1375
Timestamp: 2025-05-09T09:59:06.289Z
Learning: New tests in the parse-server repository should use async/await with promise-based patterns rather than callback patterns with `done()`. The preferred pattern is to create a Promise that resolves when an expected event occurs, then await that Promise.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-08-27T09:08:34.252Z
Learnt from: EmpiDev
Repo: parse-community/parse-server PR: 9770
File: src/triggers.js:446-454
Timestamp: 2025-08-27T09:08:34.252Z
Learning: When analyzing function signature changes in Parse Server codebase, verify that call sites are actually incorrect before flagging them. Passing tests are a strong indicator that function calls are already properly aligned with new signatures.

Applied to files:

  • spec/CloudCode.spec.js
📚 Learning: 2025-08-27T12:33:06.237Z
Learnt from: EmpiDev
Repo: parse-community/parse-server PR: 9770
File: src/triggers.js:467-477
Timestamp: 2025-08-27T12:33:06.237Z
Learning: In the Parse Server codebase, maybeRunAfterFindTrigger is called in production with Parse.Query objects constructed via withJSON(), so the plain object query handling bug only affects tests, not production code paths.

Applied to files:

  • spec/CloudCode.spec.js
🧬 Code graph analysis (1)
spec/CloudCode.spec.js (2)
spec/helper.js (2)
  • Parse (4-4)
  • reconfigureServer (180-214)
src/cloud-code/Parse.Cloud.js (1)
  • emailAdapter (603-603)
🔇 Additional comments (1)
spec/CloudCode.spec.js (1)

3309-3322: Trigger validation message extension looks consistent

Updating the validation message to include beforePasswordResetRequest keeps this test aligned with the new _User-only hook semantics and mirrors the existing style for beforeLogin / afterLogin. Just ensure the literal stays in sync with the actual error message in src/triggers.js so this test doesn’t become brittle on future wording tweaks.

Copy link
Member

@mtrezza mtrezza left a comment

Choose a reason for hiding this comment

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

Looks good!

@mtrezza mtrezza merged commit 94cee5b into parse-community:alpha Nov 19, 2025
26 of 28 checks passed
@mtrezza
Copy link
Member

mtrezza commented Nov 19, 2025

Thanks for the adaptions. Could you please also open a PR in the docs to document the new trigger? Just look at where the existing triggers are.

parseplatformorg pushed a commit that referenced this pull request Nov 19, 2025
# [8.5.0-alpha.12](8.5.0-alpha.11...8.5.0-alpha.12) (2025-11-19)

### Features

* Add `beforePasswordResetRequest` hook ([#9906](#9906)) ([94cee5b](94cee5b))
@parseplatformorg
Copy link
Contributor

🎉 This change has been released in version 8.5.0-alpha.12

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state:released-alpha Released as alpha version

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add beforePasswordResetRequest trigger

3 participants