diff --git a/src/components/ui/form/Captcha.jsx b/src/components/ui/form/Captcha.jsx
index c9bd0c9..ddfeaf9 100644
--- a/src/components/ui/form/Captcha.jsx
+++ b/src/components/ui/form/Captcha.jsx
@@ -26,7 +26,10 @@ export default class Captcha extends FormInputComponent {
render() {
return (
-
+
+
+ {this.renderError()}
+
);
}
diff --git a/src/i18n/be.json b/src/i18n/be.json
index 1c1e8f3..db6d51f 100644
--- a/src/i18n/be.json
+++ b/src/i18n/be.json
@@ -147,6 +147,7 @@
"pages.rules.title": "Правілы сайта",
"services.errorsDict.accountAlreadyActivated": "Гэты акаўнт ужо актываваны",
"services.errorsDict.accountNotActivated": "Акаўнт не актываваны",
+ "services.errorsDict.captchaRequired": "Please, solve the captcha",
"services.errorsDict.doYouWantRequestKey": "Не жадаеце адаслаць новы код?",
"services.errorsDict.emailFrequency": "Калі ласка, супакойцеся, вы запытваеце E‑mail дужа часта. Новы ключ можна будзе заказать {time}.",
"services.errorsDict.emailInvalid": "Указаны няправільны E‑mail",
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 6def478..5a14a93 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -147,6 +147,7 @@
"pages.rules.title": "Site rules",
"services.errorsDict.accountAlreadyActivated": "This account is already 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.emailFrequency": "Please cool down, you are requesting E‑mails too often. New key can be retrieved {time}.",
"services.errorsDict.emailInvalid": "E‑mail is invalid",
diff --git a/src/i18n/ru.json b/src/i18n/ru.json
index 41da400..7ab1e63 100644
--- a/src/i18n/ru.json
+++ b/src/i18n/ru.json
@@ -147,6 +147,7 @@
"pages.rules.title": "Правила сайта",
"services.errorsDict.accountAlreadyActivated": "Этот аккаунт уже активирован",
"services.errorsDict.accountNotActivated": "Аккаунт не активирован",
+ "services.errorsDict.captchaRequired": "Пожалуйста, решите каптчу",
"services.errorsDict.doYouWantRequestKey": "Желаете отправить новый код?",
"services.errorsDict.emailFrequency": "Пожалуйста, успокойтесь, вы запрашиваете E‑mail слишком часто. Новый ключ можно будет заказать {time}.",
"services.errorsDict.emailInvalid": "Указан неправильный E‑mail",
diff --git a/src/i18n/uk.json b/src/i18n/uk.json
index 52fb804..92a7318 100644
--- a/src/i18n/uk.json
+++ b/src/i18n/uk.json
@@ -146,6 +146,7 @@
"pages.rules.title": "Правила сайту",
"services.errorsDict.accountAlreadyActivated": "Цей обліковий запис вже активований",
"services.errorsDict.accountNotActivated": "Акаунт не активований",
+ "services.errorsDict.captchaRequired": "Будь ласка, розв`яжіть капчу",
"services.errorsDict.doYouWantRequestKey": "Бажаєте відправити новий код?",
"services.errorsDict.emailFrequency": "Будь ласка, заспокойтесь, ви запитуєте E-mail занадто часто. Новий ключ можна буде замовити {time}.",
"services.errorsDict.emailInvalid": "Вказано невірний E-mail",
diff --git a/src/index.js b/src/index.js
index d925712..a6da188 100644
--- a/src/index.js
+++ b/src/index.js
@@ -11,9 +11,6 @@ import { IntlProvider } from 'components/i18n';
import routesFactory from 'routes';
import storeFactory from 'storeFactory';
import bsodFactory from 'components/ui/bsod/factory';
-import captcha from 'services/captcha';
-
-captcha.setApiKey('6LdUZiYTAAAAAEjDGi9kEu0MRKYHYWskPFNXSYOV'); // TODO
const store = storeFactory();
diff --git a/src/services/api/options.js b/src/services/api/options.js
new file mode 100644
index 0000000..40666d5
--- /dev/null
+++ b/src/services/api/options.js
@@ -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;
+ });
+ }
+};
diff --git a/src/services/captcha.js b/src/services/captcha.js
index 61e9de6..c458d97 100644
--- a/src/services/captcha.js
+++ b/src/services/captcha.js
@@ -1,4 +1,5 @@
import { loadScript } from 'functions';
+import options from 'services/api/options';
let readyPromise;
let lang = 'en';
@@ -14,11 +15,7 @@ export default {
* @return {Promise}
*/
render(el, {skin: theme, onSetCode: callback}) {
- if (!sitekey) {
- throw new Error('Site key is required to render captcha');
- }
-
- return loadApi().then(() =>
+ return this.loadApi().then(() =>
window.grecaptcha.render(el, {
sitekey,
theme,
@@ -43,17 +40,26 @@ export default {
*/
setApiKey(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;
-}
diff --git a/src/services/errorsDict/errorsDict.intl.json b/src/services/errorsDict/errorsDict.intl.json
index cc60382..4c7af43 100644
--- a/src/services/errorsDict/errorsDict.intl.json
+++ b/src/services/errorsDict/errorsDict.intl.json
@@ -1,4 +1,5 @@
{
+ "captchaRequired": "Please, solve the captcha",
"invalidPassword": "You have entered wrong account password.",
"suggestResetPassword": "Are you have {link}?",
"forgotYourPassword": "forgot your password",
diff --git a/src/services/errorsDict/errorsDict.js b/src/services/errorsDict/errorsDict.js
index 22b6edf..86a500d 100644
--- a/src/services/errorsDict/errorsDict.js
+++ b/src/services/errorsDict/errorsDict.js
@@ -5,6 +5,8 @@ import { Link } from 'react-router';
import messages from './errorsDict.intl.json';
+/* eslint-disable react/prop-types, react/display-name, react/no-multi-comp, no-use-before-define */
+
export default {
resolve(error) {
let payload = {};
@@ -74,6 +76,8 @@ const errorsMap = {
'error.email_not_found': () => ,
'error.account_already_activated': () => ,
+ 'error.captcha_required': () => ,
+
suggestResetPassword: () => (
diff --git a/src/services/request/request.js b/src/services/request/request.js
index 9e551bc..a94a433 100644
--- a/src/services/request/request.js
+++ b/src/services/request/request.js
@@ -62,7 +62,11 @@ export default {
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 handleResponseSuccess = (resp) => Promise[resp.success || typeof resp.success === 'undefined' ? 'resolve' : 'reject'](resp);