feat: added captcha on authn mfe
This commit is contained in:
committed by
Awais Ansari
parent
cf3e8b5c7f
commit
da0755467d
13
package-lock.json
generated
13
package-lock.json
generated
@@ -32,6 +32,7 @@
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-error-boundary": "^4.0.13",
|
||||
"react-google-recaptcha-v3": "^1.11.0",
|
||||
"react-helmet": "6.1.0",
|
||||
"react-loading-skeleton": "3.5.0",
|
||||
"react-redux": "7.2.9",
|
||||
@@ -22541,6 +22542,18 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-google-recaptcha-v3": {
|
||||
"version": "1.11.0",
|
||||
"resolved": "https://registry.npmjs.org/react-google-recaptcha-v3/-/react-google-recaptcha-v3-1.11.0.tgz",
|
||||
"integrity": "sha512-kLQqpz/77m8+trpBwzqcxNtvWZYoZ/YO6Vm2cVTHW8hs80BWUfDpC7RDwuAvpswwtSYApWfaSpIDFWAIBNIYxQ==",
|
||||
"dependencies": {
|
||||
"hoist-non-react-statics": "^3.3.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.3 || ^17.0 || ^18.0 || ^19.0",
|
||||
"react-dom": "^17.0 || ^18.0 || ^19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-helmet": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz",
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"react-error-boundary": "^4.0.13",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-google-recaptcha-v3": "^1.11.0",
|
||||
"react-helmet": "6.1.0",
|
||||
"react-loading-skeleton": "3.5.0",
|
||||
"react-redux": "7.2.9",
|
||||
|
||||
@@ -2,6 +2,7 @@ import React from 'react';
|
||||
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import { AppProvider } from '@edx/frontend-platform/react';
|
||||
import { GoogleReCaptchaProvider } from 'react-google-recaptcha-v3';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||
|
||||
@@ -34,31 +35,35 @@ registerIcons();
|
||||
|
||||
const MainApp = () => (
|
||||
<AppProvider store={configureStore()}>
|
||||
<Helmet>
|
||||
<link rel="shortcut icon" href={getConfig().FAVICON_URL} type="image/x-icon" />
|
||||
</Helmet>
|
||||
<Routes>
|
||||
<Route path="/" element={<Navigate replace to={updatePathWithQueryParams(REGISTER_PAGE)} />} />
|
||||
<Route
|
||||
path={REGISTER_EMBEDDED_PAGE}
|
||||
element={<EmbeddedRegistrationRoute><RegistrationPage /></EmbeddedRegistrationRoute>}
|
||||
/>
|
||||
<Route
|
||||
path={LOGIN_PAGE}
|
||||
element={
|
||||
<UnAuthOnlyRoute><Logistration selectedPage={LOGIN_PAGE} /></UnAuthOnlyRoute>
|
||||
}
|
||||
/>
|
||||
<Route path={REGISTER_PAGE} element={<UnAuthOnlyRoute><Logistration /></UnAuthOnlyRoute>} />
|
||||
<Route path={RESET_PAGE} element={<UnAuthOnlyRoute><ForgotPasswordPage /></UnAuthOnlyRoute>} />
|
||||
<Route path={PASSWORD_RESET_CONFIRM} element={<ResetPasswordPage />} />
|
||||
<Route path={AUTHN_PROGRESSIVE_PROFILING} element={<ProgressiveProfiling />} />
|
||||
<Route path={RECOMMENDATIONS} element={<RecommendationsPage />} />
|
||||
<Route path={PAGE_NOT_FOUND} element={<NotFoundPage />} />
|
||||
<Route path="*" element={<Navigate replace to={PAGE_NOT_FOUND} />} />
|
||||
</Routes>
|
||||
<RouteTracker />
|
||||
<MainAppSlot />
|
||||
<GoogleReCaptchaProvider
|
||||
reCaptchaKey="6LeQu6QrAAAAADR7XB--kDIKyAsqJu9SO22Jiptd"
|
||||
useEnterprise
|
||||
>
|
||||
<Helmet>
|
||||
<link rel="shortcut icon" href={getConfig().FAVICON_URL} type="image/x-icon" />
|
||||
</Helmet>
|
||||
{getConfig().ZENDESK_KEY && <Zendesk />}
|
||||
<Routes>
|
||||
<Route path="/" element={<Navigate replace to={updatePathWithQueryParams(REGISTER_PAGE)} />} />
|
||||
<Route
|
||||
path={REGISTER_EMBEDDED_PAGE}
|
||||
element={<EmbeddedRegistrationRoute><RegistrationPage /></EmbeddedRegistrationRoute>}
|
||||
/>
|
||||
<Route
|
||||
path={LOGIN_PAGE}
|
||||
element={
|
||||
<UnAuthOnlyRoute><Logistration selectedPage={LOGIN_PAGE} /></UnAuthOnlyRoute>
|
||||
}
|
||||
/>
|
||||
<Route path={REGISTER_PAGE} element={<UnAuthOnlyRoute><Logistration /></UnAuthOnlyRoute>} />
|
||||
<Route path={RESET_PAGE} element={<UnAuthOnlyRoute><ForgotPasswordPage /></UnAuthOnlyRoute>} />
|
||||
<Route path={PASSWORD_RESET_CONFIRM} element={<ResetPasswordPage />} />
|
||||
<Route path={AUTHN_PROGRESSIVE_PROFILING} element={<ProgressiveProfiling />} />
|
||||
<Route path={RECOMMENDATIONS} element={<RecommendationsPage />} />
|
||||
<Route path={PAGE_NOT_FOUND} element={<NotFoundPage />} />
|
||||
<Route path="*" element={<Navigate replace to={PAGE_NOT_FOUND} />} />
|
||||
</Routes>
|
||||
</GoogleReCaptchaProvider>
|
||||
</AppProvider>
|
||||
);
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { Form, Spinner, StatefulButton } from '@openedx/paragon';
|
||||
import classNames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useGoogleReCaptcha } from 'react-google-recaptcha-v3';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import Skeleton from 'react-loading-skeleton';
|
||||
|
||||
@@ -60,6 +61,7 @@ import { trackRegistrationPageViewed, trackRegistrationSuccess } from '../tracki
|
||||
const RegistrationPage = (props) => {
|
||||
const { formatMessage } = useIntl();
|
||||
const dispatch = useDispatch();
|
||||
const { executeRecaptcha } = useGoogleReCaptcha();
|
||||
|
||||
const registrationEmbedded = isHostAvailableInQueryParams();
|
||||
const platformName = getConfig().SITE_NAME;
|
||||
@@ -106,6 +108,8 @@ const RegistrationPage = (props) => {
|
||||
const [formStartTime, setFormStartTime] = useState(null);
|
||||
// temporary error state for embedded experience because we don't want to show errors on blur
|
||||
const [temporaryErrors, setTemporaryErrors] = useState({ ...backedUpFormData.errors });
|
||||
const [captchaError, setCaptchaError] = useState('');
|
||||
const intl = useIntl();
|
||||
|
||||
const { cta, host } = queryParams;
|
||||
const buttonLabel = cta
|
||||
@@ -230,7 +234,8 @@ const RegistrationPage = (props) => {
|
||||
}
|
||||
};
|
||||
|
||||
const registerUser = () => {
|
||||
const registerUser = async () => {
|
||||
let recaptchaToken = '';
|
||||
const totalRegistrationTime = (Date.now() - formStartTime) / 1000;
|
||||
let payload = { ...formFields, app_name: APP_NAME };
|
||||
|
||||
@@ -259,16 +264,35 @@ const RegistrationPage = (props) => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (executeRecaptcha) {
|
||||
try {
|
||||
recaptchaToken = await executeRecaptcha('submit_post');
|
||||
if (!recaptchaToken) {
|
||||
setCaptchaError(intl.formatMessage(messages['discussions.captcha.verification.label']));
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
setCaptchaError(intl.formatMessage(messages['discussions.captcha.verification.label']));
|
||||
return;
|
||||
}
|
||||
setCaptchaError('');
|
||||
}
|
||||
// Preparing payload for submission
|
||||
payload = prepareRegistrationPayload(
|
||||
payload,
|
||||
configurableFormFields,
|
||||
flags.showMarketingEmailOptInCheckbox,
|
||||
totalRegistrationTime,
|
||||
queryParams);
|
||||
if (recaptchaToken) {
|
||||
payload = prepareRegistrationPayload(
|
||||
payload,
|
||||
configurableFormFields,
|
||||
flags.showMarketingEmailOptInCheckbox,
|
||||
totalRegistrationTime,
|
||||
queryParams);
|
||||
|
||||
// making register call
|
||||
dispatch(registerNewUser(payload));
|
||||
const updatedpayload = {
|
||||
...payload,
|
||||
captcha_token: recaptchaToken,
|
||||
};
|
||||
// making register call
|
||||
dispatch(registerNewUser(updatedpayload));
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubmit = (e) => {
|
||||
@@ -393,8 +417,12 @@ const RegistrationPage = (props) => {
|
||||
setFormFields={setConfigurableFormFields}
|
||||
autoSubmitRegisterForm={autoSubmitRegForm}
|
||||
fieldDescriptions={fieldDescriptions}
|
||||
countriesCodesList={countriesCodesList}
|
||||
/>
|
||||
{captchaError && (
|
||||
<div className="mt-3 pgn__form-text-invalid pgn__form-text">
|
||||
{captchaError}
|
||||
</div>
|
||||
)}
|
||||
<StatefulButton
|
||||
id="register-user"
|
||||
name="register-user"
|
||||
|
||||
@@ -206,6 +206,11 @@ const messages = defineMessages({
|
||||
defaultMessage: 'Did you mean',
|
||||
description: 'Did you mean alert suggestion',
|
||||
},
|
||||
'discussions.captcha.verification.label': {
|
||||
id: 'discussions.captcha.verification.label',
|
||||
defaultMessage: 'CAPTCHA verification failed.',
|
||||
description: 'CAPTCHA verification failed',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
|
||||
Reference in New Issue
Block a user