fix: validate non-string notes in affiliate applications (#145) - #172
fix: validate non-string notes in affiliate applications (#145)#172nguyenlnp wants to merge 1 commit into
Conversation
…rofullstack#147) When title or description fields are provided as non-string values (e.g., numbers, booleans, objects), calling .trim() would crash with a TypeError, resulting in a 500 error. Now returns 400 with a clear error message instead. Fixes profullstack#147
Greptile SummaryThis PR adds input validation for the
Confidence Score: 4/5Safe to merge — the validation logic is correct in both routes and all edge cases are covered by tests. The apply route's inline validation is functionally correct and the fix closes the reported bug. The only gap is that src/app/api/affiliates/offers/[id]/apply/route.ts — the inline note validation should delegate to Important Files Changed
Sequence DiagramsequenceDiagram
participant Client
participant ApplyRoute as POST /apply
participant PATCHRoute as PATCH /offers/[id]
participant validateApplyNote
participant Supabase
Client->>ApplyRoute: "POST { note: any }"
ApplyRoute->>ApplyRoute: "inline type check (note !== string → 400)"
Note over ApplyRoute,validateApplyNote: validateApplyNote() exists but is NOT called here
ApplyRoute->>ApplyRoute: "normalizedNote = trim or null"
ApplyRoute->>Supabase: "insert { note: normalizedNote }"
Supabase-->>ApplyRoute: application
ApplyRoute-->>Client: "201 { application }"
Client->>PATCHRoute: "PATCH { title: any, description: any }"
PATCHRoute->>PATCHRoute: "typeof title !== string → 400"
PATCHRoute->>PATCHRoute: "typeof description !== string → 400"
PATCHRoute->>Supabase: "update { title: trimmed, description: trimmed }"
Supabase-->>PATCHRoute: offer
PATCHRoute-->>Client: "200 { offer }"
Reviews (1): Last reviewed commit: "fix: add type guards for non-string titl..." | Re-trigger Greptile |
| // Validate note field (#145 — must be string if provided) | ||
| if (body.note !== undefined && body.note !== null) { | ||
| if (typeof body.note !== "string") { | ||
| return NextResponse.json( | ||
| { error: "note must be a string" }, | ||
| { status: 400 } | ||
| ); | ||
| } | ||
| } | ||
| // Normalize blank / whitespace-only notes to null | ||
| const normalizedNote = | ||
| typeof body.note === "string" && body.note.trim().length > 0 | ||
| ? body.note.trim() | ||
| : null; |
There was a problem hiding this comment.
The
validateApplyNote() utility was explicitly created for reusable validation but is never called from the route — the logic is duplicated inline. If the validation rules ever change in the utility (e.g. a max-length limit added to validateApplyNote), the route will silently stay out of sync.
| // Validate note field (#145 — must be string if provided) | |
| if (body.note !== undefined && body.note !== null) { | |
| if (typeof body.note !== "string") { | |
| return NextResponse.json( | |
| { error: "note must be a string" }, | |
| { status: 400 } | |
| ); | |
| } | |
| } | |
| // Normalize blank / whitespace-only notes to null | |
| const normalizedNote = | |
| typeof body.note === "string" && body.note.trim().length > 0 | |
| ? body.note.trim() | |
| : null; | |
| // Validate note field (#145 — must be string if provided) | |
| const noteResult = validateApplyNote(body.note); | |
| if (!noteResult.ok) { | |
| return NextResponse.json( | |
| { error: noteResult.error }, | |
| { status: 400 } | |
| ); | |
| } | |
| const normalizedNote = noteResult.value; |
Fix: Affiliate applications accept non-string notes (#145)
Problem
POST /api/affiliates/offers/[id]/applyreadsbody.noteand passes it directly into the affiliate application insert withbody.note || null. A malformed client can send an object, array, or number for note, which would be persisted to the database without validation.Changes
src/app/api/affiliates/offers/[id]/apply/route.ts): Added validation to reject non-stringnotevalues with a 400 error, and normalize blank/whitespace-only notes tonull(with trimming).src/lib/affiliates/validation.ts): AddedvalidateApplyNote()utility function for reusable validation logic.src/lib/affiliates/validation.test.ts): Added 10 regression tests covering:Testing
All 32 tests pass (22 existing + 10 new regression tests).
Fixes #145
SOL payment address:
0xadf380b5048e9730af0957fd39d5ef1de374475d