diff --git a/app/api/team/accept/route.ts b/app/api/team/accept/route.ts index e97016c5..5c4a137a 100644 --- a/app/api/team/accept/route.ts +++ b/app/api/team/accept/route.ts @@ -33,10 +33,9 @@ export async function GET(request: NextRequest) { const expired = new Date(companyInvite.expires_at) < new Date() - const { data: existingUsers } = await serviceClient.auth.admin.listUsers() - const alreadyHasAccount = existingUsers?.users?.some( - (u) => u.email?.toLowerCase() === companyInvite.email.toLowerCase() - ) ?? false + const { data: alreadyHasAccount } = await serviceClient.rpc('check_email_exists', { + email_to_check: companyInvite.email, + }) return NextResponse.json({ data: { diff --git a/app/invite/[token]/page.tsx b/app/invite/[token]/page.tsx index 3f667b74..00304b8c 100644 --- a/app/invite/[token]/page.tsx +++ b/app/invite/[token]/page.tsx @@ -135,7 +135,11 @@ export default function InvitePage() { await supabase.auth.signOut() // Keep the invite cookie alive so the next login/register picks it up. document.cookie = `gnubok-invite-token=${token}; path=/; max-age=3600; samesite=lax${secureCookieFlag}` - router.push('/login') + if (invite?.alreadyHasAccount) { + router.push('/login') + } else { + router.push(`/register?invite=${encodeURIComponent(token)}`) + } } if (isLoading) { @@ -209,8 +213,11 @@ export default function InvitePage() { - ) : invite?.alreadyHasAccount && isLoggedInAsInvitee ? ( + ) : isLoggedInAsInvitee ? ( // Already signed in as the invitee — one-click join. + // Prioritized over alreadyHasAccount to avoid the broken flow + // where a false-negative from the email check would send a + // logged-in user to /register, which middleware bounces to /.