Skip to content

fix: enforce RSVP idempotency in Firestore rules (#735) - #764

Open
saurabhhhcodes wants to merge 2 commits into
roshankumar0036singh:mainfrom
saurabhhhcodes:fix/735-double-rsvp-idempotency
Open

fix: enforce RSVP idempotency in Firestore rules (#735)#764
saurabhhhcodes wants to merge 2 commits into
roshankumar0036singh:mainfrom
saurabhhhcodes:fix/735-double-rsvp-idempotency

Conversation

@saurabhhhcodes

Copy link
Copy Markdown
Contributor

Closes #735

Analysis

The app's RSVP paths were already partly protected: the client performRsvp toggles via a transaction guarded by rsvpLoading, and the cloud function registerForEvent throws already-exists inside its transaction. What was missing:

  • The create rule on events/{eventId}/participants/{participantId} never explicitly stated that a duplicate create is rejected — the protection existed only implicitly (a blind setDoc of a full payload falls through to the update rule, which permits only status/buddyPreference/updatedAt).
  • No rules tests documented the duplicate-RSVP behavior at all.

Changes

  • firestore.rules: added !exists(.../participants/$(request.auth.uid)) to the participant create rule — defense-in-depth so future refactors can't silently allow double RSVPs.
  • tests/firestore.rules.test.ts:
    • Duplicate RSVP create at own participant path -> denied (new)
    • Re-register is allowed after withdrawing (delete then create) (new)
    • Fixed the pre-existing Authenticated user creates participant -> allowed test, which failed with a null-value error because no users/{uid} document was seeded for getUserData().

Verification

Rules suite via Firestore emulator: 49/52 passing. The 3 remaining failures are pre-existing and unrelated (campusId seeds in event-create tests, club check-in fixture) — confirmed identical on a pristine rules file.

Saurabh Kumar Bajpai added 2 commits August 12, 2026 03:31
…singh#623)

The QR scanner recorded attendance purely client-side without
verifying the operator was authorized, so any authenticated user who
photographed another attendee's QR could check them in (ghost
attendance). Firestore rules already deny such writes, but the client
attempted them blindly and surfaced generic errors.

Adds an up-front authorization check in handleBarCodeScanned: the
scanner must be the event owner or an admin, otherwise the scan is
rejected with a clear message before any write is attempted (online
or queued-offline).
…h#735)

A duplicate RSVP write to an existing participant path fell through to
the update rule, which only permits status/buddyPreference/updatedAt,
so the full payload was rejected — but the create rule did not state
this intent explicitly, and no test covered it.

- firestore.rules: add !exists() guard to participant create (defense in
  depth; mirrors the client transaction check and the cloud function's
  already-exists guard)
- tests/firestore.rules.test.ts: add 'Duplicate RSVP create -> denied'
  and 'Re-register after withdrawing -> allowed' tests; seed users doc in
  the existing create test, which previously failed with a null-value
  error because getUserData() had no user document to read
- Rules suite: 49/52 passing (remaining 3 failures are pre-existing and
  unrelated: campusId seeds, club check-in fixture)
@sonarqubecloud

Copy link
Copy Markdown

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.

[Bug/Feature]: Event registration does not prevent double RSVP — same user can register multiple times

1 participant