Skip to content

fix: move feedback stats updates to backend function#520

Open
riddhima25bet10005-a11y wants to merge 13 commits into
roshankumar0036singh:mainfrom
riddhima25bet10005-a11y:fix/issue-519
Open

fix: move feedback stats updates to backend function#520
riddhima25bet10005-a11y wants to merge 13 commits into
roshankumar0036singh:mainfrom
riddhima25bet10005-a11y:fix/issue-519

Conversation

@riddhima25bet10005-a11y
Copy link
Copy Markdown
Contributor

@riddhima25bet10005-a11y riddhima25bet10005-a11y commented Jun 1, 2026

Closes #519

Moved the privileged feedback stats and reputation updates to a Cloud Function to avoid client-side permission issues.

Summary by CodeRabbit

  • New Features
    • Added a server-side feedback submission handler and an "Event Map" live preview page.
  • Refactor
    • Simplified client feedback flow and centralized server-side processing logic.
  • Tests
    • Added and updated tests covering feedback submission validations, error paths, and success scenarios.
  • Chores
    • Updated PR/automation scripts, PR documentation, and improved structured logging for daily digests.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 1, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

Client submitFeedback now writes only the feedback document via a Firestore transaction; a new Cloud Function onFeedbackSubmit (Firestore onCreate) validates feedback and performs protected batched updates (event stats, club reputation, user points, feedbackRequests completion). Tests, exports, logging, a live-preview HTML, PR bodies, and automation scripts were added/updated.

Changes

Feedback Submission Refactoring

Layer / File(s) Summary
Simplified client-side feedback submission
app/src/lib/feedbackService.js, app/src/lib/__tests__/feedbackService.test.js
submitFeedback now uses Firestore runTransaction to check for existing feedback and write the feedback document (optionally including feedbackRequestId). Tests were updated to mock runTransaction and cover success, duplicate-feedback, and transaction-failure paths.
Server-side feedback processing trigger
cloud-functions/src/onFeedbackSubmit.ts, cloud-functions/src/onFeedbackSubmit.test.ts, cloud-functions/src/index.ts, cloud-functions/lib/index.js
Adds onFeedbackSubmit Firestore onCreate trigger that validates inputs (clubId, optional feedbackRequestId format, attendance), fetches and verifies the event, and commits a batched write updating events/{eventId}.stats (feedbackCount, attendee/no-show counters, rating aggregates), optionally updates users/{encodedClubId}.reputation, awards users/{userId}.points when attended, and marks feedbackRequests/{id} completed. Tests cover validation failures, success paths, and batch commit errors. Trigger re-exported from function entrypoints.
Logging and exports wiring
cloud-functions/lib/dailyDigest.js, cloud-functions/src/index.ts, cloud-functions/lib/index.js
Adds structured logEntry calls to daily digest for start and successful completion; re-exports new trigger and adjusts export ordering and schedule-call formatting.
Live preview, PR bodies, and automation scripts
live-preview-map.html, pr_body.md, pr_body_215.md, pr_body_219.md, pr_script.ps1, pr_script_359.ps1, pr_script_364.ps1, pr_script_364_fix.ps1, rebuild_and_pull.ps1, push_cloud_fixes*.ps1, fix_tests_and_push.ps1, resolve_and_push.ps1
Adds a standalone Leaflet-based live preview HTML page; adds/updates multiple PR body markdown files documenting fixes; adds/updates many PowerShell automation scripts and a rebuild/pull helper.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

level:intermediate, type:refactor, type:testing, quality:clean, level:critical

Suggested reviewers

  • roshankumar0036singh

Poem

🐰 A nibble, a note, a tiny log,
I hop and carry feedback through fog.
Client writes safe, server tallies true,
Counters climb and points accrue.
Little rabbit cheers — hops due!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes multiple out-of-scope changes: several PowerShell automation scripts (pr_script*.ps1, rebuild_and_pull.ps1, fix_tests_and_push.ps1, push_cloud_fixes*.ps1, resolve_and_push.ps1), PR documentation files (pr_body*.md), and a live-preview HTML file unrelated to the feedback fix. Remove out-of-scope automation scripts and documentation files; retain only core feedback fix code: feedbackService.js, onFeedbackSubmit.ts/test, index.ts re-export, and related test files.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: moving feedback stats updates from client-side (feedbackService.js) to a backend Cloud Function (onFeedbackSubmit.ts) to resolve permission issues.
Linked Issues check ✅ Passed The PR successfully addresses issue #519 by eliminating client-side writes to protected documents (event.stats, club reputation) and moving all privileged updates to a trusted Cloud Function trigger.

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

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

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

app/src/lib/__tests__/feedbackService.test.js

ESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox.

app/src/lib/feedbackService.js

ESLint skipped: the ESLint configuration for this file references a package that is not available in the sandbox.

cloud-functions/lib/dailyDigest.js

Oops! Something went wrong! :(

ESLint: 10.4.1

TypeError [ERR_IMPORT_ATTRIBUTE_MISSING]: Module "file:///cloud-functions/.eslintrc.json?mtime=1780413665657" needs an import attribute of "type: json"
at validateAttributes (node:internal/modules/esm/assert:88:15)
at defaultLoadSync (node:internal/modules/esm/load:164:3)
at #loadAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:776:12)
at #loadSync (node:internal/modules/esm/loader:796:49)
at ModuleLoader.load (node:internal/modules/esm/loader:762:26)
at ModuleLoader.loadAndTranslate (node:internal/modules/esm/loader:504:31)
at #getOrCreateModuleJobAfterResolve (node:internal/modules/esm/loader:555:36)
at afterResolve (node:internal/modules/esm/loader:603:52)
at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:609:12)
at node:internal/modules/esm/loader:628:32

  • 4 others

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
Copy Markdown
Contributor

@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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/src/lib/feedbackService.js (1)

19-36: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Don't overwrite a document that's processed by a create-only trigger.

This path is always events/{eventId}/feedback/{userId}, so a second submit becomes an update. onFeedbackSubmit only runs on creates, which means retries or edits can change the feedback document without reapplying stats, reputation, points, or request completion. Either enforce create-only semantics here or make the backend handler idempotent for updates too.

🤖 Prompt for 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.

In `@app/src/lib/feedbackService.js` around lines 19 - 36, The code currently
calls setDoc(feedbackRef, payload) which will overwrite an existing
events/{eventId}/feedback/{userId} doc and bypass the onFeedbackSubmit
create-only trigger; change this to a create-only write by first checking for
existence (getDoc/transaction) and only writing if the doc does not exist—e.g.,
use a Firestore transaction or getDoc(feedbackRef) and if the doc.exists() then
return/error, otherwise setDoc(feedbackRef, payload); reference feedbackRef,
payload, feedbackRequestId and the onFeedbackSubmit create-only behavior when
making the change.
🤖 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 `@cloud-functions/src/onFeedbackSubmit.ts`:
- Around line 18-65: The batch currently trusts client-supplied fields
(attended, eventRating, clubRating, clubId, feedbackRequestId) before writing
via eventRef, clubRef, userRef, requestRef and statsUpdate; change the code to
first read canonical documents (event doc for eventId, feedbackRequest doc for
feedbackRequestId, and event's club owner) and validate ownership and ranges
server-side: confirm the feedbackRequest belongs to userId and references
eventId, ensure clubId matches the event's club, clamp/validate eventRating and
clubRating to allowed ranges, and verify attended is consistent with
event/registration state; only then mutate statsUpdate, reputation increment,
user points and request status in the batch. Ensure all checks occur prior to
calling batch.set and abort/throw if validation fails.
- Around line 68-73: The current try/catch around batch.commit() in
onFeedbackSubmit.ts swallows failures—after logging the error the function
returns normally—so change the catch to rethrow the caught error (or throw a new
Error that includes the original) after logging so the invocation fails and
retries/alerts can occur; update the catch block that wraps await batch.commit()
(referencing batch.commit(), eventId and userId in the log) to log the error and
then rethrow it.

---

Outside diff comments:
In `@app/src/lib/feedbackService.js`:
- Around line 19-36: The code currently calls setDoc(feedbackRef, payload) which
will overwrite an existing events/{eventId}/feedback/{userId} doc and bypass the
onFeedbackSubmit create-only trigger; change this to a create-only write by
first checking for existence (getDoc/transaction) and only writing if the doc
does not exist—e.g., use a Firestore transaction or getDoc(feedbackRef) and if
the doc.exists() then return/error, otherwise setDoc(feedbackRef, payload);
reference feedbackRef, payload, feedbackRequestId and the onFeedbackSubmit
create-only behavior when making the change.
🪄 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 Plus

Run ID: 069e2f9b-dcca-49cc-9b09-a2a82d7e7146

📥 Commits

Reviewing files that changed from the base of the PR and between bdb830b and 2a3f91a.

📒 Files selected for processing (3)
  • app/src/lib/feedbackService.js
  • cloud-functions/src/index.ts
  • cloud-functions/src/onFeedbackSubmit.ts

Comment thread cloud-functions/src/onFeedbackSubmit.ts Outdated
Comment thread cloud-functions/src/onFeedbackSubmit.ts
 into fix/issue-519

# Conflicts:
#	cloud-functions/lib/certificateService.js
#	cloud-functions/lib/dailyDigest.js
#	cloud-functions/lib/eventNotifications.js
#	cloud-functions/lib/index.js
#	cloud-functions/lib/reputation.js
#	cloud-functions/package-lock.json
#	cloud-functions/src/index.ts
@riddhima25bet10005-a11y
Copy link
Copy Markdown
Contributor Author

Hey @roshankumar0036singh
I will try fixing the sonarcloud failure tomorrow.

Copy link
Copy Markdown
Contributor

@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.

🧹 Nitpick comments (1)
app/src/lib/__tests__/feedbackService.test.js (1)

24-45: ⚡ Quick win

Assert the transaction write contract, not just that it ran.

These tests currently pass as long as submitFeedback() calls runTransaction() and resolves. They do not verify the PR’s key guarantee: the client performs exactly one feedback-doc write and does not regress into other client-side writes. Please assert mockTransaction.set call count and payload for both attended and no-show flows.

Suggested test tightening
 test('submits attended feedback successfully', async () => {
+    let mockTransaction;
     runTransaction.mockImplementationOnce(async (_, callback) => {
-            const mockTransaction = {
-                get: jest.fn().mockResolvedValue({ exists: () => false }),
-                set: jest.fn(),
-            };
-            return await callback(mockTransaction);
+            mockTransaction = {
+                get: jest.fn().mockResolvedValue({ exists: () => false }),
+                set: jest.fn(),
+            };
+            return await callback(mockTransaction);
     });

     const result = await submitFeedback({
         feedbackRequestId: 'req1',
         eventId: 'event1',
@@
 
     expect(runTransaction).toHaveBeenCalled();
+    expect(mockTransaction.set).toHaveBeenCalledTimes(1);
+    expect(mockTransaction.set).toHaveBeenCalledWith(
+        expect.anything(),
+        expect.objectContaining({
+            feedbackRequestId: 'req1',
+            eventId: 'event1',
+            clubId: 'club1',
+            userId: 'user1',
+            attended: true,
+            eventRating: 5,
+            clubRating: 4,
+            feedback: 'Great event',
+        }),
+    );
     expect(result).toEqual({ success: true });
 });

Also applies to: 48-67

🤖 Prompt for 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.

In `@app/src/lib/__tests__/feedbackService.test.js` around lines 24 - 45, The
tests currently only verify runTransaction was invoked; update the
submitFeedback tests to assert the transaction write contract by checking that
the mockTransaction.set method on the object passed into the runTransaction
callback is called exactly once and with the expected document path and payload
for both attended and no-show flows: in the attended test confirm
mockTransaction.set called once with the feedback document containing attended:
true, eventRating, clubRating, feedback and correct ids (feedbackRequestId,
eventId, clubId, userId); in the no-show test assert mockTransaction.set called
once with attended: false and the no-show-specific payload (no ratings), and
keep existing runTransaction and result assertions. Ensure you reference the
mockTransaction used in runTransaction.mockImplementationOnce and the
submitFeedback function when adding these assertions.
🤖 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.

Nitpick comments:
In `@app/src/lib/__tests__/feedbackService.test.js`:
- Around line 24-45: The tests currently only verify runTransaction was invoked;
update the submitFeedback tests to assert the transaction write contract by
checking that the mockTransaction.set method on the object passed into the
runTransaction callback is called exactly once and with the expected document
path and payload for both attended and no-show flows: in the attended test
confirm mockTransaction.set called once with the feedback document containing
attended: true, eventRating, clubRating, feedback and correct ids
(feedbackRequestId, eventId, clubId, userId); in the no-show test assert
mockTransaction.set called once with attended: false and the no-show-specific
payload (no ratings), and keep existing runTransaction and result assertions.
Ensure you reference the mockTransaction used in
runTransaction.mockImplementationOnce and the submitFeedback function when
adding these assertions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 30756cf6-7216-426a-9866-96c5fb25a530

📥 Commits

Reviewing files that changed from the base of the PR and between 2a3f91a and 2671bbe.

📒 Files selected for processing (23)
  • app/src/lib/__tests__/feedbackService.test.js
  • app/src/lib/feedbackService.js
  • cloud-functions/lib/dailyDigest.js
  • cloud-functions/lib/index.js
  • cloud-functions/src/index.ts
  • cloud-functions/src/onFeedbackSubmit.test.ts
  • cloud-functions/src/onFeedbackSubmit.ts
  • fix_tests_and_push.ps1
  • live-preview-map.html
  • pr_body.md
  • pr_body_215.md
  • pr_body_219.md
  • pr_script.ps1
  • pr_script_359.ps1
  • pr_script_364.ps1
  • pr_script_364_fix.ps1
  • push_cloud_fixes.ps1
  • push_cloud_fixes2.ps1
  • push_cloud_fixes3.ps1
  • push_cloud_fixes4.ps1
  • push_cloud_fixes5.ps1
  • rebuild_and_pull.ps1
  • resolve_and_push.ps1
💤 Files with no reviewable changes (16)
  • push_cloud_fixes.ps1
  • push_cloud_fixes3.ps1
  • resolve_and_push.ps1
  • push_cloud_fixes5.ps1
  • fix_tests_and_push.ps1
  • pr_body.md
  • push_cloud_fixes2.ps1
  • pr_script_364_fix.ps1
  • pr_script_364.ps1
  • push_cloud_fixes4.ps1
  • rebuild_and_pull.ps1
  • pr_body_219.md
  • live-preview-map.html
  • pr_body_215.md
  • pr_script_359.ps1
  • pr_script.ps1
🚧 Files skipped from review as they are similar to previous changes (6)
  • cloud-functions/src/index.ts
  • cloud-functions/lib/dailyDigest.js
  • app/src/lib/feedbackService.js
  • cloud-functions/lib/index.js
  • cloud-functions/src/onFeedbackSubmit.test.ts
  • cloud-functions/src/onFeedbackSubmit.ts

@riddhima25bet10005-a11y
Copy link
Copy Markdown
Contributor Author

Hi @roshankumar0036singh
Everything is clean.
Kindly review and merge.

@roshankumar0036singh
Copy link
Copy Markdown
Owner

@riddhima25bet10005-a11y clean up the pr you have pusehd too many ai related files

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Jun 2, 2026

@riddhima25bet10005-a11y
Copy link
Copy Markdown
Contributor Author

Hi @roshankumar0036singh
I have cleaned up the ai related files.
Kindly review.

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.

Feedback Submission Completely Broken (Client-Side Admin Writes)

2 participants