674 lines
23 KiB
TypeScript
674 lines
23 KiB
TypeScript
import { AppPath } from '@/types/AppPath';
|
|
import { ApolloError, useApolloClient } from '@apollo/client';
|
|
import { useCallback } from 'react';
|
|
import {
|
|
snapshot_UNSTABLE,
|
|
useGotoRecoilSnapshot,
|
|
useRecoilCallback,
|
|
useRecoilValue,
|
|
useSetRecoilState,
|
|
} from 'recoil';
|
|
|
|
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
|
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
|
import { billingState } from '@/client-config/states/billingState';
|
|
import { clientConfigApiStatusState } from '@/client-config/states/clientConfigApiStatusState';
|
|
import { supportChatState } from '@/client-config/states/supportChatState';
|
|
import { ColorScheme } from '@/workspace-member/types/WorkspaceMember';
|
|
import { REACT_APP_SERVER_BASE_URL } from '~/config';
|
|
import {
|
|
AuthTokenPair,
|
|
useCheckUserExistsLazyQuery,
|
|
useGetAuthTokensFromLoginTokenMutation,
|
|
useGetCurrentUserLazyQuery,
|
|
useGetLoginTokenFromCredentialsMutation,
|
|
useGetLoginTokenFromEmailVerificationTokenMutation,
|
|
useSignUpMutation,
|
|
useSignInMutation,
|
|
useSignUpInWorkspaceMutation,
|
|
} from '~/generated/graphql';
|
|
|
|
import { currentWorkspaceMembersState } from '@/auth/states/currentWorkspaceMembersStates';
|
|
import { isDeveloperDefaultSignInPrefilledState } from '@/client-config/states/isDeveloperDefaultSignInPrefilledState';
|
|
import { DateFormat } from '@/localization/constants/DateFormat';
|
|
import { TimeFormat } from '@/localization/constants/TimeFormat';
|
|
import { dateTimeFormatState } from '@/localization/states/dateTimeFormatState';
|
|
import { detectDateFormat } from '@/localization/utils/detectDateFormat';
|
|
import { detectTimeFormat } from '@/localization/utils/detectTimeFormat';
|
|
import { detectTimeZone } from '@/localization/utils/detectTimeZone';
|
|
import { getDateFormatFromWorkspaceDateFormat } from '@/localization/utils/getDateFormatFromWorkspaceDateFormat';
|
|
import { getTimeFormatFromWorkspaceTimeFormat } from '@/localization/utils/getTimeFormatFromWorkspaceTimeFormat';
|
|
import { currentUserState } from '../states/currentUserState';
|
|
import { tokenPairState } from '../states/tokenPairState';
|
|
|
|
import { currentUserWorkspaceState } from '@/auth/states/currentUserWorkspaceState';
|
|
import { isCurrentUserLoadedState } from '@/auth/states/isCurrentUserLoadedState';
|
|
import {
|
|
SignInUpStep,
|
|
signInUpStepState,
|
|
} from '@/auth/states/signInUpStepState';
|
|
import { workspacePublicDataState } from '@/auth/states/workspacePublicDataState';
|
|
import { BillingCheckoutSession } from '@/auth/types/billingCheckoutSession.type';
|
|
import { apiConfigState } from '@/client-config/states/apiConfigState';
|
|
import { captchaState } from '@/client-config/states/captchaState';
|
|
import { isEmailVerificationRequiredState } from '@/client-config/states/isEmailVerificationRequiredState';
|
|
import { isMultiWorkspaceEnabledState } from '@/client-config/states/isMultiWorkspaceEnabledState';
|
|
import { sentryConfigState } from '@/client-config/states/sentryConfigState';
|
|
import { useIsCurrentLocationOnAWorkspace } from '@/domain-manager/hooks/useIsCurrentLocationOnAWorkspace';
|
|
import { useLastAuthenticatedWorkspaceDomain } from '@/domain-manager/hooks/useLastAuthenticatedWorkspaceDomain';
|
|
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';
|
|
import { APP_LOCALES } from 'twenty-shared/translations';
|
|
import { isDefined } from 'twenty-shared/utils';
|
|
import { iconsState } from 'twenty-ui/display';
|
|
import { cookieStorage } from '~/utils/cookie-storage';
|
|
import { getWorkspaceUrl } from '~/utils/getWorkspaceUrl';
|
|
import { dynamicActivate } from '~/utils/i18n/dynamicActivate';
|
|
import { availableWorkspacesState } from '@/auth/states/availableWorkspacesState';
|
|
import { useSignUpInNewWorkspace } from '@/auth/sign-in-up/hooks/useSignUpInNewWorkspace';
|
|
import {
|
|
countAvailableWorkspaces,
|
|
getFirstAvailableWorkspaces,
|
|
} from '@/auth/utils/availableWorkspacesUtils';
|
|
import { useRequestFreshCaptchaToken } from '@/captcha/hooks/useRequestFreshCaptchaToken';
|
|
|
|
export const useAuth = () => {
|
|
const setTokenPair = useSetRecoilState(tokenPairState);
|
|
const setCurrentUser = useSetRecoilState(currentUserState);
|
|
const setAvailableWorkspaces = useSetRecoilState(availableWorkspacesState);
|
|
const setCurrentWorkspaceMember = useSetRecoilState(
|
|
currentWorkspaceMemberState,
|
|
);
|
|
const setCurrentUserWorkspace = useSetRecoilState(currentUserWorkspaceState);
|
|
const { origin } = useOrigin();
|
|
const { requestFreshCaptchaToken } = useRequestFreshCaptchaToken();
|
|
const setCurrentWorkspaceMembers = useSetRecoilState(
|
|
currentWorkspaceMembersState,
|
|
);
|
|
const isMultiWorkspaceEnabled = useRecoilValue(isMultiWorkspaceEnabledState);
|
|
const isEmailVerificationRequired = useRecoilValue(
|
|
isEmailVerificationRequiredState,
|
|
);
|
|
|
|
const { refreshObjectMetadataItems } = useRefreshObjectMetadataItems();
|
|
const { createWorkspace } = useSignUpInNewWorkspace();
|
|
|
|
const setSignInUpStep = useSetRecoilState(signInUpStepState);
|
|
const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState);
|
|
const { redirect } = useRedirect();
|
|
const { redirectToWorkspaceDomain } = useRedirectToWorkspaceDomain();
|
|
|
|
const [getLoginTokenFromCredentials] =
|
|
useGetLoginTokenFromCredentialsMutation();
|
|
const [signIn] = useSignInMutation();
|
|
const [signUp] = useSignUpMutation();
|
|
const [signUpInWorkspace] = useSignUpInWorkspaceMutation();
|
|
const [getAuthTokensFromLoginToken] =
|
|
useGetAuthTokensFromLoginTokenMutation();
|
|
const [getLoginTokenFromEmailVerificationToken] =
|
|
useGetLoginTokenFromEmailVerificationTokenMutation();
|
|
const [getCurrentUser] = useGetCurrentUserLazyQuery();
|
|
|
|
const { isOnAWorkspace } = useIsCurrentLocationOnAWorkspace();
|
|
|
|
const workspacePublicData = useRecoilValue(workspacePublicDataState);
|
|
|
|
const { setLastAuthenticateWorkspaceDomain } =
|
|
useLastAuthenticatedWorkspaceDomain();
|
|
const [checkUserExistsQuery, { data: checkUserExistsData }] =
|
|
useCheckUserExistsLazyQuery();
|
|
|
|
const client = useApolloClient();
|
|
|
|
const goToRecoilSnapshot = useGotoRecoilSnapshot();
|
|
|
|
const setDateTimeFormat = useSetRecoilState(dateTimeFormatState);
|
|
|
|
const [, setSearchParams] = useSearchParams();
|
|
|
|
const navigate = useNavigate();
|
|
|
|
const clearSession = useRecoilCallback(
|
|
({ snapshot }) =>
|
|
async () => {
|
|
const emptySnapshot = snapshot_UNSTABLE();
|
|
|
|
const iconsValue = snapshot.getLoadable(iconsState).getValue();
|
|
const authProvidersValue = snapshot
|
|
.getLoadable(workspaceAuthProvidersState)
|
|
.getValue();
|
|
const billing = snapshot.getLoadable(billingState).getValue();
|
|
const isDeveloperDefaultSignInPrefilled = snapshot
|
|
.getLoadable(isDeveloperDefaultSignInPrefilledState)
|
|
.getValue();
|
|
const supportChat = snapshot.getLoadable(supportChatState).getValue();
|
|
const captcha = snapshot.getLoadable(captchaState).getValue();
|
|
const clientConfigApiStatus = snapshot
|
|
.getLoadable(clientConfigApiStatusState)
|
|
.getValue();
|
|
const isCurrentUserLoaded = snapshot
|
|
.getLoadable(isCurrentUserLoadedState)
|
|
.getValue();
|
|
const isMultiWorkspaceEnabled = snapshot
|
|
.getLoadable(isMultiWorkspaceEnabledState)
|
|
.getValue();
|
|
const domainConfiguration = snapshot
|
|
.getLoadable(domainConfigurationState)
|
|
.getValue();
|
|
const apiConfig = snapshot.getLoadable(apiConfigState).getValue();
|
|
const sentryConfig = snapshot.getLoadable(sentryConfigState).getValue();
|
|
const workspacePublicData = snapshot
|
|
.getLoadable(workspacePublicDataState)
|
|
.getValue();
|
|
|
|
const initialSnapshot = emptySnapshot.map(({ set }) => {
|
|
set(iconsState, iconsValue);
|
|
set(workspaceAuthProvidersState, authProvidersValue);
|
|
set(billingState, billing);
|
|
set(
|
|
isDeveloperDefaultSignInPrefilledState,
|
|
isDeveloperDefaultSignInPrefilled,
|
|
);
|
|
set(supportChatState, supportChat);
|
|
set(captchaState, captcha);
|
|
set(apiConfigState, apiConfig);
|
|
set(sentryConfigState, sentryConfig);
|
|
set(workspacePublicDataState, workspacePublicData);
|
|
set(clientConfigApiStatusState, clientConfigApiStatus);
|
|
set(isCurrentUserLoadedState, isCurrentUserLoaded);
|
|
set(isMultiWorkspaceEnabledState, isMultiWorkspaceEnabled);
|
|
set(domainConfigurationState, domainConfiguration);
|
|
return undefined;
|
|
});
|
|
|
|
goToRecoilSnapshot(initialSnapshot);
|
|
|
|
sessionStorage.clear();
|
|
localStorage.clear();
|
|
await client.clearStore();
|
|
// We need to explicitly clear the state to trigger the cookie deletion which include the parent domain
|
|
setLastAuthenticateWorkspaceDomain(null);
|
|
navigate(AppPath.SignInUp);
|
|
},
|
|
[navigate, client, goToRecoilSnapshot, setLastAuthenticateWorkspaceDomain],
|
|
);
|
|
|
|
const handleGetLoginTokenFromCredentials = useCallback(
|
|
async (email: string, password: string, captchaToken?: string) => {
|
|
try {
|
|
const getLoginTokenResult = await getLoginTokenFromCredentials({
|
|
variables: {
|
|
email,
|
|
password,
|
|
captchaToken,
|
|
origin,
|
|
},
|
|
});
|
|
if (isDefined(getLoginTokenResult.errors)) {
|
|
throw getLoginTokenResult.errors;
|
|
}
|
|
|
|
if (!getLoginTokenResult.data?.getLoginTokenFromCredentials) {
|
|
throw new Error('No login token');
|
|
}
|
|
|
|
return getLoginTokenResult.data.getLoginTokenFromCredentials;
|
|
} catch (error) {
|
|
// TODO: Get intellisense for graphql error extensions code (codegen?)
|
|
if (
|
|
error instanceof ApolloError &&
|
|
error.graphQLErrors[0]?.extensions?.subCode === 'EMAIL_NOT_VERIFIED'
|
|
) {
|
|
setSearchParams({ email });
|
|
setSignInUpStep(SignInUpStep.EmailVerification);
|
|
throw error;
|
|
}
|
|
throw error;
|
|
}
|
|
},
|
|
[getLoginTokenFromCredentials, setSearchParams, setSignInUpStep, origin],
|
|
);
|
|
|
|
const handleGetLoginTokenFromEmailVerificationToken = useCallback(
|
|
async (
|
|
emailVerificationToken: string,
|
|
email: string,
|
|
captchaToken?: string,
|
|
) => {
|
|
const loginTokenResult = await getLoginTokenFromEmailVerificationToken({
|
|
variables: {
|
|
email,
|
|
emailVerificationToken,
|
|
captchaToken,
|
|
origin,
|
|
},
|
|
});
|
|
|
|
if (isDefined(loginTokenResult.errors)) {
|
|
throw loginTokenResult.errors;
|
|
}
|
|
|
|
if (!loginTokenResult.data?.getLoginTokenFromEmailVerificationToken) {
|
|
throw new Error('No login token');
|
|
}
|
|
|
|
return loginTokenResult.data.getLoginTokenFromEmailVerificationToken;
|
|
},
|
|
[getLoginTokenFromEmailVerificationToken, origin],
|
|
);
|
|
|
|
const loadCurrentUser = useCallback(async () => {
|
|
const currentUserResult = await getCurrentUser({
|
|
fetchPolicy: 'network-only',
|
|
});
|
|
|
|
if (isDefined(currentUserResult.error)) {
|
|
throw new Error(currentUserResult.error.message);
|
|
}
|
|
|
|
const user = currentUserResult.data?.currentUser;
|
|
|
|
if (!user) {
|
|
throw new Error('No current user result');
|
|
}
|
|
|
|
let workspaceMember = null;
|
|
|
|
setCurrentUser(user);
|
|
|
|
if (isDefined(user.workspaceMembers)) {
|
|
const workspaceMembers = user.workspaceMembers.map((workspaceMember) => ({
|
|
...workspaceMember,
|
|
colorScheme: workspaceMember.colorScheme as ColorScheme,
|
|
locale: workspaceMember.locale ?? 'en',
|
|
}));
|
|
|
|
setCurrentWorkspaceMembers(workspaceMembers);
|
|
}
|
|
|
|
if (isDefined(user.availableWorkspaces)) {
|
|
setAvailableWorkspaces(user.availableWorkspaces);
|
|
}
|
|
|
|
if (isDefined(user.currentUserWorkspace)) {
|
|
setCurrentUserWorkspace(user.currentUserWorkspace);
|
|
}
|
|
|
|
if (isDefined(user.workspaceMember)) {
|
|
workspaceMember = {
|
|
...user.workspaceMember,
|
|
colorScheme: user.workspaceMember?.colorScheme as ColorScheme,
|
|
locale: user.workspaceMember?.locale ?? 'en',
|
|
};
|
|
|
|
setCurrentWorkspaceMember(workspaceMember);
|
|
|
|
// TODO: factorize with UserProviderEffect
|
|
setDateTimeFormat({
|
|
timeZone:
|
|
workspaceMember.timeZone && workspaceMember.timeZone !== 'system'
|
|
? workspaceMember.timeZone
|
|
: detectTimeZone(),
|
|
dateFormat: isDefined(user.workspaceMember.dateFormat)
|
|
? getDateFormatFromWorkspaceDateFormat(
|
|
user.workspaceMember.dateFormat,
|
|
)
|
|
: DateFormat[detectDateFormat()],
|
|
timeFormat: isDefined(user.workspaceMember.timeFormat)
|
|
? getTimeFormatFromWorkspaceTimeFormat(
|
|
user.workspaceMember.timeFormat,
|
|
)
|
|
: TimeFormat[detectTimeFormat()],
|
|
});
|
|
dynamicActivate(
|
|
(workspaceMember.locale as keyof typeof APP_LOCALES) ?? 'en',
|
|
);
|
|
}
|
|
|
|
const workspace = user.currentWorkspace ?? null;
|
|
|
|
setCurrentWorkspace(workspace);
|
|
|
|
if (isDefined(workspace) && isOnAWorkspace) {
|
|
setLastAuthenticateWorkspaceDomain({
|
|
workspaceId: workspace.id,
|
|
workspaceUrl: getWorkspaceUrl(workspace.workspaceUrls),
|
|
});
|
|
}
|
|
|
|
return {
|
|
user,
|
|
workspaceMember,
|
|
workspace,
|
|
};
|
|
}, [
|
|
getCurrentUser,
|
|
isOnAWorkspace,
|
|
setCurrentUser,
|
|
setCurrentUserWorkspace,
|
|
setCurrentWorkspace,
|
|
setCurrentWorkspaceMember,
|
|
setCurrentWorkspaceMembers,
|
|
setDateTimeFormat,
|
|
setLastAuthenticateWorkspaceDomain,
|
|
setAvailableWorkspaces,
|
|
]);
|
|
|
|
const handleSetAuthTokens = useCallback(
|
|
(tokens: AuthTokenPair) => {
|
|
setTokenPair(tokens);
|
|
cookieStorage.setItem('tokenPair', JSON.stringify(tokens));
|
|
},
|
|
[setTokenPair],
|
|
);
|
|
|
|
const handleGetAuthTokensFromLoginToken = useCallback(
|
|
async (loginToken: string) => {
|
|
const getAuthTokensResult = await getAuthTokensFromLoginToken({
|
|
variables: {
|
|
loginToken,
|
|
origin,
|
|
},
|
|
});
|
|
|
|
if (isDefined(getAuthTokensResult.errors)) {
|
|
throw getAuthTokensResult.errors;
|
|
}
|
|
|
|
if (!getAuthTokensResult.data?.getAuthTokensFromLoginToken) {
|
|
throw new Error('No getAuthTokensFromLoginToken result');
|
|
}
|
|
|
|
handleSetAuthTokens(
|
|
getAuthTokensResult.data.getAuthTokensFromLoginToken.tokens,
|
|
);
|
|
|
|
// 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,
|
|
loadCurrentUser,
|
|
origin,
|
|
handleSetAuthTokens,
|
|
refreshObjectMetadataItems,
|
|
],
|
|
);
|
|
|
|
const handleCredentialsSignIn = useCallback(
|
|
async (email: string, password: string, captchaToken?: string) => {
|
|
signIn({
|
|
variables: { email, password, captchaToken },
|
|
onCompleted: async (data) => {
|
|
handleSetAuthTokens(data.signIn.tokens);
|
|
const { user } = await loadCurrentUser();
|
|
|
|
const availableWorkspacesCount = countAvailableWorkspaces(
|
|
user.availableWorkspaces,
|
|
);
|
|
|
|
if (availableWorkspacesCount === 0) {
|
|
return createWorkspace();
|
|
}
|
|
|
|
if (availableWorkspacesCount === 1) {
|
|
const targetWorkspace = getFirstAvailableWorkspaces(
|
|
user.availableWorkspaces,
|
|
);
|
|
return await redirectToWorkspaceDomain(
|
|
getWorkspaceUrl(targetWorkspace.workspaceUrls),
|
|
targetWorkspace.loginToken ? AppPath.Verify : AppPath.SignInUp,
|
|
{
|
|
...(targetWorkspace.loginToken && {
|
|
loginToken: targetWorkspace.loginToken,
|
|
}),
|
|
email: user.email,
|
|
},
|
|
);
|
|
}
|
|
|
|
setSignInUpStep(SignInUpStep.WorkspaceSelection);
|
|
},
|
|
onError: (error) => {
|
|
if (
|
|
error instanceof ApolloError &&
|
|
error.graphQLErrors[0]?.extensions?.subCode === 'EMAIL_NOT_VERIFIED'
|
|
) {
|
|
setSearchParams({ email });
|
|
setSignInUpStep(SignInUpStep.EmailVerification);
|
|
throw error;
|
|
}
|
|
throw error;
|
|
},
|
|
});
|
|
},
|
|
[
|
|
handleSetAuthTokens,
|
|
redirectToWorkspaceDomain,
|
|
signIn,
|
|
loadCurrentUser,
|
|
setSearchParams,
|
|
setSignInUpStep,
|
|
createWorkspace,
|
|
],
|
|
);
|
|
|
|
const handleCredentialsSignUp = useCallback(
|
|
async (email: string, password: string, captchaToken?: string) => {
|
|
return signUp({
|
|
variables: { email, password, captchaToken },
|
|
onCompleted: async (data) => {
|
|
handleSetAuthTokens(data.signUp.tokens);
|
|
const { user } = await loadCurrentUser();
|
|
|
|
if (countAvailableWorkspaces(user.availableWorkspaces) === 0) {
|
|
return createWorkspace();
|
|
}
|
|
|
|
setSignInUpStep(SignInUpStep.WorkspaceSelection);
|
|
},
|
|
});
|
|
},
|
|
[
|
|
handleSetAuthTokens,
|
|
signUp,
|
|
loadCurrentUser,
|
|
setSignInUpStep,
|
|
createWorkspace,
|
|
],
|
|
);
|
|
|
|
const handleCredentialsSignInInWorkspace = useCallback(
|
|
async (email: string, password: string, captchaToken?: string) => {
|
|
const { loginToken } = await handleGetLoginTokenFromCredentials(
|
|
email,
|
|
password,
|
|
captchaToken,
|
|
);
|
|
await handleGetAuthTokensFromLoginToken(loginToken.token);
|
|
},
|
|
[handleGetLoginTokenFromCredentials, handleGetAuthTokensFromLoginToken],
|
|
);
|
|
|
|
const handleSignOut = useCallback(async () => {
|
|
await clearSession();
|
|
}, [clearSession]);
|
|
|
|
const handleCredentialsSignUpInWorkspace = useCallback(
|
|
async ({
|
|
email,
|
|
password,
|
|
workspaceInviteHash,
|
|
workspacePersonalInviteToken,
|
|
captchaToken,
|
|
verifyEmailNextPath,
|
|
}: {
|
|
email: string;
|
|
password: string;
|
|
workspaceInviteHash?: string;
|
|
workspacePersonalInviteToken?: string;
|
|
captchaToken?: string;
|
|
verifyEmailNextPath?: string;
|
|
}) => {
|
|
try {
|
|
const signUpInWorkspaceResult = await signUpInWorkspace({
|
|
variables: {
|
|
email,
|
|
password,
|
|
workspaceInviteHash,
|
|
workspacePersonalInviteToken,
|
|
captchaToken,
|
|
locale: i18n.locale ?? 'en',
|
|
...(workspacePublicData?.id
|
|
? { workspaceId: workspacePublicData.id }
|
|
: {}),
|
|
verifyEmailNextPath,
|
|
},
|
|
});
|
|
|
|
if (isDefined(signUpInWorkspaceResult.errors)) {
|
|
throw signUpInWorkspaceResult.errors;
|
|
}
|
|
|
|
if (!signUpInWorkspaceResult.data?.signUpInWorkspace) {
|
|
throw new Error('No login token');
|
|
}
|
|
|
|
if (isEmailVerificationRequired) {
|
|
setSearchParams({ email });
|
|
setSignInUpStep(SignInUpStep.EmailVerification);
|
|
return null;
|
|
}
|
|
|
|
if (isMultiWorkspaceEnabled) {
|
|
return await redirectToWorkspaceDomain(
|
|
getWorkspaceUrl(
|
|
signUpInWorkspaceResult.data.signUpInWorkspace.workspace
|
|
.workspaceUrls,
|
|
),
|
|
isEmailVerificationRequired ? AppPath.SignInUp : AppPath.Verify,
|
|
{
|
|
...(!isEmailVerificationRequired && {
|
|
loginToken:
|
|
signUpInWorkspaceResult.data.signUpInWorkspace.loginToken
|
|
.token,
|
|
}),
|
|
email,
|
|
},
|
|
);
|
|
}
|
|
|
|
await handleGetAuthTokensFromLoginToken(
|
|
signUpInWorkspaceResult.data?.signUpInWorkspace.loginToken.token,
|
|
);
|
|
} finally {
|
|
requestFreshCaptchaToken();
|
|
}
|
|
},
|
|
[
|
|
signUpInWorkspace,
|
|
workspacePublicData,
|
|
isMultiWorkspaceEnabled,
|
|
handleGetAuthTokensFromLoginToken,
|
|
setSignInUpStep,
|
|
setSearchParams,
|
|
isEmailVerificationRequired,
|
|
redirectToWorkspaceDomain,
|
|
requestFreshCaptchaToken,
|
|
],
|
|
);
|
|
|
|
const buildRedirectUrl = useCallback(
|
|
(
|
|
path: string,
|
|
params: {
|
|
workspacePersonalInviteToken?: string;
|
|
workspaceInviteHash?: string;
|
|
billingCheckoutSession?: BillingCheckoutSession;
|
|
action?: string;
|
|
},
|
|
) => {
|
|
const url = new URL(`${REACT_APP_SERVER_BASE_URL}${path}`);
|
|
if (isDefined(params.workspaceInviteHash)) {
|
|
url.searchParams.set('workspaceInviteHash', params.workspaceInviteHash);
|
|
}
|
|
if (isDefined(params.workspacePersonalInviteToken)) {
|
|
url.searchParams.set(
|
|
'inviteToken',
|
|
params.workspacePersonalInviteToken,
|
|
);
|
|
}
|
|
if (isDefined(params.billingCheckoutSession)) {
|
|
url.searchParams.set(
|
|
'billingCheckoutSessionState',
|
|
JSON.stringify(params.billingCheckoutSession),
|
|
);
|
|
}
|
|
|
|
if (isDefined(params.action)) {
|
|
url.searchParams.set('action', params.action);
|
|
}
|
|
|
|
if (isDefined(workspacePublicData)) {
|
|
url.searchParams.set('workspaceId', workspacePublicData.id);
|
|
}
|
|
|
|
return url.toString();
|
|
},
|
|
[workspacePublicData],
|
|
);
|
|
|
|
const handleGoogleLogin = useCallback(
|
|
(params: {
|
|
workspacePersonalInviteToken?: string;
|
|
workspaceInviteHash?: string;
|
|
billingCheckoutSession?: BillingCheckoutSession;
|
|
action: string;
|
|
}) => {
|
|
redirect(buildRedirectUrl('/auth/google', params));
|
|
},
|
|
[buildRedirectUrl, redirect],
|
|
);
|
|
|
|
const handleMicrosoftLogin = useCallback(
|
|
(params: {
|
|
workspacePersonalInviteToken?: string;
|
|
workspaceInviteHash?: string;
|
|
billingCheckoutSession?: BillingCheckoutSession;
|
|
action: string;
|
|
}) => {
|
|
redirect(buildRedirectUrl('/auth/microsoft', params));
|
|
},
|
|
[buildRedirectUrl, redirect],
|
|
);
|
|
|
|
return {
|
|
getLoginTokenFromCredentials: handleGetLoginTokenFromCredentials,
|
|
getLoginTokenFromEmailVerificationToken:
|
|
handleGetLoginTokenFromEmailVerificationToken,
|
|
getAuthTokensFromLoginToken: handleGetAuthTokensFromLoginToken,
|
|
|
|
loadCurrentUser,
|
|
|
|
checkUserExists: { checkUserExistsData, checkUserExistsQuery },
|
|
clearSession,
|
|
signOut: handleSignOut,
|
|
signUpWithCredentials: handleCredentialsSignUp,
|
|
signUpWithCredentialsInWorkspace: handleCredentialsSignUpInWorkspace,
|
|
signInWithCredentialsInWorkspace: handleCredentialsSignInInWorkspace,
|
|
signInWithCredentials: handleCredentialsSignIn,
|
|
signInWithGoogle: handleGoogleLogin,
|
|
signInWithMicrosoft: handleMicrosoftLogin,
|
|
setAuthTokens: handleSetAuthTokens,
|
|
};
|
|
};
|