Fix metadata mocks loaded during login issue (#12446)
If you tried to add a delay in `refreshObjectMetadataItems` like this` await new Promise((resolve) => setTimeout(resolve, 5000))`, then this caused an issue where the user was redirected to his workspace because the metadata was not loaded. This happened because I had removed the call to fetch metadata explicitly in useAuth (instead relying on the effect to fetch it because it was done twice). I had removed it because this was causing issues in the onboarding process where /metadata was called too early and then cached with the wrong reply. The correct fix is instead to change the fetch policy to `network only` to stop hiding re-renders to the object metadata effect with Apollo's cache mechanism. Now the [] reply isn't cached in the onboarding, the metadata effect is only triggered during initial page load and refresh should be called explicitely. I also noticed a bug on the server side where sometimes the frontend was passing a token for public requests (login token exchange request, public domain data request). I removed the check so that the backend completely ignores the token when it's passed on public request. The downside is that we're losing information for logs (who did that request to a public endpoint), but it doesn't make much sense to throw authentication errors on that endpoint imo. Probably a better root-cause fix would be to understand why a token is still passed on the frontend, but that would require more investigation — the bug happened when I was signing up and redirected from the app.xxx domain to the workspace domain
This commit is contained in:
@ -58,6 +58,7 @@ import { useOrigin } from '@/domain-manager/hooks/useOrigin';
|
||||
import { useRedirect } from '@/domain-manager/hooks/useRedirect';
|
||||
import { useRedirectToWorkspaceDomain } from '@/domain-manager/hooks/useRedirectToWorkspaceDomain';
|
||||
import { domainConfigurationState } from '@/domain-manager/states/domainConfigurationState';
|
||||
import { useRefreshObjectMetadataItems } from '@/object-metadata/hooks/useRefreshObjectMetadataItem';
|
||||
import { workspaceAuthProvidersState } from '@/workspace/states/workspaceAuthProvidersState';
|
||||
import { i18n } from '@lingui/core';
|
||||
import { useNavigate, useSearchParams } from 'react-router-dom';
|
||||
@ -85,6 +86,8 @@ export const useAuth = () => {
|
||||
isEmailVerificationRequiredState,
|
||||
);
|
||||
|
||||
const { refreshObjectMetadataItems } = useRefreshObjectMetadataItems();
|
||||
|
||||
const setSignInUpStep = useSetRecoilState(signInUpStepState);
|
||||
const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState);
|
||||
const setWorkspaces = useSetRecoilState(workspacesState);
|
||||
@ -379,9 +382,19 @@ export const useAuth = () => {
|
||||
),
|
||||
);
|
||||
|
||||
// TODO: We can't parallelize this yet because when loadCurrentUSer is loaded
|
||||
// then UserProvider updates its children and PrefetchDataProvider is triggered
|
||||
// which requires the correct metadata to be loaded (not the mocks)
|
||||
await refreshObjectMetadataItems();
|
||||
await loadCurrentUser();
|
||||
},
|
||||
[getAuthTokensFromLoginToken, setTokenPair, loadCurrentUser, origin],
|
||||
[
|
||||
getAuthTokensFromLoginToken,
|
||||
setTokenPair,
|
||||
loadCurrentUser,
|
||||
origin,
|
||||
refreshObjectMetadataItems,
|
||||
],
|
||||
);
|
||||
|
||||
const handleCredentialsSignIn = useCallback(
|
||||
|
||||
@ -5,28 +5,39 @@ import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { useLoadMockedObjectMetadataItems } from '@/object-metadata/hooks/useLoadMockedObjectMetadataItems';
|
||||
import { useRefreshObjectMetadataItems } from '@/object-metadata/hooks/useRefreshObjectMetadataItem';
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { isWorkspaceActiveOrSuspended } from 'twenty-shared/workspace';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
|
||||
export const ObjectMetadataItemsLoadEffect = () => {
|
||||
const currentUser = useRecoilValue(currentUserState);
|
||||
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
||||
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
|
||||
|
||||
const { refreshObjectMetadataItems } = useRefreshObjectMetadataItems();
|
||||
const { loadMockedObjectMetadataItems } = useLoadMockedObjectMetadataItems();
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
isUndefinedOrNull(currentUser) ||
|
||||
!isWorkspaceActiveOrSuspended(currentWorkspace)
|
||||
) {
|
||||
loadMockedObjectMetadataItems();
|
||||
} else {
|
||||
refreshObjectMetadataItems();
|
||||
if (objectMetadataItems.length > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const loadObjectMetadata = async () => {
|
||||
if (
|
||||
isUndefinedOrNull(currentUser) ||
|
||||
!isWorkspaceActiveOrSuspended(currentWorkspace)
|
||||
) {
|
||||
await loadMockedObjectMetadataItems();
|
||||
} else {
|
||||
await refreshObjectMetadataItems();
|
||||
}
|
||||
};
|
||||
|
||||
loadObjectMetadata();
|
||||
}, [
|
||||
currentUser,
|
||||
currentWorkspace,
|
||||
objectMetadataItems.length,
|
||||
loadMockedObjectMetadataItems,
|
||||
refreshObjectMetadataItems,
|
||||
]);
|
||||
|
||||
@ -4,14 +4,13 @@ import { isAppWaitingForFreshObjectMetadataState } from '@/object-metadata/state
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { mapPaginatedObjectMetadataItemsToObjectMetadataItems } from '@/object-metadata/utils/mapPaginatedObjectMetadataItemsToObjectMetadataItems';
|
||||
import { FetchPolicy } from '@apollo/client';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { ObjectMetadataItemsQuery } from '~/generated-metadata/graphql';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
|
||||
type FetchPolicy = 'network-only' | 'cache-first';
|
||||
|
||||
export const useRefreshObjectMetadataItems = (
|
||||
fetchPolicy: FetchPolicy = 'cache-first',
|
||||
fetchPolicy: FetchPolicy = 'network-only',
|
||||
) => {
|
||||
const client = useApolloMetadataClient();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user