#14: integrate captcha with backend. Add validation message

This commit is contained in:
SleepWalker
2016-08-05 08:41:33 +03:00
parent cfb3d739c0
commit 32c333d159
11 changed files with 57 additions and 21 deletions

View File

@@ -26,7 +26,10 @@ export default class Captcha extends FormInputComponent {
render() { render() {
return ( return (
<div ref={this.setEl} className={styles.captcha} /> <div>
<div ref={this.setEl} className={styles.captcha} />
{this.renderError()}
</div>
); );
} }

View File

@@ -147,6 +147,7 @@
"pages.rules.title": "Правілы сайта", "pages.rules.title": "Правілы сайта",
"services.errorsDict.accountAlreadyActivated": "Гэты акаўнт ужо актываваны", "services.errorsDict.accountAlreadyActivated": "Гэты акаўнт ужо актываваны",
"services.errorsDict.accountNotActivated": "Акаўнт не актываваны", "services.errorsDict.accountNotActivated": "Акаўнт не актываваны",
"services.errorsDict.captchaRequired": "Please, solve the captcha",
"services.errorsDict.doYouWantRequestKey": "Не жадаеце адаслаць новы код?", "services.errorsDict.doYouWantRequestKey": "Не жадаеце адаслаць новы код?",
"services.errorsDict.emailFrequency": "Калі ласка, супакойцеся, вы запытваеце Email дужа часта. Новы ключ можна будзе заказать {time}.", "services.errorsDict.emailFrequency": "Калі ласка, супакойцеся, вы запытваеце Email дужа часта. Новы ключ можна будзе заказать {time}.",
"services.errorsDict.emailInvalid": "Указаны няправільны Email", "services.errorsDict.emailInvalid": "Указаны няправільны Email",

View File

@@ -147,6 +147,7 @@
"pages.rules.title": "Site rules", "pages.rules.title": "Site rules",
"services.errorsDict.accountAlreadyActivated": "This account is already activated", "services.errorsDict.accountAlreadyActivated": "This account is already activated",
"services.errorsDict.accountNotActivated": "The account is not activated", "services.errorsDict.accountNotActivated": "The account is not activated",
"services.errorsDict.captchaRequired": "Please, solve the captcha",
"services.errorsDict.doYouWantRequestKey": "Do you want to request a new key?", "services.errorsDict.doYouWantRequestKey": "Do you want to request a new key?",
"services.errorsDict.emailFrequency": "Please cool down, you are requesting Emails too often. New key can be retrieved {time}.", "services.errorsDict.emailFrequency": "Please cool down, you are requesting Emails too often. New key can be retrieved {time}.",
"services.errorsDict.emailInvalid": "Email is invalid", "services.errorsDict.emailInvalid": "Email is invalid",

View File

@@ -147,6 +147,7 @@
"pages.rules.title": "Правила сайта", "pages.rules.title": "Правила сайта",
"services.errorsDict.accountAlreadyActivated": "Этот аккаунт уже активирован", "services.errorsDict.accountAlreadyActivated": "Этот аккаунт уже активирован",
"services.errorsDict.accountNotActivated": "Аккаунт не активирован", "services.errorsDict.accountNotActivated": "Аккаунт не активирован",
"services.errorsDict.captchaRequired": "Пожалуйста, решите каптчу",
"services.errorsDict.doYouWantRequestKey": "Желаете отправить новый код?", "services.errorsDict.doYouWantRequestKey": "Желаете отправить новый код?",
"services.errorsDict.emailFrequency": "Пожалуйста, успокойтесь, вы запрашиваете Email слишком часто. Новый ключ можно будет заказать {time}.", "services.errorsDict.emailFrequency": "Пожалуйста, успокойтесь, вы запрашиваете Email слишком часто. Новый ключ можно будет заказать {time}.",
"services.errorsDict.emailInvalid": "Указан неправильный Email", "services.errorsDict.emailInvalid": "Указан неправильный Email",

View File

@@ -146,6 +146,7 @@
"pages.rules.title": "Правила сайту", "pages.rules.title": "Правила сайту",
"services.errorsDict.accountAlreadyActivated": "Цей обліковий запис вже активований", "services.errorsDict.accountAlreadyActivated": "Цей обліковий запис вже активований",
"services.errorsDict.accountNotActivated": "Акаунт не активований", "services.errorsDict.accountNotActivated": "Акаунт не активований",
"services.errorsDict.captchaRequired": "Будь ласка, розв`яжіть капчу",
"services.errorsDict.doYouWantRequestKey": "Бажаєте відправити новий код?", "services.errorsDict.doYouWantRequestKey": "Бажаєте відправити новий код?",
"services.errorsDict.emailFrequency": "Будь ласка, заспокойтесь, ви запитуєте E-mail занадто часто. Новий ключ можна буде замовити {time}.", "services.errorsDict.emailFrequency": "Будь ласка, заспокойтесь, ви запитуєте E-mail занадто часто. Новий ключ можна буде замовити {time}.",
"services.errorsDict.emailInvalid": "Вказано невірний E-mail", "services.errorsDict.emailInvalid": "Вказано невірний E-mail",

View File

@@ -11,9 +11,6 @@ import { IntlProvider } from 'components/i18n';
import routesFactory from 'routes'; import routesFactory from 'routes';
import storeFactory from 'storeFactory'; import storeFactory from 'storeFactory';
import bsodFactory from 'components/ui/bsod/factory'; import bsodFactory from 'components/ui/bsod/factory';
import captcha from 'services/captcha';
captcha.setApiKey('6LdUZiYTAAAAAEjDGi9kEu0MRKYHYWskPFNXSYOV'); // TODO
const store = storeFactory(); const store = storeFactory();

View File

@@ -0,0 +1,17 @@
import request from 'services/request';
let options;
export default {
get() {
if (options) {
return Promise.resolve(options);
}
return request.get('/api/options').then((resp) => {
options = resp;
return resp;
});
}
};

View File

@@ -1,4 +1,5 @@
import { loadScript } from 'functions'; import { loadScript } from 'functions';
import options from 'services/api/options';
let readyPromise; let readyPromise;
let lang = 'en'; let lang = 'en';
@@ -14,11 +15,7 @@ export default {
* @return {Promise} * @return {Promise}
*/ */
render(el, {skin: theme, onSetCode: callback}) { render(el, {skin: theme, onSetCode: callback}) {
if (!sitekey) { return this.loadApi().then(() =>
throw new Error('Site key is required to render captcha');
}
return loadApi().then(() =>
window.grecaptcha.render(el, { window.grecaptcha.render(el, {
sitekey, sitekey,
theme, theme,
@@ -43,17 +40,26 @@ export default {
*/ */
setApiKey(apiKey) { setApiKey(apiKey) {
sitekey = apiKey; sitekey = apiKey;
},
/**
* @api private
*
* @return {Promise}
*/
loadApi() {
if (!readyPromise) {
readyPromise = Promise.all([
new Promise((resolve) => {
window.onReCaptchaReady = resolve;
}),
options.get().then((resp) => this.setApiKey(resp.reCaptchaPublicKey))
]);
loadScript(`https://www.google.com/recaptcha/api.js?onload=onReCaptchaReady&render=explicit&hl=${lang}`);
}
return readyPromise;
} }
}; };
function loadApi() {
if (!readyPromise) {
readyPromise = new Promise((resolve) => {
window.onReCaptchaReady = resolve;
});
loadScript(`https://www.google.com/recaptcha/api.js?onload=onReCaptchaReady&render=explicit&hl=${lang}`);
}
return readyPromise;
}

View File

@@ -1,4 +1,5 @@
{ {
"captchaRequired": "Please, solve the captcha",
"invalidPassword": "You have entered wrong account password.", "invalidPassword": "You have entered wrong account password.",
"suggestResetPassword": "Are you have {link}?", "suggestResetPassword": "Are you have {link}?",
"forgotYourPassword": "forgot your password", "forgotYourPassword": "forgot your password",

View File

@@ -5,6 +5,8 @@ import { Link } from 'react-router';
import messages from './errorsDict.intl.json'; import messages from './errorsDict.intl.json';
/* eslint-disable react/prop-types, react/display-name, react/no-multi-comp, no-use-before-define */
export default { export default {
resolve(error) { resolve(error) {
let payload = {}; let payload = {};
@@ -74,6 +76,8 @@ const errorsMap = {
'error.email_not_found': () => <Message {...messages.emailNotFound} />, 'error.email_not_found': () => <Message {...messages.emailNotFound} />,
'error.account_already_activated': () => <Message {...messages.accountAlreadyActivated} />, 'error.account_already_activated': () => <Message {...messages.accountAlreadyActivated} />,
'error.captcha_required': () => <Message {...messages.captchaRequired} />,
suggestResetPassword: () => ( suggestResetPassword: () => (
<span> <span>
<br/> <br/>

View File

@@ -62,7 +62,11 @@ export default {
const checkStatus = (resp) => Promise[resp.status >= 200 && resp.status < 300 ? 'resolve' : 'reject'](resp); const checkStatus = (resp) => Promise[resp.status >= 200 && resp.status < 300 ? 'resolve' : 'reject'](resp);
const toJSON = (resp) => resp.json().then((json) => ({...json, originalResponse: resp})); const toJSON = (resp) => resp.json().then((json) => {
json.originalResponse = resp;
return json;
});
const rejectWithJSON = (resp) => toJSON(resp).then((resp) => {throw resp;}); const rejectWithJSON = (resp) => toJSON(resp).then((resp) => {throw resp;});
const handleResponseSuccess = (resp) => Promise[resp.success || typeof resp.success === 'undefined' ? 'resolve' : 'reject'](resp); const handleResponseSuccess = (resp) => Promise[resp.success || typeof resp.success === 'undefined' ? 'resolve' : 'reject'](resp);