diff --git a/lib/shared/session-utils.js b/lib/shared/session-utils.js --- a/lib/shared/session-utils.js +++ b/lib/shared/session-utils.js @@ -11,7 +11,10 @@ type LogInActionSource, } from '../types/account-types.js'; import type { AppState } from '../types/redux-types.js'; -import type { PreRequestUserState } from '../types/session-types.js'; +import type { + PreRequestUserState, + IdentityCallPreRequestUserState, +} from '../types/session-types.js'; import type { CurrentUserInfo } from '../types/user-types.js'; function invalidSessionDowngrade( @@ -44,6 +47,33 @@ ); } +function identityInvalidSessionDowngrade( + currentReduxState: AppState, + actionCurrentUserInfo: ?CurrentUserInfo, + preRequestUserState: ?IdentityCallPreRequestUserState, +): boolean { + // If this action represents a session downgrade - oldState has a loggedIn + // currentUserInfo, but the action has an anonymous one - then it is only + // valid if the currentUserInfo used for the request matches what oldState + // currently has. If the currentUserInfo in Redux has changed since the + // request, and is currently loggedIn, then the session downgrade does not + // apply to it. In this case we will simply swallow the action. + const currentCurrentUserInfo = currentReduxState.currentUserInfo; + return !!( + currentCurrentUserInfo && + !currentCurrentUserInfo.anonymous && + // Note that an undefined actionCurrentUserInfo represents an action that + // doesn't affect currentUserInfo, whereas a null one represents an action + // that sets it to null + (actionCurrentUserInfo === null || + (actionCurrentUserInfo && actionCurrentUserInfo.anonymous)) && + preRequestUserState && + (preRequestUserState.currentUserInfo?.id !== currentCurrentUserInfo.id || + preRequestUserState.commServicesAccessToken !== + currentReduxState.commServicesAccessToken) + ); +} + function invalidSessionRecovery( currentReduxState: AppState, actionCurrentUserInfo: ?CurrentUserInfo, @@ -68,4 +98,8 @@ ); } -export { invalidSessionDowngrade, invalidSessionRecovery }; +export { + invalidSessionDowngrade, + identityInvalidSessionDowngrade, + invalidSessionRecovery, +}; diff --git a/lib/types/session-types.js b/lib/types/session-types.js --- a/lib/types/session-types.js +++ b/lib/types/session-types.js @@ -77,6 +77,11 @@ }, }; +export type IdentityCallPreRequestUserState = $ReadOnly<{ + ...PreRequestUserState, + +commServicesAccessToken: ?string, +}>; + export type SetSessionPayload = { +sessionChange: ClientSessionChange, +preRequestUserState: ?PreRequestUserState,