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"