#26: suggest resend confirmation key in validation errors

This commit is contained in:
SleepWalker 2016-05-22 18:16:51 +03:00
parent 24fbde289f
commit 87d48c8722
8 changed files with 88 additions and 40 deletions

View File

@ -84,7 +84,7 @@ export function recoverPassword({
return dispatch(authenticate(resp.jwt));
})
.catch(validationErrorsHandler(dispatch))
.catch(validationErrorsHandler(dispatch, '/forgot-password'))
);
}
@ -126,7 +126,7 @@ export function activate({key = ''}) {
return dispatch(authenticate(resp.jwt));
})
.catch(validationErrorsHandler(dispatch))
.catch(validationErrorsHandler(dispatch, '/reactivate'))
);
}
@ -332,19 +332,27 @@ function needActivation() {
});
}
function validationErrorsHandler(dispatch) {
function validationErrorsHandler(dispatch, repeatUrl) {
return (resp) => {
if (resp.errors) {
let errorMessage = resp.errors[Object.keys(resp.errors)[0]];
const error = {
type: resp.errors[Object.keys(resp.errors)[0]],
payload: {
isGuest: true
}
};
if (resp.data) {
errorMessage = {
type: errorMessage,
payload: resp.data
};
Object.assign(error.payload, resp.data);
}
dispatch(setError(errorMessage));
return Promise.reject(errorMessage);
if (['error.key_not_exists', 'error.key_expire'].includes(error.type) && repeatUrl) {
Object.assign(error.payload, {
repeatUrl
});
}
dispatch(setError(error));
}
return Promise.reject(resp);

View File

@ -13,7 +13,7 @@ function resetTimer() {
export default function AuthError({error, onClose = function() {}}) {
resetTimer();
if (error.type === 'error.email_frequency') {
if (error.payload && error.payload.canRepeatIn) {
if (error.payload && error.payload.canRepeatIn) {
error.payload.msLeft = error.payload.canRepeatIn * 1000;
setTimeout(onClose, error.payload.msLeft - Date.now() + 1500); // 1500 to let the user see, that time is elapsed

View File

@ -51,6 +51,7 @@ export default class RecoverPasswordBody extends BaseAuthBody {
required
value={key}
readOnly={!!key}
autoComplete="off"
placeholder={messages.enterTheCode}
/>

View File

@ -100,6 +100,7 @@
"components.userbar.register": "Join",
"pages.root.siteName": "Ely.by",
"services.accountNotActivated": "The account is not activated",
"services.doYouWantRequestKey": "Do you want to request a new key?",
"services.emailFrequency": "Please cool down, you are requesting emails too often. New key can be retrieved {time}.",
"services.emailInvalid": "Email is invalid",
"services.emailIsTempmail": "Tempmail E-mail addresses is not allowed",
@ -108,7 +109,7 @@
"services.emailToLong": "Email is too long",
"services.forgotYourPassword": "forgot your password",
"services.invalidPassword": "You have entered wrong account password.",
"services.keyNotExists": "The key is incorrect",
"services.keyNotExists": "The key is incorrect or has expired.",
"services.keyRequired": "Please, enter an activation key",
"services.loginNotExist": "Sorry, Ely doesn't recognise your login.",
"services.loginRequired": "Please enter email or username",

View File

@ -100,6 +100,7 @@
"components.userbar.register": "Регистрация",
"pages.root.siteName": "Ely.by",
"services.accountNotActivated": "Аккаунт не активирован",
"services.doYouWantRequestKey": "Не хотите отправить новый код?",
"services.emailFrequency": "Пожалуйста, успокойтесь, вы запрашиваете E-mail слишком часто. Новый ключ можно будет заказать {time}.",
"services.emailInvalid": "Указан неправильный E-mail",
"services.emailIsTempmail": "Использование сервисов временных E-mail адресов запрещено",
@ -108,7 +109,7 @@
"services.emailToLong": "E-mail слишком длинный",
"services.forgotYourPassword": "забыли свой пароль",
"services.invalidPassword": "Вы указали неверный пароль от аккаунта.",
"services.keyNotExists": "Указанный ключ не существует или устарел",
"services.keyNotExists": "Указанный ключ не существует или устарел.",
"services.keyRequired": "Пожалуйста, введите код активации",
"services.loginNotExist": "К сожалению, на Ely нет пользователя с указанным логином.",
"services.loginRequired": "Пожалуйста, укажите E-mail или ник",

View File

@ -59,11 +59,11 @@ class ChangeEmailPage extends Component {
switch (step) {
case 0:
return accounts.requestEmailChange();
return accounts.requestEmailChange().catch(handleErrors());
case 1:
return accounts.setNewEmail(data);
return accounts.setNewEmail(data).catch(handleErrors('/profile/change-email'));
case 2:
return accounts.confirmNewEmail(data);
return accounts.confirmNewEmail(data).catch(handleErrors('/profile/change-email'));
default:
throw new Error(`Unsupported step ${step}`);
}
@ -74,6 +74,27 @@ class ChangeEmailPage extends Component {
};
}
function handleErrors(repeatUrl) {
return (resp) => {
if (resp.errors) {
if (resp.errors.key) {
resp.errors.key = {
type: resp.errors.key,
payload: {}
};
if (['error.key_not_exists', 'error.key_expire'].includes(resp.errors.key.type) && repeatUrl) {
Object.assign(resp.errors.key.payload, {
repeatUrl
});
}
}
}
return Promise.reject(resp);
};
}
import { connect } from 'react-redux';
export default connect((state) => ({

View File

@ -22,7 +22,8 @@
"passwordsDoesNotMatch": "The passwords does not match",
"rulesAgreementRequired": "You must accept rules in order to create an account",
"keyRequired": "Please, enter an activation key",
"keyNotExists": "The key is incorrect",
"keyNotExists": "The key is incorrect or has expired.",
"doYouWantRequestKey": "Do you want to request a new key?",
"emailFrequency": "Please cool down, you are requesting emails too often. New key can be retrieved {time}.",
"accountNotActivated": "The account is not activated",
"oldHashStrategy": "Sorry, but your account's password is too old. Please change your password in order to perform this action."

View File

@ -1,6 +1,7 @@
import React from 'react';
import { FormattedMessage as Message, FormattedRelative as Relative } from 'react-intl';
import { Link } from 'react-router';
import messages from './errorsDict.intl.json';
@ -9,7 +10,7 @@ export default {
let payload = {};
if (error.type) {
payload = error.payload;
payload = error.payload || {};
error = error.type;
}
return errorsMap[error] ? errorsMap[error](payload) : error;
@ -23,17 +24,10 @@ const errorsMap = {
'error.password_invalid': () => <Message {...messages.invalidPassword} />,
'error.old_hash_strategy': () => <Message {...messages.oldHashStrategy} />,
'error.password_incorrect': () => (
'error.password_incorrect': (props) => (
<span>
<Message {...messages.invalidPassword} />
<br/>
<Message {...messages.suggestResetPassword} values={{
link: (
<a href="#">
<Message {...messages.forgotYourPassword} />
</a>
)
}} />
{props.isGuest ? errorsMap.suggestResetPassword() : null}
</span>
),
@ -47,17 +41,10 @@ const errorsMap = {
'error.email_too_long': () => <Message {...messages.emailToLong} />,
'error.email_invalid': () => <Message {...messages.emailInvalid} />,
'error.email_is_tempmail': () => <Message {...messages.emailIsTempmail} />,
'error.email_not_available': () => (
'error.email_not_available': (props) => (
<span>
<Message {...messages.emailNotAvailable} />
<br/>
<Message {...messages.suggestResetPassword} values={{
link: (
<a href="#">
<Message {...messages.forgotYourPassword} />
</a>
)
}} />
{props.isGuest ? errorsMap.suggestResetPassword() : null}
</span>
),
@ -65,10 +52,16 @@ const errorsMap = {
'error.password_too_short': () => <Message {...messages.passwordTooShort} />,
'error.rePassword_does_not_match': () => <Message {...messages.passwordsDoesNotMatch} />,
'error.rulesAgreement_required': () => <Message {...messages.rulesAgreementRequired} />,
'error.you_must_accept_rules': () => this.errorsMap['error.rulesAgreement_required'](),
'error.you_must_accept_rules': () => errorsMap['error.rulesAgreement_required'](),
'error.key_required': () => <Message {...messages.keyRequired} />,
'error.key_is_required': () => this.errorsMap['error.key_required'](),
'error.key_not_exists': () => <Message {...messages.keyNotExists} />,
'error.key_is_required': () => errorsMap['error.key_required'](),
'error.key_not_exists': (props) => (
<span>
<Message {...messages.keyNotExists} />
{props.repeatUrl ? errorsMap.resendKey(props.repeatUrl) : null}
</span>
),
'error.key_expire': (props) => errorsMap['error.key_not_exists'](props),
'error.newPassword_required': () => <Message {...messages.newPasswordRequired} />,
'error.newRePassword_required': () => <Message {...messages.newRePasswordRequired} />,
@ -78,5 +71,27 @@ const errorsMap = {
'error.email_frequency': (props) => <Message {...messages.emailFrequency} values={{
time: <Relative value={props.msLeft} updateInterval={1000} />
}} />
}} />,
suggestResetPassword: () => (
<span>
<br/>
<Message {...messages.suggestResetPassword} values={{
link: (
<Link to="/forgot-password">
<Message {...messages.forgotYourPassword} />
</Link>
)
}} />
</span>
),
resendKey: (url) => (
<span>
{' '}
<Link to={url}>
<Message {...messages.doYouWantRequestKey} />
</Link>
</span>
)
};