#239 Allow Admins To Create User Accounts#249
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
b-at-neu
left a comment
There was a problem hiding this comment.
Code Review — Cycle 1 · needs revision
2 open — 1 🟠 Medium, 1 🟡 Low (see inline)
Revision — Cycle 1fixed R1-M1, R1-L1 · 6fbbee1 |
b-at-neu
left a comment
There was a problem hiding this comment.
Code Review — Cycle 2 · approved
2 open — ⚪ Nit (see inline) — R1-M1 and R1-L1 both resolved; no Critical/Medium/Low remain
Revision needed — bug: "Failed to create auth user"Vercel logs show an unhandled throw with message "Failed to create auth user" as soon as the create user form is submitted. The Required investigation and fix:
Do not change the duplicate-email |
6fbbee1 to
3ce8566
Compare
Revision — Cycle 2fixed R2-N1, R2-N2 · 3ce8566 |
b-at-neu
left a comment
There was a problem hiding this comment.
Code Review — Bug Fix Required
Cycle 3 — 1 Critical finding
R3-C1 · Critical — authServer.admin.createUser failure throws instead of returning a user-facing error
Vercel logs show an unhandled server throw with message "Failed to create auth user" as soon as the create user form is submitted. The current code does not handle the case where authServer.admin.createUser fails for reasons other than duplicate email.
Required fixes:
-
Guard against unavailable admin API. If
authServer.adminisundefinedor the method doesn't exist, the action throws with no useful message. Add a check before calling: if the admin API is unavailable, return{ error: 'User creation is not available.' }rather than throwing. -
Catch all
authServer.admin.createUserfailures gracefully. The current error-mapping only handles duplicate-email error codes. Any other failure (network error, auth backend rejection, invalid credentials, admin plugin not enabled) falls through to a raw throw. Wrap the entire call in a try/catch that:- Maps known user-actionable codes to
{ error: '...' }(existing duplicate email path — keep as-is) - For any other error:
throw new Error('Failed to create auth user')but only AFTER logging the original error withconsole.errorso it appears in Vercel logs with context - This ensures the dialog shows "Something went wrong. Please try again." toast rather than a blank crash
- Maps known user-actionable codes to
-
Confirm the return shape. Log
authServer.admin.createUserresult shape in development to verify it returns{ data, error }as assumed. If it throws rather than returning{ error }, the try/catch approach replaces the current result-inspection pattern.
The neonAuthId extraction (data.user.id or data.id) should also be verified against the actual runtime shape and use optional chaining with a fallback throw.
d03dc93 to
df756a0
Compare
Revision — Cycle 7fixed R7-C1 · df756a0 |
b-at-neu
left a comment
There was a problem hiding this comment.
Code Review — Cycle 4 · approved
0 open — R3-C1 fully resolved; no Critical/Medium/Low/Nit remain
b-at-neu
left a comment
There was a problem hiding this comment.
Code Review — Cycle 6 · needs revision
3 open — 1 🟠 Medium, 1 🟡 Low, 1 ⚪ Nit (see inline)
…ma to lib/constants, add createUser server action (admin-gated, calls authServer.admin.createUser, upserts app User row in a transaction), and wire a CreateUserDialog into the Users page header. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace authServer.admin.createUser with a Prisma-only pre-invite approach: make neonAuthId nullable, createUser inserts a pending row, and resolveRealUser links it on the invited user's first OTP sign-in. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Call authServer.admin.createUser before creating the app row so the Neon Auth account is pre-provisioned and the user can sign in via OTP immediately; revert resolveRealUser to the original atomic upsert (race-safe, no nullable neonAuthId needed); remove the make-neon-auth-id-nullable migration. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove authServer.admin.createUser (returns 401); createUser now pre-creates a User row with email only. resolveRealUser() gains a three-step lookup: linked fast-path, email-match link for pre-invited users, then create with P2002 race guard. neonAuthId made nullable to support pre-invite rows with no auth account yet. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
df756a0 to
87c7419
Compare
Revision — Cycle 6fixed R6-M1, R6-N1, R6-L1 · 87c7419 |
b-at-neu
left a comment
There was a problem hiding this comment.
Code Review — Cycle 8 · approved
0 open — R6-M1, R6-N1, R6-L1 all resolved; no Critical/Medium remain
Closes #239
Summary
Userrow with email only (no Neon Auth API call); when the invitee completes OTP sign-up,resolveRealUser()links theirneonAuthIdprisma.user.createwith a P2002 unique-constraint catch, matching the same pattern used inresolveRealUserChanges
lib/auth/server.ts— extractupsertAppUserhelper (exported);resolveRealUsernow delegates to itlib/constants.ts— addcreateUserSchema(zod):email, optionalname,isAdmin(default false)prisma/actions/users.ts— addcreateUserserver action: admin-gate, zod-parse, atomiccreate+ P2002 catch for duplicate email, optional admin flag,revalidatePath('/users')components/features/create-user-dialog.tsx— new client component:FormDialogwith Email/Name/Admin fields, toasts on success/errorapp/(main)/(auth)/users/page.tsx— wireCreateUserDialogintoPageHeaderactionsslotTesting plan
/usersand confirm a "Create user" button appears in the header/usersstill redirects and thecreateUseraction returns{ error: 'Unauthorized' }when called directlyAutomated checks