()
| 23 | "rounded-2xl border border-white/70 bg-white/72 px-8 py-8 shadow-[0_4px_14px_rgba(15,23,42,0.045),inset_0_1px_0_rgba(255,255,255,0.86),inset_0_-8px_18px_rgba(255,255,255,0.12)] backdrop-blur-2xl"; |
| 24 | |
| 25 | export default function VerifyMfaPage() { |
| 26 | const router = useRouter(); |
| 27 | const searchParams = useSearchParams(); |
| 28 | const { user, authLoading, signOut } = useAuth(); |
| 29 | const [factors, setFactors] = useState<MfaFactor[]>([]); |
| 30 | const [selectedFactorId, setSelectedFactorId] = useState(""); |
| 31 | const [code, setCode] = useState(""); |
| 32 | const [loading, setLoading] = useState(true); |
| 33 | const [verifying, setVerifying] = useState(false); |
| 34 | const [error, setError] = useState<string | null>(null); |
| 35 | |
| 36 | const nextPath = safeNextPath(searchParams.get("next")); |
| 37 | const canVerify = |
| 38 | !loading && !verifying && !!selectedFactorId && code.trim().length === 6; |
| 39 | |
| 40 | useEffect(() => { |
| 41 | if (authLoading) return; |
| 42 | if (!user) { |
| 43 | router.replace("/login"); |
| 44 | return; |
| 45 | } |
| 46 | |
| 47 | let cancelled = false; |
| 48 | |
| 49 | async function loadMfaState() { |
| 50 | setLoading(true); |
| 51 | setError(null); |
| 52 | setCode(""); |
| 53 | try { |
| 54 | const required = await needsMfaVerification(); |
| 55 | if (cancelled) return; |
| 56 | if (!required) { |
| 57 | router.replace(nextPath); |
| 58 | return; |
| 59 | } |
| 60 | |
| 61 | const { data, error: factorError } = |
| 62 | await supabase.auth.mfa.listFactors(); |
| 63 | if (cancelled) return; |
| 64 | if (factorError) throw factorError; |
| 65 | |
| 66 | const verified = (data.totp ?? []) as MfaFactor[]; |
| 67 | setFactors(verified); |
| 68 | setSelectedFactorId(verified[0]?.id ?? ""); |
| 69 | if (verified.length === 0) { |
| 70 | setError( |
| 71 | "No verified authenticator factor is available for this account.", |
| 72 | ); |
| 73 | } |
| 74 | } catch (loadError) { |
| 75 | if (cancelled) return; |
| 76 | setError( |
| 77 | loadError instanceof Error |
| 78 | ? loadError.message |
| 79 | : "Unable to load authenticator verification.", |
| 80 | ); |
| 81 | } finally { |
| 82 | if (!cancelled) setLoading(false); |
nothing calls this directly
no test coverage detected
searching dependent graphs…