From b5e6703f359e4e456324c28b0ebf5775188daf11 Mon Sep 17 00:00:00 2001 From: Antoine Moreaux Date: Wed, 1 Oct 2025 15:15:40 +0200 Subject: [PATCH] =?UTF-8?q?refactor(captcha):=20add=20path-based=20captcha?= =?UTF-8?q?=20check=20and=20cleanup=20unused=20to=E2=80=A6=20(#14803)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …ken requests --- .../src/modules/auth/hooks/useAuth.ts | 8 ++++++-- .../auth/sign-in-up/hooks/useSignInWithGoogle.ts | 6 ++++-- .../CaptchaProviderScriptLoaderEffect.tsx | 16 ++++++++++++++-- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/packages/twenty-front/src/modules/auth/hooks/useAuth.ts b/packages/twenty-front/src/modules/auth/hooks/useAuth.ts index 4f2e559baf..3e3b558cfb 100644 --- a/packages/twenty-front/src/modules/auth/hooks/useAuth.ts +++ b/packages/twenty-front/src/modules/auth/hooks/useAuth.ts @@ -65,6 +65,7 @@ import { type AuthToken } from '~/generated/graphql'; import { cookieStorage } from '~/utils/cookie-storage'; import { getWorkspaceUrl } from '~/utils/getWorkspaceUrl'; import { loginTokenState } from '../states/loginTokenState'; +import { isCaptchaScriptLoadedState } from '@/captcha/states/isCaptchaScriptLoadedState'; export const useAuth = () => { const setTokenPair = useSetRecoilState(tokenPairState); @@ -72,6 +73,7 @@ export const useAuth = () => { const { origin } = useOrigin(); const { requestFreshCaptchaToken } = useRequestFreshCaptchaToken(); + const isCaptchaScriptLoaded = useRecoilValue(isCaptchaScriptLoadedState); const isMultiWorkspaceEnabled = useRecoilValue(isMultiWorkspaceEnabledState); const isEmailVerificationRequired = useRecoilValue( isEmailVerificationRequiredState, @@ -164,6 +166,7 @@ export const useAuth = () => { set(isCurrentUserLoadedState, isCurrentUserLoaded); set(isMultiWorkspaceEnabledState, isMultiWorkspaceEnabled); set(domainConfigurationState, domainConfiguration); + set(isCaptchaScriptLoadedState, isCaptchaScriptLoaded); return undefined; }); @@ -183,6 +186,7 @@ export const useAuth = () => { setLastAuthenticateWorkspaceDomain, loadMockedObjectMetadataItems, navigate, + isCaptchaScriptLoaded, ], ); @@ -493,8 +497,8 @@ export const useAuth = () => { const handleSignOut = useCallback(async () => { await clearSession(); - await requestFreshCaptchaToken(); - }, [clearSession, requestFreshCaptchaToken]); + if (isCaptchaScriptLoaded) await requestFreshCaptchaToken(); + }, [clearSession, isCaptchaScriptLoaded, requestFreshCaptchaToken]); const handleCredentialsSignUpInWorkspace = useCallback( async ({ diff --git a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInWithGoogle.ts b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInWithGoogle.ts index 49e5534717..dd741cd037 100644 --- a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInWithGoogle.ts +++ b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInWithGoogle.ts @@ -3,6 +3,8 @@ import { useParams, useSearchParams } from 'react-router-dom'; import { useAuth } from '@/auth/hooks/useAuth'; import { type BillingCheckoutSession } from '@/auth/types/billingCheckoutSession.type'; import { type SocialSSOSignInUpActionType } from '@/auth/types/socialSSOSignInUp.type'; +import { BillingPlanKey } from '~/generated/graphql'; +import { SubscriptionInterval } from '~/generated-metadata/graphql'; export const useSignInWithGoogle = () => { const workspaceInviteHash = useParams().workspaceInviteHash; @@ -10,8 +12,8 @@ export const useSignInWithGoogle = () => { const workspacePersonalInviteToken = searchParams.get('inviteToken') ?? undefined; const billingCheckoutSession = { - plan: 'PRO', - interval: 'Month', + plan: BillingPlanKey.PRO, + interval: SubscriptionInterval.Month, requirePaymentMethod: true, } as BillingCheckoutSession; diff --git a/packages/twenty-front/src/modules/captcha/components/CaptchaProviderScriptLoaderEffect.tsx b/packages/twenty-front/src/modules/captcha/components/CaptchaProviderScriptLoaderEffect.tsx index 2ed72ff107..95d6f39603 100644 --- a/packages/twenty-front/src/modules/captcha/components/CaptchaProviderScriptLoaderEffect.tsx +++ b/packages/twenty-front/src/modules/captcha/components/CaptchaProviderScriptLoaderEffect.tsx @@ -1,5 +1,6 @@ import { useEffect } from 'react'; import { useRecoilState, useRecoilValue } from 'recoil'; +import { useLocation } from 'react-router-dom'; import { useRequestFreshCaptchaToken } from '@/captcha/hooks/useRequestFreshCaptchaToken'; import { isCaptchaScriptLoadedState } from '@/captcha/states/isCaptchaScriptLoadedState'; @@ -7,6 +8,7 @@ import { getCaptchaUrlByProvider } from '@/captcha/utils/getCaptchaUrlByProvider import { captchaState } from '@/client-config/states/captchaState'; import { CaptchaDriverType } from '~/generated/graphql'; import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; +import { isCaptchaRequiredForPath } from '@/captcha/utils/isCaptchaRequiredForPath'; export const CaptchaProviderScriptLoaderEffect = () => { const captcha = useRecoilValue(captchaState); @@ -14,9 +16,14 @@ export const CaptchaProviderScriptLoaderEffect = () => { isCaptchaScriptLoadedState, ); const { requestFreshCaptchaToken } = useRequestFreshCaptchaToken(); + const location = useLocation(); useEffect(() => { - if (!captcha?.provider || !captcha.siteKey) { + if ( + !captcha?.provider || + !captcha.siteKey || + !isCaptchaRequiredForPath(location.pathname) + ) { return; } @@ -45,7 +52,12 @@ export const CaptchaProviderScriptLoaderEffect = () => { }; document.body.appendChild(scriptElement); } - }, [captcha?.provider, captcha?.siteKey, setIsCaptchaScriptLoaded]); + }, [ + captcha?.provider, + captcha?.siteKey, + setIsCaptchaScriptLoaded, + location.pathname, + ]); useEffect(() => { if (isUndefinedOrNull(captcha?.provider) || !isCaptchaScriptLoaded) {