fix: activate pending users on login#210
Conversation
If a pending user can authenticate (via login form or invite link), they should be activated. Previously only the invite callback path called /me/activate, so users who logged in directly stayed pending. Now recordLogin() sets status='active' for pending users. Locked users are excluded from the update. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughrecordLogin was clarified to only update Changes
Sequence Diagram(s)sequenceDiagram
participant Browser
participant AdminApp as Admin App (set-password)
participant Supabase
participant API as /user-profiles/me/activate
Browser->>AdminApp: Submit new password
AdminApp->>Supabase: setSession / update password
AdminApp->>Supabase: auth.getSession()
Supabase-->>AdminApp: session (access_token)
AdminApp->>API: POST /user-profiles/me/activate (Authorization: Bearer access_token)
API-->>AdminApp: 200 OK (activation enqueued/done)
AdminApp->>Supabase: auth.refreshSession() / setSession with new JWT
Supabase-->>Browser: redirect to /profile?setup=true
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning Review ran into problems🔥 ProblemsTimed out fetching pipeline failures after 30000ms Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/api/src/user-profiles/user-profiles.service.ts`:
- Around line 271-280: The recordLogin update call in user-profiles.service.ts
updates lastLoginAt, lastSeenAt and status but omits updatedAt; modify the
.set(...) in the recordLogin flow to also set updatedAt to the same now value so
status transitions use the same timestamp semantics as other status-update paths
(refer to recordLogin, lastLoginAt, lastSeenAt, status, updatedAt and
this.db.schema.userProfiles in the service).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 1c4e6a90-f756-4a50-bdab-6b11bd8a4aba
📒 Files selected for processing (1)
apps/api/src/user-profiles/user-profiles.service.ts
| .set({ lastLoginAt: now, lastSeenAt: now, status: 'active' }) | ||
| .where( | ||
| and( | ||
| eq(this.db.schema.userProfiles.id, userId), | ||
| or( | ||
| eq(this.db.schema.userProfiles.status, 'active'), | ||
| eq(this.db.schema.userProfiles.status, 'pending'), | ||
| ), | ||
| ), | ||
| ) |
There was a problem hiding this comment.
Include updatedAt when transitioning user status in recordLogin.
This query now changes status, but it does not update updatedAt, which makes status transitions here inconsistent with other status-update paths.
Suggested patch
- .set({ lastLoginAt: now, lastSeenAt: now, status: 'active' })
+ .set({
+ lastLoginAt: now,
+ lastSeenAt: now,
+ status: 'active',
+ updatedAt: now,
+ })📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .set({ lastLoginAt: now, lastSeenAt: now, status: 'active' }) | |
| .where( | |
| and( | |
| eq(this.db.schema.userProfiles.id, userId), | |
| or( | |
| eq(this.db.schema.userProfiles.status, 'active'), | |
| eq(this.db.schema.userProfiles.status, 'pending'), | |
| ), | |
| ), | |
| ) | |
| .set({ | |
| lastLoginAt: now, | |
| lastSeenAt: now, | |
| status: 'active', | |
| updatedAt: now, | |
| }) | |
| .where( | |
| and( | |
| eq(this.db.schema.userProfiles.id, userId), | |
| or( | |
| eq(this.db.schema.userProfiles.status, 'active'), | |
| eq(this.db.schema.userProfiles.status, 'pending'), | |
| ), | |
| ), | |
| ) |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/api/src/user-profiles/user-profiles.service.ts` around lines 271 - 280,
The recordLogin update call in user-profiles.service.ts updates lastLoginAt,
lastSeenAt and status but omits updatedAt; modify the .set(...) in the
recordLogin flow to also set updatedAt to the same now value so status
transitions use the same timestamp semantics as other status-update paths (refer
to recordLogin, lastLoginAt, lastSeenAt, status, updatedAt and
this.db.schema.userProfiles in the service).
- Remove early activation from both auth callback paths (query-param and hash-fragment) — users stay pending until password is set - Revert recordLogin() to only update timestamps, not activate - Add middleware redirect: pending users are sent to /auth/set-password for all routes except the set-password page itself and auth callback - Activate account only after password is successfully set on the set-password page, then refresh session so JWT reflects active status - Decode user_status from JWT claims in middleware for pending detection Validated with Codex: uses server-controlled user_profiles.status (injected into JWT via custom_access_token_hook) instead of user-editable user_metadata. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
# Conflicts: # apps/admin/src/app/auth/callback/route.ts
Summary
pendingstatus despite being authenticatedrecordLogin()now setsstatus='active'for pending users — if they can authenticate, they've completed onboardingTest plan
🤖 Generated with Claude Code
Summary by CodeRabbit