Skip to content

fix(core): patch storage quota evasion loophole in update pipeline - #224

Merged
yash-pouranik merged 2 commits into
geturbackend:mainfrom
ShreyasPatil3105:fix/issue-216-quota-evasion
May 29, 2026
Merged

fix(core): patch storage quota evasion loophole in update pipeline#224
yash-pouranik merged 2 commits into
geturbackend:mainfrom
ShreyasPatil3105:fix/issue-216-quota-evasion

Conversation

@ShreyasPatil3105

@ShreyasPatil3105 ShreyasPatil3105 commented May 28, 2026

Copy link
Copy Markdown
Contributor

Pull Request Description

Fixes #216

Summary of Changes:
Implemented the BSON.calculateObjectSize() validation step within the updateSingleData pipeline in data.controller.js. By calculating the size delta between the existing document and the incoming payload, the system now enforces the databaseLimit storage quota on document updates prior to database persistence, resolving the identified quota evasion loophole. Additionally, integrated a non-blocking background update tracking loop for the databaseUsed metric.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • UI/UX improvement (Frontend only)
  • Refactor / Chore

Testing & Validation

Backend Verification:

  • I have run npm test in the backend/ directory and all tests passed.
  • I have verified the API endpoints using Postman/Thunder Client.
  • New unit tests have been added (if applicable).

Frontend Verification:

  • I have run npm run lint in the frontend/ directory.
  • Verified the UI changes on different screen sizes (Responsive).
  • Checked for any console errors in the browser dev tools.

Checklist

  • My code follows the code style of this project.
  • I have performed a self-review of my code.
  • I have commented my code, particularly in hard-to-understand areas.
  • My changes generate no new warnings or errors.
  • I have updated the documentation (README/Docs) accordingly.

Summary by CodeRabbit

  • New Features

    • Added per-project database storage quota enforcement that prevents data updates from exceeding project limits.
  • Bug Fixes

    • Fixed pagination limit handling to properly enforce lower bounds across cursor and non-cursor pagination modes.
    • Improved error handling for bulk insert operations with more consistent error messaging for duplicate keys and other failures.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@ShreyasPatil3105, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 39 minutes and 48 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bc660e2f-4905-4225-83f7-a85ff8388798

📥 Commits

Reviewing files that changed from the base of the PR and between 74ffbec and 8ab184e.

📒 Files selected for processing (1)
  • apps/public-api/src/controllers/data.controller.js
📝 Walkthrough

Walkthrough

The PR adds per-project storage quota enforcement to updateSingleData by measuring BSON size delta and blocking updates that exceed limits, refactors error handling in bulk insert operations to use a consistent pattern, clamps pagination limits to a minimum of 1, and applies minor formatting updates throughout the controller.

Changes

Data Controller Updates

Layer / File(s) Summary
Storage quota enforcement for document updates
apps/public-api/src/controllers/data.controller.js
Imports AppError in reformatted destructuring. updateSingleData calculates BSON size delta between existing and merged documents, blocks updates exceeding project.databaseLimit with HTTP 403, and asynchronously increments project.databaseUsed when size increases. Directly addresses quota evasion vulnerability in issue #216.
Error handling standardization in bulk insert
apps/public-api/src/controllers/data.controller.js
Reorganizes bulkInsertData error handler to use next(new AppError(...)) pattern, preserving HTTP 409 for duplicate-key violations and HTTP 500 for generic failures.
Pagination metadata refinement
apps/public-api/src/controllers/data.controller.js
getAllData response metadata now clamps limit to a minimum of 1 for both cursor and offset-based pagination modes; cursor value explicitly set from req.query.cursor or null.
Code formatting and cleanup
apps/public-api/src/controllers/data.controller.js
Whitespace and structural formatting applied to imports, function signatures, blank lines, and $set payloads in deleteSingleDoc and recoverSingleDoc. No functional logic changes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A quota was breached, oh what a plight!
Documents grew bold, updates took flight,
BSON size checked, now limits hold tight,
Error paths cleared, pagination's right,
Code flows cleaner—the future looks bright! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely summarizes the primary change: patching a storage quota evasion vulnerability in the update pipeline.
Linked Issues check ✅ Passed The PR implements all required technical changes from issue #216: retrieves existing documents, computes BSON size delta, validates against databaseLimit with HTTP 403 rejection, and integrates background Project.databaseUsed increment via findByIdAndUpdate.
Out of Scope Changes check ✅ Passed Minor formatting changes in deleteSingleDoc/recoverSingleDoc and getAllData pagination logic are tangential but closely related to core updates; no unrelated feature additions or breaking changes detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/public-api/src/controllers/data.controller.js`:
- Around line 535-553: The code path inside the non-external DB block returns
raw JSON errors (res.status(404).json({ error: ... }) and res.status(403).json({
error: ... })) which breaks the controller contract; replace those returns with
the standard error handling using the AppError class and the controller's error
middleware (e.g., import AppError and call next(new AppError("Document not
found.", 404)) for the 404 and next(new AppError("Storage quota exceeded. Please
upgrade your plan.", 403)) for the quota check) so errors follow the { success,
data, message } response shape and no raw DB details are leaked; update
references in this block (the existingDoc check and the quota branch that uses
sizeDelta / project.databaseUsed/project.databaseLimit) accordingly.
- Around line 532-571: The current flow does findOne → local quota check →
findOneAndUpdate → separate Project.findByIdAndUpdate which allows race
conditions and never decrements storage for shrink updates; fix by performing
the document read, quota check, document update and Project.$inc inside a single
MongoDB transaction/session so the quota check and the $inc are atomic: use
mongoose.startSession(), session.startTransaction(), perform
Model.findOne({queryFilter}).session(session) to get existingDoc (abort if
null), compute sizeDelta = newSize - oldSize, if sizeDelta>0 verify
(project.databaseUsed || 0) + sizeDelta <= project.databaseLimit else allow
negative deltas, then run Model.findOneAndUpdate(queryFilter, { $set:
sanitizedData }, { new: true, runValidators: true, session }) and
Project.findByIdAndUpdate(project._id, { $inc: { databaseUsed: sizeDelta } }, {
session }), commitTransaction on success and abort/rollback and return
appropriate error on failure; ensure you always apply the computed sizeDelta
(can be negative) so shrinks free quota and avoid separate non-atomic updates
via Project.findByIdAndUpdate outside a transaction.
- Around line 288-299: The code clamps limit only in responseMeta but still uses
the raw parsed value when paginating; compute a single clampedLimit (e.g. const
limit = Math.max(1, Math.min(parseInt(req.query.limit, 10) || 100, 100))) before
any pagination logic and use that variable wherever slicing/pagination occurs
(cursor handling, nextCursor calculation, or array.slice calls) and also
reference the same limit variable in responseMeta; update any places using the
raw parsed value so nextCursor and returned metadata are consistent.
- Around line 200-206: In bulkInsertData (and the related bulk insert error
branches) the AppError constructor is being called with the arguments reversed;
AppError expects (statusCode, message). Update each call in data.controller.js
(notably the branches using isDuplicateKeyError and the final bulk insert
failure path) to call new AppError with the status code first and the error
message second (e.g., new AppError(409, "Duplicate value violates unique
constraint.") and new AppError(500, "Failed to insert bulk data")). Ensure all
occurrences in bulkInsertData use this corrected argument order.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4c63cc70-0213-4c62-8850-291eb63b2fba

📥 Commits

Reviewing files that changed from the base of the PR and between 75c1e5e and 74ffbec.

📒 Files selected for processing (1)
  • apps/public-api/src/controllers/data.controller.js

Comment thread apps/public-api/src/controllers/data.controller.js Outdated
Comment thread apps/public-api/src/controllers/data.controller.js
Comment thread apps/public-api/src/controllers/data.controller.js Outdated
Comment thread apps/public-api/src/controllers/data.controller.js Outdated
@ShreyasPatil3105

Copy link
Copy Markdown
Contributor Author

Hi @yash-pouranik, I just pushed the updates to resolve the CodeRabbit review (implemented the MongoDB atomic transaction for the quota check and fixed the existing AppError argument bugs).

It looks like the CodeRabbit bot hit its hourly rate limit so it couldn't generate the final summary, but the code is fully updated and ready for your review whenever you have time!

@ShreyasPatil3105

Copy link
Copy Markdown
Contributor Author

Hi @yash-pouranik, just a gentle ping on this one whenever you have a free moment! The CodeRabbit checks are all green and the atomic transaction logic is good to go. Absolutely no rush at all on my end just wanted to keep it on your radar. Thank You!!

@yash-pouranik

Copy link
Copy Markdown
Member

really sry, will surelly try to merge it, this night, else tomorrow eve.

@yash-pouranik yash-pouranik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

just Answer one thing, else is good

Comment thread apps/public-api/src/controllers/data.controller.js
@yash-pouranik
yash-pouranik merged commit e5cf7c3 into geturbackend:main May 29, 2026
8 checks passed
@yash-pouranik

Copy link
Copy Markdown
Member

@ShreyasPatil3105
Thank you for the PR
hope to see more contribs from u
all the best
please leave a star

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Quota Evasion Loophole via Document Updates

2 participants