From a624841d5f8e366a813115fa970eec69ed8683be Mon Sep 17 00:00:00 2001 From: 49659410+tx0c <> Date: Wed, 20 Sep 2023 23:30:16 +0000 Subject: [PATCH] feat(turnstile): Use Cloudflare Turnstile instead of Google reCAPTCHA resolves #3313 --- .env.dev | 1 + .env.prod | 1 + package-lock.json | 17 ++++++++ package.json | 1 + src/components/Forms/EmailSignUpForm/Init.tsx | 30 +++++++++----- .../AppreciationButton/index.tsx | 39 ++++++++++++------- 6 files changed, 67 insertions(+), 22 deletions(-) diff --git a/.env.dev b/.env.dev index 228087110e..51feee5bbd 100644 --- a/.env.dev +++ b/.env.dev @@ -32,6 +32,7 @@ NEXT_PUBLIC_CURATION_CONTRACT_ADDRESS=0xa219c6722008aa22828b31a13ab9ba93bb91222c NEXT_PUBLIC_GOOGLE_CLIENT_ID=315393900359-2r9fundftis7dc0tdeo2hf8630nfdd8h.apps.googleusercontent.com NEXT_PUBLIC_TWITTER_CLIENT_ID=bWF1QmMzY2JPLTB2alJiZHdsMjI6MTpjaQ NEXT_PUBLIC_FACEBOOK_CLIENT_ID=823885921293850 +NEXT_PUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY=0x4AAAAAAAKiedvR5qiLUhIs DEBUG=false PLAYWRIGHT_RUNTIME_ENV=ci PLAYWRIGHT_TEST_BASE_URL=https://web-develop.matters.town diff --git a/.env.prod b/.env.prod index b21a036455..0af85a78ac 100644 --- a/.env.prod +++ b/.env.prod @@ -27,6 +27,7 @@ NEXT_PUBLIC_LOGBOOKS_URL=https://logbook.matters.town NEXT_PUBLIC_ALCHEMY_KEY=bOu-fCphi9mvePsxg968Qe-pidHQNdlT NEXT_PUBLIC_USDT_CONTRACT_ADDRESS=0xc2132D05D31c914a87C6611C10748AEb04B58e8F NEXT_PUBLIC_CURATION_CONTRACT_ADDRESS=0x5edebbdae7b5c79a69aacf7873796bb1ec664db8 +NEXT_PUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY=0x4AAAAAAAKVODkJMwfIxG78 DEBUG=false NEXT_PUBLIC_GOOGLE_CLIENT_ID= NEXT_PUBLIC_TWITTER_CLIENT_ID=cmdKbUlyd1ZZZDZYa3dTampidGo6MTpjaQ diff --git a/package-lock.json b/package-lock.json index b9ddb188d8..0ab400e132 100644 --- a/package-lock.json +++ b/package-lock.json @@ -101,6 +101,7 @@ "@formatjs/cli": "^6.1.3", "@graphql-codegen/cli": "3.3.1", "@graphql-codegen/client-preset": "3.0.1", + "@marsidev/react-turnstile": "^0.3.1", "@playwright/test": "^1.35.1", "@storybook/addon-a11y": "^7.0.26", "@storybook/addon-actions": "^7.0.26", @@ -6904,6 +6905,16 @@ "resolved": "https://registry.npmjs.org/@lokesh.dhakar/quantize/-/quantize-1.3.0.tgz", "integrity": "sha512-4KBSyaMj65d8A+2vnzLxtHFu4OmBU4IKO0yLxZ171Itdf9jGV4w+WbG7VsKts2jUdRkFSzsZqpZOz6hTB3qGAw==" }, + "node_modules/@marsidev/react-turnstile": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@marsidev/react-turnstile/-/react-turnstile-0.3.1.tgz", + "integrity": "sha512-XnpIUqufuZp2VoC14fmYztB2/8lSABh8eFG6TWAR7Loipdy0p2lZXzuvUOTcQl69j1XKvWu3WChFCBWx/Cbd1A==", + "dev": true, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, "node_modules/@matters/apollo-upload-client": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/@matters/apollo-upload-client/-/apollo-upload-client-11.1.0.tgz", @@ -44054,6 +44065,12 @@ "resolved": "https://registry.npmjs.org/@lokesh.dhakar/quantize/-/quantize-1.3.0.tgz", "integrity": "sha512-4KBSyaMj65d8A+2vnzLxtHFu4OmBU4IKO0yLxZ171Itdf9jGV4w+WbG7VsKts2jUdRkFSzsZqpZOz6hTB3qGAw==" }, + "@marsidev/react-turnstile": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@marsidev/react-turnstile/-/react-turnstile-0.3.1.tgz", + "integrity": "sha512-XnpIUqufuZp2VoC14fmYztB2/8lSABh8eFG6TWAR7Loipdy0p2lZXzuvUOTcQl69j1XKvWu3WChFCBWx/Cbd1A==", + "dev": true + }, "@matters/apollo-upload-client": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/@matters/apollo-upload-client/-/apollo-upload-client-11.1.0.tgz", diff --git a/package.json b/package.json index 661ce88d0d..f74846dce2 100644 --- a/package.json +++ b/package.json @@ -127,6 +127,7 @@ "@formatjs/cli": "^6.1.3", "@graphql-codegen/cli": "3.3.1", "@graphql-codegen/client-preset": "3.0.1", + "@marsidev/react-turnstile": "^0.3.1", "@playwright/test": "^1.35.1", "@storybook/addon-a11y": "^7.0.26", "@storybook/addon-actions": "^7.0.26", diff --git a/src/components/Forms/EmailSignUpForm/Init.tsx b/src/components/Forms/EmailSignUpForm/Init.tsx index b5265853e7..e8423e42eb 100644 --- a/src/components/Forms/EmailSignUpForm/Init.tsx +++ b/src/components/Forms/EmailSignUpForm/Init.tsx @@ -1,6 +1,8 @@ +import type { TurnstileInstance } from '@marsidev/react-turnstile' +import { Turnstile } from '@marsidev/react-turnstile' import { useFormik } from 'formik' import _pickBy from 'lodash/pickBy' -import { useContext } from 'react' +import { useContext, useRef } from 'react' import { FormattedMessage, useIntl } from 'react-intl' import { @@ -18,7 +20,7 @@ import { IconLeft20, LanguageContext, Media, - ReCaptchaContext, + // ReCaptchaContext, TextIcon, useMutation, } from '~/components' @@ -59,9 +61,8 @@ const Init: React.FC = ({ const isNormal = authFeedType === 'normal' const isWallet = authFeedType === 'wallet' - const { token, refreshToken } = useContext(ReCaptchaContext) + const turnstileRef = useRef(null) - // const { token, refreshToken } = useContext(ReCaptchaContext) const [sendCode] = useMutation( SEND_CODE, undefined, @@ -93,7 +94,12 @@ const Init: React.FC = ({ const redirectUrl = signupCallbackUrl(email) await sendCode({ variables: { - input: { email, type: 'register', token, redirectUrl }, + input: { + email, + type: 'register', + token: turnstileRef.current?.getResponse(), + redirectUrl, + }, }, }) @@ -104,16 +110,22 @@ const Init: React.FC = ({ const [messages, codes] = parseFormSubmitErrors(error as any) setFieldError('email', intl.formatMessage(messages[codes[0]])) - - if (refreshToken) { - refreshToken() - } } }, }) const InnerForm = (
+ setStatus('error')} + // onExpire={() => setStatus('expired')} + // onSuccess={token => { setToken(token); setStatus('solved') }} + /> + } type="email" diff --git a/src/views/ArticleDetail/AppreciationButton/index.tsx b/src/views/ArticleDetail/AppreciationButton/index.tsx index 4691d137d4..b50baa8b6b 100644 --- a/src/views/ArticleDetail/AppreciationButton/index.tsx +++ b/src/views/ArticleDetail/AppreciationButton/index.tsx @@ -1,10 +1,12 @@ import { useQuery } from '@apollo/react-hooks' -import { useContext, useState } from 'react' +import type { TurnstileInstance } from '@marsidev/react-turnstile' +import { Turnstile } from '@marsidev/react-turnstile' +import { useContext, useRef, useState } from 'react' import { useDebouncedCallback } from 'use-debounce' import { APPRECIATE_DEBOUNCE, EXTERNAL_LINKS, Z_INDEX } from '~/common/enums' import { - ReCaptchaContext, + // ReCaptchaContext, toast, Tooltip, Translate, @@ -41,7 +43,10 @@ const AppreciationButton = ({ disabled, }: AppreciationButtonProps) => { const viewer = useContext(ViewerContext) - const { token, refreshToken } = useContext(ReCaptchaContext) + + const turnstileRef = useRef(null) + // const { token, refreshToken } = useContext(ReCaptchaContext) + const { data, client } = useQuery(CLIENT_PREFERENCE, { variables: { id: 'local' }, }) @@ -67,9 +72,9 @@ const AppreciationButton = ({ variables: { id: article.id, amount, - token, + token: turnstileRef.current?.getResponse(), }, - }).then(refreshToken) + }) // .then(refreshToken) } catch (e) { console.error(e) } @@ -87,7 +92,7 @@ const AppreciationButton = ({ variables: { id: article.id, amount: 1, - token, + token: turnstileRef.current?.getResponse(), superLike: true, }, update: (cache) => { @@ -216,13 +221,21 @@ const AppreciationButton = ({ // Appreciable if (canAppreciate && !disabled) { return ( - 0 ? appreciatedCount : undefined} - total={total} - isSuperLike={isSuperLike} - superLiked={superLiked} - /> + <> + + 0 ? appreciatedCount : undefined} + total={total} + isSuperLike={isSuperLike} + superLiked={superLiked} + /> + ) }