parse-server icon indicating copy to clipboard operation
parse-server copied to clipboard

feat: Allow short circuit of beforeFind

Open EmpiDev opened this issue 10 months ago • 7 comments

Pull Request

Issue

Closes: https://github.com/parse-community/parse-server/issues/8693

Approach

This PR continues and supersedes #8694 by @dblythy. Adds ability to return objects (or an empty array) from a beforeFind trigger.

Tasks

  • [x] Add tests

Summary by CodeRabbit

  • New Features
    • Improved support for returning objects or arrays of objects directly from cloud triggers, allowing for more flexible query responses.
  • Bug Fixes
    • Ensured that objects returned from triggers are handled correctly without unnecessary conversions.
  • Tests
    • Added comprehensive tests to verify the behavior of triggers returning objects or arrays, including unsaved objects and empty results.
  • Refactor
    • Centralized trigger handling for find and get operations to ensure consistent execution and security enforcement.
    • Enhanced trigger processing with improved parameter handling, JSON serialization, and query construction for better robustness and clarity.

EmpiDev avatar May 27 '25 09:05 EmpiDev

🚀 Thanks for opening this pull request!

📝 Walkthrough

Walkthrough

Centralizes beforeFind/afterFind handling; allows beforeFind to short‑circuit find/get by returning objects/arrays; propagates isGet through trigger requests and RestQuery; refilters returned objects to enforce ACLs before afterFind; updates trigger utilities and adds tests for these behaviors.

Changes

Cohort / File(s) Change Summary
Tests
spec/CloudCode.spec.js
Added extensive tests for beforeFind short‑circuiting (single object, arrays, get, empty), ACL/protectedFields scenarios, and direct maybeRunAfterFindTrigger edge cases.
REST trigger orchestration
src/rest.js
Added internal runFindTriggers to centralize beforeFind/afterFind for find/get; supports beforeFind returning objects/arrays, performs refilter-by-ID query (with triggers disabled) to enforce ACLs, then runs afterFind; find/get now enforce role security and delegate to runFindTriggers.
Trigger utilities
src/triggers.js
toJSONwithObjects preserves className; getRequestObject(...) and maybeRun* functions accept isGet; maybeRunAfterFindTrigger coerces queries/objects into Parse.Query/Parse.Object, validates classNameQuery, normalizes inputs, improves logging, and returns JSON results.
Query layer
src/RestQuery.js
Introduced boolean isGet propagated into _UnsafeRestQuery and used instead of repeated method checks; isGet passed to trigger-related calls (e.g., maybeRunQueryTrigger, runAfterFindTrigger).

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant REST as REST Handler
    participant Triggers
    participant DB

    Client->>REST: find/get request
    REST->>Triggers: beforeFind(request { isGet, query, auth, ... })
    alt beforeFind returns objects/array
        Triggers-->>REST: objects/array
        REST->>REST: refilter by IDs (no triggers) to enforce ACLs
        REST->>Triggers: afterFind(request { isGet, query, auth, ... }, results)
        Triggers-->>REST: processedResults
        REST-->>Client: processedResults
    else
        Triggers-->>REST: (maybe modified) query/options
        REST->>DB: execute query (find/get)
        DB-->>REST: results
        REST->>Triggers: afterFind(request { isGet, query, auth, ... }, results)
        Triggers-->>REST: finalResults
        REST-->>Client: finalResults
    end

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Assessment against linked issues

Objective Addressed Explanation
Allow beforeFind to return objects, bypassing RestQuery (#8693) beforeFind can return objects/arrays; runFindTriggers handles the short‑circuit path.
Support returning arrays or empty array from beforeFind to short‑circuit queries (#8693) Arrays and empty arrays are supported and tested.
Ensure afterFind receives objects returned from beforeFind short‑circuiting (#8693) Returned objects are re-filtered for ACLs then passed to afterFind.
Add tests covering beforeFind short‑circuiting and maybeRunAfterFindTrigger behavior (#8693) New test suites added in spec/CloudCode.spec.js.

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
Linked Issues Check ✅ Passed The changes introduce centralized beforeFind handling that respects returned object arrays or empty arrays to bypass the default RestQuery flow, re-filters results for ACL compliance, and runs afterFind triggers as specified in issue #8693.
Out of Scope Changes Check ✅ Passed All additions and signature adjustments in rest.js, triggers.js, and RestQuery.js directly support the beforeFind short-circuit feature—including centralized runFindTriggers logic, isGet propagation, and trigger invocation changes—and there are no unrelated or extraneous modifications outside that objective.
Description Check ✅ Passed The description accurately follows the repository template by including the Pull Request header with security and licensing links, a filled-in Issue section referencing the specific linked issue, a concise Approach section summarizing the changes, and a trimmed Tasks list reflecting only the relevant test addition.
Title Check ✅ Passed The title clearly and concisely summarizes the primary change by describing the new ability to return objects from Parse.Cloud.beforeFind and bypass the database query, directly reflecting the pull request’s main feature and objectives.
✨ 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[bot] avatar May 27 '25 09:05 coderabbitai[bot]

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

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

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

parseplatformorg avatar May 27 '25 11:05 parseplatformorg

Started CI...

mtrezza avatar May 30 '25 11:05 mtrezza

Hi @mtrezza, just wondering if there's anything else I should do to trigger a re-run of the tests?

EmpiDev avatar Jun 06 '25 07:06 EmpiDev

@EmpiDev You don't have permission to trigger a CI run. Once your first PR has been merged, the CI will run automatically.

mtrezza avatar Jun 07 '25 15:06 mtrezza

Hi @mtrezza,

I'm still encountering some test failures when running npm test. On the feat/before-found branch, 3 tests are failing:

BRANCH: FEAT BEFORE FOUND

3300 specs, 3 failures, 73 pending specs
Finished in 382.402 seconds
Randomized with seed 83016

Failures:

1) httpRequest should fail gracefully
   - Timeout - Async function did not complete within 10000ms

2) Server Url Checks does not have unhandled promise rejection in the case of load error
   - Timeout - Async function did not complete within 10000ms

3) Non-spec failure
   - Spec "httpRequest should fail gracefully" ran a "toBeRejected" expectation after it finished.
     → Did you forget to `return` or `await` the result of `expectAsync`?
     → Was `done()` invoked before an async operation completed?
     → Did an expectation follow a call to `done()`?

I noticed that these same tests are also failing on the alpha branch. Is that expected behavior, or should they pass there?

Thanks in advance for your help! Let me know if you want me to dig further.

EmpiDev avatar Jun 12 '25 11:06 EmpiDev

These may be flaky tests. I'd have to re-run the CI to see whether they pass. If a test passes locally on your machine but fails in the CI with a timeout, then it's likely flaky. I've restarted the CI.

mtrezza avatar Jun 24 '25 00:06 mtrezza

Codecov Report

:white_check_mark: All modified and coverable lines are covered by tests. :white_check_mark: Project coverage is 93.04%. Comparing base (1b23475) to head (852f29f). :warning: Report is 21 commits behind head on alpha.

Additional details and impacted files
@@            Coverage Diff             @@
##            alpha    #9770      +/-   ##
==========================================
+ Coverage   93.00%   93.04%   +0.03%     
==========================================
  Files         187      187              
  Lines       15105    15147      +42     
  Branches      174      174              
==========================================
+ Hits        14048    14093      +45     
+ Misses       1045     1042       -3     
  Partials       12       12              

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

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

codecov[bot] avatar Jun 24 '25 00:06 codecov[bot]

@Moumouls would you kindly review the changes made after your feedback and close the feedback that you see as addressed?

mtrezza avatar Aug 03 '25 12:08 mtrezza

Started CI

mtrezza avatar Sep 19 '25 19:09 mtrezza

everything seems okay here @mtrezza :)

Moumouls avatar Sep 21 '25 08:09 Moumouls

Merged alpha branch to run CI again;

@EmpiDev could you please resolve the lint issues? @Moumouls could you please resolve any open comments - there are some hidden in the thread.

mtrezza avatar Sep 21 '25 15:09 mtrezza

@mtrezza i don't see some unresolved comments, or i can't resolve them because file are outdated or i approved the PR already

Moumouls avatar Sep 21 '25 16:09 Moumouls

@mtrezza I have resolved the lint issues.

EmpiDev avatar Sep 22 '25 10:09 EmpiDev

thanks @mtrezza , i reviewed, there is still one open comment: https://github.com/parse-community/parse-server/pull/9770#discussion_r2388521470

Moumouls avatar Sep 29 '25 16:09 Moumouls

Waiting for CI...

mtrezza avatar Oct 14 '25 16:10 mtrezza

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

parseplatformorg avatar Oct 14 '25 16:10 parseplatformorg

🎉 This change has been released in version 8.3.0

parseplatformorg avatar Nov 01 '25 20:11 parseplatformorg