// 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 (
{title ?

{titleText}

: null} {enable ? ( <>

{enable.secret}

Add FreeSewing to your Authenticator App by scanning the QR code above. If you cannot scan the QR code, you can manually enter the secret below it. lease enter a code from your Authenticator App to confirm this action setCode(evt.target.value)} className="tw:daisy-input tw:w-64 tw:m-auto tw:text-4xl tw:daisy-input-bordered tw:daisy-input-lg tw:flex tw:flex-row tw:text-center tw:mb-8 tw:tracking-widest" type="text" inputMode="numeric" pattern="[0-9]{6}" placeholder="000000" /> ) : null} {disable ? (
Please enter your password to confirm this action
true} />
Please enter a code from your Authenticator App to confirm this action
setCode(evt.target.value)} className="tw:input tw:w-full tw:text-4xl tw:input-bordered tw:input-lg tw:flex tw:flex-row tw:text-center tw:mb-8 tw:tracking-widest" type="text" placeholder={'000000'} />
) : null} {scratchCodes ? ( <>

MFA Scratch Codes

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.

MFA Scratch Codes code + '\n').join('') } />
              {scratchCodes.map((code) => code + '\n')}
            
) : (
{account.mfaEnabled ? ( disable ? null : ( ) ) : enable ? null : (
Please consider enabling Two-Factor Authentication

We do not enforce a password policy, but we do recommend you enable Multi-Factor Authentication to keep your FreeSewing account safe.

)}
)}
) } const Bullet = ({ num, children }) => (
{num}
{children}
)