Skip to content

Commit

Permalink
ReCaptcha: migrate back to v2 solution (#2446)
Browse files Browse the repository at this point in the history
* show recaptcha in the site footer

* replace badge in footer with text

* add invisible reCaptcha v2

* handle unsolved reCaptcha case

* migrate the rest of components to invisible reCaptcha v2

* remove unused code

* refactoring

* add env for demo

* fix tests

* update values for demo

* update link to secret in vault

* mock recaptcha for tests

* ohhh victor victor

* fix token metadata update test

* deprecate variable for ReCaptcha v3
  • Loading branch information
tom2drum authored Dec 9, 2024
1 parent cd27e8f commit a8bb817
Show file tree
Hide file tree
Showing 60 changed files with 343 additions and 284 deletions.
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 @@ -889,8 +889,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 @@ -349,7 +349,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 @@ -452,7 +452,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 @@ -614,6 +614,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 @@ -848,5 +849,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 @@ -102,7 +102,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

0 comments on commit a8bb817

Please sign in to comment.