kopia lustrzana https://gitlab.com/soapbox-pub/soapbox
89 wiersze
3.0 KiB
TypeScript
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;
|