Skip to content

Conversation

@coratgerl
Copy link
Contributor

@coratgerl coratgerl commented Oct 27, 2025

Pull Request

Issue

Fixes: #7519

  • Add tests
  • Add changes to documentation (guides, repository pages, code comments)
  • Add security check
  • Add new Parse Error codes to Parse JS SDK

Summary by CodeRabbit

  • New Features

    • Added a deprecated server option allowPublicExplain (default: true) to control whether explain queries work without the master key.
  • Deprecations

    • Introduced DEPPS12: allowPublicExplain default will change to false in a future release; deprecation note and timeline published.
  • Behavior

    • When disabled, explain requests without the master key are rejected.
  • Tests

    • Added tests covering explain behavior with and without the master key.

@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 deprecation on explain feat: Add deprecation on explain Oct 27, 2025
@parse-github-assistant
Copy link

parse-github-assistant bot commented Oct 27, 2025

🚀 Thanks for opening this pull request!

@parseplatformorg
Copy link
Contributor

parseplatformorg commented Oct 27, 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 27, 2025

📝 Walkthrough

Walkthrough

Adds a deprecated DatabaseOptions flag allowPublicExplain (default true), validates it, documents and records a deprecation, prevents forwarding it to the Mongo client, enforces it in REST runFindTriggers (reject non-master explain when false), and adds tests and changelog/deprecation notes.

Changes

Cohort / File(s) Summary
Documentation & Changelog
DEPRECATIONS.md, changelogs/CHANGELOG_alpha.md
Add DEPPS12 deprecation entry for databaseOptions.allowPublicExplain and changelog mention for 8.4.0-alpha.3.
Options API
src/Options/Definitions.js, src/Options/docs.js, src/Options/index.js
Introduce allowPublicExplain DatabaseOptions boolean option (env: PARSE_SERVER_DATABASE_ALLOW_PUBLIC_EXPLAIN), default true, marked deprecated with future default change to false.
Configuration Validation
src/Config.js
Validate/default databaseOptions.allowPublicExplain: apply default when undefined and require boolean when provided.
Runtime / REST
src/rest.js
In runFindTriggers, when restOptions.explain is present and request is non-master, consult config.databaseOptions.allowPublicExplain (default true) and reject with Parse.Error.INVALID_QUERY if false.
Deprecator
src/Deprecator/Deprecations.js
Add deprecation entry for databaseOptions.allowPublicExplain (changeNewDefault: 'false' with solution guidance).
Mongo Adapter
src/Adapters/Storage/Mongo/MongoStorageAdapter.js
Stop forwarding allowPublicExplain into internal _mongoOptions by removing the key during adapter initialization (plus minor whitespace tweak).
Types
types/Options/index.d.ts
Add optional allowPublicExplain?: boolean to DatabaseOptions types.
Tests
spec/ParseQuery.spec.js
Add tests covering explain behavior with/without master key under different allowPublicExplain settings; note duplicated test blocks present in the file.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API as REST API
    participant Config as Server Config

    rect rgb(250,245,240)
    Note over Client,API: Non-master request with explain
    Client->>API: GET /classes/Thing?explain=true (no master key)
    API->>Config: read databaseOptions.allowPublicExplain
    alt allowPublicExplain == true
        API-->>Client: run explain and return result
    else allowPublicExplain == false
        API-->>Client: INVALID_QUERY (requires master key)
    end
    end

    rect rgb(235,250,240)
    Note over Client,API: Master-key request with explain
    Client->>API: GET /classes/Thing?explain=true + master key
    API-->>Client: run explain and return result
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Areas needing extra attention:
    • src/rest.js — correctness of the allowPublicExplain check and exact error type/message.
    • src/Config.js / src/Options/* — consistency of default, env var, parser, and docs.
    • src/Adapters/Storage/Mongo/MongoStorageAdapter.js — ensure removing the key doesn’t affect other adapter behavior.
    • spec/ParseQuery.spec.js — duplicated test blocks; verify no accidental duplication and test determinism.
    • DEPRECATIONS.md / changelog — dates/titles and DEPPS12 formatting.

Possibly related PRs

Suggested reviewers

  • mtrezza

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: Add deprecation on explain' is concise and directly describes the main change: adding deprecation handling for the explain feature.
Description check ✅ Passed The PR description follows the template with Issue section completed linking to #7519, and Task checklist items for tests and documentation marked as done. All required sections are present.
Linked Issues check ✅ Passed The PR successfully addresses issue #7519 by restricting explain queries to master key users through a deprecation mechanism that defaults allowPublicExplain to true with a path to false in future versions.
Out of Scope Changes check ✅ Passed All changes are scoped to implementing the explain deprecation feature with validation, tests, and documentation updates; a formatting-only change in MongoStorageAdapter is incidental.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0824ff6 and e36a4ba.

📒 Files selected for processing (1)
  • types/Options/index.d.ts (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). (15)
  • GitHub Check: Node 22
  • GitHub Check: MongoDB 7, ReplicaSet
  • GitHub Check: Node 20
  • GitHub Check: Node 18
  • GitHub Check: MongoDB 6, ReplicaSet
  • GitHub Check: MongoDB 8, ReplicaSet
  • GitHub Check: Redis Cache
  • GitHub Check: PostgreSQL 18, PostGIS 3.6
  • GitHub Check: PostgreSQL 16, PostGIS 3.5
  • GitHub Check: PostgreSQL 15, PostGIS 3.5
  • GitHub Check: PostgreSQL 15, PostGIS 3.3
  • GitHub Check: PostgreSQL 17, PostGIS 3.5
  • GitHub Check: PostgreSQL 15, PostGIS 3.4
  • GitHub Check: Docker Build
  • GitHub Check: Code Analysis (javascript)
🔇 Additional comments (1)
types/Options/index.d.ts (1)

241-241: LGTM! Clean type definition addition.

The optional boolean property is correctly defined and follows the existing conventions in this file. The type signature appropriately reflects that this is a configuration flag with a default value.


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.

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: 3

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

5407-5411: Clean up commented code or document the intention.

The commented-out code suggests this deprecation is planned but not yet enforced. If this is a phased approach (warn now, enforce later), consider adding a comment explaining the timeline:

-        // fail('Should have thrown an error');
       } catch (error) {
-        // Uncomment this after the Deprecation DEPPS12
-        // expect(error.code).toEqual(Parse.Error.INVALID_QUERY);
-        // expect(error.message).toEqual('Using the explain query parameter without the master key');
+        // TODO: Enforce restriction in next major version (DEPPS12)
+        // expect(error.code).toEqual(Parse.Error.INVALID_QUERY);
+        // expect(error.message).toEqual('Using the explain query parameter without the master key');
       }
📜 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 705b1ef.

📒 Files selected for processing (4)
  • DEPRECATIONS.md (1 hunks)
  • changelogs/CHANGELOG_alpha.md (1 hunks)
  • spec/ParseQuery.spec.js (1 hunks)
  • src/rest.js (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-26T14:06:31.853Z
Learnt from: EmpiDev
PR: parse-community/parse-server#9770
File: spec/CloudCode.spec.js:446-469
Timestamp: 2025-08-26T14:06:31.853Z
Learning: In the Parse Server codebase, when handling query objects in maybeRunAfterFindTrigger, objects without a where property that contain options like limit/skip should be treated as query JSON with an empty where clause using the spread pattern { where: {}, ...query }, not nested as { where: query }.

Applied to files:

  • src/rest.js
🧬 Code graph analysis (2)
src/rest.js (1)
spec/helper.js (1)
  • auth (394-394)
spec/ParseQuery.spec.js (2)
spec/helper.js (2)
  • TestObject (279-281)
  • Parse (4-4)
src/rest.js (1)
  • Deprecator (16-16)
🪛 GitHub Check: Lint
spec/ParseQuery.spec.js

[failure] 5394-5394:
'Deprecator' is not defined

🪛 markdownlint-cli2 (0.18.1)
changelogs/CHANGELOG_alpha.md

3-3: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)

DEPRECATIONS.md

17-17: Table pipe style
Expected: leading_and_trailing; Actual: leading_only; Missing trailing pipe

(MD055, table-pipe-style)


17-17: Table column count
Expected: 7; Actual: 5; Too few cells, row will be missing data

(MD056, table-column-count)


18-18: Table column count
Expected: 7; Actual: 9; Too many cells, extra data will be missing

(MD056, table-column-count)

⏰ 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 16, PostGIS 3.5
  • GitHub Check: MongoDB 8, ReplicaSet
  • GitHub Check: MongoDB 6, ReplicaSet
  • GitHub Check: Node 18
  • GitHub Check: Node 20
  • GitHub Check: PostgreSQL 15, PostGIS 3.5
  • GitHub Check: Redis Cache
  • GitHub Check: PostgreSQL 17, PostGIS 3.5
  • GitHub Check: PostgreSQL 15, PostGIS 3.3
  • GitHub Check: PostgreSQL 18, PostGIS 3.6
  • GitHub Check: MongoDB 7, ReplicaSet
  • GitHub Check: PostgreSQL 15, PostGIS 3.4
  • GitHub Check: Docker Build
🔇 Additional comments (3)
changelogs/CHANGELOG_alpha.md (1)

1-6: LGTM!

The changelog entry follows the established format and clearly documents the DEPPS12 deprecation with appropriate links.

src/rest.js (2)

16-16: LGTM!

The Deprecator import is correctly added to support the new deprecation logging functionality.


39-50: LGTM!

The deprecation logging is correctly implemented:

  • Properly detects when explain is used without master key authorization
  • Logs a clear deprecation message without breaking existing functionality
  • Preserves the commented error path for future enforcement when the deprecation period ends

@codecov
Copy link

codecov bot commented Oct 27, 2025

Codecov Report

❌ Patch coverage is 88.88889% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 93.05%. Comparing base (9776386) to head (e36a4ba).
⚠️ Report is 4 commits behind head on alpha.

Files with missing lines Patch % Lines
src/Config.js 75.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            alpha    #9890      +/-   ##
==========================================
+ Coverage   93.04%   93.05%   +0.01%     
==========================================
  Files         187      187              
  Lines       15160    15168       +8     
  Branches      177      177              
==========================================
+ Hits        14106    14115       +9     
+ Misses       1042     1041       -1     
  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 27, 2025
coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 27, 2025
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.

This PR requires a new Parse Server config option to enable / disable explain requiring master key. The option will be deprecated, so this is not a RuntimeDeprecation but a deprecation of the config option.

The new option should be in the DatabaseOptions interface, maybe called allowPublicExplain which is true by default.

Then replace the current test with 3 tests:

  • reconfigure server with allowPublicExplain: true and ensure it works with and without master key
  • reconfigure server with allowPublicExplain: false and ensure it works with master key and not without master key
  • do not reconfigure server, i.e. don't explicitly set allowPublicExplain to test default value and ensure it works with and without master key

@coratgerl
Copy link
Contributor Author

Done @mtrezza. Note that I had to remove this line in MongoStorageAdapter because it mutates the databaseOptions. This mutation causes the test to remove the value before it is injected into ParseApp, which then defaults to using the default options. This deletion is weird since we already remove the option below in this._mongoOptions.

image

@coratgerl coratgerl requested a review from mtrezza October 29, 2025 19:27
coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 29, 2025
@mtrezza
Copy link
Member

mtrezza commented Nov 6, 2025

Thanks, could you take a look at the conflicts?

@mtrezza mtrezza removed their request for review November 6, 2025 15:53
@coratgerl
Copy link
Contributor Author

Done @mtrezza :)

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

18-18: Fix malformed DEPPS12 row (too many cells).

Row has 11 cells due to a duplicated tail; markdown/table parsing breaks.

Apply:

-| DEPPS12 | Database option `allowPublicExplain` defaults to `true` | [#7519](https://github.com/parse-community/parse-server/issues/7519) | 8.3.0 (2025)                    | 9.0.0 (2027)                    | deprecated            | -     || 9.0.0 (2027)                    | deprecated            | -     |
+| DEPPS12 | Database option `allowPublicExplain` defaults to `true` | [#7519](https://github.com/parse-community/parse-server/issues/7519) | 8.3.0 (2025)                    | 9.0.0 (2027)                    | deprecated            | -     |
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bb8eedb and 0824ff6.

📒 Files selected for processing (10)
  • DEPRECATIONS.md (1 hunks)
  • changelogs/CHANGELOG_alpha.md (1 hunks)
  • spec/ParseQuery.spec.js (2 hunks)
  • src/Adapters/Storage/Mongo/MongoStorageAdapter.js (2 hunks)
  • src/Config.js (1 hunks)
  • src/Deprecator/Deprecations.js (1 hunks)
  • src/Options/Definitions.js (1 hunks)
  • src/Options/docs.js (1 hunks)
  • src/Options/index.js (1 hunks)
  • src/rest.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • spec/ParseQuery.spec.js
  • changelogs/CHANGELOG_alpha.md
🧰 Additional context used
🧠 Learnings (3)
📚 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:

  • src/rest.js
📚 Learning: 2025-08-26T14:06:31.853Z
Learnt from: EmpiDev
Repo: parse-community/parse-server PR: 9770
File: spec/CloudCode.spec.js:446-469
Timestamp: 2025-08-26T14:06:31.853Z
Learning: In the Parse Server codebase, when handling query objects in maybeRunAfterFindTrigger, objects without a where property that contain options like limit/skip should be treated as query JSON with an empty where clause using the spread pattern { where: {}, ...query }, not nested as { where: query }.

Applied to files:

  • src/rest.js
  • src/Deprecator/Deprecations.js
📚 Learning: 2025-09-21T15:43:32.265Z
Learnt from: mtrezza
Repo: parse-community/parse-server PR: 9858
File: src/GraphQL/ParseGraphQLServer.js:176-178
Timestamp: 2025-09-21T15:43:32.265Z
Learning: The GraphQL playground feature in ParseGraphQLServer.js (applyPlayground method) is intended for development environments only, which is why it includes the master key in client-side headers.

Applied to files:

  • src/rest.js
🧬 Code graph analysis (2)
src/Options/Definitions.js (1)
resources/buildConfigDefinitions.js (1)
  • parsers (12-12)
src/Config.js (2)
src/Controllers/DatabaseController.js (1)
  • databaseOptions (1741-1741)
types/Options/index.d.ts (1)
  • DatabaseOptions (229-241)
🪛 Biome (2.1.2)
src/Options/index.js

[error] 658-658: Expected a statement but instead found '?'.

Expected a statement here.

(parse)

🪛 markdownlint-cli2 (0.18.1)
DEPRECATIONS.md

18-18: Table column count
Expected: 7; Actual: 11; Too many cells, extra data will be missing

(MD056, table-column-count)

🔇 Additional comments (6)
src/Options/index.js (1)

658-660: Expose allowPublicExplain in DatabaseOptions (Flow).

Looks good and matches docs/definitions.

Note: If Biome flags a parse error here, ensure the linter is configured for Flow or excludes this file.

src/Adapters/Storage/Mongo/MongoStorageAdapter.js (1)

149-149: Do not forward Parse‑specific options to Mongo client (incl. allowPublicExplain).

Good defensive cleanup; also preserves the original options object.

Also applies to: 158-167, 175-176

src/Options/docs.js (1)

243-243: Docs: add databaseOptions.allowPublicExplain.

Accurate description and deprecation note.

src/Deprecator/Deprecations.js (1)

21-26: Add deprecation entry for databaseOptions.allowPublicExplain.

Matches policy; message is clear.

src/Options/Definitions.js (1)

1086-1092: Generated definitions updated with allowPublicExplain.

Consistent with Options/index.js and docs.

Confirm this file was regenerated from Options/index.js (no manual edits drift).

src/rest.js (1)

38-47: Aggregate endpoint is already protected by master-key-only middleware; no additional guard needed.

The aggregate endpoint at src/Routers/AggregateRouter.js line 128 uses middleware.promiseEnforceMasterKeyAccess middleware, which rejects all non-master requests with a 403 error (src/middlewares.js:510-518). This is more restrictive than the conditional allowPublicExplain guard in the find path—non-master users cannot access aggregate at all, making the concern moot.

The original change is correct. The find and aggregate endpoints use complementary security models: find operations are conditionally gated by allowPublicExplain, while aggregate operations are completely restricted to master key access.

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.

Restrict explain to the master key

3 participants