feat(auth): add withAuthenticatedUser and withOptionalUser wrappers#34
Merged
Conversation
Hoist token extraction, JWT verification, user lookup, and 401 responses out of every API route into a single deep wrapper. Handlers receive a populated AuthContext (userDoc, email, freshly rotated token) and can focus on the resource they own. The optional sibling supports note.ts' guest creation flow without conflating contracts behind a flag. Removes the @ts-ignore in utils/jwt.ts by giving authenticateToken and generateAccessToken proper return types via a TokenPayload alias. Tests cover the missing-header, invalid-token, missing-user, happy-path, error-propagation, and guest paths via mocked jwt + Mongoose User.
Drop the hand-rolled token extraction, JWT verification, and 401 boilerplate now that the wrapper owns that contract.
Remove the duplicated auth boilerplate. Widen UserDocInterface to expose the schema fields (settings, projects, etc.) the route reads through the typed userDoc on AuthContext.
Drop the duplicated token/email plumbing. The wrapper hands the route both the userDoc and a freshly rotated newToken so the trailing generateAccessToken call is no longer needed.
Drop the duplicated auth boilerplate. The action switch now uses ctx.userDoc and ctx.newToken, removing two interleaved generateAccessToken calls that were threading the same email through the function.
Replace the local isGuestUser flag and the inline JWT/User lookup with the OptionalAuthContext supplied by the wrapper. Guest creation flow is now expressed by the discriminated ctx rather than a stateful boolean threaded through the handler.
Centralise the password contract for shared projects in a small pure module so the read path (public_project) and write path (project) can agree on what "open", "passwordRequired", "incorrect" and "ok" mean. The discriminated ShareAccessResult lets callers handle each case explicitly instead of branching on string messages. Tests use a real bcrypt round-trip to prove the seam, not a mock.
Both SHARE branches now delegate password hashing to the share module. The optional-chaining null guard is kept so the existing sharing.test.ts regression continues to detect the original Bug 4 crash, but the salt-rounds policy and the bcrypt dependency now live in one place.
Replace the inline bcrypt branch with a call to the shared module. The read path is now null-safe — the previous \`shareDoc.password.length\` crash when password was null/undefined is gone, since the helper treats empty/null as "open access" by contract. Also adds an explicit null guard for \`shareDoc\` so a missing share url returns a clear 400 instead of falling into the bare catch. Status codes for passwordRequired/incorrect are intentionally kept at 200 to preserve the current client contract; see CONTEXT.md follow-ups.
- README "API conventions" section explains how to use withAuthenticatedUser, withOptionalUser, hashSharePassword and verifySharePassword in route handlers. - CONTEXT.md (new) defines the project vocabulary across the Domain (User/Project/Note/Share/Settings) and the two new architecture seams (Identity/Auth, Share). Includes a "Known follow-ups" section so future architecture reviews don't re-suggest the same out-of-scope items. - .markdownlint-cli2.jsonc relaxes MD013 (line length) and MD028 (blank line in blockquote) so prose docs are not constrained to 80-char wrapping; pre-existing README content already exceeded that threshold.
- pages/api/auth: drop the second User.findOne and populate the
userDoc the wrapper already loaded. Auth checks now make one Mongo
round-trip instead of two.
- pages/api/note: delete the empty if (action === REMOVE) {} branch
carried over from the original; it never did anything.
- utils/auth/withAuthenticatedUser: document why extractBearer anchors
the prefix at the start of the header.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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.
Hoist token extraction, JWT verification, user lookup, and 401 responses
out of every API route into a single deep wrapper. Handlers receive a
populated AuthContext (userDoc, email, freshly rotated token) and can
focus on the resource they own. The optional sibling supports note.ts'
guest creation flow without conflating contracts behind a flag.
Removes the @ts-ignore in utils/jwt.ts by giving authenticateToken and
generateAccessToken proper return types via a TokenPayload alias.
Tests cover the missing-header, invalid-token, missing-user, happy-path,
error-propagation, and guest paths via mocked jwt + Mongoose User.