fix: prevent users from inviting themselves in referral flow#386
fix: prevent users from inviting themselves in referral flow#386jhosepm352-design wants to merge 1 commit into
Conversation
Greptile SummaryThis PR adds a self-invite guard to the referral POST endpoint: the authenticated user's email is stripped from the candidate list before any invites are sent, and a targeted "You cannot invite yourself" error is returned when the resulting valid-email list is empty. It also introduces deduplication via
Confidence Score: 3/5The change introduces a self-invite guard that silently no-ops for accounts where The self-invite filter compares email strings against src/app/api/referrals/route.ts — the self-invite guard and the error-message heuristic both need attention around the Important Files Changed
Reviews (1): Last reviewed commit: "fix: prevent users from inviting themsel..." | Re-trigger Greptile |
| const userEmail = user.email?.toLowerCase(); | ||
| const validEmails = Array.from( | ||
| new Set(normalizedEmails.filter((e: string) => emailRegex.test(e) && e !== userEmail)) | ||
| ); |
There was a problem hiding this comment.
user.email is typed as string | undefined in Supabase Auth — the optional-chain on line 85 confirms the developer knows this. When userEmail resolves to undefined, the filter condition e !== userEmail becomes e !== undefined, which is always true for any email string. That means the entire self-invite guard is silently bypassed for accounts without a stored email (e.g. certain OAuth providers), and the PR's primary goal is not met for those users.
| const userEmail = user.email?.toLowerCase(); | |
| const validEmails = Array.from( | |
| new Set(normalizedEmails.filter((e: string) => emailRegex.test(e) && e !== userEmail)) | |
| ); | |
| const userEmail = user.email?.trim().toLowerCase(); | |
| if (!userEmail) { | |
| return NextResponse.json( | |
| { error: "Unable to determine your email address" }, | |
| { status: 400 } | |
| ); | |
| } | |
| const validEmails = Array.from( | |
| new Set(normalizedEmails.filter((e: string) => emailRegex.test(e) && e !== userEmail)) | |
| ); |
| if (validEmails.length === 0) { | ||
| const onlySelf = normalizedEmails.every(e => e === userEmail || !emailRegex.test(e)); | ||
| return NextResponse.json( | ||
| { error: onlySelf ? "You cannot invite yourself" : "No valid email addresses provided" }, | ||
| { status: 400 } | ||
| ); | ||
| } |
There was a problem hiding this comment.
The
onlySelf heuristic has a false-positive when userEmail is undefined: the condition e === userEmail becomes e === undefined, which is always false for email strings, so onlySelf falls through entirely to !emailRegex.test(e). Any submission consisting purely of syntactically invalid addresses (e.g. ["notanemail"]) then reports "You cannot invite yourself" even though no self-invite was attempted. Tightening the guard to require at least one entry that matches userEmail avoids the mislead.
| if (validEmails.length === 0) { | |
| const onlySelf = normalizedEmails.every(e => e === userEmail || !emailRegex.test(e)); | |
| return NextResponse.json( | |
| { error: onlySelf ? "You cannot invite yourself" : "No valid email addresses provided" }, | |
| { status: 400 } | |
| ); | |
| } | |
| if (validEmails.length === 0) { | |
| const hasSelfEntry = userEmail !== undefined && normalizedEmails.some(e => e === userEmail); | |
| const onlySelf = hasSelfEntry && normalizedEmails.every(e => e === userEmail || !emailRegex.test(e)); | |
| return NextResponse.json( | |
| { error: onlySelf ? "You cannot invite yourself" : "No valid email addresses provided" }, | |
| { status: 400 } | |
| ); | |
| } |
Prevents users from inviting their own email address in the referral flow. Also improves the error message to explicitly notify the user when they try to invite themselves.