Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/FullstoryInitHandler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ import ONYXKEYS from './ONYXKEYS';
*/
function FullstoryInitHandler() {
const [userMetadata] = useOnyx(ONYXKEYS.USER_METADATA);
const [session] = useOnyx(ONYXKEYS.SESSION);

useEffect(() => {
FS.init(userMetadata);
FS.init(userMetadata, session);
FS.getSessionURL()
.then((url) => {
if (!url) {
Expand All @@ -29,7 +30,7 @@ function FullstoryInitHandler() {
error: error instanceof Error ? error.message : String(error),
});
});
}, [userMetadata]);
}, [userMetadata, session]);
Comment thread
truph01 marked this conversation as resolved.
Outdated

return null;
}
Expand Down
2 changes: 1 addition & 1 deletion src/libs/Fullstory/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
return CONST.FULLSTORY.CLASS.UNMASK;
};

const shouldInitializeFullstory: ShouldInitialize = (userMetadata, envName) => {
const shouldInitializeFullstory: ShouldInitialize = (userMetadata, envName, _session) => {

Check failure on line 71 in src/libs/Fullstory/common.ts

View workflow job for this annotation

GitHub Actions / ESLint check

'_session' is defined but never used
const isTestEmail = userMetadata.email !== undefined && userMetadata.email.startsWith('fullstory') && userMetadata.email.endsWith(CONST.EMAIL.QA_DOMAIN);
if ((CONST.ENVIRONMENT.PRODUCTION !== envName && !isTestEmail) || Str.extractEmailDomain(userMetadata.email ?? '') === CONST.EXPENSIFY_PARTNER_NAME) {
return false;
Expand Down
6 changes: 3 additions & 3 deletions src/libs/Fullstory/index.native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const FS: Fullstory = {

getChatFSClass,

init: (userMetadata) => FS.consentAndIdentify(userMetadata),
init: (userMetadata, session) => FS.consentAndIdentify(userMetadata, session),

onReady: async () => FullStory.onReady(),

Expand All @@ -25,7 +25,7 @@ const FS: Fullstory = {
FullStory.identify(String(localMetadata.accountID), localMetadata);
},

consentAndIdentify: (userMetadata) => {
consentAndIdentify: (userMetadata, session) => {
// On the first subscribe for UserMetadata, this function will be called. We need
// to confirm that we actually have any value here before proceeding.
if (!userMetadata?.accountID) {
Expand All @@ -37,7 +37,7 @@ const FS: Fullstory = {
// after the init function since this function is also called on updates for
// UserMetadata onyx key.
getEnvironment().then((envName: string) => {
if (!FS.shouldInitialize(userMetadata, envName)) {
if (!FS.shouldInitialize(userMetadata, envName, session)) {
return;
}

Expand Down
8 changes: 4 additions & 4 deletions src/libs/Fullstory/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

getChatFSClass,

init: () => {},
init: (_userMetadata, _session) => {},

Check failure on line 22 in src/libs/Fullstory/index.ts

View workflow job for this annotation

GitHub Actions / ESLint check

'_session' is defined but never used

Check failure on line 22 in src/libs/Fullstory/index.ts

View workflow job for this annotation

GitHub Actions / ESLint check

'_userMetadata' is defined but never used

onReady: async () =>
new Promise((resolve) => {
Expand All @@ -36,7 +36,7 @@
}
}),

shouldInitialize: (userMetadata, envName) => shouldInitializeFullstory(userMetadata, envName) && !isSupportAuthToken(),
shouldInitialize: (userMetadata, envName, session) => shouldInitializeFullstory(userMetadata, envName, session) && !isSupportAuthToken(session),

consent: (shouldConsent) => FullStory(CONST.FULLSTORY.OPERATION.SET_IDENTITY, {consent: shouldConsent}),

Expand All @@ -52,7 +52,7 @@
});
},

consentAndIdentify: (userMetadata) => {
consentAndIdentify: (userMetadata, session) => {
// On the first subscribe for UserMetadata, this function will be called. We need
// to confirm that we actually have any value here before proceeding.
if (!userMetadata?.accountID) {
Expand All @@ -64,7 +64,7 @@
// after the init function since this function is also called on updates for
// UserMetadata onyx key.
getEnvironment().then((envName: string) => {
if (!FS.shouldInitialize(userMetadata, envName)) {
if (!FS.shouldInitialize(userMetadata, envName, session)) {
// On web, if we started FS at some point in a browser, it will run forever. So let's shut it down if we don't want it to run.
if (isInitialized()) {
FullStory(CONST.FULLSTORY.OPERATION.SHUTDOWN);
Expand Down
8 changes: 4 additions & 4 deletions src/libs/Fullstory/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type CONST from '@src/CONST';
import type {OnyxInputOrEntry, Report, UserMetadata} from '@src/types/onyx';
import type {OnyxInputOrEntry, Report, Session, UserMetadata} from '@src/types/onyx';

import type {OnyxEntry} from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
Expand Down Expand Up @@ -27,7 +27,7 @@ interface FSPageLikeConstructor {

type GetChatFSClass = (report: OnyxInputOrEntry<Report>) => FSClass;

type ShouldInitialize = (userMetadata: UserMetadata, envName: string) => boolean;
type ShouldInitialize = (userMetadata: UserMetadata, envName: string, session: OnyxEntry<Session>) => boolean;

type Fullstory = {
/**
Expand All @@ -43,7 +43,7 @@ type Fullstory = {
/**
* Initializes Fullstory.
*/
init: (userMetadata: OnyxEntry<UserMetadata>) => void;
init: (userMetadata: OnyxEntry<UserMetadata>, session: OnyxEntry<Session>) => void;

/**
* Executes a function when the Fullstory library is ready, either by initialization or by observing the start event.
Expand All @@ -68,7 +68,7 @@ type Fullstory = {
/**
* Initializes the Fullstory metadata with the provided metadata information.
*/
consentAndIdentify: (userMetadata: OnyxEntry<UserMetadata>) => void;
consentAndIdentify: (userMetadata: OnyxEntry<UserMetadata>, session: OnyxEntry<Session>) => void;

/**
* Sets the identity as anonymous using the Fullstory library.
Expand Down
47 changes: 27 additions & 20 deletions src/libs/actions/Session/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ import updateSessionAuthTokens from './updateSessionAuthTokens';

const INVALID_TOKEN = 'pizza';

let session: Session = {};
let deprecatedSession: Session = {};
let authPromiseResolver: ((value: boolean) => void) | null = null;

let isHybridAppSetupFinished = false;
Expand All @@ -92,25 +92,32 @@ let hasSwitchedAccountInHybridMode = false;
Onyx.connect({
key: ONYXKEYS.SESSION,
callback: (value) => {
session = value ?? {};
deprecatedSession = value ?? {};

if (!session.creationDate) {
session.creationDate = new Date().getTime();
if (!deprecatedSession.creationDate) {
deprecatedSession.creationDate = new Date().getTime();
}
if (session.authToken && authPromiseResolver) {
if (deprecatedSession.authToken && authPromiseResolver) {
authPromiseResolver(true);
authPromiseResolver = null;
}
if (CONFIG.IS_HYBRID_APP && isHybridAppSetupFinished && session.authToken && !isAnonymousUser(value)) {
HybridAppModule.sendAuthToken({authToken: session.authToken});
if (CONFIG.IS_HYBRID_APP && isHybridAppSetupFinished && deprecatedSession.authToken && !isAnonymousUser(value)) {
HybridAppModule.sendAuthToken({authToken: deprecatedSession.authToken});
}
},
});

let fullstorySession: Session = {};
// Use connectWithoutView because it is only for fullstory initialization

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd really love for all the full story stuff to exist in its own module. That will also help isolate the connectWithoutView() calls a bit more. Would you mind doing the small refactor? I'm not sure how much it would involve, so we could do that in a separate issue if it's too much.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MelvinBot, give me plan to do it

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tgolen Resolved via fc0285b

Onyx.connectWithoutView({
key: ONYXKEYS.SESSION,
callback: (value) => (fullstorySession = value ?? {}),
});

// Use connectWithoutView because it is only for fullstory initialization
Onyx.connectWithoutView({
key: ONYXKEYS.USER_METADATA,
callback: Fullstory.consentAndIdentify,
callback: (value) => Fullstory.consentAndIdentify(value, fullstorySession),
});

let stashedSession: Session = {};
Expand Down Expand Up @@ -139,12 +146,12 @@ Onyx.connectWithoutView({
},
});

function isSupportAuthToken(): boolean {
return session.authTokenType === CONST.AUTH_TOKEN_TYPES.SUPPORT;
function isSupportAuthToken(session: OnyxEntry<Session> = deprecatedSession): boolean {
return session?.authTokenType === CONST.AUTH_TOKEN_TYPES.SUPPORT;
}

function isSupportalSession(): boolean {
return isSupportAuthToken() || !!session?.isSupportAuthTokenUsed;
return isSupportAuthToken() || !!deprecatedSession?.isSupportAuthTokenUsed;
}

/**
Expand Down Expand Up @@ -305,7 +312,7 @@ function callSAMLSignOut(params: LogOutParams, authToken: string): Promise<void
* Checks if the account is an anonymous account.
*/
function isAnonymousUser(sessionParam?: OnyxEntry<Session>): boolean {
return (sessionParam?.authTokenType ?? session.authTokenType) === CONST.AUTH_TOKEN_TYPES.ANONYMOUS;
return (sessionParam?.authTokenType ?? deprecatedSession.authTokenType) === CONST.AUTH_TOKEN_TYPES.ANONYMOUS;
}

function hasStashedSession(stashedSessionParam: Session | undefined, stashedCredentialsParam: Credentials | undefined): boolean {
Expand All @@ -316,7 +323,7 @@ function hasStashedSession(stashedSessionParam: Session | undefined, stashedCred
* Checks if the user has authToken
*/
function hasAuthToken(): boolean {
return !!session.authToken;
return !!deprecatedSession.authToken;
}

/**
Expand Down Expand Up @@ -378,7 +385,7 @@ function signOutAndRedirectToSignIn(shouldResetToHome?: boolean, shouldStashSess
// session.
const signOutPromise: Promise<void | Response<never>> =
!shouldRestoreStashedSession && !shouldStashSession
? signOut({autoGeneratedLogin: credentials?.autoGeneratedLogin, signedInWithSAML: !!session.signedInWithSAML, authToken: session.authToken})
? signOut({autoGeneratedLogin: credentials?.autoGeneratedLogin, signedInWithSAML: !!deprecatedSession.signedInWithSAML, authToken: deprecatedSession.authToken})
: Promise.resolve();

// The function redirectToSignIn will clear the whole storage, so let's create our onyx params
Expand All @@ -391,7 +398,7 @@ function signOutAndRedirectToSignIn(shouldResetToHome?: boolean, shouldStashSess
if (!isSupportal && shouldStashSession) {
onyxSetParams = {
[ONYXKEYS.STASHED_CREDENTIALS]: credentials,
[ONYXKEYS.STASHED_SESSION]: session,
[ONYXKEYS.STASHED_SESSION]: deprecatedSession,
};
}

Expand All @@ -413,7 +420,7 @@ function signOutAndRedirectToSignIn(shouldResetToHome?: boolean, shouldStashSess
newDotCurrentAccountEmail: stashedSession.email ?? '',
authToken: stashedSession.authToken ?? '',
policyID: '',
accountID: session.accountID ? String(session.accountID) : '',
accountID: deprecatedSession.accountID ? String(deprecatedSession.accountID) : '',
});
hasSwitchedAccountInHybridMode = true;
}
Expand Down Expand Up @@ -620,8 +627,8 @@ function beginSignIn(email: string) {
*/
function buildOnyxDataToCleanUpAnonymousUser(): OnyxUpdate<typeof ONYXKEYS.PERSONAL_DETAILS_LIST> {
const data: Record<string, null> = {};
if (session.authTokenType === CONST.AUTH_TOKEN_TYPES.ANONYMOUS && session.accountID) {
data[session.accountID] = null;
if (deprecatedSession.authTokenType === CONST.AUTH_TOKEN_TYPES.ANONYMOUS && deprecatedSession.accountID) {
data[deprecatedSession.accountID] = null;
}
return {
onyxMethod: Onyx.METHOD.MERGE,
Expand Down Expand Up @@ -719,7 +726,7 @@ function setupNewDotAfterTransitionFromOldDot(hybridAppSettings: HybridAppSettin
const stashedData = hybridApp?.delegateAccessData?.isDelegateAccess
? {
[ONYXKEYS.STASHED_CREDENTIALS]: credentials,
[ONYXKEYS.STASHED_SESSION]: session,
[ONYXKEYS.STASHED_SESSION]: deprecatedSession,
}
: {
[ONYXKEYS.STASHED_CREDENTIALS]: {},
Expand Down Expand Up @@ -1446,7 +1453,7 @@ function clearTwoFactorAuthSecretKey() {
*/
function waitForUserSignIn(): Promise<boolean> {
return new Promise<boolean>((resolve) => {
if (session.authToken) {
if (deprecatedSession.authToken) {
resolve(true);
} else {
authPromiseResolver = resolve;
Expand Down
2 changes: 1 addition & 1 deletion src/pages/settings/InitialSettingsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ function InitialSettingsPage({currentUserPersonalDetails}: InitialSettingsPagePr
* Return a list of menu items data for general section
* @returns object with translationKey, style and items for the general section
*/
const signOutTranslationKey = isSupportAuthToken() && hasStashedSession(stashedSession, stashedCredentials) ? 'initialSettingsPage.restoreStashed' : 'initialSettingsPage.signOut';
const signOutTranslationKey = isSupportAuthToken(session) && hasStashedSession(stashedSession, stashedCredentials) ? 'initialSettingsPage.restoreStashed' : 'initialSettingsPage.signOut';
const generalMenuItemsData: Menu = {
sectionStyle: {
...styles.pt4,
Expand Down
Loading