forked from abdlelahalwali8-a11y/dr-appointments-hub
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuse2FA.ts
More file actions
1 lines (1 loc) · 5.62 KB
/
Copy pathuse2FA.ts
File metadata and controls
1 lines (1 loc) · 5.62 KB
1
import { useState, useCallback } from 'react';\nimport { supabase } from '@/integrations/supabase/client';\nimport { toast } from '@/hooks/use-toast';\n\nexport interface TwoFactorAuthState {\n isEnabled: boolean;\n secret?: string;\n qrCode?: string;\n backupCodes?: string[];\n}\n\nexport const use2FA = () => {\n const [loading, setLoading] = useState(false);\n const [twoFAState, setTwoFAState] = useState<TwoFactorAuthState>({\n isEnabled: false,\n });\n\n // Generate 2FA secret and QR code\n const generateSecret = useCallback(async () => {\n try {\n setLoading(true);\n \n // In a real application, you would use a library like 'speakeasy' or 'qrcode'\n // For now, we'll simulate the generation\n const secret = Math.random().toString(36).substring(2, 15);\n const backupCodes = Array.from({ length: 10 }, () => \n Math.random().toString(36).substring(2, 10).toUpperCase()\n );\n\n setTwoFAState({\n isEnabled: false,\n secret,\n backupCodes,\n });\n\n return { secret, backupCodes };\n } catch (error) {\n console.error('Error generating 2FA secret:', error);\n toast({ \n title: \"خطأ\", \n description: \"فشل في إنشاء المصادقة الثنائية\", \n variant: \"destructive\" \n });\n return null;\n } finally {\n setLoading(false);\n }\n }, []);\n\n // Enable 2FA\n const enable2FA = useCallback(async (verificationCode: string) => {\n try {\n setLoading(true);\n \n const { data: { user } } = await supabase.auth.getUser();\n \n if (!user) throw new Error('User not authenticated');\n\n // Verify the code (in a real app, you'd validate against the secret)\n if (verificationCode.length !== 6 || isNaN(Number(verificationCode))) {\n throw new Error('Invalid verification code');\n }\n\n // Save 2FA settings to database\n const { error } = await supabase\n .from('user_2fa_settings')\n .upsert({\n user_id: user.id,\n is_enabled: true,\n secret: twoFAState.secret,\n backup_codes: twoFAState.backupCodes,\n created_at: new Date().toISOString(),\n });\n\n if (error) throw error;\n\n setTwoFAState(prev => ({ ...prev, isEnabled: true }));\n toast({ \n title: \"تم\", \n description: \"تم تفعيل المصادقة الثنائية بنجاح\" \n });\n\n return true;\n } catch (error: any) {\n console.error('Error enabling 2FA:', error);\n toast({ \n title: \"خطأ\", \n description: error.message || \"فشل في تفعيل المصادقة الثنائية\", \n variant: \"destructive\" \n });\n return false;\n } finally {\n setLoading(false);\n }\n }, [twoFAState]);\n\n // Disable 2FA\n const disable2FA = useCallback(async () => {\n try {\n setLoading(true);\n \n const { data: { user } } = await supabase.auth.getUser();\n \n if (!user) throw new Error('User not authenticated');\n\n // Delete 2FA settings from database\n const { error } = await supabase\n .from('user_2fa_settings')\n .update({ is_enabled: false })\n .eq('user_id', user.id);\n\n if (error) throw error;\n\n setTwoFAState({\n isEnabled: false,\n secret: undefined,\n backupCodes: undefined,\n });\n\n toast({ \n title: \"تم\", \n description: \"تم تعطيل المصادقة الثنائية\" \n });\n\n return true;\n } catch (error: any) {\n console.error('Error disabling 2FA:', error);\n toast({ \n title: \"خطأ\", \n description: error.message || \"فشل في تعطيل المصادقة الثنائية\", \n variant: \"destructive\" \n });\n return false;\n } finally {\n setLoading(false);\n }\n }, []);\n\n // Verify 2FA code during login\n const verify2FACode = useCallback(async (code: string) => {\n try {\n if (code.length !== 6 || isNaN(Number(code))) {\n throw new Error('Invalid code format');\n }\n\n // In a real app, validate the code against the secret\n return true;\n } catch (error: any) {\n console.error('Error verifying 2FA code:', error);\n return false;\n }\n }, []);\n\n // Use backup code\n const useBackupCode = useCallback(async (backupCode: string) => {\n try {\n setLoading(true);\n \n const { data: { user } } = await supabase.auth.getUser();\n \n if (!user) throw new Error('User not authenticated');\n\n // Check if backup code is valid and hasn't been used\n const { data: twoFAData } = await supabase\n .from('user_2fa_settings')\n .select('backup_codes')\n .eq('user_id', user.id)\n .single();\n\n if (!twoFAData?.backup_codes?.includes(backupCode)) {\n throw new Error('Invalid backup code');\n }\n\n // Remove used backup code\n const updatedCodes = twoFAData.backup_codes.filter((code: string) => code !== backupCode);\n \n const { error } = await supabase\n .from('user_2fa_settings')\n .update({ backup_codes: updatedCodes })\n .eq('user_id', user.id);\n\n if (error) throw error;\n\n return true;\n } catch (error: any) {\n console.error('Error using backup code:', error);\n return false;\n } finally {\n setLoading(false);\n }\n }, []);\n\n return {\n twoFAState,\n loading,\n generateSecret,\n enable2FA,\n disable2FA,\n verify2FACode,\n useBackupCode,\n };\n};\n\nexport default use2FA;\n