Add PUT /users/:id endpoint with input hardening - #9
Open
pppmppp wants to merge 6 commits into
Open
Conversation
Finds a user by id and mutates name/email in place, returning the updated object — or undefined when the id does not exist. Exported alongside the existing getAllUsers, getUserById, and createUser helpers. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Validates that both name and email are present (400 if either is missing) before looking up the user, so a bad body is rejected even when the id exists. Returns the updated user on success (200) or 404 when the id is not found. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers the implementation plan, model used (Claude Sonnet 4.6), commit split, and the key review finding: input validation must run before the store lookup so a missing field always returns 400 regardless of whether the id exists. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The route layer trims and validates name/email before calling the store, so the falsy guard in updateUser could never fire through the normal request path. Worse, its falsy check diverged from the route's .trim() semantics: a whitespace-only string would pass the store guard but be rejected by the route. Removed the throw; validation belongs in the route, not the store. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The previous code used destructuring defaults and .trim() directly, but
defaults only apply when a field is undefined — not null. Sending
{ name: null } or { name: 123 } bypassed the default and threw a
TypeError on .trim(), producing a 500 instead of a 400. Both handlers
now coerce through a typeof check (non-strings become "") and trim once
before validation, so any malformed field gets a clean 400. POST also
gains the req.body || {} guard that PUT already had, fixing the same
crash when Content-Type is absent.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces the stub write-up with full answers to the four submission questions: what the approved plan contained and whether it was edited, why Sonnet 4.6 was chosen, how the five commits were split and why, and what two rounds of code review caught (and what was already correct). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PUT /users/:idto update an existing user's name and email (200 on success, 404 for unknown id, 400 for missing or blank fields)updateUserhelper todb/store.js, returning a shallow copy so callers cannot mutate the stored recordreq.body || {}guard prevents a crash whenContent-Typeis absent;typeofcheck before.trim()prevents a TypeError crash fromnullor non-string fields:idis a positive integer before hitting the store, so malformed ids return 400 instead of a misleading 404NOTES.mdwrite-up (required by the grading suite)Commit breakdown
Add updateUser helper to the in-memory store— store layer onlyAdd PUT /users/:id route to update an existing user— route wired up; all 9 tests greenAdd NOTES.md submission write-up— grading write-upRemove dead validation throw from updateUser— store guard was unreachable via the route and diverged semantically from the route's.trim()checkGuard against null and non-string body fields in PUT and POST handlers—nullfields and non-string values now return 400 instead of an unhandled 500Test plan
npm test— all 9 tests passPUT /users/:idwith valid body → 200 + updated userPUT /users/:idwith unknown id → 404PUT /users/:idwith missing field → 400PUT /users/abc(non-numeric id) → 400PUT /users/1with{ name: null }→ 400 (not 500)POST /userswithoutContent-Typeheader → 400 (not 500)🤖 Generated with Claude Code