import { CodeBlock } from "@/accounts/components/CodeBlock"; import { Verify2FACodeForm } from "@/accounts/components/Verify2FACodeForm"; import { appHomeRoute } from "@/accounts/services/redirect"; import type { TwoFactorSecret } from "@/accounts/services/user"; import { enableTwoFactor, setupTwoFactor } from "@/accounts/services/user"; import { CenteredFill } from "@/base/components/containers"; import { LinkButton } from "@/base/components/LinkButton"; import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; import { encryptWithRecoveryKey } from "@ente/shared/crypto/helpers"; import { getData, LS_KEYS, setLSUser } from "@ente/shared/storage/localStorage"; import { Paper, Stack, styled, Typography } from "@mui/material"; import { t } from "i18next"; import { useRouter } from "next/router"; import React, { useEffect, useState } from "react"; const Page: React.FC = () => { const [twoFactorSecret, setTwoFactorSecret] = useState< TwoFactorSecret | undefined >(); const router = useRouter(); useEffect(() => { void setupTwoFactor().then(setTwoFactorSecret); }, []); const handleSubmit = async (otp: string) => { const { encryptedData: encryptedTwoFactorSecret, nonce: twoFactorSecretDecryptionNonce, } = await encryptWithRecoveryKey(twoFactorSecret!.secretCode); await enableTwoFactor({ code: otp, encryptedTwoFactorSecret, twoFactorSecretDecryptionNonce, }); await setLSUser({ ...getData(LS_KEYS.USER), isTwoFactorEnabled: true, }); await router.push(appHomeRoute); }; return ( {t("two_factor")} {t("go_back")} ); }; export default Page; const ContentsPaper = styled(Paper)(({ theme }) => ({ marginBlock: theme.spacing(2), padding: theme.spacing(4, 2), // Wide enough to fit the QR code secret in one line under default settings. width: "min(440px, 95vw)", display: "flex", flexDirection: "column", gap: theme.spacing(4), })); interface InstructionsProps { twoFactorSecret: TwoFactorSecret | undefined; } const Instructions: React.FC = ({ twoFactorSecret }) => { const [setupMode, setSetupMode] = useState<"qr" | "manual">("qr"); return ( {setupMode == "qr" ? ( setSetupMode("manual")} /> ) : ( setSetupMode("qr")} /> )} ); }; interface SetupManualModeProps { twoFactorSecret: TwoFactorSecret | undefined; onChangeMode: () => void; } const SetupManualMode: React.FC = ({ twoFactorSecret, onChangeMode, }) => ( <> {t("two_factor_manual_entry_message")} {t("scan_qr_title")} ); interface SetupQRModeProps { twoFactorSecret?: TwoFactorSecret; onChangeMode: () => void; } const SetupQRMode: React.FC = ({ twoFactorSecret, onChangeMode, }) => ( <> {t("two_factor_qr_help")} {!twoFactorSecret ? ( ) : ( )} {t("two_factor_manual_entry_title")} ); const QRCode = styled("img")(` width: 200px; height: 200px; `); const LoadingQRCode = styled(Stack)( ({ theme }) => ` width: 200px; height: 200px; border: 1px solid ${theme.vars.palette.stroke.muted}; align-items: center; justify-content: center; `, );