Skip to content

Commit

Permalink
chore: [IOPID-2160] Delete local and remote FF of session refresh (#6255
Browse files Browse the repository at this point in the history
)

## Short description
Delete local and remote FF of session refresh

## List of changes proposed in this pull request
- Delete local feature flag to activate session refresh
- Delete remote feature flag to activate session refresh
- fix: Add logic to control if FL is active in
`ts/sagas/startup/watchApplicationActivitySaga.ts`

## Demo 
> [!Note]
> in order to speed up the testing process I replaced the
`backgroundActivityTimeout` field with 10 so that the functionality is
activated after 10 seconds of background and not after 2 minutes

<p>

| Local Flow with fast login active | Local Flow with fast login not
active | Production flow with fast login active | Production flow with
fast login not active |
| - | - | - | - |
| <video
src="https://github.com/user-attachments/assets/cd4ef2b3-a807-47df-8a92-1f5150cc9009"/>
| <video
src="https://github.com/user-attachments/assets/240232af-8be3-4d3c-87a2-0966274e1652"/>
| <video
src="https://github.com/user-attachments/assets/acd0efe2-dcf1-441a-9d58-7f681b2fee88"/>
| <video
src="https://github.com/user-attachments/assets/102965d8-b6d8-44ac-9b0e-2df553d44416"/>
|

</p>

## How to test

**NB**: in order to speed up the testing process at [this
line](https://github.com/pagopa/io-app/blob/01481f800f15c6322d8b9ec8ccddb471bedf6615/ts/sagas/startup/watchApplicationActivitySaga.ts#L21)
you can replace the `backgroundActivityTimeout` const with '10' so that
the functionality is activated after 10 seconds of background and not
after 2 minutes

> [!Note]
> if you have decided to test the flow with the fast login active, the
session refresh will be active, otherwise not

Run the application and put the application in the background for at
least 2 minutes. When you put it back in foreground the application will
be shown the screen to identify you and the token will be refreshed.
  • Loading branch information
Ladirico authored Oct 11, 2024
1 parent 787ee9c commit ce2b2f5
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 91 deletions.
6 changes: 1 addition & 5 deletions ts/features/fastLogin/store/actions/sessionRefreshActions.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import { ActionType, createStandardAction } from "typesafe-actions";

export const setAutomaticSessionRefresh = createStandardAction(
"SET_AUTOMATIC_SESSION_REFRESH_AFTER_TWO_MIN_BACKGROUND"
)<{ enabled: boolean | undefined }>();

export const areTwoMinElapsedFromLastActivity = createStandardAction(
"ARE_TWO_MINUTES_ELAPSED_FROM_LAST_ACTIVITY"
)<{ hasTwoMinPassed: boolean }>();

export type automaticSessionRefreshActions = ActionType<
typeof setAutomaticSessionRefresh | typeof areTwoMinElapsedFromLastActivity
typeof areTwoMinElapsedFromLastActivity
>;
36 changes: 22 additions & 14 deletions ts/features/fastLogin/store/reducers/sessionRefreshReducer.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
import AsyncStorage from "@react-native-async-storage/async-storage";
import { PersistConfig, persistReducer } from "redux-persist";
import { getType } from "typesafe-actions";
import {
areTwoMinElapsedFromLastActivity,
setAutomaticSessionRefresh
} from "../actions/sessionRefreshActions";
createMigrate,
MigrationManifest,
PersistConfig,
PersistedState,
persistReducer
} from "redux-persist";
import { getType } from "typesafe-actions";
import _ from "lodash";
import { areTwoMinElapsedFromLastActivity } from "../actions/sessionRefreshActions";
import { Action } from "../../../../store/actions/types";
import {
logoutFailure,
logoutSuccess
} from "../../../../store/actions/authentication";
import { isDevEnv } from "../../../../utils/environment";

export type AutomaticSessionRefreshState = {
enabled: boolean | undefined;
areAlreadyTwoMinAfterLastActivity: boolean;
};

export const automaticSessionRefreshInitialState: AutomaticSessionRefreshState =
{
enabled: undefined,
areAlreadyTwoMinAfterLastActivity: false
};

Expand All @@ -30,11 +33,6 @@ const AutomaticSessionRefreshReducer = (
case getType(logoutSuccess):
case getType(logoutFailure):
return automaticSessionRefreshInitialState;
case getType(setAutomaticSessionRefresh):
return {
...state,
enabled: action.payload.enabled
};
case getType(areTwoMinElapsedFromLastActivity):
return {
...state,
Expand All @@ -45,13 +43,23 @@ const AutomaticSessionRefreshReducer = (
}
};

const CURRENT_REDUX_SESSION_REFRESH_STORE_VERSION = -1;
const CURRENT_REDUX_SESSION_REFRESH_STORE_VERSION = 0;

const migrations: MigrationManifest = {
// we changed the way we compute the installation ID
"0": (state: PersistedState) =>
_.omit(
state,
"features.loginFeatures.fastLogin.automaticSessionRefresh.enabled"
)
};

const persistConfig: PersistConfig = {
key: "sessionRefresh",
storage: AsyncStorage,
version: CURRENT_REDUX_SESSION_REFRESH_STORE_VERSION,
whitelist: ["enabled"]
migrate: createMigrate(migrations, { debug: isDevEnv }),
whitelist: []
};

export const automaticSessionRefreshPersistor = persistReducer<
Expand Down
39 changes: 0 additions & 39 deletions ts/features/fastLogin/store/selectors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@ import { isPropertyWithMinAppVersionEnabled } from "../../../../store/reducers/f
export const fastLoginOptInSelector = (state: GlobalState) =>
state.features.loginFeatures.fastLogin.optIn;

export const isAutomaticSessionRefreshToggleActiveSelector = (
state: GlobalState
) => !!state.features.loginFeatures.fastLogin.automaticSessionRefresh.enabled;

export const hasTwoMinutesElapsedSinceLastActivitySelector = (
state: GlobalState
) =>
Expand Down Expand Up @@ -46,25 +42,6 @@ export const fastLoginOptInFFEnabled = createSelector(
})
);

/**
* return the remote config about AutomaticSessionRefresh enabled/disabled
* based on a minumum version of the app.
* if there is no data, false is the default value -> (AutomaticSessionRefresh disabled)
*/
export const automaticSessionRefreshFFEnabled = createSelector(
backendStatusSelector,
backendStatus =>
isPropertyWithMinAppVersionEnabled({
backendStatus,
mainLocalFlag: fastLoginEnabled,
configPropertyName: "fastLogin",
// In this case I do not have a local feature flag, but locally the
// value is chosen using a toogle. So I set this required field as true
optionalLocalFlag: true,
optionalConfig: "sessionRefresh"
})
);

const isFastLoginOptInEnabledSelector = createSelector(
fastLoginOptInFFEnabled,
fastLoginOptInSelector,
Expand Down Expand Up @@ -103,22 +80,6 @@ export const isFastLoginEnabledSelector = createSelector(
(fastloginFFEnabled, optInEnabled) => fastloginFFEnabled && !!optInEnabled
);

/**
* if the fast login is active and has been chosen by the user (opt-in is true)
* then if the remote FF of this functionality (automaticSessionRefreshFFEnabled)
* is active or the user has activated the toogle in the ‘dev’ section of
* the settings (isAutomaticSessionRefreshToggleActiveSelector), the user will
* see the implementation of the session refresh when
* returning to foreground after at least 2 minutes of background
*/
export const isAutomaticSessionRefreshEnabledSelector = createSelector(
isFastLoginEnabledSelector,
automaticSessionRefreshFFEnabled,
isAutomaticSessionRefreshToggleActiveSelector,
(isFastLoginEnabled, sessionRefresh, isSessionRefreshToggleActive) =>
isFastLoginEnabled && (sessionRefresh || isSessionRefreshToggleActive)
);

const fastLoginTokenRefreshHandlerSelector = (state: GlobalState) =>
state.features.loginFeatures.fastLogin.tokenRefreshHandler;

Expand Down
12 changes: 9 additions & 3 deletions ts/sagas/startup/watchApplicationActivitySaga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from "../../store/reducers/startup";
import { handlePendingMessageStateIfAllowed } from "../../features/pushNotifications/sagas/common";
import { areTwoMinElapsedFromLastActivity } from "../../features/fastLogin/store/actions/sessionRefreshActions";
import { isFastLoginEnabledSelector } from "../../features/fastLogin/store/selectors";

/**
* Listen to APP_STATE_CHANGE_ACTION and:
Expand Down Expand Up @@ -85,10 +86,15 @@ export function* watchApplicationActivitySaga(): IterableIterator<ReduxSagaEffec
timestamp: Date.now()
};
if (timeSinceLastStateChange >= backgroundActivityTimeoutMillis) {
// this dispatch will be used to determine whether or not to refresh the session
yield* put(
areTwoMinElapsedFromLastActivity({ hasTwoMinPassed: true })
const isFastLoginEnabled = yield* select(
isFastLoginEnabledSelector
);
// this dispatch will be used to determine whether or not to refresh the session
if (isFastLoginEnabled) {
yield* put(
areTwoMinElapsedFromLastActivity({ hasTwoMinPassed: true })
);
}
// The app was in background for a long time, request identification
yield* put(identificationRequest());
// refresh session token
Expand Down
14 changes: 7 additions & 7 deletions ts/screens/modal/IdentificationModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ import {
} from "../../utils/identification";
import {
hasTwoMinutesElapsedSinceLastActivitySelector,
isAutomaticSessionRefreshEnabledSelector
isFastLoginEnabledSelector
} from "../../features/fastLogin/store/selectors";
import { refreshSessionToken } from "../../features/fastLogin/store/actions/tokenRefreshActions";
import { areTwoMinElapsedFromLastActivity } from "../../features/fastLogin/store/actions/sessionRefreshActions";
Expand Down Expand Up @@ -85,9 +85,9 @@ const IdentificationModal = () => {
const hasTwoMinutesElapsedSinceLastActivity = useIOSelector(
hasTwoMinutesElapsedSinceLastActivitySelector
);
const isActiveSessionRefresh = useIOSelector(
isAutomaticSessionRefreshEnabledSelector
);

const isFastLoginEnabled = useIOSelector(isFastLoginEnabledSelector);

const previousIdentificationProgressState = usePrevious(
identificationProgressState
);
Expand Down Expand Up @@ -184,15 +184,15 @@ const IdentificationModal = () => {
* background and returned to the foreground then the dispatch
* of the action that refreshes the session will be performed
*/
if (hasTwoMinutesElapsedSinceLastActivity && isActiveSessionRefresh) {
if (hasTwoMinutesElapsedSinceLastActivity && isFastLoginEnabled) {
onSuccessDispatchTokenRefresh();
}
},
[
hasTwoMinutesElapsedSinceLastActivity,
identificationProgressState,
isFastLoginEnabled,
onIdentificationSuccess,
hasTwoMinutesElapsedSinceLastActivity,
isActiveSessionRefresh,
onSuccessDispatchTokenRefresh
]
);
Expand Down
24 changes: 1 addition & 23 deletions ts/screens/profile/DeveloperModeSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@ import I18n from "../../i18n";
import { AlertModal } from "../../components/ui/AlertModal";
import { LightModalContext } from "../../components/ui/LightModal";
import { isPlaygroundsEnabled } from "../../config";
import {
isAutomaticSessionRefreshToggleActiveSelector,
isFastLoginEnabledSelector
} from "../../features/fastLogin/store/selectors";
import { isFastLoginEnabledSelector } from "../../features/fastLogin/store/selectors";
import { lollipopPublicKeySelector } from "../../features/lollipop/store/reducers/lollipop";
import { toThumbprint } from "../../features/lollipop/utils/crypto";
import { notificationsInstallationSelector } from "../../features/pushNotifications/store/reducers/installation";
Expand Down Expand Up @@ -56,7 +53,6 @@ import { getDeviceId } from "../../utils/device";
import { isDevEnv } from "../../utils/environment";

import { ITW_ROUTES } from "../../features/itwallet/navigation/routes";
import { setAutomaticSessionRefresh } from "../../features/fastLogin/store/actions/sessionRefreshActions";
import { isCieIDLocalFeatureEnabledSelector } from "../../features/cieLogin/store/selectors";
import { cieIDFeatureSetEnabled } from "../../features/cieLogin/store/actions";
import DSEnableSwitch from "./components/DSEnableSwitch";
Expand Down Expand Up @@ -301,18 +297,6 @@ const DeveloperDataSection = () => {
const DesignSystemSection = () => {
const navigation = useIONavigation();
const { themeType, setTheme } = useIOThemeContext();
const dispatch = useIODispatch();

const isAutomaticSessionRefreshToggleActive = useIOSelector(
isAutomaticSessionRefreshToggleActiveSelector
);

const dispatchAutomaticSessionRefresh = React.useCallback(
(enabled: boolean) => {
dispatch(setAutomaticSessionRefresh({ enabled }));
},
[dispatch]
);

return (
<ContentWrapper>
Expand All @@ -337,12 +321,6 @@ const DesignSystemSection = () => {
setTheme(themeType === "dark" ? "light" : "dark")
}
/>
<Divider />
<ListItemSwitch
label={I18n.t("profile.main.sessionRefresh")}
value={isAutomaticSessionRefreshToggleActive}
onSwitchValueChange={dispatchAutomaticSessionRefresh}
/>
</ContentWrapper>
);
};
Expand Down

0 comments on commit ce2b2f5

Please sign in to comment.