mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 11:31:11 -05:00
Refactor: Implement email confirmation for password auth
This commit is contained in:
@@ -18,7 +18,7 @@ import type { OAuthProvider } from '@/types/identity';
|
|||||||
interface PasswordSetupDialogProps {
|
interface PasswordSetupDialogProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onOpenChange: (open: boolean) => void;
|
onOpenChange: (open: boolean) => void;
|
||||||
onSuccess: (email?: string) => void;
|
onSuccess: (email?: string, needsConfirmation?: boolean) => void;
|
||||||
provider?: OAuthProvider;
|
provider?: OAuthProvider;
|
||||||
mode?: 'standalone' | 'disconnect';
|
mode?: 'standalone' | 'disconnect';
|
||||||
}
|
}
|
||||||
@@ -61,8 +61,8 @@ export function PasswordSetupDialog({
|
|||||||
setConfirmPassword('');
|
setConfirmPassword('');
|
||||||
|
|
||||||
if (result.needsRelogin && result.email) {
|
if (result.needsRelogin && result.email) {
|
||||||
// Pass email to parent for redirect handling
|
// Pass email and confirmation flag to parent for redirect handling
|
||||||
onSuccess(result.email);
|
onSuccess(result.email, result.needsEmailConfirmation);
|
||||||
} else {
|
} else {
|
||||||
onSuccess();
|
onSuccess();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,14 +122,22 @@ export function SecurityTab() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePasswordSetupSuccess = async (email?: string) => {
|
const handlePasswordSetupSuccess = (email?: string, needsConfirmation?: boolean) => {
|
||||||
if (email) {
|
if (email) {
|
||||||
// Password was set, user was logged out, needs to sign in with email/password
|
// Password was set, user was logged out, needs to confirm email
|
||||||
toast({
|
if (needsConfirmation) {
|
||||||
title: 'Password Set Successfully',
|
toast({
|
||||||
description: 'Please sign in with your email and password to complete setup.',
|
title: 'Check Your Email',
|
||||||
duration: 6000,
|
description: 'A confirmation link has been sent to your email. Click it to activate password authentication, then sign in.',
|
||||||
});
|
duration: 10000,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
toast({
|
||||||
|
title: 'Password Set Successfully',
|
||||||
|
description: 'Please sign in with your email and password to complete setup.',
|
||||||
|
duration: 6000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Redirect to auth page with email pre-filled
|
// Redirect to auth page with email pre-filled
|
||||||
navigate(`/auth?email=${encodeURIComponent(email)}&message=complete-password-setup`);
|
navigate(`/auth?email=${encodeURIComponent(email)}&message=complete-password-setup`);
|
||||||
@@ -137,16 +145,15 @@ export function SecurityTab() {
|
|||||||
// Normal password change flow (user already had email identity)
|
// Normal password change flow (user already had email identity)
|
||||||
setAddingPassword(true);
|
setAddingPassword(true);
|
||||||
|
|
||||||
try {
|
loadIdentities().then(() => {
|
||||||
await loadIdentities();
|
|
||||||
toast({
|
toast({
|
||||||
title: 'Password Updated',
|
title: 'Password Updated',
|
||||||
description: 'Your password has been successfully updated.',
|
description: 'Your password has been successfully updated.',
|
||||||
});
|
});
|
||||||
setPasswordSetupProvider(null);
|
setPasswordSetupProvider(null);
|
||||||
} finally {
|
}).finally(() => {
|
||||||
setAddingPassword(false);
|
setAddingPassword(false);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -185,7 +192,7 @@ export function SecurityTab() {
|
|||||||
<PasswordSetupDialog
|
<PasswordSetupDialog
|
||||||
open={!!passwordSetupProvider}
|
open={!!passwordSetupProvider}
|
||||||
onOpenChange={(open) => !open && setPasswordSetupProvider(null)}
|
onOpenChange={(open) => !open && setPasswordSetupProvider(null)}
|
||||||
onSuccess={handlePasswordSetupSuccess}
|
onSuccess={(email, needsConfirmation) => handlePasswordSetupSuccess(email, needsConfirmation)}
|
||||||
provider={passwordSetupProvider}
|
provider={passwordSetupProvider}
|
||||||
mode={addPasswordMode}
|
mode={addPasswordMode}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -213,9 +213,13 @@ export async function addPasswordToAccount(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 1: Update password
|
// Step 1: Update password AND trigger email confirmation
|
||||||
console.log('[IdentityService] Setting password for user');
|
// Re-confirming the email will trigger Supabase to create the email identity
|
||||||
const { error: updateError } = await supabase.auth.updateUser({ password });
|
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
|
||||||
|
});
|
||||||
if (updateError) throw updateError;
|
if (updateError) throw updateError;
|
||||||
|
|
||||||
// Step 2: Get user profile for email personalization
|
// Step 2: Get user profile for email personalization
|
||||||
@@ -248,17 +252,18 @@ export async function addPasswordToAccount(
|
|||||||
|
|
||||||
// Step 4: Log the password addition
|
// Step 4: Log the password addition
|
||||||
await logIdentityChange(user!.id, 'password_added', {
|
await logIdentityChange(user!.id, 'password_added', {
|
||||||
method: 'oauth_with_relogin_required'
|
method: 'oauth_with_email_confirmation_required'
|
||||||
});
|
});
|
||||||
|
|
||||||
// Step 5: Sign the user out so they can sign back in with email/password
|
// Step 5: Sign the user out so they can confirm email
|
||||||
console.log('[IdentityService] Signing user out to force re-login');
|
console.log('[IdentityService] Signing user out to complete email confirmation');
|
||||||
await supabase.auth.signOut();
|
await supabase.auth.signOut();
|
||||||
|
|
||||||
// Return success with relogin flag
|
// Return success with relogin and email confirmation flags
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
needsRelogin: true,
|
needsRelogin: true,
|
||||||
|
needsEmailConfirmation: true,
|
||||||
email: userEmail
|
email: userEmail
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -390,7 +390,7 @@ export default function Auth() {
|
|||||||
<Alert className="mb-4">
|
<Alert className="mb-4">
|
||||||
<AlertCircle className="h-4 w-4" />
|
<AlertCircle className="h-4 w-4" />
|
||||||
<AlertDescription>
|
<AlertDescription>
|
||||||
Your password has been set. Please sign in with your email and password to complete the setup.
|
<strong>Password setup in progress.</strong> Check your email for a confirmation link. After confirming your email, sign in below with your email and password.
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -31,5 +31,6 @@ export interface IdentityOperationResult {
|
|||||||
success: boolean;
|
success: boolean;
|
||||||
error?: string;
|
error?: string;
|
||||||
needsRelogin?: boolean;
|
needsRelogin?: boolean;
|
||||||
|
needsEmailConfirmation?: boolean;
|
||||||
email?: string;
|
email?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,12 +76,22 @@ serve(async (req) => {
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3>🔐 Complete Your Setup</h3>
|
<h3>🔐 Complete Your Setup</h3>
|
||||||
<p>To activate your password authentication, please sign in with your new credentials:</p>
|
<p><strong>Important:</strong> To complete your password setup, you need to confirm your email address.</p>
|
||||||
|
|
||||||
<a href="${siteUrl}/auth?email=${encodeURIComponent(email)}" class="button">
|
<ol style="padding-left: 20px; margin: 15px 0; line-height: 1.8;">
|
||||||
Sign In Now
|
<li style="margin-bottom: 8px;">Check your inbox for a <strong>confirmation email</strong> from ThrillWiki</li>
|
||||||
|
<li style="margin-bottom: 8px;">Click the confirmation link in that email</li>
|
||||||
|
<li style="margin-bottom: 8px;">Return to the sign-in page and log in with your email and password</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<a href="${siteUrl}/auth?email=${encodeURIComponent(email)}&message=complete-password-setup" class="button">
|
||||||
|
Go to Sign In Page
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
<p style="margin-top: 15px; font-size: 14px; color: #666;">
|
||||||
|
<strong>Note:</strong> You must confirm your email before you can sign in with your password.
|
||||||
|
</p>
|
||||||
|
|
||||||
<div class="security-notice">
|
<div class="security-notice">
|
||||||
<strong>⚠️ Security Notice</strong><br>
|
<strong>⚠️ Security Notice</strong><br>
|
||||||
If you didn't add a password to your account, please contact our support team immediately at <strong>support@thrillwiki.com</strong>
|
If you didn't add a password to your account, please contact our support team immediately at <strong>support@thrillwiki.com</strong>
|
||||||
|
|||||||
Reference in New Issue
Block a user