misc_pterodactyl-panel/resources/scripts/components/auth/LoginCheckpointContainer.tsx

115 lines
4.1 KiB
TypeScript
Raw Normal View History

2022-11-25 20:25:03 +00:00
import type { ActionCreator } from 'easy-peasy';
2020-04-25 20:01:16 +00:00
import { useFormikContext, withFormik } from 'formik';
2022-11-25 20:25:03 +00:00
import { useState } from 'react';
import type { Location, RouteProps } from 'react-router-dom';
import { Link, useLocation, useNavigate } from 'react-router-dom';
import tw from 'twin.macro';
2022-11-25 20:25:03 +00:00
import loginCheckpoint from '@/api/auth/loginCheckpoint';
import LoginFormContainer from '@/components/auth/LoginFormContainer';
import Button from '@/components/elements/Button';
2022-11-25 20:25:03 +00:00
import Field from '@/components/elements/Field';
import useFlash from '@/plugins/useFlash';
import type { FlashStore } from '@/state/flashes';
2020-04-25 20:01:16 +00:00
interface Values {
code: string;
recoveryCode: '';
2020-04-25 20:01:16 +00:00
}
2022-11-25 20:25:03 +00:00
type OwnProps = RouteProps;
2020-04-25 20:01:16 +00:00
type Props = OwnProps & {
clearAndAddHttpError: ActionCreator<FlashStore['clearAndAddHttpError']['payload']>;
};
2022-11-25 20:25:03 +00:00
function LoginCheckpointContainer() {
const { isSubmitting, setFieldValue } = useFormikContext<Values>();
const [isMissingDevice, setIsMissingDevice] = useState(false);
2019-06-17 01:07:57 +00:00
2020-04-25 20:01:16 +00:00
return (
<LoginFormContainer title={'Device Checkpoint'} css={tw`w-full flex`}>
<div css={tw`mt-6`}>
2020-04-25 20:01:16 +00:00
<Field
light
name={isMissingDevice ? 'recoveryCode' : 'code'}
title={isMissingDevice ? 'Recovery Code' : 'Authentication Code'}
description={
isMissingDevice
? 'Enter one of the recovery codes generated when you setup 2-Factor authentication on this account in order to continue.'
: 'Enter the two-factor token generated by your device.'
}
2020-07-11 19:07:54 +00:00
type={'text'}
autoComplete={'one-time-code'}
autoFocus
2020-04-25 20:01:16 +00:00
/>
</div>
<div css={tw`mt-6`}>
<Button size={'xlarge'} type={'submit'} disabled={isSubmitting} isLoading={isSubmitting}>
Continue
</Button>
2020-04-25 20:01:16 +00:00
</div>
<div css={tw`mt-6 text-center`}>
<span
onClick={() => {
setFieldValue('code', '');
setFieldValue('recoveryCode', '');
2022-11-25 20:25:03 +00:00
setIsMissingDevice(s => !s);
}}
css={tw`cursor-pointer text-xs text-neutral-500 tracking-wide uppercase no-underline hover:text-neutral-700`}
>
{!isMissingDevice ? "I've Lost My Device" : 'I Have My Device'}
</span>
</div>
<div css={tw`mt-6 text-center`}>
2020-04-25 20:01:16 +00:00
<Link
to={'/auth/login'}
css={tw`text-xs text-neutral-500 tracking-wide uppercase no-underline hover:text-neutral-700`}
2020-04-25 20:01:16 +00:00
>
Return to Login
</Link>
</div>
</LoginFormContainer>
);
2022-11-25 20:25:03 +00:00
}
2019-06-22 20:33:11 +00:00
2022-11-25 20:25:03 +00:00
const EnhancedForm = withFormik<Props & { location: Location }, Values>({
handleSubmit: ({ code, recoveryCode }, { setSubmitting, props: { clearAndAddHttpError, location } }) => {
loginCheckpoint(location.state?.token || '', code, recoveryCode)
2022-11-25 20:25:03 +00:00
.then(response => {
if (response.complete) {
2022-06-26 19:30:05 +00:00
// @ts-expect-error this is valid
window.location = response.intended || '/';
2020-04-25 20:01:16 +00:00
return;
}
2020-04-25 20:03:37 +00:00
2020-04-25 20:01:16 +00:00
setSubmitting(false);
})
2022-11-25 20:25:03 +00:00
.catch(error => {
console.error(error);
2020-04-25 20:01:16 +00:00
setSubmitting(false);
2020-10-23 04:33:06 +00:00
clearAndAddHttpError({ error });
});
2020-04-25 20:01:16 +00:00
},
2019-06-17 01:07:57 +00:00
2020-04-25 20:01:16 +00:00
mapPropsToValues: () => ({
code: '',
recoveryCode: '',
2020-04-25 20:01:16 +00:00
}),
})(LoginCheckpointContainer);
2022-11-25 20:25:03 +00:00
export default ({ ...props }: OwnProps) => {
const { clearAndAddHttpError } = useFlash();
2020-04-25 20:01:16 +00:00
2022-11-25 20:25:03 +00:00
const location = useLocation();
const navigate = useNavigate();
2020-04-25 20:01:16 +00:00
if (!location.state?.token) {
2022-11-25 20:25:03 +00:00
navigate('/auth/login');
2020-04-25 20:01:16 +00:00
return null;
}
2022-11-25 20:25:03 +00:00
return <EnhancedForm clearAndAddHttpError={clearAndAddHttpError} location={location} {...props} />;
2019-06-17 01:07:57 +00:00
};