// Dependencies import { welcomeSteps } from './shared.mjs' import { horFlexClasses } from '@freesewing/utils' // Context import { LoadingStatusContext } from '@freesewing/react/context/LoadingStatus' // Hooks import React, { useState, useContext } from 'react' import { useAccount } from '@freesewing/react/hooks/useAccount' import { useBackend } from '@freesewing/react/hooks/useBackend' // Components import { Link as WebLink } from '@freesewing/react/components/Link' import { NoIcon, LockIcon } from '@freesewing/react/components/Icon' import { PasswordInput } from '@freesewing/react/components/Input' import { Popout } from '@freesewing/react/components/Popout' import { NumberCircle } from '@freesewing/react/components/Number' import { CopyToClipboardButton } from '@freesewing/react/components/CopyToClipboardButton' /* * Component for the account/security/password page * * @params {object} props - All React props * @params {bool} props.welcome - Set to true to use this component on the welcome page */ export const Mfa = ({ welcome = false, title = true }) => { // Hooks const backend = useBackend() const { account, setAccount } = useAccount() const { setLoadingStatus } = useContext(LoadingStatusContext) // State const [enable, setEnable] = useState(false) const [disable, setDisable] = useState(false) const [code, setCode] = useState('') const [password, setPassword] = useState('') const [scratchCodes, setScratchCodes] = useState(false) // Helper method to enable MFA const enableMfa = async () => { setLoadingStatus([true, 'Contacting backend']) const [status, body] = await backend.enableMfa() if (status === 200) { setEnable(body.mfa) setLoadingStatus([true, 'Settings saved', true, true]) } else setLoadingStatus([true, 'An error occured. Please report this.', true, false]) } // Helper method to disable MFA const disableMfa = async () => { setLoadingStatus([true, 'Contacting backend']) const [status, body] = await backend.disableMfa({ mfa: false, password, token: code, }) if (status === 200) { if (body.result === 'success') { setAccount(body.account) setLoadingStatus([true, 'Settings saved', true, true]) } else setLoadingStatus([true, 'An error occured. Please report this.', true, false]) setDisable(false) setEnable(false) setCode('') setPassword('') } } // Helper method to confirm MFA const confirmMfa = async () => { setLoadingStatus([true, 'Contacting backend']) const [status, body] = await backend.confirmMfa({ mfa: true, secret: enable.secret, token: code, }) if (status === 200 && body.result === 'success') { setAccount(body.account) setScratchCodes(body.scratchCodes) setLoadingStatus([true, 'Settings saved', true, true]) } else setLoadingStatus([true, 'An error occured, please repor this', true, false]) setEnable(false) setCode('') } // Figure out what title to use let titleText = `Mult-Factor Authentication is ${account.mfaEnabled ? 'enabled' : 'disabled'}` if (enable) titleText = 'Set up Multi-Factor Authentication' return (
{enable.secret}
You can use any of these scratch codes as a one-time MFA code when you do not have access to your code-generating app (for example, when you have lost your phone.
You can use each of these codes only once. Write them down, because this is the only time you will get to see them.
{scratchCodes.map((code) => code + '\n')}
We do not enforce a password policy, but we do recommend you enable Multi-Factor Authentication to keep your FreeSewing account safe.