Refactor: Simplify Add Password flow

This commit is contained in:
gpt-engineer-app[bot]
2025-10-14 17:18:08 +00:00
parent 70f94b8a30
commit d6035bebac
2 changed files with 57 additions and 49 deletions

View File

@@ -11,7 +11,6 @@ import { TOTPSetup } from '@/components/auth/TOTPSetup';
import { GoogleIcon } from '@/components/icons/GoogleIcon';
import { DiscordIcon } from '@/components/icons/DiscordIcon';
import { PasswordUpdateDialog } from './PasswordUpdateDialog';
import { PasswordSetupDialog } from '@/components/auth/PasswordSetupDialog';
import {
getUserIdentities,
checkDisconnectSafety,
@@ -22,6 +21,8 @@ import {
} from '@/lib/identityService';
import type { UserIdentity, OAuthProvider } from '@/types/identity';
import { toast as sonnerToast } from '@/components/ui/sonner';
import { supabase } from '@/integrations/supabase/client';
export function SecurityTab() {
const { user } = useAuth();
const { toast } = useToast();
@@ -30,9 +31,7 @@ export function SecurityTab() {
const [identities, setIdentities] = useState<UserIdentity[]>([]);
const [loadingIdentities, setLoadingIdentities] = useState(true);
const [disconnectingProvider, setDisconnectingProvider] = useState<OAuthProvider | null>(null);
const [passwordSetupProvider, setPasswordSetupProvider] = useState<OAuthProvider | null>(null);
const [hasPassword, setHasPassword] = useState(false);
const [addPasswordMode, setAddPasswordMode] = useState<'standalone' | 'disconnect'>('standalone');
const [addingPassword, setAddingPassword] = useState(false);
const [showOrphanedPasswordOption, setShowOrphanedPasswordOption] = useState(false);
@@ -98,13 +97,12 @@ export function SecurityTab() {
if (!safetyCheck.canDisconnect) {
if (safetyCheck.reason === 'no_password_backup') {
// Show password setup dialog
setAddPasswordMode('disconnect');
setPasswordSetupProvider(provider);
// Trigger password reset flow first
await handleAddPassword();
toast({
title: "Password Required",
description: "Set a password before disconnecting your last social login to maintain account access.",
variant: "default"
title: "Password Required First",
description: "Check your email for a password reset link. Once you've set a password, you can disconnect your social login.",
duration: 10000
});
return;
}
@@ -139,42 +137,43 @@ export function SecurityTab() {
}
};
const handlePasswordSetupSuccess = (email?: string, needsConfirmation?: boolean) => {
if (email && needsConfirmation) {
// Password setup initiated via reset flow
const handleAddPassword = async () => {
setAddingPassword(true);
const { data: { user } } = await supabase.auth.getUser();
if (!user?.email) {
toast({
title: 'Check Your Email',
description: "Click the password reset link from Supabase to complete setup. You'll receive two emails: one with the reset link, and one with instructions from ThrillWiki.",
duration: 15000,
title: "No Email Found",
description: "Your account doesn't have an email address associated with it.",
variant: "destructive"
});
// Stay on settings page - user will complete setup via email link
} else if (email) {
// Fallback: direct password set (shouldn't happen with new flow)
setAddingPassword(false);
return;
}
// Trigger password reset email directly (no modal needed!)
const { error } = await supabase.auth.resetPasswordForEmail(
user.email,
{
redirectTo: `${window.location.origin}/auth/callback?action=password-setup-direct`
}
);
if (error) {
toast({
title: 'Password Set Successfully',
description: 'You can now sign in with your email and password.',
duration: 6000,
title: "Failed to Send Email",
description: error.message,
variant: "destructive"
});
} else {
// Normal password change flow (user already had email identity)
setAddingPassword(true);
loadIdentities().then(() => {
toast({
title: 'Password Updated',
description: 'Your password has been successfully updated.',
});
setPasswordSetupProvider(null);
}).finally(() => {
setAddingPassword(false);
sonnerToast.success("Password Reset Email Sent!", {
description: "Check your email for a password reset link from Supabase. Click the link to set your password. You'll also receive a notification email from ThrillWiki.",
duration: 15000,
});
}
};
const handleAddPassword = () => {
setAddPasswordMode('standalone');
setPasswordSetupProvider('google' as OAuthProvider);
setAddingPassword(false);
};
const handleSendConfirmationEmail = async () => {
@@ -224,16 +223,6 @@ export function SecurityTab() {
}}
/>
{passwordSetupProvider && (
<PasswordSetupDialog
open={!!passwordSetupProvider}
onOpenChange={(open) => !open && setPasswordSetupProvider(null)}
onSuccess={(email, needsConfirmation) => handlePasswordSetupSuccess(email, needsConfirmation)}
provider={passwordSetupProvider}
mode={addPasswordMode}
/>
)}
<div className="space-y-8">
{/* Password Section - Conditional based on auth method */}
<div className="space-y-4">
@@ -263,7 +252,7 @@ export function SecurityTab() {
{addingPassword ? (
<>
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
Adding Password...
Sending Email...
</>
) : (
'Add Password'