Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ReCaptcha: migrate back to v2 solution #2446

Merged
merged 16 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN=xxx
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=xxx
NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY=xxx
NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY=xxx
NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID=UA-XXXXXX-X
NEXT_PUBLIC_MIXPANEL_PROJECT_TOKEN=xxx
NEXT_PUBLIC_GROWTH_BOOK_CLIENT_KEY=xxx
Expand Down
4 changes: 2 additions & 2 deletions configs/app/features/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import { getEnvValue } from '../utils';
const title = 'My account';

const config: Feature<{ isEnabled: true; recaptchaSiteKey: string }> = (() => {
if (getEnvValue('NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED') === 'true' && services.reCaptchaV3.siteKey) {
if (getEnvValue('NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED') === 'true' && services.reCaptchaV2.siteKey) {
return Object.freeze({
title,
isEnabled: true,
recaptchaSiteKey: services.reCaptchaV3.siteKey,
recaptchaSiteKey: services.reCaptchaV2.siteKey,
});
}

Expand Down
4 changes: 2 additions & 2 deletions configs/app/features/csvExport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import services from '../services';
const title = 'Export data to CSV file';

const config: Feature<{ reCaptcha: { siteKey: string } }> = (() => {
if (services.reCaptchaV3.siteKey) {
if (services.reCaptchaV2.siteKey) {
return Object.freeze({
title,
isEnabled: true,
reCaptcha: {
siteKey: services.reCaptchaV3.siteKey,
siteKey: services.reCaptchaV2.siteKey,
},
});
}
Expand Down
2 changes: 1 addition & 1 deletion configs/app/features/publicTagsSubmission.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const apiHost = getEnvValue('NEXT_PUBLIC_ADMIN_SERVICE_API_HOST');
const title = 'Public tag submission';

const config: Feature<{ api: { endpoint: string; basePath: string } }> = (() => {
if (services.reCaptchaV3.siteKey && addressMetadata.isEnabled && apiHost) {
if (services.reCaptchaV2.siteKey && addressMetadata.isEnabled && apiHost) {
return Object.freeze({
title,
isEnabled: true,
Expand Down
4 changes: 2 additions & 2 deletions configs/app/services.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getEnvValue } from './utils';

export default Object.freeze({
reCaptchaV3: {
siteKey: getEnvValue('NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY'),
reCaptchaV2: {
siteKey: getEnvValue('NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY'),
},
});
2 changes: 1 addition & 1 deletion configs/envs/.env.jest
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,4 @@ NEXT_PUBLIC_AUTH0_CLIENT_ID=xxx
NEXT_PUBLIC_STATS_API_HOST=https://localhost:3004
NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://localhost:3005
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://localhost:3006
NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY=xxx
NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY=xxx
2 changes: 1 addition & 1 deletion configs/envs/.env.pw
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ NEXT_PUBLIC_CONTRACT_INFO_API_HOST=http://localhost:3005
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=http://localhost:3006
NEXT_PUBLIC_METADATA_SERVICE_API_HOST=http://localhost:3007
NEXT_PUBLIC_NAME_SERVICE_API_HOST=http://localhost:3008
NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY=xxx
NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY=xxx
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=xxx
NEXT_PUBLIC_VIEWS_ADDRESS_FORMAT=['base16','bech32']
NEXT_PUBLIC_VIEWS_ADDRESS_BECH_32_PREFIX=tom
Expand Down
6 changes: 3 additions & 3 deletions deploy/tools/envs-validator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ function printDeprecationWarning(envsMap: Record<string, string>) {
if (envsMap.NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY && envsMap.NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY) {
console.log('❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗');
// eslint-disable-next-line max-len
console.warn('The NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY variables are now deprecated and will be removed in the next release. Please migrate to the NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY variable.');
console.warn('The NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY variable is now deprecated and will be removed in the next release. Please migrate to the NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY variable.');
console.log('❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗\n');
}

Expand Down Expand Up @@ -182,9 +182,9 @@ function printDeprecationWarning(envsMap: Record<string, string>) {
function checkDeprecatedEnvs(envsMap: Record<string, string>) {
!silent && console.log(`🌀 Checking deprecated environment variables...`);

if (envsMap.NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY && !envsMap.NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY) {
if (!envsMap.NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY && envsMap.NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY) {
// eslint-disable-next-line max-len
console.log('🚨 The NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY variable is no longer supported. Please pass NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY or remove it completely.');
console.log('🚨 The NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY variable is no longer supported. Please pass NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY or remove it completely.');
throw new Error();
}

Expand Down
4 changes: 2 additions & 2 deletions deploy/tools/envs-validator/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -882,8 +882,8 @@ const schema = yup

// 6. External services envs
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: yup.string(),
NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY: yup.string(), // DEPRECATED
NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY: yup.string(),
NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY: yup.string(),
NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY: yup.string(), // DEPRECATED
NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID: yup.string(),
NEXT_PUBLIC_MIXPANEL_PROJECT_TOKEN: yup.string(),
NEXT_PUBLIC_GROWTH_BOOK_CLIENT_KEY: yup.string(),
Expand Down
4 changes: 2 additions & 2 deletions deploy/tools/envs-validator/test/.env.alt
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ NEXT_PUBLIC_VIEWS_CONTRACT_EXTRA_VERIFICATION_METHODS=none
NEXT_PUBLIC_HOMEPAGE_STATS=[]
NEXT_PUBLIC_VIEWS_ADDRESS_FORMAT=['base16','bech32']
NEXT_PUBLIC_VIEWS_ADDRESS_BECH_32_PREFIX=foo
NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY=deprecated
NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY=xxx
NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY=xxx
NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY=deprecated
2 changes: 1 addition & 1 deletion deploy/tools/envs-validator/test/.env.base
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ NEXT_PUBLIC_AUTH_URL=https://example.com
NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
NEXT_PUBLIC_LOGOUT_URL=https://example.com
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=xxx
NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY=xxx
NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY=xxx
NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID=UA-XXXXXX-X
NEXT_PUBLIC_MIXPANEL_PROJECT_TOKEN=xxx
NEXT_PUBLIC_GROWTH_BOOK_CLIENT_KEY=xxx
Expand Down
2 changes: 1 addition & 1 deletion deploy/values/review-l2/values.yaml.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,4 @@ frontend:
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: ref+vault://deployment-values/blockscout/dev/review-l2?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID
NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID: ref+vault://deployment-values/blockscout/dev/review-l2?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID
NEXT_PUBLIC_OG_IMAGE_URL: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/base-mainnet.png
NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY: ref+vault://deployment-values/blockscout/common?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY
NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY: ref+vault://deployment-values/blockscout/eth-sepolia/testnet?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/RE_CAPTCHA_CLIENT_KEY
3 changes: 2 additions & 1 deletion deploy/values/review/values.yaml.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,12 @@ frontend:
NEXT_PUBLIC_DATA_AVAILABILITY_ENABLED: true
NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES: "['/apps']"
PROMETHEUS_METRICS_ENABLED: true
NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED: true
envFromSecret:
NEXT_PUBLIC_AUTH0_CLIENT_ID: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_AUTH0_CLIENT_ID
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID
NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID
NEXT_PUBLIC_GROWTH_BOOK_CLIENT_KEY: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_GROWTH_BOOK_CLIENT_KEY
NEXT_PUBLIC_MIXPANEL_PROJECT_TOKEN: ref+vault://deployment-values/blockscout/common?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_MIXPANEL_PROJECT_TOKEN
NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY: ref+vault://deployment-values/blockscout/common?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY
NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY: ref+vault://deployment-values/blockscout/eth-sepolia/testnet?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/RE_CAPTCHA_CLIENT_KEY
NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN: ref+vault://deployment-values/blockscout/common?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN
1 change: 0 additions & 1 deletion docs/DEPRECATED_ENVS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,3 @@
| NEXT_PUBLIC_NETWORK_GOVERNANCE_TOKEN_SYMBOL | `string` | Network governance token symbol | - | - | `GNO` | v1.12.0 | v1.29.0 | Replaced by NEXT_PUBLIC_NETWORK_SECONDARY_COIN_SYMBOL |
| NEXT_PUBLIC_SWAP_BUTTON_URL | `string` | Application ID in the marketplace or website URL | - | - | `uniswap` | v1.24.0 | v1.31.0 | Replaced by NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS |
| NEXT_PUBLIC_HOMEPAGE_SHOW_AVG_BLOCK_TIME | `boolean` | Set to false if average block time is useless for the network | - | `true` | `false` | v1.0.x+ | v1.35.0 | Replaced by NEXT_PUBLIC_HOMEPAGE_STATS |
| NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY | `string` | Google reCAPTCHA v2 site key | - | - | `<your-secret>` | v1.0.x+ | v1.36.0 | Replaced by NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY |
9 changes: 5 additions & 4 deletions docs/ENVS.md
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ Settings for meta tags, OG tags and SEO
| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
| --- | --- | --- | --- | --- | --- | --- |
| NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED | `boolean` | Set to true if network has account feature | Required | - | `true` | v1.0.x+ |
| NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY | `boolean` | See [below](ENVS.md#google-recaptcha) | Required | - | `<your-secret>` | v1.36.0+ |
| NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY | `boolean` | See [below](ENVS.md#google-recaptcha) | Required | - | `<your-secret>` | v1.0.x+ |
| NEXT_PUBLIC_AUTH0_CLIENT_ID | `string` | **DEPRECATED** Client id for [Auth0](https://auth0.com/) provider | - | - | `<your-secret>` | v1.0.x+ |
| NEXT_PUBLIC_AUTH_URL | `string` | **DEPRECATED** Account auth base url; it is used for building login URL (`${ NEXT_PUBLIC_AUTH_URL }/auth/auth0`) and logout return URL (`${ NEXT_PUBLIC_AUTH_URL }/auth/logout`); if not provided the base app URL will be used instead | - | - | `https://blockscout.com` | v1.0.x+ |
| NEXT_PUBLIC_LOGOUT_URL | `string` | **DEPRECATED** Account logout url. Required if account is supported for the app instance. | - | - | `https://blockscoutcom.us.auth0.com/v2/logout` | v1.0.x+ |
Expand Down Expand Up @@ -451,7 +451,7 @@ This feature is **enabled by default** with the `coinzilla` ads provider. To swi

| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
| --- | --- | --- | --- | --- | --- | --- |
| NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY | `string` | See [below](ENVS.md#google-recaptcha) | true | - | `<your-secret>` | v1.36.0+ |
| NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY | `string` | See [below](ENVS.md#google-recaptcha) | true | - | `<your-secret>` | v1.0.x+ |

&nbsp;

Expand Down Expand Up @@ -613,6 +613,7 @@ This feature allows you to submit an application with a public address tag.
| --- | --- | --- | --- | --- | --- | --- |
| NEXT_PUBLIC_METADATA_SERVICE_API_HOST | `string` | Metadata Service API endpoint url | Required | - | `https://metadata.services.blockscout.com` | v1.30.0+ |
| NEXT_PUBLIC_ADMIN_SERVICE_API_HOST | `string` | Admin Service API endpoint url | Required | - | `https://admin-rs.services.blockscout.com` | v1.1.0+ |
| NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY | `string` | See [below](ENVS.md#google-recaptcha) | true | - | `<your-secret>` | v1.0.x+ |

&nbsp;

Expand Down Expand Up @@ -847,5 +848,5 @@ For obtaining the variables values please refer to [reCAPTCHA documentation](htt

| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
| --- | --- | --- | --- | --- | --- | --- |
| NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY | `string` | Google reCAPTCHA v3 site key | - | - | `<your-secret>` | v1.36.0+ |
| NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY | `string` | **DEPRECATED** Google reCAPTCHA v2 site key | - | - | `<your-secret>` | v1.0.x+ |
| NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY | `string` | **DEPRECATED** Google reCAPTCHA v3 site key | - | - | `<your-secret>` | v1.36.0+ |
| NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY | `string` | Google reCAPTCHA v2 site key | - | - | `<your-secret>` | v1.0.x+ |
2 changes: 1 addition & 1 deletion nextjs/csp/policies/googleReCaptcha.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type CspDev from 'csp-dev';
import config from 'configs/app';

export function googleReCaptcha(): CspDev.DirectiveDescriptor {
if (!config.services.reCaptchaV3.siteKey) {
if (!config.services.reCaptchaV2.siteKey) {
return {};
}

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
"react": "18.3.1",
"react-device-detect": "^2.2.3",
"react-dom": "18.3.1",
"react-google-recaptcha-v3": "1.10.1",
"react-google-recaptcha": "3.1.0",
"react-hook-form": "7.52.1",
"react-identicons": "^1.2.5",
"react-intersection-observer": "^9.5.2",
Expand Down
3 changes: 3 additions & 0 deletions playwright-ct.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ const config: PlaywrightTestConfig = defineConfig({
// Mock for growthbook to test feature flags
{ find: 'lib/growthbook/useFeatureValue', replacement: './playwright/mocks/lib/growthbook/useFeatureValue.js' },

// Mock for reCaptcha hook
{ find: 'ui/shared/reCaptcha/useReCaptcha', replacement: './playwright/mocks/ui/shared/recaptcha/useReCaptcha.js' },

// The createWeb3Modal() function from web3modal/wagmi/react somehow pollutes the global styles which causes the tests to fail
// We don't call this function in TestApp and since we use useWeb3Modal() and useWeb3ModalState() hooks in the code, we have to mock the module
// Otherwise it will complain that createWeb3Modal() is no called before the hooks are used
Expand Down
8 changes: 8 additions & 0 deletions playwright/mocks/ui/shared/recaptcha/useReCaptcha.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const useReCaptcha = () => {
return {
ref: { current: null },
executeAsync: () => Promise.resolve('recaptcha_token'),
};
};

export default useReCaptcha;
15 changes: 14 additions & 1 deletion theme/globals/recaptcha.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
const styles = () => {
return {
'.grecaptcha-badge': {
zIndex: 'toast',
visibility: 'hidden',
},
'div:has(div):has(iframe[title="recaptcha challenge expires in two minutes"])': {
'&::after': {
content: `" "`,
display: 'block',
position: 'fixed',
top: 0,
left: 0,
width: '100vw',
height: '100vh',
zIndex: 100000,
bgColor: 'blackAlpha.300',
},
},
};
};
Expand Down
63 changes: 34 additions & 29 deletions ui/csvExport/CsvExportForm.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Alert, Button, chakra, Flex } from '@chakra-ui/react';
import React from 'react';
import { GoogleReCaptchaProvider } from 'react-google-recaptcha-v3';
import type { SubmitHandler } from 'react-hook-form';
import { useForm, FormProvider } from 'react-hook-form';

Expand All @@ -13,7 +12,8 @@ import type { ResourceName } from 'lib/api/resources';
import dayjs from 'lib/date/dayjs';
import downloadBlob from 'lib/downloadBlob';
import useToast from 'lib/hooks/useToast';
import FormFieldReCaptcha from 'ui/shared/forms/fields/FormFieldReCaptcha';
import ReCaptcha from 'ui/shared/reCaptcha/ReCaptcha';
import useReCaptcha from 'ui/shared/reCaptcha/useReCaptcha';

import CsvExportFormField from './CsvExportFormField';

Expand All @@ -36,16 +36,23 @@ const CsvExportForm = ({ hash, resource, filterType, filterValue, fileNameTempla
});
const { handleSubmit, formState } = formApi;
const toast = useToast();
const recaptcha = useReCaptcha();

const onFormSubmit: SubmitHandler<FormFields> = React.useCallback(async(data) => {
try {
const token = await recaptcha.executeAsync();

if (!token) {
throw new Error('ReCaptcha is not solved');
}

const url = buildUrl(resource, { hash } as never, {
address_id: hash,
from_period: exportType !== 'holders' ? data.from : null,
to_period: exportType !== 'holders' ? data.to : null,
filter_type: filterType,
filter_value: filterValue,
recaptcha_v3_response: data.reCaptcha,
recaptcha_response: token,
});

const response = await fetch(url, {
Expand Down Expand Up @@ -76,9 +83,9 @@ const CsvExportForm = ({ hash, resource, filterType, filterValue, fileNameTempla
});
}

}, [ resource, hash, exportType, filterType, filterValue, fileNameTemplate, toast ]);
}, [ recaptcha, resource, hash, exportType, filterType, filterValue, fileNameTemplate, toast ]);

if (!config.services.reCaptchaV3.siteKey) {
if (!config.services.reCaptchaV2.siteKey) {
return (
<Alert status="error">
CSV export is not available at the moment since reCaptcha is not configured for this application.
Expand All @@ -88,31 +95,29 @@ const CsvExportForm = ({ hash, resource, filterType, filterValue, fileNameTempla
}

return (
<GoogleReCaptchaProvider reCaptchaKey={ config.services.reCaptchaV3.siteKey }>
<FormProvider { ...formApi }>
<chakra.form
noValidate
onSubmit={ handleSubmit(onFormSubmit) }
<FormProvider { ...formApi }>
<chakra.form
noValidate
onSubmit={ handleSubmit(onFormSubmit) }
>
<Flex columnGap={ 5 } rowGap={ 3 } flexDir={{ base: 'column', lg: 'row' }} alignItems={{ base: 'flex-start', lg: 'center' }} flexWrap="wrap">
{ exportType !== 'holders' && <CsvExportFormField name="from" formApi={ formApi }/> }
{ exportType !== 'holders' && <CsvExportFormField name="to" formApi={ formApi }/> }
</Flex>
<ReCaptcha ref={ recaptcha.ref }/>
<Button
variant="solid"
size="lg"
type="submit"
mt={ 8 }
isLoading={ formState.isSubmitting }
loadingText="Download"
isDisabled={ Boolean(formState.errors.from || formState.errors.to) }
>
<Flex columnGap={ 5 } rowGap={ 3 } flexDir={{ base: 'column', lg: 'row' }} alignItems={{ base: 'flex-start', lg: 'center' }} flexWrap="wrap">
{ exportType !== 'holders' && <CsvExportFormField name="from" formApi={ formApi }/> }
{ exportType !== 'holders' && <CsvExportFormField name="to" formApi={ formApi }/> }
<FormFieldReCaptcha/>
</Flex>
<Button
variant="solid"
size="lg"
type="submit"
mt={ 8 }
isLoading={ formState.isSubmitting }
loadingText="Download"
isDisabled={ Boolean(formState.errors.from || formState.errors.to) }
>
Download
</Button>
</chakra.form>
</FormProvider>
</GoogleReCaptchaProvider>
Download
</Button>
</chakra.form>
</FormProvider>
);
};

Expand Down
1 change: 0 additions & 1 deletion ui/csvExport/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export interface FormFields {
from: string;
to: string;
reCaptcha: string;
}
Loading
Loading