diff --git a/src/lib/identityService.ts b/src/lib/identityService.ts index 7e84a85a..f4cfb263 100644 --- a/src/lib/identityService.ts +++ b/src/lib/identityService.ts @@ -213,50 +213,56 @@ export async function addPasswordToAccount( }; } - // Step 1: Update password AND trigger email confirmation - // Re-confirming the email will trigger Supabase to create the email identity - console.log('[IdentityService] Setting password and triggering email confirmation'); - const { error: updateError } = await supabase.auth.updateUser({ - password, - email: userEmail // Re-confirm email to create email identity provider - }); + // Step 1: Set the password (does NOT create email identity yet) + console.log('[IdentityService] Setting password'); + const { error: updateError } = await supabase.auth.updateUser({ password }); if (updateError) throw updateError; - - // Step 2: Get user profile for email personalization - console.log('[IdentityService] Fetching user profile for email'); + + // Step 2: Trigger signup confirmation email (this creates the email identity) + console.log('[IdentityService] Sending signup confirmation email'); + const { error: resendError } = await supabase.auth.resend({ + type: 'signup', + email: userEmail, + options: { + emailRedirectTo: `${window.location.origin}/auth?confirmed=password-setup` + } + }); + + if (resendError) { + console.error('[IdentityService] Failed to send confirmation email:', resendError); + throw resendError; + } + + // Step 3: Get user profile for custom notification email + console.log('[IdentityService] Fetching user profile'); const { data: profile } = await supabase .from('profiles') .select('display_name, username') .eq('user_id', user!.id) .single(); - - // Step 3: Send password addition email (before logging out) - console.log('[IdentityService] Sending password addition email'); + + // Step 4: Send our custom "Password Added" notification (informational) + console.log('[IdentityService] Sending custom notification email'); try { - const { error: emailError } = await supabase.functions.invoke('send-password-added-email', { + await supabase.functions.invoke('send-password-added-email', { body: { email: userEmail, displayName: profile?.display_name, username: profile?.username, }, }); - - if (emailError) { - console.error('[IdentityService] Failed to send email:', emailError); - } else { - console.log('[IdentityService] Email sent successfully'); - } } catch (emailError) { - console.error('[IdentityService] Email sending error:', emailError); + console.error('[IdentityService] Custom email failed (non-blocking):', emailError); } - - // Step 4: Log the password addition + + // Step 5: Log the action await logIdentityChange(user!.id, 'password_added', { - method: 'oauth_with_email_confirmation_required' + method: 'oauth_password_addition_with_signup_confirmation', + confirmation_email_sent: true }); - - // Step 5: Sign the user out so they can confirm email - console.log('[IdentityService] Signing user out to complete email confirmation'); + + // Step 6: Sign user out (they must confirm via email) + console.log('[IdentityService] Signing user out'); await supabase.auth.signOut(); // Return success with relogin and email confirmation flags @@ -306,45 +312,49 @@ export async function triggerOrphanedPasswordConfirmation( }; } - console.log('[IdentityService] Triggering email confirmation for orphaned password'); + console.log('[IdentityService] Resending signup confirmation email'); - // Step 1: Get user profile for email personalization + // Send Supabase signup confirmation email + const { error: resendError } = await supabase.auth.resend({ + type: 'signup', + email: user.email, + options: { + emailRedirectTo: `${window.location.origin}/auth?confirmed=password-confirmation` + } + }); + + if (resendError) { + console.error('[IdentityService] Failed to resend confirmation:', resendError); + throw resendError; + } + + console.log('[IdentityService] Confirmation email resent successfully'); + + // Optional: Get profile for custom notification const { data: profile } = await supabase .from('profiles') .select('display_name, username') .eq('user_id', user.id) .single(); - // Step 2: Send password confirmation email via edge function - console.log('[IdentityService] Invoking send-password-added-email edge function'); - const { data: emailData, error: emailError } = await supabase.functions.invoke( - 'send-password-added-email', - { + // Optional: Send custom notification email (non-blocking) + try { + await supabase.functions.invoke('send-password-added-email', { body: { email: user.email, displayName: profile?.display_name, username: profile?.username, }, - } - ); - - if (emailError) { - console.error('[IdentityService] Edge function invocation failed:', emailError); - throw new Error(emailError.message || 'Failed to send confirmation email'); + }); + } catch (emailError) { + console.error('[IdentityService] Custom email failed (non-blocking):', emailError); } - if (emailData && !emailData.success) { - console.error('[IdentityService] Edge function returned error:', emailData.error); - throw new Error(emailData.error || 'Email service returned an error'); - } - - console.log('[IdentityService] Confirmation email sent successfully'); - - // Step 3: Log the action for audit trail + // Log the action await logIdentityChange(user.id, 'orphaned_password_confirmation_triggered', { method: source || 'manual_button_click', timestamp: new Date().toISOString(), - email_sent: true + confirmation_email_sent: true }); return {