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);