Skip to content

Conversation

@mtrezza
Copy link
Member

@mtrezza mtrezza commented Oct 31, 2025

Pull Request

Issue

As part of the email verification and password reset improvements in #8488, the queries used for these operations have changed to use only tokens without the username/email fields.

  • _User._email_verify_token: used for email verification queries
  • _User._perishable_token: used for password reset queries

If someone upgrades to Parse Server 8, the database performance is affected negatively as the missing indexes cause collection scans.

Approach

The token indexes are created automatically when Parse Server starts, similar to how indexes for username and email fields are created.

Tasks

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

Summary by CodeRabbit

  • New Features

    • Automatic creation of database indexes at startup to speed email verification and password-reset flows.
    • Option to explicitly configure sparse indexes for Mongo storage.
  • Documentation

    • Notes on automatic index creation, potential startup impact for very large user bases, and manual-creation alternative.
  • Tests

    • Updated tests to validate the new token-related indexes are present and used.
  • Chores

    • Added a readonly test lint global and a focused-test helper for DB-specific runs.

@parse-github-assistant
Copy link

parse-github-assistant bot commented Oct 31, 2025

🚀 Thanks for opening this pull request!

@parseplatformorg
Copy link
Contributor

parseplatformorg commented Oct 31, 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.

@coderabbitai
Copy link

coderabbitai bot commented Oct 31, 2025

📝 Walkthrough

Walkthrough

Adds automatic creation of two non-unique indexes on _User (_email_verify_token, _perishable_token) during server/database initialization; updates tests, docs, ESLint globals, and test helpers; and adds explicit sparse-index configuration support to the Mongo storage adapter.

Changes

Cohort / File(s) Summary
Documentation
8.0.0.md
Adds "Database Indexes" section describing automatic creation of _User._email_verify_token and _User._perishable_token indexes at startup, notes startup-time warning for very large user bases, and updates related PR reference.
Database init / Index creation
src/Controllers/DatabaseController.js
Adds creation of two non-unique indexes on _User._email_verify_token and _User._perishable_token during initialization; each index creation logs a warning and rethrows on failure; integrated with existing index creation flow.
Storage adapter (Mongo)
src/Adapters/Storage/Mongo/MongoStorageAdapter.js
Introduces sparseOptions derived from options.sparse and merges it into indexOptions, preserving existing defaults (sparse true unless overridden).
Tests
spec/DatabaseController.spec.js
Updates test expectations to include the new _email_verify_token and _perishable_token index fields and adds Mongo-specific test blocks validating index usage for email verification and password reset flows.
Test tooling / helpers
spec/eslint.config.js, spec/helper.js
Adds fit_only_db as a readonly global in ESLint config and implements fit_only_db(db) helper mirroring it_only_db logic to permit focused tests by DB target.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant App as Parse Server
  participant DB as DatabaseDriver
  Note right of App #dfefff: Startup → DatabaseController.init
  App->>DB: ensureIndex Users (username/email existing)
  DB-->>App: OK / Error
  Note right of App #f0f7ff: New index creations
  App->>DB: ensureIndex Users (`_email_verify_token`) [non-unique]
  DB-->>App: OK
  alt index creation fails
    DB-->>App: Error
    Note right of App #fff4e0: log warning and rethrow
  end
  App->>DB: ensureIndex Users (`_perishable_token`) [non-unique]
  DB-->>App: OK
  alt index creation fails
    DB-->>App: Error
    Note right of App #fff4e0: log warning and rethrow
  end
  Note over App,DB #f7fff0: MongoStorageAdapter may include `sparseOptions` in indexOptions (configurable)
  Note right of App #e8fff0: Continue remaining initialization
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Inspect src/Controllers/DatabaseController.js for consistent error handling, index option shapes, and ordering.
  • Verify src/Adapters/Storage/Mongo/MongoStorageAdapter.js correctly merges sparseOptions with existing option groups and respects defaults.
  • Confirm spec/DatabaseController.spec.js accurately asserts index shapes and includes Mongo-specific cases.
  • Review 8.0.0.md wording and the startup caveat.
  • Validate spec/helper.js logic and spec/eslint.config.js addition for naming and lint rules.

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 (2 passed)
Check name Status Explanation
Title Check ✅ Passed The PR title "fix: Indexes _email_verify_token for email verification and _perishable_token password reset are not created automatically" is clearly related to the main changeset. The changes across multiple files (DatabaseController.js, tests, documentation, and MongoStorageAdapter.js) all work together to implement automatic index creation for these two token fields during server startup. While the phrasing uses the problem statement rather than stating the solution directly, the title is specific and identifies both the affected fields and their purpose, providing adequate context for understanding the primary change.
Description Check ✅ Passed The PR description is substantially complete and follows the template structure with filled-in sections for Issue, Approach, and Tasks. The Issue section provides detailed context about the problem (performance regression from missing indexes after the PR #8488 changes) and clearly explains why this PR is needed. The Approach section describes the solution concisely, and the Tasks section shows that both tests and documentation have been added and completed. However, the description does not include the specific issue link in the "Closes: #XXX" format that the template requests, instead providing contextual information about the problem in the Issue section.
✨ 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.

@mtrezza mtrezza changed the title fix: Missing indices _email_verify_token for email verification and _perishable_token password reset fix: Indexes _email_verify_token for email verification and _perishable_token password reset are not created automatically Oct 31, 2025
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 (2)
src/Controllers/DatabaseController.js (1)

1767-1779: Consider using sparse indexes for token fields.

The index creation logic is correct and follows the established pattern. However, since _email_verify_token and _perishable_token are typically only set during email verification and password reset flows (and are null otherwise), consider using sparse indexes instead of regular indexes to improve performance and reduce storage:

Apply this diff:

     await this.adapter
-      .ensureIndex('_User', requiredUserFields, ['_email_verify_token'], '_email_verify_token', false)
+      .ensureIndex('_User', requiredUserFields, ['_email_verify_token'], '_email_verify_token', true)
       .catch(error => {
         logger.warn('Unable to create index for email verification token: ', error);
         throw error;
       });

     await this.adapter
-      .ensureIndex('_User', requiredUserFields, ['_perishable_token'], '_perishable_token', false)
+      .ensureIndex('_User', requiredUserFields, ['_perishable_token'], '_perishable_token', true)
       .catch(error => {
         logger.warn('Unable to create index for password reset token: ', error);
         throw error;
       });

Note: Only apply this change if your queries never need to find users with null token values. If you need to query for null tokens, keep the non-sparse indexes.

spec/DatabaseController.spec.js (1)

416-417: Test expectations correctly updated.

The test assertions now properly include the two new indexes in both collation scenarios. The changes verify that the indexes are created at startup as expected.

Consider adding dedicated tests to verify:

  • Index creation succeeds during initialization
  • Appropriate error handling when index creation fails
  • Query performance improvements with the indexes (if feasible)

This would provide more comprehensive coverage beyond just checking that the indexes exist in the schema.

Also applies to: 442-443

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 00f8d4c and 09988c6.

📒 Files selected for processing (3)
  • 8.0.0.md (2 hunks)
  • spec/DatabaseController.spec.js (2 hunks)
  • src/Controllers/DatabaseController.js (1 hunks)
⏰ 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). (13)
  • GitHub Check: PostgreSQL 18, PostGIS 3.6
  • GitHub Check: Redis Cache
  • GitHub Check: MongoDB 7, ReplicaSet
  • GitHub Check: Node 18
  • GitHub Check: PostgreSQL 17, PostGIS 3.5
  • GitHub Check: MongoDB 8, ReplicaSet
  • GitHub Check: Node 20
  • GitHub Check: MongoDB 6, ReplicaSet
  • GitHub Check: PostgreSQL 16, PostGIS 3.5
  • GitHub Check: PostgreSQL 15, PostGIS 3.5
  • GitHub Check: PostgreSQL 15, PostGIS 3.4
  • GitHub Check: PostgreSQL 15, PostGIS 3.3
  • GitHub Check: Docker Build
🔇 Additional comments (1)
8.0.0.md (1)

8-8: LGTM! Clear documentation with appropriate warnings.

The migration documentation clearly explains the new automatic index creation for _email_verify_token and _perishable_token. The warning about potential startup delays for large user bases is helpful, and the suggestion to create indexes manually beforehand provides a good mitigation strategy.

Also applies to: 29-40

coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 31, 2025
@codecov
Copy link

codecov bot commented Oct 31, 2025

Codecov Report

❌ Patch coverage is 42.85714% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.99%. Comparing base (b298ccc) to head (8109230).
⚠️ Report is 5 commits behind head on alpha.

Files with missing lines Patch % Lines
src/Controllers/DatabaseController.js 33.33% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            alpha    #9893      +/-   ##
==========================================
- Coverage   93.01%   92.99%   -0.03%     
==========================================
  Files         187      187              
  Lines       15163    15170       +7     
  Branches      177      177              
==========================================
+ Hits        14104    14107       +3     
- Misses       1047     1051       +4     
  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.

coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 31, 2025
coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 31, 2025
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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1fd069c and af5f951.

📒 Files selected for processing (2)
  • src/Adapters/Storage/Mongo/MongoStorageAdapter.js (2 hunks)
  • src/Controllers/DatabaseController.js (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/Adapters/Storage/Mongo/MongoStorageAdapter.js (3)
src/Controllers/DatabaseController.js (1)
  • options (1796-1796)
src/Adapters/Storage/Postgres/PostgresStorageAdapter.js (1)
  • options (865-865)
src/Controllers/index.js (7)
  • options (58-67)
  • options (81-89)
  • options (102-102)
  • options (110-110)
  • options (130-130)
  • options (140-140)
  • options (141-141)
src/Controllers/DatabaseController.js (1)
src/RestWrite.js (1)
  • error (663-663)
🪛 Biome (2.1.2)
src/Adapters/Storage/Mongo/MongoStorageAdapter.js

[error] 690-690: type annotation are a TypeScript only feature. Convert your file to a TypeScript file or remove the syntax.

TypeScript only syntax

(parse)

⏰ 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). (13)
  • GitHub Check: PostgreSQL 15, PostGIS 3.3
  • GitHub Check: PostgreSQL 17, PostGIS 3.5
  • GitHub Check: PostgreSQL 18, PostGIS 3.6
  • GitHub Check: MongoDB 8, ReplicaSet
  • GitHub Check: PostgreSQL 16, PostGIS 3.5
  • GitHub Check: PostgreSQL 15, PostGIS 3.4
  • GitHub Check: PostgreSQL 15, PostGIS 3.5
  • GitHub Check: MongoDB 7, ReplicaSet
  • GitHub Check: Redis Cache
  • GitHub Check: Node 18
  • GitHub Check: Node 20
  • GitHub Check: MongoDB 6, ReplicaSet
  • GitHub Check: Docker Build
🔇 Additional comments (1)
src/Adapters/Storage/Mongo/MongoStorageAdapter.js (1)

687-700: LGTM! Clean implementation for explicit sparse index control.

The addition of sparseOptions follows the existing pattern and correctly allows options.sparse to override the default sparse: true behavior. This is necessary to support the non-sparse indexes being created for _email_verify_token and _perishable_token in DatabaseController.

Note: The Biome static analysis hint about type annotations is a false positive—this file consistently uses Flow type annotations throughout.

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)
8.0.0.md (1)

26-44: Wrap bare URLs in markdown link syntax.

Lines 28 and 44 contain bare URLs that should be formatted as markdown links to comply with markdown linting rules (MD034). Both related PR references follow the same pattern and can be fixed together.

Apply this diff to wrap the URLs:

  Related pull request:
  
- - https://github.com/parse-community/parse-server/pull/8488
+ - [#8488](https://github.com/parse-community/parse-server/pull/8488)

And:

  Related pull request:
  
- - https://github.com/parse-community/parse-server/pull/9893
+ - [#9893](https://github.com/parse-community/parse-server/pull/9893)

Otherwise, the new Database Indexes section is well-documented and clearly explains the automatic index creation, appropriate warnings, and the manual alternative—all aligned with the PR objectives.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between af5f951 and 8109230.

📒 Files selected for processing (3)
  • 8.0.0.md (2 hunks)
  • spec/DatabaseController.spec.js (2 hunks)
  • src/Controllers/DatabaseController.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • spec/DatabaseController.spec.js
  • src/Controllers/DatabaseController.js
🧰 Additional context used
🪛 markdownlint-cli2 (0.18.1)
8.0.0.md

28-28: Bare URL used

(MD034, no-bare-urls)


44-44: Bare URL used

(MD034, no-bare-urls)

⏰ 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). (1)
  • GitHub Check: PostgreSQL 16, PostGIS 3.5

@mtrezza mtrezza merged commit 62dd3c5 into parse-community:alpha Nov 1, 2025
42 of 46 checks passed
parseplatformorg pushed a commit that referenced this pull request Nov 1, 2025
# [8.3.0-alpha.13](8.3.0-alpha.12...8.3.0-alpha.13) (2025-11-01)

### Bug Fixes

* Indexes `_email_verify_token` for email verification and `_perishable_token` password reset are not created automatically ([#9893](#9893)) ([62dd3c5](62dd3c5))
@parseplatformorg
Copy link
Contributor

🎉 This change has been released in version 8.3.0-alpha.13

parseplatformorg pushed a commit that referenced this pull request Nov 1, 2025
# [8.3.0](8.2.5...8.3.0) (2025-11-01)

### Bug Fixes

* Error in `afterSave` trigger for `Parse.Role` due to `name` field ([#9883](#9883)) ([eb052d8](eb052d8))
* Indexes `_email_verify_token` for email verification and `_perishable_token` password reset are not created automatically ([#9893](#9893)) ([62dd3c5](62dd3c5))
* Security upgrade to parse 7.0.1 ([#9877](#9877)) ([abfa94c](abfa94c))
* Server URL verification before server is ready ([#9882](#9882)) ([178bd5c](178bd5c))
* Stale data read in validation query on `Parse.Object` update causes inconsistency between validation read and subsequent update write operation ([#9859](#9859)) ([f49efaf](f49efaf))
* Warning logged when setting option `databaseOptions.disableIndexFieldValidation` ([#9880](#9880)) ([1815b01](1815b01))

### Features

* Add option `keepUnknownIndexes` to retain indexes which are not specified in schema ([#9857](#9857)) ([89fad46](89fad46))
* Add options to skip automatic creation of internal database indexes on server start ([#9897](#9897)) ([ea91aca](ea91aca))
* Add Parse Server option `verifyServerUrl` to disable server URL verification on server launch ([#9881](#9881)) ([b298ccc](b298ccc))
* Add regex option `u` for unicode support in `Parse.Query.matches` for MongoDB ([#9867](#9867)) ([7cb962a](7cb962a))
* Add request context middleware for config and dependency injection in hooks ([#8480](#8480)) ([64f104e](64f104e))
* Add support for Postgres 18 ([#9870](#9870)) ([d275c18](d275c18))
* Allow returning objects in `Parse.Cloud.beforeFind` without invoking database query ([#9770](#9770)) ([0b47407](0b47407))
* Disable index-field validation to create index for fields that don't yet exist ([#8137](#8137)) ([1b23475](1b23475))
@parseplatformorg
Copy link
Contributor

🎉 This change has been released in version 8.3.0

@parseplatformorg parseplatformorg added the state:released Released as stable version label Nov 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state:released Released as stable version state:released-alpha Released as alpha version

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants