mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 14:50:32 +00:00
feat: locked due to failed logins.
This commit is contained in:
@@ -25,24 +25,26 @@ import { compose } from 'utils';
|
|||||||
const ERRORS_TYPES = {
|
const ERRORS_TYPES = {
|
||||||
INVALID_DETAILS: 'INVALID_DETAILS',
|
INVALID_DETAILS: 'INVALID_DETAILS',
|
||||||
USER_INACTIVE: 'USER_INACTIVE',
|
USER_INACTIVE: 'USER_INACTIVE',
|
||||||
|
LOGIN_TO_MANY_ATTEMPTS: 'LOGIN_TO_MANY_ATTEMPTS',
|
||||||
};
|
};
|
||||||
function Login({
|
function Login({ requestLogin }) {
|
||||||
requestLogin,
|
|
||||||
}) {
|
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const [shown, setShown] = useState(false);
|
const [shown, setShown] = useState(false);
|
||||||
const passwordRevealer = () => { setShown(!shown); };
|
const passwordRevealer = () => {
|
||||||
|
setShown(!shown);
|
||||||
|
};
|
||||||
|
|
||||||
// Validation schema.
|
// Validation schema.
|
||||||
const loginValidationSchema = Yup.object().shape({
|
const loginValidationSchema = Yup.object().shape({
|
||||||
crediential: Yup.string()
|
crediential: Yup.string()
|
||||||
.required()
|
.required()
|
||||||
.email().label(formatMessage({id:'email'})),
|
.email()
|
||||||
|
.label(formatMessage({ id: 'email' })),
|
||||||
password: Yup.string()
|
password: Yup.string()
|
||||||
.required()
|
.required()
|
||||||
.min(4).label(formatMessage({id:'password'}))
|
.min(4)
|
||||||
|
.label(formatMessage({ id: 'password' })),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Formik validation schema and submit handler.
|
// Formik validation schema and submit handler.
|
||||||
@@ -62,58 +64,97 @@ function Login({
|
|||||||
requestLogin({
|
requestLogin({
|
||||||
crediential: values.crediential,
|
crediential: values.crediential,
|
||||||
password: values.password,
|
password: values.password,
|
||||||
}).then(() => {
|
})
|
||||||
setSubmitting(false);
|
.then(() => {
|
||||||
}).catch((errors) => {
|
setSubmitting(false);
|
||||||
const toastBuilders = [];
|
})
|
||||||
if (errors.find((e) => e.type === ERRORS_TYPES.INVALID_DETAILS)) {
|
.catch((errors) => {
|
||||||
toastBuilders.push({
|
const toastBuilders = [];
|
||||||
message: formatMessage({ id: 'email_and_password_entered_did_not_match' }),
|
if (errors.find((e) => e.type === ERRORS_TYPES.INVALID_DETAILS)) {
|
||||||
intent: Intent.DANGER,
|
toastBuilders.push({
|
||||||
|
message: formatMessage({
|
||||||
|
id: 'email_and_password_entered_did_not_match',
|
||||||
|
}),
|
||||||
|
intent: Intent.DANGER,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (errors.find((e) => e.type === ERRORS_TYPES.USER_INACTIVE)) {
|
||||||
|
toastBuilders.push({
|
||||||
|
message: formatMessage({
|
||||||
|
id: 'the_user_has_been_suspended_from_admin',
|
||||||
|
}),
|
||||||
|
intent: Intent.DANGER,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
errors.find((e) => e.type === ERRORS_TYPES.LOGIN_TO_MANY_ATTEMPTS)
|
||||||
|
) {
|
||||||
|
toastBuilders.push({
|
||||||
|
message: formatMessage({
|
||||||
|
id: 'your_account_has_been_locked',
|
||||||
|
}),
|
||||||
|
intent: Intent.DANGER,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
toastBuilders.forEach((builder) => {
|
||||||
|
Toaster.show(builder);
|
||||||
});
|
});
|
||||||
}
|
setSubmitting(false);
|
||||||
if (errors.find((e) => e.type === ERRORS_TYPES.USER_INACTIVE)) {
|
|
||||||
toastBuilders.push({
|
|
||||||
message: formatMessage({ id: 'the_user_has_been_suspended_from_admin' }),
|
|
||||||
intent: Intent.DANGER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
toastBuilders.forEach(builder => {
|
|
||||||
Toaster.show(builder);
|
|
||||||
});
|
});
|
||||||
setSubmitting(false);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const passwordRevealerTmp = useMemo(() => (
|
const passwordRevealerTmp = useMemo(
|
||||||
<span class="password-revealer" onClick={() => passwordRevealer()}>
|
() => (
|
||||||
<If condition={shown}>
|
<span class="password-revealer" onClick={() => passwordRevealer()}>
|
||||||
<><Icon icon='eye-slash' /> <span class="text"><T id={'hide'} /></span></>
|
<If condition={shown}>
|
||||||
</If>
|
<>
|
||||||
<If condition={!shown}>
|
<Icon icon="eye-slash" />{' '}
|
||||||
<><Icon icon='eye' /> <span class="text"><T id={'show'} /></span></>
|
<span class="text">
|
||||||
</If>
|
<T id={'hide'} />
|
||||||
</span>), [shown, passwordRevealer]);
|
</span>
|
||||||
|
</>
|
||||||
|
</If>
|
||||||
|
<If condition={!shown}>
|
||||||
|
<>
|
||||||
|
<Icon icon="eye" />{' '}
|
||||||
|
<span class="text">
|
||||||
|
<T id={'show'} />
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
</If>
|
||||||
|
</span>
|
||||||
|
),
|
||||||
|
[shown, passwordRevealer],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AuthInsider>
|
<AuthInsider>
|
||||||
<div className='login-form'>
|
<div className="login-form">
|
||||||
<div className={'authentication-page__label-section'}>
|
<div className={'authentication-page__label-section'}>
|
||||||
<h3><T id={'log_in'} /></h3>
|
<h3>
|
||||||
|
<T id={'log_in'} />
|
||||||
|
</h3>
|
||||||
<T id={'need_bigcapital_account'} />
|
<T id={'need_bigcapital_account'} />
|
||||||
<Link to='/auth/register'> <T id={'create_an_account'} /></Link>
|
<Link to="/auth/register">
|
||||||
|
{' '}
|
||||||
|
<T id={'create_an_account'} />
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form onSubmit={handleSubmit} className={'authentication-page__form'}>
|
<form onSubmit={handleSubmit} className={'authentication-page__form'}>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={<T id={'email_or_phone_number'} />}
|
label={<T id={'email_or_phone_number'} />}
|
||||||
intent={(errors.crediential && touched.crediential) && Intent.DANGER}
|
intent={errors.crediential && touched.crediential && Intent.DANGER}
|
||||||
helperText={<ErrorMessage name={'crediential'} {...{ errors, touched }} />}
|
helperText={
|
||||||
|
<ErrorMessage name={'crediential'} {...{ errors, touched }} />
|
||||||
|
}
|
||||||
className={'form-group--crediential'}
|
className={'form-group--crediential'}
|
||||||
>
|
>
|
||||||
<InputGroup
|
<InputGroup
|
||||||
intent={(errors.crediential && touched.crediential) && Intent.DANGER}
|
intent={
|
||||||
|
errors.crediential && touched.crediential && Intent.DANGER
|
||||||
|
}
|
||||||
large={true}
|
large={true}
|
||||||
{...getFieldProps('crediential')}
|
{...getFieldProps('crediential')}
|
||||||
/>
|
/>
|
||||||
@@ -122,22 +163,22 @@ function Login({
|
|||||||
<FormGroup
|
<FormGroup
|
||||||
label={<T id={'password'} />}
|
label={<T id={'password'} />}
|
||||||
labelInfo={passwordRevealerTmp}
|
labelInfo={passwordRevealerTmp}
|
||||||
intent={(errors.password && touched.password) && Intent.DANGER}
|
intent={errors.password && touched.password && Intent.DANGER}
|
||||||
helperText={<ErrorMessage name={'password'} {...{ errors, touched }} />}
|
helperText={
|
||||||
|
<ErrorMessage name={'password'} {...{ errors, touched }} />
|
||||||
|
}
|
||||||
className={'form-group--password has-password-revealer'}
|
className={'form-group--password has-password-revealer'}
|
||||||
>
|
>
|
||||||
<InputGroup
|
<InputGroup
|
||||||
large={true}
|
large={true}
|
||||||
intent={(errors.password && touched.password) && Intent.DANGER}
|
intent={errors.password && touched.password && Intent.DANGER}
|
||||||
type={shown ? 'text' : 'password'}
|
type={shown ? 'text' : 'password'}
|
||||||
{...getFieldProps('password')}
|
{...getFieldProps('password')}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
<div className={'login-form__checkbox-section'}>
|
<div className={'login-form__checkbox-section'}>
|
||||||
<Checkbox
|
<Checkbox large={true} className={'checkbox--remember-me'}>
|
||||||
large={true}
|
|
||||||
className={'checkbox--remember-me'}>
|
|
||||||
<T id={'keep_me_logged_in'} />
|
<T id={'keep_me_logged_in'} />
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
</div>
|
</div>
|
||||||
@@ -165,6 +206,4 @@ function Login({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
export default compose(withAuthenticationActions)(Login);
|
||||||
withAuthenticationActions,
|
|
||||||
)(Login);
|
|
||||||
|
|||||||
@@ -876,4 +876,6 @@ export default {
|
|||||||
day: 'day.',
|
day: 'day.',
|
||||||
day_partially_paid: 'Day Partially paid',
|
day_partially_paid: 'Day Partially paid',
|
||||||
paid: 'Paid',
|
paid: 'Paid',
|
||||||
|
your_account_has_been_locked:
|
||||||
|
'Your account has been locked due to repeated failed login attempts. Please wait a few minutes before trying again.',
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user