Skip to content

⭐ Controllers

Terrence Daniels edited this page Aug 14, 2026 · 1 revision

6 controllers — articles, comments, favorites, profiles, user, users — the most bug-dense layer in this backend. Real, user-facing bugs, not style nits:

  • articles.js: no null-check on a favorited-username lookup (crashed into a generic 500 instead of a 404), createArticle didn't default tagList (crashed on a valid RealWorld payload that omits it), and a missing await on article.setAuthor(...) — a real race condition.
  • comments.js: deleteComment never checked that the comment it was deleting actually belonged to the article named in the URL slug, unlike its siblings in the same file — meaning a client could delete a comment by ID through any article's URL. Fixed to match the file's own established pattern.
  • user.ts: updateUser's password guard was if (password !== undefined || password !== "") — a logical tautology, always true regardless of the value. Every PUT /user request that omitted a password crashed with a 500 (bcrypt.hash throws on undefined) — not silent corruption, a hard crash on the single most common update. Also found: email silently went missing from PUT /user responses unless the client happened to update it directly, and a blind Object.entries(user).forEach(...) let a client set any field, including id/createdAt/updatedAt — narrowed to an explicit username/bio/image/email whitelist.
  • users.ts: login-issued JWTs baked in username: undefinedsignIn signed the raw login request body instead of the actual DB record. Verified by decoding a token post-revert and confirming decoded.username really was undefined. Also: signUp checked email uniqueness but never username, and no DB constraint enforced it either — two accounts could silently share a username, breaking every username-based lookup elsewhere in the app.
  • favorites.js: added unchanged — no bugs found.

Every fix above was proven meaningful the same way: deliberately reverted, watched fail against a real test, then restored. See Testing Strategy for the in-memory-SQLite approach that made testing 6 Sequelize-heavy controllers tractable.

Clone this wiki locally