From ff21f40145f98a2cec032375b2b5e6c5336429fa Mon Sep 17 00:00:00 2001
From: edwardcho1231 <67028780+edwardcho1231@users.noreply.github.com>
Date: Mon, 25 Mar 2024 09:28:51 -0400
Subject: [PATCH 1/3] Asub 8192/captcha2 login (#1978)
* add new compoent for bot protection
* update styles
* update login-link
* address feedback
* address feedback
* fix intl
* use useSales from component repo
* remove unused vars
* add test and clean up
* address feedback
* fix captcha error logic
* update css styles to use logical properties
* update width to inline-size
* clean up unused styles
* address feedback
* clean up
* update tests
* update tests
* fix lint errors
* fix lint warnings
---
blocks/identity-block/_index.scss | 12 ++++
.../bot-challenge-protection/index.jsx | 64 ++++++++++++++++++
.../bot-challenge-protection/index.test.jsx | 50 ++++++++++++++
.../features/login-links/default.jsx | 4 +-
.../identity-block/features/login/default.jsx | 40 ++++++++---
.../features/login/default.test.jsx | 32 ++++++---
blocks/identity-block/intl.json | 17 ++++-
blocks/identity-block/package-lock.json | 26 ++++++++
blocks/identity-block/package.json | 3 +-
blocks/identity-block/themes/news.json | 66 ++++++++++++++++---
locale/en.json | 7 +-
package-lock.json | 31 +++++++--
12 files changed, 315 insertions(+), 37 deletions(-)
create mode 100644 blocks/identity-block/components/bot-challenge-protection/index.jsx
create mode 100644 blocks/identity-block/components/bot-challenge-protection/index.test.jsx
diff --git a/blocks/identity-block/_index.scss b/blocks/identity-block/_index.scss
index d8bcd60fab..c430c88a87 100644
--- a/blocks/identity-block/_index.scss
+++ b/blocks/identity-block/_index.scss
@@ -62,11 +62,23 @@
.b-login-form {
@include scss.block-components("login-form");
@include scss.block-properties("login-form");
+ &__bot-protection-section {
+ @include scss.block-components("login-form-bot-protection-section");
+ @include scss.block-properties("login-form-bot-protection-section");
+ }
+ &__privacy-statement {
+ @include scss.block-components("login-form-privacy-statement");
+ @include scss.block-properties("login-form-privacy-statement");
+ }
}
.b-login-links {
@include scss.block-components("login-links");
@include scss.block-properties("login-links");
+ &__inner-link {
+ @include scss.block-components("login-links-inner-link");
+ @include scss.block-properties("login-links-inner-link");
+ }
}
.b-reset-password {
diff --git a/blocks/identity-block/components/bot-challenge-protection/index.jsx b/blocks/identity-block/components/bot-challenge-protection/index.jsx
new file mode 100644
index 0000000000..fb2f70a6ca
--- /dev/null
+++ b/blocks/identity-block/components/bot-challenge-protection/index.jsx
@@ -0,0 +1,64 @@
+import React, { useState, useEffect } from "react";
+import { useFusionContext } from "fusion:context";
+import getProperties from "fusion:properties";
+import getTranslatedPhrases from "fusion:intl";
+import { Paragraph, useIdentity, useSales } from "@wpmedia/arc-themes-components";
+import ReCAPTCHA from "react-google-recaptcha";
+
+const BotChallengeProtection = ({ challengeIn, setCaptchaToken, className, captchaError, setCaptchaError }) => {
+ const { Identity, isInitialized } = useIdentity();
+ const { Sales } = useSales();
+ const [siteKey, setSiteKey] = useState();
+
+ const onChange = (value) => {
+ setCaptchaToken(value);
+ setCaptchaError(null);
+ localStorage.setItem('ArcXP_captchaToken', value);
+ };
+
+ useEffect(() => {
+ const checkCaptcha = async () => {
+ const config = await Identity.getConfig();
+ const {recaptchaSiteKey, recaptchaScore } = config;
+ const isIdentityCaptchaEnabled = config?.[`${challengeIn}Recaptcha`];
+
+ if(['signup', 'signin', 'magicLink'].includes(challengeIn)) {
+ if (isIdentityCaptchaEnabled && recaptchaScore === '-1' && recaptchaSiteKey) {
+ setSiteKey(recaptchaSiteKey);
+ }
+ }
+
+ if (challengeIn === 'checkout') {
+ const salesConfig = await Sales.getConfig();
+ const isSalesCaptchaEnabled = salesConfig?.checkoutRecaptchaEnabled;
+ if (isSalesCaptchaEnabled && recaptchaScore === '-1' && recaptchaSiteKey) {
+ setSiteKey(recaptchaSiteKey);
+ }
+ }
+
+ };
+ checkCaptcha();
+
+ }, [Identity, Sales, challengeIn]);
+
+ const { arcSite } = useFusionContext();
+ const { locale } = getProperties(arcSite);
+ const phrases = getTranslatedPhrases(locale);
+
+ if (!isInitialized) {
+ return null;
+ }
+
+ return (
+
+ {!!siteKey && {}}
+ />}
+ {captchaError && {phrases.t("identity-block.bot-protection-error")}}
+
+ );
+};
+
+export default BotChallengeProtection;
diff --git a/blocks/identity-block/components/bot-challenge-protection/index.test.jsx b/blocks/identity-block/components/bot-challenge-protection/index.test.jsx
new file mode 100644
index 0000000000..b1f5a40b00
--- /dev/null
+++ b/blocks/identity-block/components/bot-challenge-protection/index.test.jsx
@@ -0,0 +1,50 @@
+import React from "react";
+import { render, screen } from "@testing-library/react";
+import { useIdentity } from "@wpmedia/arc-themes-components";
+import BotChallengeProtection from ".";
+
+const mockLogin = jest.fn(() => Promise.resolve());
+
+const mockIdentity = {
+ isLoggedIn: jest.fn(() => false),
+ getConfig: jest.fn(() => ({})),
+ login: mockLogin,
+};
+
+const mockSales = {
+ getConfig: jest.fn(() => {})
+}
+
+jest.mock("@wpmedia/arc-themes-components", () => ({
+ ...jest.requireActual("@wpmedia/arc-themes-components"),
+ useIdentity: jest.fn(() => ({
+ isInitialized: true,
+ Identity: {
+ ...mockIdentity,
+ },
+ })),
+ useSales: jest.fn(() => ({
+ isInitialized: true,
+ Sales: {
+ ...mockSales,
+ },
+ })),
+}));
+
+describe("Bot challenge protection", () => {
+ it("renders with required items", () => {
+ render();
+
+ expect(screen.getByTestId("bot-challege-protection-container")).not.toBeNull();
+ });
+ it("it does not render if identity is not initialized", () => {
+ useIdentity.mockImplementation(() => ({
+ isInitialized: false,
+ Identity: {
+ ...mockIdentity,
+ },
+ }))
+ render();
+ expect(screen.queryByTestId("bot-challege-protection-container")).toBeNull();
+ });
+});
diff --git a/blocks/identity-block/features/login-links/default.jsx b/blocks/identity-block/features/login-links/default.jsx
index a8d069d53f..4a1615492c 100644
--- a/blocks/identity-block/features/login-links/default.jsx
+++ b/blocks/identity-block/features/login-links/default.jsx
@@ -2,7 +2,7 @@ import React from "react";
import PropTypes from "@arc-fusion/prop-types";
import { useFusionContext } from "fusion:context";
import getTranslatedPhrases from "fusion:intl";
-import { Link, Stack } from "@wpmedia/arc-themes-components";
+import { Link, Paragraph, Stack } from "@wpmedia/arc-themes-components";
const BLOCK_CLASS_NAME = "b-login-links";
const defaultLoginURL = "/account/login/";
@@ -35,7 +35,7 @@ const LoginLinks = ({ customFields }) => {
{phrases.t("identity-block.login-links-forgot")}
) : null}
{showSignUp ? (
- {phrases.t("identity-block.login-links-signup")}
+ {phrases.t("identity-block.login-links-signup")}{phrases.t("identity-block.sign-up-natural")}
) : null}
);
diff --git a/blocks/identity-block/features/login/default.jsx b/blocks/identity-block/features/login/default.jsx
index 22d87f570a..349424939b 100644
--- a/blocks/identity-block/features/login/default.jsx
+++ b/blocks/identity-block/features/login/default.jsx
@@ -1,11 +1,13 @@
-import React, { useState, useEffect } from "react";
+/* global grecaptcha */
+import React, { useState } from "react";
import PropTypes from "@arc-fusion/prop-types";
import { useFusionContext } from "fusion:context";
import getProperties from "fusion:properties";
import getTranslatedPhrases from "fusion:intl";
-import { Input, useIdentity } from "@wpmedia/arc-themes-components";
+import { Input, useIdentity, Paragraph } from "@wpmedia/arc-themes-components";
import HeadlinedSubmitForm from "../../components/headlined-submit-form";
import useLogin from "../../components/login";
+import BotChallengeProtection from "../../components/bot-challenge-protection";
import useOIDCLogin from "../../utils/useOIDCLogin";
import validateURL from "../../utils/validate-redirect-url";
@@ -14,8 +16,8 @@ const BLOCK_CLASS_NAME = "b-login-form";
const Login = ({ customFields }) => {
const { redirectURL, redirectToPreviousPage, loggedInPageLocation, OIDC } = customFields;
- const url_string = window.location.href;
- const url = new URL(url_string);
+ const urlString = window.location.href;
+ const url = new URL(urlString);
const { isAdmin, arcSite } = useFusionContext();
const { locale } = getProperties(arcSite);
@@ -23,7 +25,9 @@ const Login = ({ customFields }) => {
const isOIDC = OIDC && url.searchParams.get("client_id") && url.searchParams.get("response_type") === "code";
const { Identity, isInitialized } = useIdentity();
+ const [captchaToken, setCaptchaToken] = useState();
const [error, setError] = useState();
+ const [captchaError, setCaptchaError] = useState();
const { loginRedirect } = useLogin({
isAdmin,
redirectURL,
@@ -42,9 +46,14 @@ const Login = ({ customFields }) => {
buttonLabel={phrases.t("identity-block.log-in")}
className={BLOCK_CLASS_NAME}
formErrorText={error}
- headline={phrases.t("identity-block.log-in")}
- onSubmit={({ email, password }) =>
- Identity.login(email, password, {rememberMe: true})
+ headline={phrases.t("identity-block.log-in-headline")}
+ onSubmit={({ email, password }) => {
+ setError(null);
+ setCaptchaError(null);
+ return Identity.login(email, password, {
+ rememberMe: true,
+ recaptchaToken: captchaToken
+ })
.then(() => {
if (isOIDC) {
loginByOIDC();
@@ -53,12 +62,23 @@ const Login = ({ customFields }) => {
window.location = validatedURL;
}
})
- .catch(() => setError(phrases.t("identity-block.login-form-error")))
+ .catch((e) => {
+ if (e?.code === "130001") {
+ setCaptchaError(true);
+ }
+ else {
+ setError(phrases.t("identity-block.login-form-error"));
+ }
+ if (grecaptcha) {
+ grecaptcha.reset();
+ }
+ })
+ }
}
>
{
showDefaultError={false}
type="password"
/>
+
+ {phrases.t("identity-block.privacy-statement")}
);
};
diff --git a/blocks/identity-block/features/login/default.test.jsx b/blocks/identity-block/features/login/default.test.jsx
index c316678b98..a5c8ace853 100644
--- a/blocks/identity-block/features/login/default.test.jsx
+++ b/blocks/identity-block/features/login/default.test.jsx
@@ -1,11 +1,12 @@
import React from "react";
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
-import Login from "./default";
import { useIdentity } from "@wpmedia/arc-themes-components";
+import Login from "./default";
const defaultCustomFields = {
redirectURL: "",
redirectToPreviousPage: true,
+ signUpURL: ""
};
const mockLogin = jest.fn(() => Promise.resolve());
@@ -15,6 +16,10 @@ const mockIdentity = {
login: mockLogin,
};
+const mockSales = {
+ getConfig: jest.fn(() => {})
+}
+
jest.mock("@wpmedia/arc-themes-components", () => ({
...jest.requireActual("@wpmedia/arc-themes-components"),
useIdentity: jest.fn(() => ({
@@ -23,27 +28,33 @@ jest.mock("@wpmedia/arc-themes-components", () => ({
...mockIdentity,
},
})),
+ useSales: jest.fn(() => ({
+ isInitialized: true,
+ Sales: {
+ ...mockSales,
+ },
+ })),
}));
jest.mock("fusion:properties", () => jest.fn(() => ({})));
describe("Identity Login Feature", () => {
it("renders", () => {
render();
- expect(screen.queryByRole("form")).not.toBeNull();
+ expect(screen.getByRole("form")).not.toBeNull();
});
it("shows login form", () => {
render();
- expect(screen.queryByRole("form")).not.toBeNull();
+ expect(screen.getByRole("form")).not.toBeNull();
expect(screen.getByLabelText("identity-block.password")).not.toBeNull();
- expect(screen.getByLabelText("identity-block.email")).not.toBeNull();
+ expect(screen.getByLabelText("identity-block.email-label")).not.toBeNull();
});
it("submits the login form", async () => {
render();
- await waitFor(() => expect(screen.getByLabelText("identity-block.email")));
- fireEvent.change(screen.getByLabelText("identity-block.email"), {
+ await waitFor(() => expect(screen.getByLabelText("identity-block.email-label")));
+ fireEvent.change(screen.getByLabelText("identity-block.email-label"), {
target: { value: "email@test.com" },
});
await waitFor(() => expect(screen.getByLabelText("identity-block.password")));
@@ -60,6 +71,9 @@ describe("Identity Login Feature", () => {
describe("Identity Login Feature - rejected Login", () => {
beforeEach(() => {
mockLogin.mockImplementation(() => Promise.reject());
+ global.grecaptcha = {
+ reset: jest.fn()
+ }
});
afterEach(() => {
@@ -69,8 +83,8 @@ describe("Identity Login Feature - rejected Login", () => {
it("rejects the login", async () => {
render();
- await waitFor(() => expect(screen.getByLabelText("identity-block.email")));
- fireEvent.change(screen.getByLabelText("identity-block.email"), {
+ await waitFor(() => expect(screen.getByLabelText("identity-block.email-label")));
+ fireEvent.change(screen.getByLabelText("identity-block.email-label"), {
target: { value: "email@test.com" },
});
@@ -83,7 +97,7 @@ describe("Identity Login Feature - rejected Login", () => {
fireEvent.click(screen.getByRole("button"));
await waitFor(() => expect(mockLogin).toHaveBeenCalled());
- await waitFor(() => screen.getByText("identity-block.login-form-error"));
+ await screen.findByText("identity-block.login-form-error");
});
});
diff --git a/blocks/identity-block/intl.json b/blocks/identity-block/intl.json
index 3147bad767..b335b9cc9f 100644
--- a/blocks/identity-block/intl.json
+++ b/blocks/identity-block/intl.json
@@ -629,7 +629,7 @@
"bn": "কোনো অ্যাকাউন্ট নেই?\nসাইন আপ করুন",
"bo": "ཁྱེད་ལ་དྲ་གྲངས་མེད་དམ། ཐོ་འགོད།",
"de": "Sign up for an account.",
- "en": "Don't have an account? Sign up",
+ "en": "Need to create an account? ",
"es": "Sign up for an account.",
"fr": "Sign up for an account.",
"id": "Belum memiliki akun? Daftar",
@@ -1273,5 +1273,20 @@
"vi": "Tên người dùng",
"zh-CN": "用户名",
"zh-TW": "使用者名稱"
+ },
+ "identity-block.bot-protection-error": {
+ "en": "Please verify that you are not a robot."
+ },
+ "identity-block.email-label": {
+ "en": "Email"
+ },
+ "identity-block.log-in-headline": {
+ "en": "Log in to your account"
+ },
+ "identity-block.privacy-statement": {
+ "en": "By creating an account, you agree to the Terms of Service and acknowledge our Privacy Policy."
+ },
+ "identity-block.sign-up-natural": {
+ "en": "Sign up"
}
}
\ No newline at end of file
diff --git a/blocks/identity-block/package-lock.json b/blocks/identity-block/package-lock.json
index 6e888512c4..f812007dd1 100644
--- a/blocks/identity-block/package-lock.json
+++ b/blocks/identity-block/package-lock.json
@@ -17,6 +17,14 @@
"resolved": "https://registry.npmjs.org/@arc-publishing/sdk-identity/-/sdk-identity-1.79.0.tgz",
"integrity": "sha512-eblhb/AMa2uKr3/sWphlonIw5gKrz2KigUYnQDU2riWZn9Z+EECmQsbpbZbkWGDaTXrtkEX3DRqBIPJsPaEsXg=="
},
+ "hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "requires": {
+ "react-is": "^16.7.0"
+ }
+ },
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -45,6 +53,24 @@
"react-is": "^16.8.1"
}
},
+ "react-async-script": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/react-async-script/-/react-async-script-1.2.0.tgz",
+ "integrity": "sha512-bCpkbm9JiAuMGhkqoAiC0lLkb40DJ0HOEJIku+9JDjxX3Rcs+ztEOG13wbrOskt3n2DTrjshhaQ/iay+SnGg5Q==",
+ "requires": {
+ "hoist-non-react-statics": "^3.3.0",
+ "prop-types": "^15.5.0"
+ }
+ },
+ "react-google-recaptcha": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/react-google-recaptcha/-/react-google-recaptcha-3.1.0.tgz",
+ "integrity": "sha512-cYW2/DWas8nEKZGD7SCu9BSuVz8iOcOLHChHyi7upUuVhkpkhYG/6N3KDiTQ3XAiZ2UAZkfvYKMfAHOzBOcGEg==",
+ "requires": {
+ "prop-types": "^15.5.0",
+ "react-async-script": "^1.2.0"
+ }
+ },
"react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
diff --git a/blocks/identity-block/package.json b/blocks/identity-block/package.json
index d5fbb51c1b..2c008b9440 100644
--- a/blocks/identity-block/package.json
+++ b/blocks/identity-block/package.json
@@ -30,6 +30,7 @@
},
"dependencies": {
"@arc-fusion/prop-types": "^0.1.5",
- "@arc-publishing/sdk-identity": "^1.79.0"
+ "@arc-publishing/sdk-identity": "^1.79.0",
+ "react-google-recaptcha": "^3.1.0"
}
}
diff --git a/blocks/identity-block/themes/news.json b/blocks/identity-block/themes/news.json
index 82b1ed1fc2..915ac4501b 100644
--- a/blocks/identity-block/themes/news.json
+++ b/blocks/identity-block/themes/news.json
@@ -239,22 +239,27 @@
"login-form": {
"styles": {
"default": {
- "font-family": "var(--font-family-primary)",
+ "font-family": "Inter",
+ "padding-block-end": "var(--global-spacing-5)",
"components": {
"button": {
"font-size": "var(--global-font-size-4)"
},
"heading": {
- "border-block-end-color": "var(--border-color)",
- "border-block-end-style": "var(--global-border-style-1)",
- "border-block-end-width": "var(--global-border-width-1)",
- "font-size": "var(--global-font-size-9)",
- "margin-block-end": "var(--global-spacing-4)",
- "padding-block-end": "var(--global-spacing-2)",
- "text-align": "center"
+ "font-size": "var(--heading-level-4-font-size)",
+ "font-family": "var(--font-family-secondary)",
+ "font-weight": 700,
+ "font-style": "normal",
+ "line-height": "140%",
+ "text-align": "center",
+ "padding-block-end": 0,
+ "padding-block-start": 0,
+ "padding-inline-end": 0,
+ "padding-inline-start": 0,
+ "margin-block-end": "var(--global-spacing-5)"
},
"input": {
- "margin-block-end": "var(--global-spacing-5)"
+ "margin-block-end": "var(--global-spacing-4)"
},
"input-error-tip": {
"color": "var(--status-color-danger)"
@@ -280,12 +285,46 @@
}
}
},
+ "login-form-bot-protection-section": {
+ "styles": {
+ "default": {
+ "margin-block-start": "var(--global-spacing-5)",
+ "margin-block-end": "var(--global-spacing-5)",
+ "components": {
+ "paragraph": {
+ "color": "#f00"
+ }
+ }
+ }
+ }
+ },
+ "login-form-privacy-statement": {
+ "styles": {
+ "default": {
+ "display": "block",
+ "text-align": "center",
+ "inline-size": "100%",
+ "margin-block-start": 0,
+ "margin-block-end": "var(--global-spacing-5)",
+ "margin-inline-end": 0,
+ "margin-inline-start": 0,
+ "line-height": "150%",
+ "font-size": "0.75rem"
+ }
+ }
+ },
"login-links": {
"styles": {
"default": {
+ "font-family": "inter",
"components": {
+ "paragraph": {
+ "text-align": "center",
+ "font-family": "inter"
+ },
"link": {
- "text-align": "center"
+ "text-align": "center",
+ "font-family": "inter"
},
"link-hover": {
"color": "var(--text-color-subtle)"
@@ -295,6 +334,13 @@
"desktop": {}
}
},
+ "login-links-inner-link": {
+ "styles": {
+ "default": {
+ "text-decoration": "underline"
+ }
+ }
+ },
"reset-password": {
"styles": {
"default": {
diff --git a/locale/en.json b/locale/en.json
index cb45782a46..c375579f27 100644
--- a/locale/en.json
+++ b/locale/en.json
@@ -108,6 +108,7 @@
"identity-block.account": "Account",
"identity-block.account-information": "Account Information",
"identity-block.add-password": "Add Password",
+ "identity-block.bot-protection-error": "Please verify that you are not a robot.",
"identity-block.cancel": "Cancel",
"identity-block.confirm-password": "Confirm password",
"identity-block.confirm-password-error": "Passwords must match",
@@ -118,6 +119,7 @@
"identity-block.disconnect-account": "Disconnect",
"identity-block.edit": "Edit",
"identity-block.email": "Email address",
+ "identity-block.email-label": "Email",
"identity-block.email-requirements": "Please enter a valid email address",
"identity-block.forgot-password-error": "There was an error processing your request.",
"identity-block.forgot-password-headline": "Forgot Password",
@@ -126,11 +128,12 @@
"identity-block.forgot-password-instruction-submitted": "If there is an account associated with your email address, you’ll receive a link in your inbox to reset your password.",
"identity-block.forgot-password-submit": "Send",
"identity-block.log-in": "Log In",
+ "identity-block.log-in-headline": "Log in to your account",
"identity-block.log-out": "Log Out",
"identity-block.login-form-error": "There's been an error logging you in",
"identity-block.login-links-forgot": "Forgot your password?",
"identity-block.login-links-login": "Already have an account? Log in",
- "identity-block.login-links-signup": "Don't have an account? Sign up",
+ "identity-block.login-links-signup": "Need to create an account? ",
"identity-block.login-options": "Log in options",
"identity-block.manage-account": "Manage Your Account",
"identity-block.new-password": "New Password",
@@ -142,6 +145,7 @@
"identity-block.password-requirements-numbers": "Must have at least %{requirementCount} number(s).",
"identity-block.password-requirements-special": "Must have at least %{requirementCount} special character(s).",
"identity-block.password-requirements-uppercase": "Must have at least %{requirementCount} uppercase character(s).",
+ "identity-block.privacy-statement": "By creating an account, you agree to the Terms of Service and acknowledge our Privacy Policy.",
"identity-block.reset-password-error": "There was an error processing your request.",
"identity-block.reset-password-headline": "Create your new password",
"identity-block.reset-password-headline-submitted": "New password saved",
@@ -151,6 +155,7 @@
"identity-block.reset-password-submit-submitted": "Continue to log in",
"identity-block.save": "Save",
"identity-block.sign-up": "Sign Up",
+ "identity-block.sign-up-natural": "Sign up",
"identity-block.sign-up-form-error": "There's been an error creating your account",
"identity-block.terms-privacy-text": "By creating an account, you agree to the Terms of Service<\/a> and acknowledge our Privacy Policy<\/a>.",
"identity-block.update-email-error": "There's been an error updating your email address",
diff --git a/package-lock.json b/package-lock.json
index f19d5af83c..f7f1d7f6cc 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -398,7 +398,8 @@
"license": "CC-BY-NC-ND-4.0",
"dependencies": {
"@arc-fusion/prop-types": "^0.1.5",
- "@arc-publishing/sdk-identity": "^1.79.0"
+ "@arc-publishing/sdk-identity": "^1.79.0",
+ "react-google-recaptcha": "^3.1.0"
},
"peerDependencies": {
"@wpmedia/arc-themes-components": "*"
@@ -14732,7 +14733,6 @@
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
- "dev": true,
"dependencies": {
"react-is": "^16.7.0"
}
@@ -14740,8 +14740,7 @@
"node_modules/hoist-non-react-statics/node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
- "dev": true
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/hosted-git-info": {
"version": "4.1.0",
@@ -23181,6 +23180,18 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-async-script": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/react-async-script/-/react-async-script-1.2.0.tgz",
+ "integrity": "sha512-bCpkbm9JiAuMGhkqoAiC0lLkb40DJ0HOEJIku+9JDjxX3Rcs+ztEOG13wbrOskt3n2DTrjshhaQ/iay+SnGg5Q==",
+ "dependencies": {
+ "hoist-non-react-statics": "^3.3.0",
+ "prop-types": "^15.5.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.4.1"
+ }
+ },
"node_modules/react-clientside-effect": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/react-clientside-effect/-/react-clientside-effect-1.2.6.tgz",
@@ -23265,6 +23276,18 @@
}
}
},
+ "node_modules/react-google-recaptcha": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/react-google-recaptcha/-/react-google-recaptcha-3.1.0.tgz",
+ "integrity": "sha512-cYW2/DWas8nEKZGD7SCu9BSuVz8iOcOLHChHyi7upUuVhkpkhYG/6N3KDiTQ3XAiZ2UAZkfvYKMfAHOzBOcGEg==",
+ "dependencies": {
+ "prop-types": "^15.5.0",
+ "react-async-script": "^1.2.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.4.1"
+ }
+ },
"node_modules/react-helmet-async": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz",
From 382b77e32961a3c1723c46a338a3759a1cb1a180 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 25 Mar 2024 14:12:04 -0400
Subject: [PATCH 2/3] Bump @babel/eslint-parser from 7.23.10 to 7.24.1 (#2045)
Bumps [@babel/eslint-parser](https://github.com/babel/babel/tree/HEAD/eslint/babel-eslint-parser) from 7.23.10 to 7.24.1.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.1/eslint/babel-eslint-parser)
---
updated-dependencies:
- dependency-name: "@babel/eslint-parser"
dependency-type: direct:development
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
package-lock.json | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index f7f1d7f6cc..218d61171d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1050,9 +1050,9 @@
}
},
"node_modules/@babel/eslint-parser": {
- "version": "7.23.10",
- "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.23.10.tgz",
- "integrity": "sha512-3wSYDPZVnhseRnxRJH6ZVTNknBz76AEnyC+AYYhasjP3Yy23qz0ERR7Fcd2SHmYuSFJ2kY9gaaDd3vyqU09eSw==",
+ "version": "7.24.1",
+ "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.24.1.tgz",
+ "integrity": "sha512-d5guuzMlPeDfZIbpQ8+g1NaCNuAGBBGNECh0HVqz1sjOeVLh2CEaifuOysCH18URW6R7pqXINvf5PaR/dC6jLQ==",
"dev": true,
"dependencies": {
"@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1",
From 092cfba210c365041ea36372b70f9933adc3fc48 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 25 Mar 2024 14:17:41 -0400
Subject: [PATCH 3/3] Bump @babel/preset-env from 7.24.1 to 7.24.3 (#2047)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.24.1 to 7.24.3.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.3/packages/babel-preset-env)
---
updated-dependencies:
- dependency-name: "@babel/preset-env"
dependency-type: direct:development
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
package-lock.json | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 218d61171d..29755cd8e1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1854,9 +1854,9 @@
}
},
"node_modules/@babel/plugin-transform-async-generator-functions": {
- "version": "7.24.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.1.tgz",
- "integrity": "sha512-OTkLJM0OtmzcpOgF7MREERUCdCnCBtBsq3vVFbuq/RKMK0/jdYqdMexWi3zNs7Nzd95ase65MbTGrpFJflOb6A==",
+ "version": "7.24.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.3.tgz",
+ "integrity": "sha512-Qe26CMYVjpQxJ8zxM1340JFNjZaF+ISWpr1Kt/jGo+ZTUzKkfw/pphEWbRCb+lmSM6k/TOgfYLvmbHkUQ0asIg==",
"dev": true,
"dependencies": {
"@babel/helper-environment-visitor": "^7.22.20",
@@ -2675,9 +2675,9 @@
}
},
"node_modules/@babel/preset-env": {
- "version": "7.24.1",
- "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.1.tgz",
- "integrity": "sha512-CwCMz1Z28UHLI2iE+cbnWT2epPMV9bzzoBGM6A3mOS22VQd/1TPoWItV7S7iL9TkPmPEf5L/QzurmztyyDN9FA==",
+ "version": "7.24.3",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.3.tgz",
+ "integrity": "sha512-fSk430k5c2ff8536JcPvPWK4tZDwehWLGlBp0wrsBUjZVdeQV6lePbwKWZaZfK2vnh/1kQX1PzAJWsnBmVgGJA==",
"dev": true,
"dependencies": {
"@babel/compat-data": "^7.24.1",
@@ -2707,7 +2707,7 @@
"@babel/plugin-syntax-top-level-await": "^7.14.5",
"@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
"@babel/plugin-transform-arrow-functions": "^7.24.1",
- "@babel/plugin-transform-async-generator-functions": "^7.24.1",
+ "@babel/plugin-transform-async-generator-functions": "^7.24.3",
"@babel/plugin-transform-async-to-generator": "^7.24.1",
"@babel/plugin-transform-block-scoped-functions": "^7.24.1",
"@babel/plugin-transform-block-scoping": "^7.24.1",
@@ -2756,7 +2756,7 @@
"@babel/plugin-transform-unicode-sets-regex": "^7.24.1",
"@babel/preset-modules": "0.1.6-no-external-plugins",
"babel-plugin-polyfill-corejs2": "^0.4.10",
- "babel-plugin-polyfill-corejs3": "^0.10.1",
+ "babel-plugin-polyfill-corejs3": "^0.10.4",
"babel-plugin-polyfill-regenerator": "^0.6.1",
"core-js-compat": "^3.31.0",
"semver": "^6.3.1"
@@ -10123,13 +10123,13 @@
}
},
"node_modules/babel-plugin-polyfill-corejs3": {
- "version": "0.10.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.1.tgz",
- "integrity": "sha512-XiFei6VGwM4ii6nKC1VCenGD8Z4bjiNYcrdkM8oqM3pbuemmyb8biMgrDX1ZHSbIuMLXatM6JJ/StPYIuTl6MQ==",
+ "version": "0.10.4",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz",
+ "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==",
"dev": true,
"dependencies": {
"@babel/helper-define-polyfill-provider": "^0.6.1",
- "core-js-compat": "^3.36.0"
+ "core-js-compat": "^3.36.1"
},
"peerDependencies": {
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"