"use client" import { zodResolver } from "@hookform/resolvers/zod" import { Loader2 } from "lucide-react" import { type ComponentProps, useContext, useState } from "react" import { useForm } from "react-hook-form" import * as z from "zod" import { AuthUIContext } from "../../../lib/auth-ui-provider" import { cn, getLocalizedError } from "../../../lib/utils" import { PasswordInput } from "../../password-input" import { Button } from "../../ui/button" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "../../ui/dialog" import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "../../ui/form" import type { SettingsCardClassNames } from "../shared/settings-card" import { BackupCodesDialog } from "./backup-codes-dialog" interface TwoFactorPasswordDialogProps extends ComponentProps { classNames?: SettingsCardClassNames isTwoFactorEnabled: boolean } export function TwoFactorPasswordDialog({ classNames, onOpenChange, isTwoFactorEnabled, ...props }: TwoFactorPasswordDialogProps) { const { localization, authClient, basePath, viewPaths, navigate, toast, twoFactor, localizeErrors } = useContext(AuthUIContext) const [showBackupCodesDialog, setShowBackupCodesDialog] = useState(false) const [backupCodes, setBackupCodes] = useState([]) const [totpURI, setTotpURI] = useState(null) const formSchema = z.object({ password: z.string().min(1, { message: localization.PASSWORD_REQUIRED }) }) const form = useForm({ resolver: zodResolver(formSchema), defaultValues: { password: "" } }) const { isSubmitting } = form.formState async function enableTwoFactor({ password }: z.infer) { try { const response = await authClient.twoFactor.enable({ password, fetchOptions: { throw: true } }) onOpenChange?.(false) setBackupCodes(response.backupCodes) if (twoFactor?.includes("totp")) { setTotpURI(response.totpURI) } setTimeout(() => { setShowBackupCodesDialog(true) }, 250) } catch (error) { toast({ variant: "error", message: getLocalizedError({ error, localization, localizeErrors }) }) } } async function disableTwoFactor({ password }: z.infer) { try { await authClient.twoFactor.disable({ password, fetchOptions: { throw: true } }) toast({ variant: "success", message: localization.TWO_FACTOR_DISABLED }) onOpenChange?.(false) } catch (error) { toast({ variant: "error", message: getLocalizedError({ error, localization, localizeErrors }) }) } } return ( <> {localization.TWO_FACTOR} {isTwoFactorEnabled ? localization.TWO_FACTOR_DISABLE_INSTRUCTIONS : localization.TWO_FACTOR_ENABLE_INSTRUCTIONS}
( {localization.PASSWORD} )} />
{ setShowBackupCodesDialog(open) if (!open) { const url = `${basePath}/${viewPaths.TWO_FACTOR}` navigate( twoFactor?.includes("totp") && totpURI ? `${url}?totpURI=${totpURI}` : url ) } }} backupCodes={backupCodes} /> ) }