fix: enforce security, validation, runtime stability, and dashboard correctness#8
fix: enforce security, validation, runtime stability, and dashboard correctness#8ArhanAnsari wants to merge 24 commits intoJavaScript-Mastery-Pro:mainfrom
Conversation
… error handling and authorization checks
…E endpoints for assignments
…r handling and validation
…E endpoints for students
…es in GET endpoint
…al calculations for students and assignments
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 21 minutes and 19 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the 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 have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (10)
📝 WalkthroughWalkthroughThis PR adds authentication-based authorization scoping to API endpoints (restricting updates/deletions to authenticated teachers), introduces MongoDB ObjectId validation for studentId fields, standardizes error responses with generic messages, updates CGPA grade mappings (D: 4→5), enhances dashboard data validation, and improves MongoDB connection configuration with TLS and timeout settings. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 10
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
app/api/profile/route.ts (1)
94-114:⚠️ Potential issue | 🟡 Minor
academicHistoryentry lengths are unbounded.The array length is capped at 20, but each entry's
year,title, anddescriptionstrings are not length-validated. A malicious/buggy client can push very large strings (e.g., megabytes of text per entry × 20 entries) into the Teacher document, bloating storage and response payloads. Consider enforcing per-field max lengths (e.g., 10/200/2000) here and/or in the Mongoose schema.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/api/profile/route.ts` around lines 94 - 114, The academicHistory validation currently checks array length and types but not string lengths; update the validation around academicHistory in route.ts to enforce per-field max lengths (for example: year max 10 chars, title max 200 chars, description max 2000 chars) and ensure description is optional but when present is a string within that limit; adjust the Array.every check on academicHistory to include these length checks and return the same 400 NextResponse.json error if any entry exceeds limits, and also mirror these constraints in the Teacher/Mongoose schema (add maxlength validators for year, title, description) so DB-level validation prevents oversized entries.app/api/attendance/route.ts (1)
132-147:⚠️ Potential issue | 🟠 MajorVerify
studentIdownership before upserting attendance.The POST path validates only ObjectId shape. A teacher can upsert attendance for any valid
studentId, including another tenant’s student, while supplying arbitrarystudentNameandclass. CheckStudent.exists({ _id: studentId, teacherId: userId })before writing.🛡️ Suggested direction
+import { Student } from '@/models/Student'if (isBulk) { + const studentIds = [ + ...new Set((parsed.data as z.infer<typeof BulkSchema>).map((record) => record.studentId)), + ]; + const ownedCount = await Student.countDocuments({ + _id: { $in: studentIds }, + teacherId: userId, + }); + if (ownedCount !== studentIds.length) { + return NextResponse.json({ error: "Invalid studentId" }, { status: 400 }); + } + const ops = (parsed.data as z.infer<typeof BulkSchema>).map((record) => ({Apply the same ownership check for the single-record branch before
findOneAndUpdate.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/api/attendance/route.ts` around lines 132 - 147, The single-record POST branch currently upserts attendance without verifying the teacher actually owns the student; before calling Attendance.findOneAndUpdate use Student.exists({ _id: studentId, teacherId: userId }) (where studentId is parsed from AttendanceSchema and userId is the authenticated teacher id) and return an authorization error (e.g., 403) if the check fails; ensure you reference Attendance.findOneAndUpdate and AttendanceSchema for locating the upsert and Student.exists for the ownership check so only the owning teacher can upsert that student’s attendance.
🧹 Nitpick comments (2)
app/api/profile/route.ts (1)
116-131: PUT silently 404s for users who haven't hitGET /api/profileyet.
findOneAndUpdatewithoutupsertreturnsnullwhen noTeacherdocument exists forclerkId: userId, producing a 404 even though the user is authenticated. SinceGETauto-bootstraps the record, this creates an ordering dependency: any flow that issuesPUTbeforeGET(e.g., direct profile edit on first login, or after a DB wipe) will fail. Consider enablingupsert: truewithsetDefaultsOnInsert: truesoPUTis self-sufficient and consistent withGET.♻️ Proposed refactor
const teacher = await Teacher.findOneAndUpdate( { clerkId: userId }, - { $set: updatePayload }, - { new: true }, + { $set: updatePayload, $setOnInsert: { clerkId: userId } }, + { new: true, upsert: true, setDefaultsOnInsert: true }, ); - - if (!teacher) { - return NextResponse.json({ error: "Teacher not found" }, { status: 404 }); - }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/api/profile/route.ts` around lines 116 - 131, The PUT handler can return 404 because Teacher.findOneAndUpdate({ clerkId: userId }, { $set: updatePayload }, { new: true }) returns null if no document exists; update the call on Teacher (findOneAndUpdate) to include upsert: true and setDefaultsOnInsert: true in the options so a new Teacher is created when missing (preserving defaults), keeping the same match on clerkId and using updatePayload for fields.scripts/seed.mjs (1)
419-425: Letfinallydisconnect instead of exiting inside the try block.Calling
process.exit(0)here can bypass graceful cleanup and pending log flushes. Letmain()resolve naturally; the existingcatchalready handles failures.♻️ Proposed fix
- process.exit(0) + return } catch (err) { console.error('\n❌ Seed operations failed:') console.error(` ${err.message ?? err}`) throw err } finally { await mongoose.disconnect()🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/seed.mjs` around lines 419 - 425, Remove the in-try forced process.exit(0) so the function can resolve naturally and let the existing catch/finally perform cleanup; specifically, delete the call to process.exit(0) inside the try block and rely on the catch to rethrow errors and the finally block that calls mongoose.disconnect() to run for graceful cleanup and log flushing (refer to the try/catch/finally and the process.exit(0) invocation in scripts/seed.mjs).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/api/announcements/`[id]/route.ts:
- Around line 35-51: The code assumes body is an object and uses `key in body`,
which throws for null/primitives; after awaiting `req.json()` check that `body`
is a non-null object (and optionally not an array) before sanitizing, and if
it's not, return a 400 via `NextResponse.json({ error: "Invalid JSON request
body" }, { status: 400 })`; then proceed to build `sanitizedBody` by iterating
`ALLOWED_FIELDS` and copying values from `body`. Ensure these checks occur
immediately after `body = await req.json()` and before any use of `in` or
property access.
In `@app/api/assignments/`[id]/route.ts:
- Around line 55-59: The current use of Assignment.findOneAndUpdate(...,
sanitizedBody, { new: true }) does not run Mongoose validators; update the call
to include runValidators: true (and set context: 'query' if any validators rely
on query context) so that fields like status, kanbanStatus, deadline, and
maxMarks are validated on update; keep the selector {_id: id, teacherId: userId}
and new: true when modifying the options for the findOneAndUpdate call.
In `@app/api/attendance/route.ts`:
- Around line 8-11: The studentId refine in AttendanceSchema currently uses
mongoose.Types.ObjectId.isValid which accepts non-canonical 12-byte values;
update the validation to use mongoose.isObjectIdOrHexString (or the provided
canonical helper) to ensure only 24-char hex ObjectId strings pass; change the
refine predicate referenced on AttendanceSchema.studentId (and the similar
validation at the other occurrence around the code referenced at lines 82-85) to
call mongoose.isObjectIdOrHexString(id) (or call the isCanonicalObjectId helper)
and keep the existing error message.
In `@app/api/grades/`[id]/route.ts:
- Around line 44-48: The Grade.findOneAndUpdate call is missing runValidators so
Mongoose schema validators won't run on updates; modify the options object
passed to Grade.findOneAndUpdate (the call that currently uses { new: true }) to
include runValidators: true (e.g., { new: true, runValidators: true }) so
schema-level constraints (like marks bounds) are enforced while still keeping
the existing route-level validation around sanitizedBody.
In `@app/api/grades/route.ts`:
- Around line 24-33: The calcGrade function uses a strict greater-than for the
A+ threshold (if (pct > 90)) causing pct === 90 to fall into "A"; change that
comparison to >= so the A+ tier is consistent with all other inclusive
thresholds (i.e., use if (pct >= 90) in calcGrade), keeping the rest of the
thresholds (>=80, >=70, etc.) unchanged and still deriving pct from (marks /
max) * 100.
- Around line 92-112: The computed grade uses a fallback max (max =
parsed.data.maxMarks ?? 100) that can differ from the document's persisted
maxMarks on an update; modify the update path so calcGrade uses the effective
stored maxMarks: fetch the existing Grade (use Grade.findOne with the same
filter of teacherId/studentId/subject/term) to determine its maxMarks if
parsed.data.maxMarks is undefined, then compute grade = calcGrade(data.marks,
effectiveMax) and include that same effectiveMax in the $set payload (or require
maxMarks on updates); ensure this logic is used instead of calling calcGrade
with the hardcoded 100 fallback in the Grade.findOneAndUpdate flow.
In `@app/api/profile/route.ts`:
- Around line 16-24: The auto-bootstrap code uses unsafe optional chaining and a
non-atomic create that can race; change the email access to
clerkUser?.emailAddresses?.[0]?.emailAddress to avoid a TypeError when
emailAddresses is undefined, and replace the find-then-create logic that calls
Teacher.create (with unique clerkId) with an atomic upsert using
Teacher.findOneAndUpdate({ clerkId: userId }, { $setOnInsert: { clerkId: userId,
name: clerkUser?.fullName ?? "", email:
clerkUser?.emailAddresses?.[0]?.emailAddress ?? "", department: "", subjects: []
} }, { upsert: true, new: true, setDefaultsOnInsert: true, lean: true }) so
concurrent requests won’t produce E11000 duplicate-key errors and you get the
created/returned teacher object safely.
In `@app/api/students/`[id]/route.ts:
- Around line 7-17: ALLOWED_UPDATE_FIELDS includes a non-existent "grade"
property which causes silent ignores; remove "grade" from the
ALLOWED_UPDATE_FIELDS array in app/api/students/[id]/route.ts so student updates
only allow actual Student model fields (look for the ALLOWED_UPDATE_FIELDS
constant and delete the "grade" entry), and ensure any client documentation or
validation references the /api/grades endpoint for grade changes instead.
- Around line 35-55: The update currently writes sanitized fields directly and
bypasses schema validation; fix by enabling Mongoose update validators when
calling Student.findOneAndUpdate — add the options { new: true, runValidators:
true, context: 'query' } so Student schema validators (email format, required
constraints, etc.) are enforced on update, and ensure sanitizedBody only
contains allowed keys (ALLOWED_UPDATE_FIELDS) before calling findOneAndUpdate.
In `@app/dashboard/OverviewClient.tsx`:
- Around line 328-335: The current pendingAssignments calculation reads from the
paginated assignments array (assignments) so it undercounts; update the logic
that calls setStats so pendingAssignments uses the API's total for active
assignments instead of filtering the current page — e.g., perform a separate
fetch for active assignments (or use the response object that holds totals,
e.g., assignmentsDataActive.total or assignmentsData.totalActive) and pass that
total into setStats.pendingAssignments; ensure you still fall back to 0 if the
fetched total is undefined.
---
Outside diff comments:
In `@app/api/attendance/route.ts`:
- Around line 132-147: The single-record POST branch currently upserts
attendance without verifying the teacher actually owns the student; before
calling Attendance.findOneAndUpdate use Student.exists({ _id: studentId,
teacherId: userId }) (where studentId is parsed from AttendanceSchema and userId
is the authenticated teacher id) and return an authorization error (e.g., 403)
if the check fails; ensure you reference Attendance.findOneAndUpdate and
AttendanceSchema for locating the upsert and Student.exists for the ownership
check so only the owning teacher can upsert that student’s attendance.
In `@app/api/profile/route.ts`:
- Around line 94-114: The academicHistory validation currently checks array
length and types but not string lengths; update the validation around
academicHistory in route.ts to enforce per-field max lengths (for example: year
max 10 chars, title max 200 chars, description max 2000 chars) and ensure
description is optional but when present is a string within that limit; adjust
the Array.every check on academicHistory to include these length checks and
return the same 400 NextResponse.json error if any entry exceeds limits, and
also mirror these constraints in the Teacher/Mongoose schema (add maxlength
validators for year, title, description) so DB-level validation prevents
oversized entries.
---
Nitpick comments:
In `@app/api/profile/route.ts`:
- Around line 116-131: The PUT handler can return 404 because
Teacher.findOneAndUpdate({ clerkId: userId }, { $set: updatePayload }, { new:
true }) returns null if no document exists; update the call on Teacher
(findOneAndUpdate) to include upsert: true and setDefaultsOnInsert: true in the
options so a new Teacher is created when missing (preserving defaults), keeping
the same match on clerkId and using updatePayload for fields.
In `@scripts/seed.mjs`:
- Around line 419-425: Remove the in-try forced process.exit(0) so the function
can resolve naturally and let the existing catch/finally perform cleanup;
specifically, delete the call to process.exit(0) inside the try block and rely
on the catch to rethrow errors and the finally block that calls
mongoose.disconnect() to run for graceful cleanup and log flushing (refer to the
try/catch/finally and the process.exit(0) invocation in scripts/seed.mjs).
🪄 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: 7218cc83-bc93-4df2-b2a8-ad1d69f9b78c
📒 Files selected for processing (16)
app/(auth)/sign-in/[[...sign-in]]/page.tsxapp/(auth)/sign-up/[[...sign-up]]/page.tsxapp/api/announcements/[id]/route.tsapp/api/assignments/[id]/route.tsapp/api/assignments/route.tsapp/api/attendance/route.tsapp/api/grades/[id]/route.tsapp/api/grades/route.tsapp/api/profile/route.tsapp/api/students/[id]/route.tsapp/api/students/route.tsapp/dashboard/OverviewClient.tsxapp/dashboard/grades/GradesClient.tsxapp/dashboard/students/StudentsClient.tsxlib/mongodb.tsscripts/seed.mjs
There was a problem hiding this comment.
Pull request overview
This PR hardens the app’s API layer and dashboard behavior by tightening authorization/tenant isolation, improving validation and error handling, and aligning data calculations across the UI and backend.
Changes:
- Enforced stricter auth/ownership filtering on multiple mutation routes and reduced unsafe error responses.
- Added ObjectId validation for
studentIdin grades/attendance APIs and improved request parsing/validation. - Improved dashboard fetch robustness (
res.okchecks) and corrected summary totals/grade-point mapping consistency.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/seed.mjs | Adds MongoDB connection diagnostics and post-seed verification counts. |
| lib/mongodb.ts | Updates shared Mongoose connection options (TLS/timeout) with cached connection logic preserved. |
| app/dashboard/students/StudentsClient.tsx | Re-formats grade-point mapping used for CGPA calculation. |
| app/dashboard/grades/GradesClient.tsx | Re-formats grade-point mapping used for CGPA calculations. |
| app/dashboard/OverviewClient.tsx | Adds response OK checks, fixes grade-point mapping for D, and corrects totals using API total fields. |
| app/api/students/route.ts | Strengthens request validation and error handling for student listing/creation. |
| app/api/students/[id]/route.ts | Adds ObjectId validation and enforces teacher ownership in update/delete queries. |
| app/api/profile/route.ts | Removes cross-user profile access and improves PUT body validation/error handling. |
| app/api/grades/route.ts | Adds studentId ObjectId validation, safer parsing, and avoids leaking stack traces. |
| app/api/grades/[id]/route.ts | Enforces teacher ownership in update/delete queries and improves parsing. |
| app/api/attendance/route.ts | Adds ObjectId validation for studentId in schema and query filters. |
| app/api/assignments/route.ts | Avoids returning stack traces in 500 responses. |
| app/api/assignments/[id]/route.ts | Enforces teacher ownership in update/delete queries and improves parsing/validation. |
| app/api/announcements/[id]/route.ts | Enforces teacher ownership in update/delete queries and improves parsing/validation. |
| app/(auth)/sign-up/[[...sign-up]]/page.tsx | Updates Tailwind gradient utility usage for auth UI. |
| app/(auth)/sign-in/[[...sign-in]]/page.tsx | Updates Tailwind gradient utility usage for auth UI. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| console.error('\n❌ MongoDB Connection Failed!') | ||
| console.error(` Error: ${err.message}`) | ||
|
|
||
| if (err.message.includes('tls') || err.message.includes('SSL') || err.message.includes('tlsv1 alert')) { | ||
| console.error('\n🔍 DIAGNOSTIC (TLS/SSL Issue):') |
There was a problem hiding this comment.
The catch block assumes err is an Error (err.message, err.name). If a non-Error is thrown, this logging/diagnostic path will itself throw and mask the root cause. Guard with err instanceof Error (or coerce via String(err)) before accessing .message / .name.
| const hostMatch = MONGODB_URI.match(/@([^\/?]+)/) | ||
| const host = hostMatch ? hostMatch[1] : 'local or unknown host' | ||
|
|
||
| console.log(`🔗 Connecting to MongoDB...`) | ||
| if (process.env.DEBUG_DB === 'true') { | ||
| console.log(`[DEBUG] Target Host: ${host}`) | ||
| console.log(`[DEBUG] Connecting with TLS and 10s timeout...`) | ||
| } | ||
|
|
||
| try { | ||
| await mongoose.connect(MONGODB_URI, { | ||
| bufferCommands: false, | ||
| tls: true, |
There was a problem hiding this comment.
tls: true is forced for all MongoDB URIs. This can break connections to local/self-hosted MongoDB instances that aren’t configured for TLS. Consider enabling TLS conditionally (e.g., only for mongodb+srv:// or via an env flag) so the seed script works in more environments.
| const hostMatch = MONGODB_URI.match(/@([^\/?]+)/) | |
| const host = hostMatch ? hostMatch[1] : 'local or unknown host' | |
| console.log(`🔗 Connecting to MongoDB...`) | |
| if (process.env.DEBUG_DB === 'true') { | |
| console.log(`[DEBUG] Target Host: ${host}`) | |
| console.log(`[DEBUG] Connecting with TLS and 10s timeout...`) | |
| } | |
| try { | |
| await mongoose.connect(MONGODB_URI, { | |
| bufferCommands: false, | |
| tls: true, | |
| const tlsEnv = process.env.MONGODB_TLS?.trim().toLowerCase() | |
| const shouldUseTls = tlsEnv === 'true' || tlsEnv === '1' | |
| ? true | |
| : tlsEnv === 'false' || tlsEnv === '0' | |
| ? false | |
| : isAtlas | |
| const hostMatch = MONGODB_URI.match(/@([^\/?]+)/) | |
| const host = hostMatch ? hostMatch[1] : 'local or unknown host' | |
| console.log(`🔗 Connecting to MongoDB...`) | |
| if (process.env.DEBUG_DB === 'true') { | |
| console.log(`[DEBUG] Target Host: ${host}`) | |
| console.log(`[DEBUG] Connecting with TLS ${shouldUseTls ? 'enabled' : 'disabled'} and 10s timeout...`) | |
| } | |
| try { | |
| await mongoose.connect(MONGODB_URI, { | |
| bufferCommands: false, | |
| tls: shouldUseTls, |
|
|
||
| process.exit(0) |
There was a problem hiding this comment.
process.exit(0) inside the success path prevents the finally block from running, so mongoose.disconnect() will not execute. Prefer returning normally and letting the script finish (or move the exit into the main().then(...) after disconnect).
| process.exit(0) | |
| return |
| .connect(MONGODB_URI, { | ||
| bufferCommands: false, | ||
| tls: true, | ||
| serverSelectionTimeoutMS: 10000, | ||
| }) |
There was a problem hiding this comment.
tls: true is always enabled for connectDB(). That works for Atlas (mongodb+srv://) but can break non-TLS/self-hosted MongoDB URIs. Consider making TLS conditional based on the URI scheme/host or an env flag to avoid unexpected connection failures in other environments.
| // Validate ObjectId | ||
| if (!mongoose.Types.ObjectId.isValid(id)) { | ||
| return NextResponse.json({ error: 'Not found' }, { status: 404 }) | ||
| return NextResponse.json({ error: "Not found" }, { status: 404 }); |
There was a problem hiding this comment.
PUT returns 404 for a malformed ObjectId (Not found), while DELETE in the same file returns 400 (Invalid id). This inconsistency makes client error handling harder. Consider returning 400 for invalid IDs in PUT as well (and keep 404 for well-formed-but-missing documents).
| return NextResponse.json({ error: "Not found" }, { status: 404 }); | |
| return NextResponse.json({ error: "Invalid id" }, { status: 400 }); |
| const ALLOWED_UPDATE_FIELDS = [ | ||
| "name", | ||
| "email", | ||
| "grade", |
There was a problem hiding this comment.
ALLOWED_UPDATE_FIELDS includes "grade", but the Student schema doesn’t define a grade field. Updates to this key will be ignored (or rejected, depending on strict mode), which is confusing for API consumers. Consider removing it from the whitelist or adding it to the schema if intended.
| "grade", |
| } else if (err.message.includes('bad auth')) { | ||
| console.error('\n🔍 DIAGNOSTIC (Auth Issue): Check if your password contains unencoded special characters.') | ||
| } | ||
| process.exit(1) |
There was a problem hiding this comment.
Calling process.exit(1) here will bypass any later cleanup code (including the finally block that disconnects Mongoose) and can truncate buffered logs. Prefer throwing/returning and letting the top-level main().catch(...) handle exiting after cleanup.
| process.exit(1) | |
| throw err |
| const data = parsed.data; | ||
| const max = data.maxMarks ?? 100; | ||
| const term = data.term ?? "Term 1"; | ||
|
|
There was a problem hiding this comment.
max defaults to 100 when maxMarks is omitted, but the update payload doesn’t ensure maxMarks is actually stored as 100. This can lead to grade docs with missing maxMarks, which breaks consumers that assume it’s numeric. Consider explicitly setting maxMarks: max when it’s not provided.
| grade: calcGrade(data.marks, max), | ||
| }, | ||
| }, | ||
| { upsert: true, new: true }, |
There was a problem hiding this comment.
Because this uses findOneAndUpdate with { upsert: true }, Mongoose schema defaults (like maxMarks: 100 in the model) are not applied unless setDefaultsOnInsert: true is set. Consider adding setDefaultsOnInsert: true (and optionally runValidators: true) to the options to keep inserted docs consistent.
| { upsert: true, new: true }, | |
| { | |
| upsert: true, | |
| new: true, | |
| setDefaultsOnInsert: true, | |
| runValidators: true, | |
| }, |
Agent-Logs-Url: https://github.com/ArhanAnsari/discord-challenge/sessions/fad4ba3f-07a4-4318-99ef-0b604087422f Co-authored-by: ArhanAnsari <109061685+ArhanAnsari@users.noreply.github.com>
Agent-Logs-Url: https://github.com/ArhanAnsari/discord-challenge/sessions/fad4ba3f-07a4-4318-99ef-0b604087422f Co-authored-by: ArhanAnsari <109061685+ArhanAnsari@users.noreply.github.com>
Agent-Logs-Url: https://github.com/ArhanAnsari/discord-challenge/sessions/fad4ba3f-07a4-4318-99ef-0b604087422f Co-authored-by: ArhanAnsari <109061685+ArhanAnsari@users.noreply.github.com>
Agent-Logs-Url: https://github.com/ArhanAnsari/discord-challenge/sessions/fad4ba3f-07a4-4318-99ef-0b604087422f Co-authored-by: ArhanAnsari <109061685+ArhanAnsari@users.noreply.github.com>
Agent-Logs-Url: https://github.com/ArhanAnsari/discord-challenge/sessions/fad4ba3f-07a4-4318-99ef-0b604087422f Co-authored-by: ArhanAnsari <109061685+ArhanAnsari@users.noreply.github.com>
… explicit Agent-Logs-Url: https://github.com/ArhanAnsari/discord-challenge/sessions/fad4ba3f-07a4-4318-99ef-0b604087422f Co-authored-by: ArhanAnsari <109061685+ArhanAnsari@users.noreply.github.com>
Agent-Logs-Url: https://github.com/ArhanAnsari/discord-challenge/sessions/fad4ba3f-07a4-4318-99ef-0b604087422f Co-authored-by: ArhanAnsari <109061685+ArhanAnsari@users.noreply.github.com>
Agent-Logs-Url: https://github.com/ArhanAnsari/discord-challenge/sessions/f0bcc66c-11ab-4988-8980-c82e8dced445 Co-authored-by: ArhanAnsari <109061685+ArhanAnsari@users.noreply.github.com>
…n-runtime-stability Harden API mutation safety and align dashboard/grade correctness with review feedback
|
Name: Arhan Ansari Summary
|
Overview
This PR resolves multiple high-impact issues identified during the BugHunt Blitz challenge. The changes focus on strengthening API security, enforcing strict validation, improving runtime stability, and ensuring consistent dashboard data behavior.
Key Fixes
🔒 Security & Authorization
teacherId) across all[id]mutation routes:⚙️ Runtime Stability & Error Handling
✅ Validation & Input Safety
studentIdin:400responses instead of causing server errors🧠 Logic & Data Correctness
res.okchecks)🗄️ Database & Setup Fixes
🎨 Minor Improvements
GRADE_POINTconfigurationNotes
Verification
npm run lintpassednpm run buildpassedSummary
This PR significantly improves:
The codebase is now stable and ready for submission.
Summary by CodeRabbit
Release Notes
Bug Fixes
Improvements
Style