fix(twenty-front): error on captcha initialisation (#11039)
This commit is contained in:
@ -1,5 +1,4 @@
|
|||||||
import { AppRouter } from '@/app/components/AppRouter';
|
import { AppRouter } from '@/app/components/AppRouter';
|
||||||
import { CaptchaProvider } from '@/captcha/components/CaptchaProvider';
|
|
||||||
import { ApolloDevLogEffect } from '@/debug/components/ApolloDevLogEffect';
|
import { ApolloDevLogEffect } from '@/debug/components/ApolloDevLogEffect';
|
||||||
import { RecoilDebugObserverEffect } from '@/debug/components/RecoilDebugObserver';
|
import { RecoilDebugObserverEffect } from '@/debug/components/RecoilDebugObserver';
|
||||||
import { AppErrorBoundary } from '@/error-handler/components/AppErrorBoundary';
|
import { AppErrorBoundary } from '@/error-handler/components/AppErrorBoundary';
|
||||||
@ -21,19 +20,17 @@ export const App = () => {
|
|||||||
<RecoilURLSyncJSON location={{ part: 'queryParams' }}>
|
<RecoilURLSyncJSON location={{ part: 'queryParams' }}>
|
||||||
<AppErrorBoundary>
|
<AppErrorBoundary>
|
||||||
<I18nProvider i18n={i18n}>
|
<I18nProvider i18n={i18n}>
|
||||||
<CaptchaProvider>
|
<RecoilDebugObserverEffect />
|
||||||
<RecoilDebugObserverEffect />
|
<ApolloDevLogEffect />
|
||||||
<ApolloDevLogEffect />
|
<SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager">
|
||||||
<SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager">
|
<IconsProvider>
|
||||||
<IconsProvider>
|
<ExceptionHandlerProvider>
|
||||||
<ExceptionHandlerProvider>
|
<HelmetProvider>
|
||||||
<HelmetProvider>
|
<AppRouter />
|
||||||
<AppRouter />
|
</HelmetProvider>
|
||||||
</HelmetProvider>
|
</ExceptionHandlerProvider>
|
||||||
</ExceptionHandlerProvider>
|
</IconsProvider>
|
||||||
</IconsProvider>
|
</SnackBarProviderScope>
|
||||||
</SnackBarProviderScope>
|
|
||||||
</CaptchaProvider>
|
|
||||||
</I18nProvider>
|
</I18nProvider>
|
||||||
</AppErrorBoundary>
|
</AppErrorBoundary>
|
||||||
</RecoilURLSyncJSON>
|
</RecoilURLSyncJSON>
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { CaptchaProvider } from '@/captcha/components/CaptchaProvider';
|
||||||
import { ApolloProvider } from '@/apollo/components/ApolloProvider';
|
import { ApolloProvider } from '@/apollo/components/ApolloProvider';
|
||||||
import { GotoHotkeysEffectsProvider } from '@/app/effect-components/GotoHotkeysEffectsProvider';
|
import { GotoHotkeysEffectsProvider } from '@/app/effect-components/GotoHotkeysEffectsProvider';
|
||||||
import { PageChangeEffect } from '@/app/effect-components/PageChangeEffect';
|
import { PageChangeEffect } from '@/app/effect-components/PageChangeEffect';
|
||||||
@ -32,46 +33,48 @@ export const AppRouterProviders = () => {
|
|||||||
const pageTitle = getPageTitleFromPath(pathname);
|
const pageTitle = getPageTitleFromPath(pathname);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ApolloProvider>
|
<CaptchaProvider>
|
||||||
<BaseThemeProvider>
|
<ApolloProvider>
|
||||||
<ClientConfigProviderEffect />
|
<BaseThemeProvider>
|
||||||
<ClientConfigProvider>
|
<ClientConfigProviderEffect />
|
||||||
<ChromeExtensionSidecarEffect />
|
<ClientConfigProvider>
|
||||||
<ChromeExtensionSidecarProvider>
|
<ChromeExtensionSidecarEffect />
|
||||||
<UserProviderEffect />
|
<ChromeExtensionSidecarProvider>
|
||||||
<WorkspaceProviderEffect />
|
<UserProviderEffect />
|
||||||
<UserProvider>
|
<WorkspaceProviderEffect />
|
||||||
<AuthProvider>
|
<UserProvider>
|
||||||
<ApolloMetadataClientProvider>
|
<AuthProvider>
|
||||||
<ObjectMetadataItemsProvider>
|
<ApolloMetadataClientProvider>
|
||||||
<ObjectMetadataItemsGater>
|
<ObjectMetadataItemsProvider>
|
||||||
<PrefetchDataProvider>
|
<ObjectMetadataItemsGater>
|
||||||
<UserThemeProviderEffect />
|
<PrefetchDataProvider>
|
||||||
<SnackBarProvider>
|
<UserThemeProviderEffect />
|
||||||
<DialogManagerScope dialogManagerScopeId="dialog-manager">
|
<SnackBarProvider>
|
||||||
<DialogManager>
|
<DialogManagerScope dialogManagerScopeId="dialog-manager">
|
||||||
<StrictMode>
|
<DialogManager>
|
||||||
<PromiseRejectionEffect />
|
<StrictMode>
|
||||||
<GotoHotkeysEffectsProvider />
|
<PromiseRejectionEffect />
|
||||||
<ServerPreconnect />
|
<GotoHotkeysEffectsProvider />
|
||||||
<PageTitle title={pageTitle} />
|
<ServerPreconnect />
|
||||||
<PageFavicon />
|
<PageTitle title={pageTitle} />
|
||||||
<Outlet />
|
<PageFavicon />
|
||||||
</StrictMode>
|
<Outlet />
|
||||||
</DialogManager>
|
</StrictMode>
|
||||||
</DialogManagerScope>
|
</DialogManager>
|
||||||
</SnackBarProvider>
|
</DialogManagerScope>
|
||||||
<MainContextStoreProvider />
|
</SnackBarProvider>
|
||||||
</PrefetchDataProvider>
|
<MainContextStoreProvider />
|
||||||
<PageChangeEffect />
|
</PrefetchDataProvider>
|
||||||
</ObjectMetadataItemsGater>
|
<PageChangeEffect />
|
||||||
</ObjectMetadataItemsProvider>
|
</ObjectMetadataItemsGater>
|
||||||
</ApolloMetadataClientProvider>
|
</ObjectMetadataItemsProvider>
|
||||||
</AuthProvider>
|
</ApolloMetadataClientProvider>
|
||||||
</UserProvider>
|
</AuthProvider>
|
||||||
</ChromeExtensionSidecarProvider>
|
</UserProvider>
|
||||||
</ClientConfigProvider>
|
</ChromeExtensionSidecarProvider>
|
||||||
</BaseThemeProvider>
|
</ClientConfigProvider>
|
||||||
</ApolloProvider>
|
</BaseThemeProvider>
|
||||||
|
</ApolloProvider>
|
||||||
|
</CaptchaProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -24,6 +24,7 @@ import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope
|
|||||||
import { isDefined } from 'twenty-shared';
|
import { isDefined } from 'twenty-shared';
|
||||||
import { useIsMatchingLocation } from '~/hooks/useIsMatchingLocation';
|
import { useIsMatchingLocation } from '~/hooks/useIsMatchingLocation';
|
||||||
import { usePageChangeEffectNavigateLocation } from '~/hooks/usePageChangeEffectNavigateLocation';
|
import { usePageChangeEffectNavigateLocation } from '~/hooks/usePageChangeEffectNavigateLocation';
|
||||||
|
import { isCaptchaRequiredForPath } from '@/captcha/utils/isCaptchaRequiredForPath';
|
||||||
|
|
||||||
// TODO: break down into smaller functions and / or hooks
|
// TODO: break down into smaller functions and / or hooks
|
||||||
// - moved usePageChangeEffectNavigateLocation into dedicated hook
|
// - moved usePageChangeEffectNavigateLocation into dedicated hook
|
||||||
@ -178,15 +179,10 @@ export const PageChangeEffect = () => {
|
|||||||
const isCaptchaScriptLoaded = useRecoilValue(isCaptchaScriptLoadedState);
|
const isCaptchaScriptLoaded = useRecoilValue(isCaptchaScriptLoadedState);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (isCaptchaScriptLoaded && isCaptchaRequiredForPath(location.pathname)) {
|
||||||
isCaptchaScriptLoaded &&
|
|
||||||
(isMatchingLocation(AppPath.SignInUp) ||
|
|
||||||
isMatchingLocation(AppPath.Invite) ||
|
|
||||||
isMatchingLocation(AppPath.ResetPassword))
|
|
||||||
) {
|
|
||||||
requestFreshCaptchaToken();
|
requestFreshCaptchaToken();
|
||||||
}
|
}
|
||||||
}, [isCaptchaScriptLoaded, isMatchingLocation, requestFreshCaptchaToken]);
|
}, [isCaptchaScriptLoaded, location.pathname, requestFreshCaptchaToken]);
|
||||||
|
|
||||||
return <></>;
|
return <></>;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,9 +2,12 @@ import React from 'react';
|
|||||||
|
|
||||||
import { CaptchaProviderScriptLoaderEffect } from '@/captcha/components/CaptchaProviderScriptLoaderEffect';
|
import { CaptchaProviderScriptLoaderEffect } from '@/captcha/components/CaptchaProviderScriptLoaderEffect';
|
||||||
import { isCaptchaRequiredForPath } from '@/captcha/utils/isCaptchaRequiredForPath';
|
import { isCaptchaRequiredForPath } from '@/captcha/utils/isCaptchaRequiredForPath';
|
||||||
|
import { useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
export const CaptchaProvider = ({ children }: React.PropsWithChildren) => {
|
export const CaptchaProvider = ({ children }: React.PropsWithChildren) => {
|
||||||
if (!isCaptchaRequiredForPath(window.location.pathname)) {
|
const location = useLocation();
|
||||||
|
|
||||||
|
if (!isCaptchaRequiredForPath(location.pathname)) {
|
||||||
return <>{children}</>;
|
return <>{children}</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { useRequestFreshCaptchaToken } from '@/captcha/hooks/useRequestFreshCaptchaToken';
|
import { useRequestFreshCaptchaToken } from '@/captcha/hooks/useRequestFreshCaptchaToken';
|
||||||
import { isCaptchaScriptLoadedState } from '@/captcha/states/isCaptchaScriptLoadedState';
|
import { isCaptchaScriptLoadedState } from '@/captcha/states/isCaptchaScriptLoadedState';
|
||||||
@ -10,7 +10,7 @@ import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
|||||||
|
|
||||||
export const CaptchaProviderScriptLoaderEffect = () => {
|
export const CaptchaProviderScriptLoaderEffect = () => {
|
||||||
const captcha = useRecoilValue(captchaState);
|
const captcha = useRecoilValue(captchaState);
|
||||||
const setIsCaptchaScriptLoaded = useSetRecoilState(
|
const [isCaptchaScriptLoaded, setIsCaptchaScriptLoaded] = useRecoilState(
|
||||||
isCaptchaScriptLoadedState,
|
isCaptchaScriptLoadedState,
|
||||||
);
|
);
|
||||||
const { requestFreshCaptchaToken } = useRequestFreshCaptchaToken();
|
const { requestFreshCaptchaToken } = useRequestFreshCaptchaToken();
|
||||||
@ -46,8 +46,9 @@ export const CaptchaProviderScriptLoaderEffect = () => {
|
|||||||
document.body.appendChild(scriptElement);
|
document.body.appendChild(scriptElement);
|
||||||
}
|
}
|
||||||
}, [captcha?.provider, captcha?.siteKey, setIsCaptchaScriptLoaded]);
|
}, [captcha?.provider, captcha?.siteKey, setIsCaptchaScriptLoaded]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isUndefinedOrNull(captcha?.provider)) {
|
if (isUndefinedOrNull(captcha?.provider) || !isCaptchaScriptLoaded) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +69,7 @@ export const CaptchaProviderScriptLoaderEffect = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return () => clearInterval(refreshInterval);
|
return () => clearInterval(refreshInterval);
|
||||||
}, [captcha?.provider, requestFreshCaptchaToken]);
|
}, [captcha?.provider, requestFreshCaptchaToken, isCaptchaScriptLoaded]);
|
||||||
|
|
||||||
return <></>;
|
return <></>;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import { isCaptchaRequiredForPath } from '@/captcha/utils/isCaptchaRequiredForPa
|
|||||||
import { captchaState } from '@/client-config/states/captchaState';
|
import { captchaState } from '@/client-config/states/captchaState';
|
||||||
import { CaptchaDriverType } from '~/generated-metadata/graphql';
|
import { CaptchaDriverType } from '~/generated-metadata/graphql';
|
||||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||||
|
import { useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
@ -20,10 +21,12 @@ export const useRequestFreshCaptchaToken = () => {
|
|||||||
isRequestingCaptchaTokenState,
|
isRequestingCaptchaTokenState,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
const requestFreshCaptchaToken = useRecoilCallback(
|
const requestFreshCaptchaToken = useRecoilCallback(
|
||||||
({ snapshot }) =>
|
({ snapshot }) =>
|
||||||
async () => {
|
async () => {
|
||||||
if (!isCaptchaRequiredForPath(window.location.pathname)) {
|
if (!isCaptchaRequiredForPath(location.pathname)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +65,7 @@ export const useRequestFreshCaptchaToken = () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[setCaptchaToken, setIsRequestingCaptchaToken],
|
[location.pathname, setCaptchaToken, setIsRequestingCaptchaToken],
|
||||||
);
|
);
|
||||||
|
|
||||||
return { requestFreshCaptchaToken };
|
return { requestFreshCaptchaToken };
|
||||||
|
|||||||
Reference in New Issue
Block a user