Skip to content

fix(experiences): persist interview submissions with review status - #1375

Open
nyxsky404 wants to merge 4 commits into
Canopus-Labs:mainfrom
nyxsky404:fix/935-interview-experience-persist
Open

fix(experiences): persist interview submissions with review status#1375
nyxsky404 wants to merge 4 commits into
Canopus-Labs:mainfrom
nyxsky404:fix/935-interview-experience-persist

Conversation

@nyxsky404

@nyxsky404 nyxsky404 commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Pull Request Description

Related Issue

Closes #935

Summary

Interview experience submit only wrote to local React state, so a refresh dropped the card even though the UI said it was submitted for review. Added /api/interview-experiences (create, mine, approved, status update), wired the form to POST, reload User-tab entries via a stable client key, and show pending/approved/rejected on cards. Failure path keeps the form open so users can retry.


Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature
  • Refactoring
  • Documentation update
  • UI/UX improvement
  • Other(please describe) ______

How Has This Been Tested?

  • vitest run tests/interviewExperienceController.unit.test.js (7 passing)
  • vitest run tests/authMiddleware.tokenVersion.unit.test.js (optionalProtect export still green)

Screenshots (if applicable)

N/A

Checklist

  • My code follows the project's guidelines
  • I have tested my changes
  • I have updated documentation where necessary
  • I have linked the related issue
  • My changes do not introduce new warnings or errors

Made with Cursor

Summary

  • Added persistent interview experience submissions through /api/interview-experiences.
  • Added validation, authentication, moderation status updates, and approved-experience retrieval.
  • Updated the form to use stable client and idempotency keys.
  • Reloaded user submissions after page loads.
  • Added pending, approved, and rejected status displays.
  • Preserved form input after submission failures to support retries.
  • Added controller and moderator authorization unit tests.
  • Verified the optionalProtect export.

Form only updated React state, so reload wiped cards despite the
moderation success copy. Add a backend resource, save on submit,
reload via client key, and surface pending/approved/rejected.

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: cb2e212f-9aab-4269-8510-221f8727bca9

📥 Commits

Reviewing files that changed from the base of the PR and between f8aca4d and 7252b61.

📒 Files selected for processing (3)
  • backend/Input_validators/ValidateInterviewExperience.js
  • backend/controllers/interviewExperienceController.js
  • backend/tests/interviewExperienceController.unit.test.js
🚧 Files skipped from review as they are similar to previous changes (3)
  • backend/Input_validators/ValidateInterviewExperience.js
  • backend/controllers/interviewExperienceController.js
  • backend/tests/interviewExperienceController.unit.test.js

📝 Walkthrough

Walkthrough

The PR adds persistent interview-experience submissions with validation, MongoDB storage, moderation endpoints, optional authentication, client-key retrieval, status badges, retry states, and unit tests.

Changes

Interview experience submission and moderation

Layer / File(s) Summary
Data contracts and authentication
backend/models/InterviewExperience.js, backend/Input_validators/ValidateInterviewExperience.js, backend/middlewares/authMiddleware.js, backend/.env.example, backend/tests/requireModerator.unit.test.js
Defines interview-experience fields, nested rounds, defaults, indexes, request validation, moderation statuses, optional JWT authentication, and moderator authorization.
Persistence and API endpoints
backend/controllers/interviewExperienceController.js, backend/routes/interviewExperienceRoutes.js, backend/server.js, backend/tests/interviewExperienceController.unit.test.js
Adds creation, approved-listing, personal-listing, and moderation-status handlers. Registers the routes and tests persistence, retrieval, approval, idempotent retries, failures, and missing records.
Client submission and reload state
frontend/src/pages/InterviewExperiences/InterviewExperiences.jsx, frontend/src/utils/apiPaths.js
Adds client-keyed API submission and loading, status badges, retry and error states, duplicate replacement, and safe rendering for missing rounds or tags.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant InterviewExperiences
  participant interviewExperienceRoutes
  participant optionalProtect
  participant interviewExperienceController
  participant InterviewExperience
  InterviewExperiences->>interviewExperienceRoutes: submit interview experience with clientKey
  interviewExperienceRoutes->>optionalProtect: attempt JWT authentication
  optionalProtect->>interviewExperienceController: continue with optional req.user
  interviewExperienceController->>InterviewExperience: create pending experience
  InterviewExperience-->>interviewExperienceController: return saved document
  interviewExperienceController-->>InterviewExperiences: return normalized experience
  InterviewExperiences->>interviewExperienceRoutes: load personal experiences
  interviewExperienceController->>InterviewExperience: query by user ID or clientKey
  InterviewExperience-->>interviewExperienceController: return matching submissions
  interviewExperienceController-->>InterviewExperiences: return submission statuses
Loading

Suggested labels: rate-limited

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the primary change: persisting interview submissions and tracking review status.
Linked Issues check ✅ Passed The changes implement persisted submissions, reloadable user data, moderation states, retry handling, and API-backed approved experiences required by issue #935.
Out of Scope Changes check ✅ Passed The backend, frontend, authentication, routing, configuration, and tests directly support persisted interview experiences and moderation.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 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 `@backend/controllers/interviewExperienceController.js`:
- Line 39: Update the submission flow around InterviewExperience.create to
generate one idempotency key per modal submission, persist it on the interview
experience with a unique index, and return the existing submission when a POST
reuses that key instead of creating a duplicate. Add a regression test covering
repeated POSTs with the same key.

In `@backend/routes/interviewExperienceRoutes.js`:
- Around line 23-27: Update the PATCH /:id/status middleware chain to enforce
the existing moderator/admin authorization check between protect and
updateInterviewExperienceStatus, preventing regular authenticated users from
changing statuses. Add or update tests to verify non-moderators receive HTTP 403
while authorized moderators retain access.

In `@frontend/src/pages/InterviewExperiences/InterviewExperiences.jsx`:
- Around line 814-831: Update loadMyExperiences to also fetch
API_PATHS.INTERVIEW_EXPERIENCES.APPROVED and store the returned approved
experiences in dedicated state. Replace the Common tab’s static EXPERIENCES
source with that state, preserving the existing personal-submissions behavior
and ensuring both datasets reload together.
🪄 Autofix

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: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ebb3e272-ade5-4f94-b417-e543a49e8fa5

📥 Commits

Reviewing files that changed from the base of the PR and between 32c4e5c and 56ef153.

📒 Files selected for processing (9)
  • backend/Input_validators/ValidateInterviewExperience.js
  • backend/controllers/interviewExperienceController.js
  • backend/middlewares/authMiddleware.js
  • backend/models/InterviewExperience.js
  • backend/routes/interviewExperienceRoutes.js
  • backend/server.js
  • backend/tests/interviewExperienceController.unit.test.js
  • frontend/src/pages/InterviewExperiences/InterviewExperiences.jsx
  • frontend/src/utils/apiPaths.js

Comment thread backend/controllers/interviewExperienceController.js
Comment thread backend/routes/interviewExperienceRoutes.js
Comment thread frontend/src/pages/InterviewExperiences/InterviewExperiences.jsx
nyxsky404 and others added 2 commits August 6, 2026 22:24
Add idempotent creates, restrict status updates to MODERATOR_EMAILS,
and load approved experiences into the Common tab.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@backend/models/InterviewExperience.js`:
- Around line 87-106: Update the create validator for InterviewExperience so
idempotencyKey is required and must be a non-empty string, matching the schema’s
unique partial index; ensure the controller rejects missing or blank keys before
creating a record.
🪄 Autofix

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: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 03146be1-cff1-4181-8700-451b7451e223

📥 Commits

Reviewing files that changed from the base of the PR and between 56ef153 and f8aca4d.

📒 Files selected for processing (9)
  • backend/.env.example
  • backend/Input_validators/ValidateInterviewExperience.js
  • backend/controllers/interviewExperienceController.js
  • backend/middlewares/authMiddleware.js
  • backend/models/InterviewExperience.js
  • backend/routes/interviewExperienceRoutes.js
  • backend/tests/interviewExperienceController.unit.test.js
  • backend/tests/requireModerator.unit.test.js
  • frontend/src/pages/InterviewExperiences/InterviewExperiences.jsx
🚧 Files skipped from review as they are similar to previous changes (4)
  • backend/routes/interviewExperienceRoutes.js
  • backend/Input_validators/ValidateInterviewExperience.js
  • backend/tests/interviewExperienceController.unit.test.js
  • frontend/src/pages/InterviewExperiences/InterviewExperiences.jsx

Comment thread backend/models/InterviewExperience.js
Reject blank or missing keys so retries cannot bypass the unique
partial index and create duplicate submissions.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread backend/controllers/interviewExperienceController.js Dismissed
try {
const experience = await InterviewExperience.findByIdAndUpdate(
req.params.id,
{ status: req.body.status },
@KaranUnique

Copy link
Copy Markdown
Contributor

@nyxsky404 CodeQL detected a potential database injection issue because req.params.id and req.body.status are user-controlled inputs. Please validate the ID and restrict status to a whitelist of allowed values before performing the update

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]: Interview experience form confirms moderation without saving the submission

3 participants