Validate and uniqueness-check username on user update (fixes #13) #17
Reference in New Issue
Block a user
No description provided.
Delete Branch "fix/username-validation-update"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Fixes #13.
PUT /admin/users/:idvalidatedpasswordandrolebut notusername, even thoughupdateUserwritesreq.body.usernameto the DB. Two consequences:createUser, which does), so it hit the DB unique constraint and surfaced as an opaque500 Internal Server Errorinstead of a meaningful409.What changed
server/src/router/v1/admin/admin.routes.js— added the same validator used on create, made optional so an update that omitsusernamestill works:.trim()sanitizer also mutatesreq.body.username, so whitespace-only input collapses and then fails themin: 3check (400), and the value the controller writes is already trimmed — consistent with create.server/src/router/v1/admin/admin.controller.js— inupdateUser, when the username is actually changing, pre-check for an existing user with that name and return409 Username already taken:Why this approach
createUser— the create path already validates the username and pre-checks uniqueness withgetRawByUsername, returning409. Reusing the exact same validator and helper keeps the two paths consistent and avoids inventing new behavior..optional()— unlike create, an update may legitimately change only the password or role. Making the validator optional preserves that; the field is only validated when present.req.body.username !== target.username— this skips the uniqueness query when the name is unchanged, and guarantees any row returned bygetRawByUsernamebelongs to a different user, so we never 409 a user against itself.409gives the client an actionable, non-500 response and matches how create already reports the same conflict.Testing
node -csyntax check on both changed files.Notes
Backend only, no schema or client changes. Branched from current
main(which already includes the #10 and #12 fixes).PUT /admin/users/:id validated password and role but not username, even though updateUser writes req.body.username. A blank/too-short username could be saved, and a duplicate hit the DB unique constraint and surfaced as an opaque 500. - Route: add the same validator used on create, body('username').optional().isString().trim().isLength({min:3,max:32}). The trim sanitizer also collapses whitespace-only input so it fails the min-length check. - Controller: when the username is changing, pre-check for another user with that name and return 409 instead of letting the DB throw a 500. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>