mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-21 17:31:12 -05:00
feat: Implement password reset flow
This commit is contained in:
@@ -213,35 +213,38 @@ export async function addPasswordToAccount(
|
||||
};
|
||||
}
|
||||
|
||||
// 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: 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`
|
||||
console.log('[IdentityService] Initiating password setup via reset flow');
|
||||
|
||||
// Step 1: Store the desired password temporarily in session storage
|
||||
// This will be used after clicking the reset link
|
||||
sessionStorage.setItem('pending_password_setup', password);
|
||||
console.log('[IdentityService] Stored pending password in session storage');
|
||||
|
||||
// Step 2: Trigger Supabase password reset email
|
||||
// This creates the email identity when user clicks link and sets password
|
||||
const { error: resetError } = await supabase.auth.resetPasswordForEmail(
|
||||
userEmail,
|
||||
{
|
||||
redirectTo: `${window.location.origin}/auth/callback?action=password-setup`
|
||||
}
|
||||
});
|
||||
|
||||
if (resendError) {
|
||||
console.error('[IdentityService] Failed to send confirmation email:', resendError);
|
||||
throw resendError;
|
||||
);
|
||||
|
||||
if (resetError) {
|
||||
console.error('[IdentityService] Failed to send password reset email:', resetError);
|
||||
sessionStorage.removeItem('pending_password_setup'); // Cleanup on failure
|
||||
throw resetError;
|
||||
}
|
||||
|
||||
|
||||
console.log('[IdentityService] Password reset email sent successfully');
|
||||
|
||||
// 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 4: Send our custom "Password Added" notification (informational)
|
||||
|
||||
// Step 4: Send custom "Password Setup Instructions" email (informational)
|
||||
console.log('[IdentityService] Sending custom notification email');
|
||||
try {
|
||||
await supabase.functions.invoke('send-password-added-email', {
|
||||
@@ -251,33 +254,32 @@ export async function addPasswordToAccount(
|
||||
username: profile?.username,
|
||||
},
|
||||
});
|
||||
console.log('[IdentityService] Custom notification email sent');
|
||||
} catch (emailError) {
|
||||
console.error('[IdentityService] Custom email failed (non-blocking):', emailError);
|
||||
// Don't fail the whole operation
|
||||
}
|
||||
|
||||
// Step 5: Log the action
|
||||
await logIdentityChange(user!.id, 'password_added', {
|
||||
method: 'oauth_password_addition_with_signup_confirmation',
|
||||
confirmation_email_sent: true
|
||||
});
|
||||
|
||||
// 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
|
||||
// Step 5: Log the action
|
||||
await logIdentityChange(user!.id, 'password_setup_initiated', {
|
||||
method: 'reset_password_flow',
|
||||
reset_email_sent: true,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
// Return success - user needs to check email and click reset link
|
||||
return {
|
||||
success: true,
|
||||
needsRelogin: true,
|
||||
needsEmailConfirmation: true,
|
||||
email: userEmail
|
||||
};
|
||||
|
||||
} catch (error: any) {
|
||||
console.error('[IdentityService] Failed to add password:', error);
|
||||
console.error('[IdentityService] Failed to initiate password setup:', error);
|
||||
// Cleanup on error
|
||||
sessionStorage.removeItem('pending_password_setup');
|
||||
return {
|
||||
success: false,
|
||||
error: error.message || 'Failed to set password'
|
||||
error: error.message || 'Failed to initiate password setup'
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -312,23 +314,24 @@ export async function triggerOrphanedPasswordConfirmation(
|
||||
};
|
||||
}
|
||||
|
||||
console.log('[IdentityService] Resending signup confirmation email');
|
||||
console.log('[IdentityService] Resending password reset email for orphaned password');
|
||||
|
||||
// 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`
|
||||
// Send Supabase password reset email
|
||||
// The user's password is already set in auth.users, they just need to click
|
||||
// the reset link to create the email identity
|
||||
const { error: resetError } = await supabase.auth.resetPasswordForEmail(
|
||||
user.email,
|
||||
{
|
||||
redirectTo: `${window.location.origin}/auth/callback?action=confirm-password`
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
if (resendError) {
|
||||
console.error('[IdentityService] Failed to resend confirmation:', resendError);
|
||||
throw resendError;
|
||||
if (resetError) {
|
||||
console.error('[IdentityService] Failed to send password reset email:', resetError);
|
||||
throw resetError;
|
||||
}
|
||||
|
||||
console.log('[IdentityService] Confirmation email resent successfully');
|
||||
console.log('[IdentityService] Password reset email sent successfully');
|
||||
|
||||
// Optional: Get profile for custom notification
|
||||
const { data: profile } = await supabase
|
||||
@@ -354,7 +357,7 @@ export async function triggerOrphanedPasswordConfirmation(
|
||||
await logIdentityChange(user.id, 'orphaned_password_confirmation_triggered', {
|
||||
method: source || 'manual_button_click',
|
||||
timestamp: new Date().toISOString(),
|
||||
confirmation_email_sent: true
|
||||
reset_email_sent: true
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -363,10 +366,10 @@ export async function triggerOrphanedPasswordConfirmation(
|
||||
email: user.email
|
||||
};
|
||||
} catch (error: any) {
|
||||
console.error('[IdentityService] Failed to trigger confirmation:', error);
|
||||
console.error('[IdentityService] Failed to trigger password reset:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error.message || 'Failed to trigger email confirmation'
|
||||
error: error.message || 'Failed to send password reset email'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user