soapbox/app/soapbox/features/auth-login/components/otp-auth-form.tsx

89 wiersze
3.0 KiB
TypeScript

import React, { useState } from 'react';
import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
import { Redirect } from 'react-router-dom';
import { otpVerify, verifyCredentials, switchAccount } from 'soapbox/actions/auth';
import { Button, Form, FormActions, FormGroup, Input } from 'soapbox/components/ui';
import { useAppDispatch } from 'soapbox/hooks';
const messages = defineMessages({
otpCodeHint: { id: 'login.fields.otp_code_hint', defaultMessage: 'Enter the two-factor code generated by your phone app or use one of your recovery codes' },
otpCodeLabel: { id: 'login.fields.otp_code_label', defaultMessage: 'Two-factor code:' },
otpLoginFail: { id: 'login.otp_log_in.fail', defaultMessage: 'Invalid code, please try again.' },
});
interface IOtpAuthForm {
mfa_token: string,
}
const OtpAuthForm: React.FC<IOtpAuthForm> = ({ mfa_token }) => {
const dispatch = useAppDispatch();
const intl = useIntl();
const [isLoading, setIsLoading] = useState(false);
const [shouldRedirect, setShouldRedirect] = useState(false);
const [codeError, setCodeError] = useState<string | boolean>('');
const getFormData = (form: any) => Object.fromEntries(
Array.from(form).map((i: any) => [i.name, i.value]),
);
const handleSubmit = (event: React.FormEvent<Element>) => {
const { code } = getFormData(event.target);
dispatch(otpVerify(code, mfa_token)).then(({ access_token }) => {
setCodeError(false);
return dispatch(verifyCredentials(access_token as string));
}).then((account: Record<string, any>) => {
setShouldRedirect(true);
return dispatch(switchAccount(account.id));
}).catch(() => {
setIsLoading(false);
setCodeError(true);
});
setIsLoading(true);
event.preventDefault();
};
if (shouldRedirect) return <Redirect to='/' />;
return (
<div>
<div className='pb-4 sm:pb-10 mb-4 border-b border-gray-200 dark:border-gray-600 border-solid -mx-4 sm:-mx-10'>
<h1 className='text-center font-bold text-2xl'>
<FormattedMessage id='login.otp_log_in' defaultMessage='OTP Login' />
</h1>
</div>
<div className='sm:pt-10 sm:w-2/3 md:w-1/2 mx-auto'>
<Form onSubmit={handleSubmit}>
<FormGroup
labelText={intl.formatMessage(messages.otpCodeLabel)}
hintText={intl.formatMessage(messages.otpCodeHint)}
errors={codeError ? [intl.formatMessage(messages.otpLoginFail)] : []}
>
<Input
name='code'
type='text'
autoComplete='off'
autoFocus
required
/>
</FormGroup>
<FormActions>
<Button
theme='primary'
type='submit'
disabled={isLoading}
>
<FormattedMessage id='login.sign_in' defaultMessage='Sign in' />
</Button>
</FormActions>
</Form>
</div>
</div>
);
};
export default OtpAuthForm;