fix: user has to login every time chrome sidepanel is opened (#5544)
We can pass the auth tokens to our front app via post message, which will also allow us to pass route names to navigate on it
This commit is contained in:
@ -0,0 +1,58 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
|
||||
import { tokenPairState } from '@/auth/states/tokenPairState';
|
||||
import { isLoadingTokensFromExtensionState } from '@/chrome-extension-sidecar/states/isLoadingTokensFromExtensionState';
|
||||
import { chromeExtensionIdState } from '@/client-config/states/chromeExtensionIdState';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
import { isInFrame } from '~/utils/isInIframe';
|
||||
|
||||
export const ChromeExtensionSidecarEffect = () => {
|
||||
const navigate = useNavigate();
|
||||
const setTokenPair = useSetRecoilState(tokenPairState);
|
||||
const chromeExtensionId = useRecoilValue(chromeExtensionIdState);
|
||||
const setIsLoadingTokensFromExtension = useSetRecoilState(
|
||||
isLoadingTokensFromExtensionState,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInFrame() && isDefined(chromeExtensionId)) {
|
||||
window.parent.postMessage(
|
||||
'loaded',
|
||||
`chrome-extension://${chromeExtensionId}`,
|
||||
);
|
||||
|
||||
const handleWindowEvents = (event: MessageEvent<any>) => {
|
||||
if (event.origin === `chrome-extension://${chromeExtensionId}`) {
|
||||
switch (event.data.type) {
|
||||
case 'tokens': {
|
||||
setTokenPair(event.data.value);
|
||||
setIsLoadingTokensFromExtension(true);
|
||||
break;
|
||||
}
|
||||
case 'navigate':
|
||||
navigate(event.data.value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
setIsLoadingTokensFromExtension(false);
|
||||
return;
|
||||
}
|
||||
};
|
||||
window.addEventListener('message', handleWindowEvents);
|
||||
return () => {
|
||||
window.removeEventListener('message', handleWindowEvents);
|
||||
};
|
||||
}
|
||||
}, [
|
||||
chromeExtensionId,
|
||||
setIsLoadingTokensFromExtension,
|
||||
setTokenPair,
|
||||
navigate,
|
||||
]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
@ -0,0 +1,56 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { isLoadingTokensFromExtensionState } from '@/chrome-extension-sidecar/states/isLoadingTokensFromExtensionState';
|
||||
import { chromeExtensionIdState } from '@/client-config/states/chromeExtensionIdState';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
import { isInFrame } from '~/utils/isInIframe';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
const AppInaccessible = ({ message }: { message: string }) => {
|
||||
return (
|
||||
<StyledContainer>
|
||||
<img
|
||||
src="/images/integrations/twenty-logo.svg"
|
||||
alt="twenty-icon"
|
||||
height={40}
|
||||
width={40}
|
||||
/>
|
||||
<h3>{message}</h3>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export const ChromeExtensionSidecarProvider: React.FC<
|
||||
React.PropsWithChildren
|
||||
> = ({ children }) => {
|
||||
const isLoadingTokensFromExtension = useRecoilValue(
|
||||
isLoadingTokensFromExtensionState,
|
||||
);
|
||||
const chromeExtensionId = useRecoilValue(chromeExtensionIdState);
|
||||
|
||||
if (!isInFrame()) return <>{children}</>;
|
||||
|
||||
if (!isDefined(chromeExtensionId))
|
||||
return (
|
||||
<AppInaccessible message={`Twenty is not accessible inside an iframe.`} />
|
||||
);
|
||||
|
||||
if (isDefined(isLoadingTokensFromExtension) && !isLoadingTokensFromExtension)
|
||||
return (
|
||||
<AppInaccessible
|
||||
message={`Unauthorized access from iframe origin. If you're trying to access from chrome extension,
|
||||
please check your chrome extension ID on your server.
|
||||
`}
|
||||
/>
|
||||
);
|
||||
|
||||
return isLoadingTokensFromExtension && <>{children}</>;
|
||||
};
|
||||
@ -0,0 +1,6 @@
|
||||
import { createState } from 'twenty-ui';
|
||||
|
||||
export const isLoadingTokensFromExtensionState = createState<boolean | null>({
|
||||
key: 'isLoadingTokensFromExtensionState',
|
||||
defaultValue: null,
|
||||
});
|
||||
@ -4,6 +4,7 @@ import { useRecoilState, useSetRecoilState } from 'recoil';
|
||||
import { authProvidersState } from '@/client-config/states/authProvidersState';
|
||||
import { billingState } from '@/client-config/states/billingState';
|
||||
import { captchaProviderState } from '@/client-config/states/captchaProviderState';
|
||||
import { chromeExtensionIdState } from '@/client-config/states/chromeExtensionIdState';
|
||||
import { isClientConfigLoadedState } from '@/client-config/states/isClientConfigLoadedState';
|
||||
import { isDebugModeState } from '@/client-config/states/isDebugModeState';
|
||||
import { isSignInPrefilledState } from '@/client-config/states/isSignInPrefilledState';
|
||||
@ -32,6 +33,8 @@ export const ClientConfigProviderEffect = () => {
|
||||
|
||||
const setCaptchaProvider = useSetRecoilState(captchaProviderState);
|
||||
|
||||
const setChromeExtensionId = useSetRecoilState(chromeExtensionIdState);
|
||||
|
||||
const { data, loading } = useGetClientConfigQuery({
|
||||
skip: isClientConfigLoaded,
|
||||
});
|
||||
@ -63,6 +66,8 @@ export const ClientConfigProviderEffect = () => {
|
||||
provider: data?.clientConfig?.captcha?.provider,
|
||||
siteKey: data?.clientConfig?.captcha?.siteKey,
|
||||
});
|
||||
|
||||
setChromeExtensionId(data?.clientConfig?.chromeExtensionId);
|
||||
}
|
||||
}, [
|
||||
data,
|
||||
@ -77,6 +82,7 @@ export const ClientConfigProviderEffect = () => {
|
||||
loading,
|
||||
setIsClientConfigLoaded,
|
||||
setCaptchaProvider,
|
||||
setChromeExtensionId,
|
||||
]);
|
||||
|
||||
return <></>;
|
||||
|
||||
@ -33,6 +33,7 @@ export const GET_CLIENT_CONFIG = gql`
|
||||
provider
|
||||
siteKey
|
||||
}
|
||||
chromeExtensionId
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
import { createState } from 'twenty-ui';
|
||||
|
||||
export const chromeExtensionIdState = createState<string | null | undefined>({
|
||||
key: 'chromeExtensionIdState',
|
||||
defaultValue: null,
|
||||
});
|
||||
Reference in New Issue
Block a user