From aa53709e0d3adb3737cf43d0e42407a5f03c6ede Mon Sep 17 00:00:00 2001 From: RiccardoMolinari95 Date: Mon, 23 Dec 2024 15:16:48 +0100 Subject: [PATCH 01/17] feat: reissuing eid --- locales/en/index.yml | 8 +++ locales/it/index.yml | 8 +++ .../ItwEidInfoBottomSheetContent.tsx | 2 +- .../components/ItwEidLifecycleAlert.tsx | 23 +++++- .../ItwIdentificationModeSelectionScreen.tsx | 25 +++++++ .../itwallet/machine/credential/actions.ts | 12 +++- ts/features/itwallet/machine/eid/actions.ts | 10 ++- ts/features/itwallet/machine/eid/context.ts | 4 +- ts/features/itwallet/machine/eid/events.ts | 7 +- ts/features/itwallet/machine/eid/machine.ts | 50 ++++++++++--- .../itwallet/navigation/ItwParamsList.ts | 4 +- .../itwallet/navigation/ItwStackNavigator.tsx | 5 ++ ts/features/itwallet/navigation/routes.ts | 3 +- .../screens/WalletCardOnboardingScreen.tsx | 20 ++++-- ...esentationEidVerificationExpiredScreen.tsx | 70 +++++++++++++++++++ .../components/WalletCardsContainer.tsx | 1 + 16 files changed, 226 insertions(+), 26 deletions(-) create mode 100644 ts/features/itwallet/presentation/screens/ItwPresentationEidVerificationExpiredScreen.tsx diff --git a/locales/en/index.yml b/locales/en/index.yml index 0351bdc8b29..85897442230 100644 --- a/locales/en/index.yml +++ b/locales/en/index.yml @@ -3475,6 +3475,7 @@ features: valid: L'ultima verifica è del {{date}}. expiring: Verifica la tua identità entro il {{date}}. expired: È necessario un rapido passaggio di verifica per continuare a usare Documenti su IO. + action: Inizia MDL: expiring: title: "Patente su IO: documento in scadenza" @@ -3528,6 +3529,13 @@ features: openPdf: "Show document" shareButton: Save or share fiscalCode: Your Fiscal Code + eid: + verificationExpired: + title: Verifica la tua identità + contentStart: "È un passaggio di sicurezza necessario per continuare ad usare " + contentBold: Documenti su IO + contentEnd: "." + primaryAction: Inizia trustmark: cta: Mostra certificato di autenticità description: Mostra il QR Code per attestare l’autenticità del documento quando ti viene richiesto. diff --git a/locales/it/index.yml b/locales/it/index.yml index 38adc05833c..134263cd930 100644 --- a/locales/it/index.yml +++ b/locales/it/index.yml @@ -3475,6 +3475,7 @@ features: valid: L'ultima verifica è del {{date}}. expiring: Verifica la tua identità entro il {{date}}. expired: È necessario un rapido passaggio di verifica per continuare a usare Documenti su IO. + action: Inizia MDL: expiring: title: "Patente su IO: documento in scadenza" @@ -3528,6 +3529,13 @@ features: openPdf: "Mostra documento" shareButton: Salva o condividi fiscalCode: Il tuo Codice Fiscale + eid: + verificationExpired: + title: Verifica la tua identità + contentStart: "È un passaggio di sicurezza necessario per continuare ad usare " + contentBold: Documenti su IO + contentEnd: "." + primaryAction: Inizia trustmark: cta: Mostra certificato di autenticità description: Mostra il QR Code per attestare l’autenticità del documento quando ti viene richiesto. diff --git a/ts/features/itwallet/common/components/ItwEidInfoBottomSheetContent.tsx b/ts/features/itwallet/common/components/ItwEidInfoBottomSheetContent.tsx index 16e950f72d4..a74e4839f52 100644 --- a/ts/features/itwallet/common/components/ItwEidInfoBottomSheetContent.tsx +++ b/ts/features/itwallet/common/components/ItwEidInfoBottomSheetContent.tsx @@ -96,7 +96,7 @@ const ItwEidInfoBottomSheetContent = ({ ))} - + = [ "valid", @@ -27,17 +29,28 @@ type Props = { * The eID statuses that will render the alert. */ lifecycleStatus?: Array; + navigation: ReturnType; }; /** * This component renders an alert that displays information on the eID status. */ export const ItwEidLifecycleAlert = ({ - lifecycleStatus = defaultLifecycleStatus + lifecycleStatus = defaultLifecycleStatus, + navigation }: Props) => { const eidOption = useIOSelector(itwCredentialsEidSelector); const maybeEidStatus = useIOSelector(itwCredentialsEidStatusSelector); + const startEidReissuing = () => { + navigation.navigate(ITW_ROUTES.MAIN, { + screen: ITW_ROUTES.IDENTIFICATION.MODE_SELECTION, + params: { + eidReissuing: true + } + }); + }; + const Content = ({ eid, eidStatus @@ -73,14 +86,18 @@ export const ItwEidLifecycleAlert = ({ { date: format(eid.jwt.expiration, "DD-MM-YYYY") } - ) + ), + action: I18n.t("features.itWallet.presentation.bottomSheets.eidInfo.alert.action"), + onPress: startEidReissuing }, jwtExpired: { testID: "itwEidLifecycleAlertTestID_jwtExpired", variant: "error", content: I18n.t( "features.itWallet.presentation.bottomSheets.eidInfo.alert.expired" - ) + ), + action: I18n.t("features.itWallet.presentation.bottomSheets.eidInfo.alert.action"), + onPress: startEidReissuing } }; diff --git a/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx b/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx index 419030f9b3e..8f104771961 100644 --- a/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx +++ b/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx @@ -17,6 +17,12 @@ import { import { itwDisabledIdentificationMethodsSelector } from "../../../../store/reducers/backendStatus/remoteConfig"; import { IOScrollViewWithLargeHeader } from "../../../../components/ui/IOScrollViewWithLargeHeader"; import { isCIEAuthenticationSupportedSelector } from "../../machine/eid/selectors"; +import { Route, useRoute } from "@react-navigation/native"; +import { ITW_ROUTES } from "../../navigation/routes"; + +export type ItwIdentificationModeSelectionScreenNavigationParams = { + eidReissuing?: boolean; +} | undefined; export const ItwIdentificationModeSelectionScreen = () => { const machineRef = ItwEidIssuanceMachineContext.useActorRef(); @@ -45,6 +51,25 @@ export const ItwIdentificationModeSelectionScreen = () => { [isCieAuthenticationSupported] ); + const route = + useRoute< + Route< + typeof ITW_ROUTES.IDENTIFICATION.MODE_SELECTION, + ItwIdentificationModeSelectionScreenNavigationParams + > + >(); + + + const { eidReissuing } = route.params || {}; + + useFocusEffect( + useCallback(() => { + if (eidReissuing) { + machineRef.send({ type: "start-reissuing" }); + } + }, [eidReissuing, machineRef]) + ); + useFocusEffect(trackItWalletIDMethod); const handleSpidPress = useCallback(() => { diff --git a/ts/features/itwallet/machine/credential/actions.ts b/ts/features/itwallet/machine/credential/actions.ts index f5f1eaf9990..734c2f4d9a8 100644 --- a/ts/features/itwallet/machine/credential/actions.ts +++ b/ts/features/itwallet/machine/credential/actions.ts @@ -101,7 +101,17 @@ export default ( CredentialIssuanceEvents >) => { assert(context.credential, "credential is undefined"); - store.dispatch(itwCredentialsStore([context.credential])); + + let cred = context.credential; + + cred = { + ...cred, + jwt: { + expiration: '2024-12-22T23:59:59Z', + } + }; + + store.dispatch(itwCredentialsStore([cred])); }, flagCredentialAsRequested: ({ diff --git a/ts/features/itwallet/machine/eid/actions.ts b/ts/features/itwallet/machine/eid/actions.ts index d7581cc2b7a..93bdaa4f4a1 100644 --- a/ts/features/itwallet/machine/eid/actions.ts +++ b/ts/features/itwallet/machine/eid/actions.ts @@ -184,7 +184,15 @@ export const createEidIssuanceActionsImplementation = ( context }: ActionArgs) => { assert(context.eid, "eID is undefined"); - store.dispatch(itwCredentialsStore([context.eid])); + + let eid = context.eid; + eid = { + ...eid, + jwt: { + expiration: '2024-12-22T23:59:59Z', + } + }; + store.dispatch(itwCredentialsStore([eid])); }, requestAssistance: () => {}, diff --git a/ts/features/itwallet/machine/eid/context.ts b/ts/features/itwallet/machine/eid/context.ts index be98c299ac2..b6e707c1ed2 100644 --- a/ts/features/itwallet/machine/eid/context.ts +++ b/ts/features/itwallet/machine/eid/context.ts @@ -41,6 +41,7 @@ export type Context = { authenticationContext: AuthenticationContext | undefined; eid: StoredCredential | undefined; failure: IssuanceFailure | undefined; + isReissuing: boolean; }; export const InitialContext: Context = { @@ -50,5 +51,6 @@ export const InitialContext: Context = { identification: undefined, authenticationContext: undefined, eid: undefined, - failure: undefined + failure: undefined, + isReissuing: false }; diff --git a/ts/features/itwallet/machine/eid/events.ts b/ts/features/itwallet/machine/eid/events.ts index 4868c1ac44b..e76b285e0af 100644 --- a/ts/features/itwallet/machine/eid/events.ts +++ b/ts/features/itwallet/machine/eid/events.ts @@ -82,6 +82,10 @@ export type ExternalErrorEvent = { error?: Error; }; +export type StartReissuing = { + type: "start-reissuing"; +}; + export type EidIssuanceEvents = | Reset | Start @@ -101,4 +105,5 @@ export type EidIssuanceEvents = | Abort | RevokeWalletInstance | ErrorActorEvent - | ExternalErrorEvent; + | ExternalErrorEvent + | StartReissuing; diff --git a/ts/features/itwallet/machine/eid/machine.ts b/ts/features/itwallet/machine/eid/machine.ts index 3da95b4605c..421ba67f436 100644 --- a/ts/features/itwallet/machine/eid/machine.ts +++ b/ts/features/itwallet/machine/eid/machine.ts @@ -71,7 +71,11 @@ export const itwEidIssuanceMachine = setup({ callbackUrl: event.authRedirectUrl } }; - }) + }), + setIsReissuing: assign(({ context }) => ({ + ...context, + isReissuing: true + })), }, actors: { createWalletInstance: fromPromise(notImplemented), @@ -92,7 +96,8 @@ export const itwEidIssuanceMachine = setup({ isSessionExpired: notImplemented, isOperationAborted: notImplemented, hasValidWalletInstanceAttestation: notImplemented, - isNFCEnabled: ({ context }) => context.cieContext?.isNFCEnabled || false + isNFCEnabled: ({ context }) => context.cieContext?.isNFCEnabled || false, + isReissuing: ({ context }) => context.isReissuing === true } }).createMachine({ id: "itwEidIssuanceMachine", @@ -121,6 +126,10 @@ export const itwEidIssuanceMachine = setup({ }, "revoke-wallet-instance": { target: "WalletInstanceRevocation" + }, + 'start-reissuing': { + target: "UserIdentification", + actions: "setIsReissuing" } } }, @@ -274,7 +283,15 @@ export const itwEidIssuanceMachine = setup({ target: "CieID" } ], - back: "#itwEidIssuanceMachine.IpzsPrivacyAcceptance" + back: [ + { + guard: "isReissuing", + target: "#itwEidIssuanceMachine.Idle" + }, + { + target: "#itwEidIssuanceMachine.IpzsPrivacyAcceptance", + } + ] } }, CieID: { @@ -554,14 +571,25 @@ export const itwEidIssuanceMachine = setup({ }, DisplayingPreview: { on: { - "add-to-wallet": { - actions: [ - "storeEidCredential", - "setWalletInstanceToValid", - "trackWalletInstanceCreation" - ], - target: "#itwEidIssuanceMachine.Success" - }, + "add-to-wallet": [ + { + guard: "isReissuing", + actions: [ + "storeEidCredential", + "setWalletInstanceToValid", + "trackWalletInstanceCreation", + "navigateToWallet" + ] + }, + { + actions: [ + "storeEidCredential", + "setWalletInstanceToValid", + "trackWalletInstanceCreation" + ], + target: "#itwEidIssuanceMachine.Success" + } + ], close: { actions: ["closeIssuance"] } diff --git a/ts/features/itwallet/navigation/ItwParamsList.ts b/ts/features/itwallet/navigation/ItwParamsList.ts index 3654b6fa7bd..5b90ba6e275 100644 --- a/ts/features/itwallet/navigation/ItwParamsList.ts +++ b/ts/features/itwallet/navigation/ItwParamsList.ts @@ -1,3 +1,4 @@ +import { ItwIdentificationModeSelectionScreenNavigationParams } from "../identification/screens/ItwIdentificationModeSelectionScreen"; import { ItwCieWrongCiePinScreenNavigationParams } from "../identification/screens/cie/ItwCieWrongCiePinScreen"; import { ItwIssuanceCredentialAsyncContinuationNavigationParams } from "../issuance/screens/ItwIssuanceCredentialAsyncContinuationScreen"; import { ItwPresentationCredentialAttachmentNavigationParams } from "../presentation/screens/ItwPresentationCredentialAttachmentScreen"; @@ -13,7 +14,7 @@ export type ItwParamsList = { [ITW_ROUTES.DISCOVERY.IPZS_PRIVACY]: undefined; [ITW_ROUTES.DISCOVERY.ALREADY_ACTIVE_SCREEN]: undefined; // IDENTIFICATION - [ITW_ROUTES.IDENTIFICATION.MODE_SELECTION]: undefined; + [ITW_ROUTES.IDENTIFICATION.MODE_SELECTION]: ItwIdentificationModeSelectionScreenNavigationParams; // IDENTIFICATION SPID [ITW_ROUTES.IDENTIFICATION.IDP_SELECTION]: undefined; [ITW_ROUTES.IDENTIFICATION.SPID.LOGIN]: undefined; @@ -46,6 +47,7 @@ export type ItwParamsList = { [ITW_ROUTES.PRESENTATION .CREDENTIAL_CARD_MODAL]: ItwPresentationCredentialCardModalNavigationParams; [ITW_ROUTES.PRESENTATION.CREDENTIAL_FISCAL_CODE_MODAL]: undefined; + [ITW_ROUTES.PRESENTATION.EID_VERIFICATION_EXPIRED]: undefined; // PLAYGROUNDS [ITW_ROUTES.PLAYGROUNDS]: undefined; [ITW_ROUTES.IDENTITY_NOT_MATCHING_SCREEN]: undefined; diff --git a/ts/features/itwallet/navigation/ItwStackNavigator.tsx b/ts/features/itwallet/navigation/ItwStackNavigator.tsx index 9be76c3d77d..86bd0f4a5bc 100644 --- a/ts/features/itwallet/navigation/ItwStackNavigator.tsx +++ b/ts/features/itwallet/navigation/ItwStackNavigator.tsx @@ -42,6 +42,7 @@ import { ItwCredentialTrustmarkScreen } from "../trustmark/screens/ItwCredential import { ItwAlreadyActiveScreen } from "../discovery/screens/ItwAlreadyActiveScreen"; import { ItwParamsList } from "./ItwParamsList"; import { ITW_ROUTES } from "./routes"; +import { ItwPresentationEidVerificationExpiredScreen } from "../presentation/screens/ItwPresentationEidVerificationExpiredScreen"; const Stack = createStackNavigator(); @@ -225,6 +226,10 @@ const InnerNavigator = () => { component={ItwLifecycleWalletRevocationScreen} options={{ headerShown: false, gestureEnabled: false }} /> + ); }; diff --git a/ts/features/itwallet/navigation/routes.ts b/ts/features/itwallet/navigation/routes.ts index 293a04cbba1..2bd5672b37b 100644 --- a/ts/features/itwallet/navigation/routes.ts +++ b/ts/features/itwallet/navigation/routes.ts @@ -42,7 +42,8 @@ export const ITW_ROUTES = { CREDENTIAL_TRUSTMARK: "ITW_PRESENTATION_CREDENTIAL_TRUSTMARK", CREDENTIAL_CARD_MODAL: "ITW_PRESENTATION_CREDENTIAL_CARD_MODAL", CREDENTIAL_FISCAL_CODE_MODAL: - "ITW_PRESENTATION_CREDENTIAL_FISCAL_CODE_MODAL" + "ITW_PRESENTATION_CREDENTIAL_FISCAL_CODE_MODAL", + EID_VERIFICATION_EXPIRED: "ITW_PRESENTATION_EID_VERIFICATION_EXPIRED", } as const, PLAYGROUNDS: "ITW_PLAYGROUNDS" as const, IDENTITY_NOT_MATCHING_SCREEN: "ITW_IDENTITY_NOT_MATCHING_SCREEN" as const, diff --git a/ts/features/itwallet/onboarding/screens/WalletCardOnboardingScreen.tsx b/ts/features/itwallet/onboarding/screens/WalletCardOnboardingScreen.tsx index 0efb8a6768f..af865e24658 100644 --- a/ts/features/itwallet/onboarding/screens/WalletCardOnboardingScreen.tsx +++ b/ts/features/itwallet/onboarding/screens/WalletCardOnboardingScreen.tsx @@ -41,6 +41,7 @@ import { } from "../../machine/credential/selectors"; import { ItwCredentialIssuanceMachineContext } from "../../machine/provider"; import { ItwOnboardingModuleCredential } from "../components/ItwOnboardingModuleCredential"; +import { ITW_ROUTES } from "../../navigation/routes"; // List of available credentials to show to the user const availableCredentials = [ @@ -100,13 +101,22 @@ const ItwCredentialOnboardingSection = () => { const itwCredentialsTypes = useIOSelector(itwCredentialsTypesSelector); + const isWalletValid = useIOSelector(itwLifecycleIsValidSelector); + const navigation = useIONavigation(); + const beginCredentialIssuance = useCallback( (type: string) => { - machineRef.send({ - type: "select-credential", - credentialType: type, - skipNavigation: true - }); + if (!isWalletValid) { + navigation.navigate(ITW_ROUTES.MAIN, { + screen: ITW_ROUTES.PRESENTATION.EID_VERIFICATION_EXPIRED + }); + } else { + machineRef.send({ + type: "select-credential", + credentialType: type, + skipNavigation: true + }); + } }, [machineRef] ); diff --git a/ts/features/itwallet/presentation/screens/ItwPresentationEidVerificationExpiredScreen.tsx b/ts/features/itwallet/presentation/screens/ItwPresentationEidVerificationExpiredScreen.tsx new file mode 100644 index 00000000000..acae9212856 --- /dev/null +++ b/ts/features/itwallet/presentation/screens/ItwPresentationEidVerificationExpiredScreen.tsx @@ -0,0 +1,70 @@ +import React, { useMemo } from "react"; +import { OperationResultScreenContent } from "../../../../components/screens/OperationResultScreenContent"; +import I18n from "../../../../i18n"; +import { useIONavigation } from "../../../../navigation/params/AppParamsList"; +import { useHeaderSecondLevel } from "../../../../hooks/useHeaderSecondLevel"; +import { BodyProps } from "@pagopa/io-app-design-system"; +import { ITW_ROUTES } from "../../navigation/routes"; + +export const ItwPresentationEidVerificationExpiredScreen = () => { + const navigation = useIONavigation(); + + useHeaderSecondLevel({ + title: "", + headerShown: false + }); + + const startEidReissuing = () => { + navigation.navigate(ITW_ROUTES.MAIN, { + screen: ITW_ROUTES.IDENTIFICATION.MODE_SELECTION, + params: { + eidReissuing: true + } + }); + }; + + const bodyPropsArray: Array = useMemo( + () => [ + { + text: I18n.t("features.itWallet.presentation.eid.verificationExpired.contentStart"), + style: { + textAlign: "center" + } + }, + { + text: I18n.t("features.itWallet.presentation.eid.verificationExpired.contentBold"), + style: { + textAlign: "center", + fontWeight: "bold" + } + }, + { + text: I18n.t("features.itWallet.presentation.eid.verificationExpired.contentEnd"), + style: { + textAlign: "center" + } + } + ], + [] + ); + + return ( + navigation.goBack() + }} + /> + ); +}; diff --git a/ts/features/wallet/components/WalletCardsContainer.tsx b/ts/features/wallet/components/WalletCardsContainer.tsx index 394dc54ee19..19881346766 100644 --- a/ts/features/wallet/components/WalletCardsContainer.tsx +++ b/ts/features/wallet/components/WalletCardsContainer.tsx @@ -161,6 +161,7 @@ const ItwWalletCardsContainer = () => { } From a0f6f558cc38010e63631aaad4bb008d2285a2b0 Mon Sep 17 00:00:00 2001 From: RiccardoMolinari95 Date: Mon, 23 Dec 2024 15:28:23 +0100 Subject: [PATCH 02/17] refactor: prettify --- .../common/components/ItwEidLifecycleAlert.tsx | 8 ++++++-- .../screens/ItwIdentificationModeSelectionScreen.tsx | 9 +++++---- ts/features/itwallet/machine/credential/actions.ts | 2 +- ts/features/itwallet/machine/eid/actions.ts | 2 +- ts/features/itwallet/machine/eid/machine.ts | 10 +++++----- ts/features/itwallet/navigation/ItwParamsList.ts | 3 ++- ts/features/itwallet/navigation/routes.ts | 2 +- .../ItwPresentationEidVerificationExpiredScreen.tsx | 12 +++++++++--- 8 files changed, 30 insertions(+), 18 deletions(-) diff --git a/ts/features/itwallet/common/components/ItwEidLifecycleAlert.tsx b/ts/features/itwallet/common/components/ItwEidLifecycleAlert.tsx index 19ee27c23e4..9ecb1c112dd 100644 --- a/ts/features/itwallet/common/components/ItwEidLifecycleAlert.tsx +++ b/ts/features/itwallet/common/components/ItwEidLifecycleAlert.tsx @@ -87,7 +87,9 @@ export const ItwEidLifecycleAlert = ({ date: format(eid.jwt.expiration, "DD-MM-YYYY") } ), - action: I18n.t("features.itWallet.presentation.bottomSheets.eidInfo.alert.action"), + action: I18n.t( + "features.itWallet.presentation.bottomSheets.eidInfo.alert.action" + ), onPress: startEidReissuing }, jwtExpired: { @@ -96,7 +98,9 @@ export const ItwEidLifecycleAlert = ({ content: I18n.t( "features.itWallet.presentation.bottomSheets.eidInfo.alert.expired" ), - action: I18n.t("features.itWallet.presentation.bottomSheets.eidInfo.alert.action"), + action: I18n.t( + "features.itWallet.presentation.bottomSheets.eidInfo.alert.action" + ), onPress: startEidReissuing } }; diff --git a/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx b/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx index 8f104771961..bda0496cdf2 100644 --- a/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx +++ b/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx @@ -20,9 +20,11 @@ import { isCIEAuthenticationSupportedSelector } from "../../machine/eid/selector import { Route, useRoute } from "@react-navigation/native"; import { ITW_ROUTES } from "../../navigation/routes"; -export type ItwIdentificationModeSelectionScreenNavigationParams = { - eidReissuing?: boolean; -} | undefined; +export type ItwIdentificationModeSelectionScreenNavigationParams = + | { + eidReissuing?: boolean; + } + | undefined; export const ItwIdentificationModeSelectionScreen = () => { const machineRef = ItwEidIssuanceMachineContext.useActorRef(); @@ -59,7 +61,6 @@ export const ItwIdentificationModeSelectionScreen = () => { > >(); - const { eidReissuing } = route.params || {}; useFocusEffect( diff --git a/ts/features/itwallet/machine/credential/actions.ts b/ts/features/itwallet/machine/credential/actions.ts index 734c2f4d9a8..5b4dc3cef90 100644 --- a/ts/features/itwallet/machine/credential/actions.ts +++ b/ts/features/itwallet/machine/credential/actions.ts @@ -107,7 +107,7 @@ export default ( cred = { ...cred, jwt: { - expiration: '2024-12-22T23:59:59Z', + expiration: "2024-12-22T23:59:59Z" } }; diff --git a/ts/features/itwallet/machine/eid/actions.ts b/ts/features/itwallet/machine/eid/actions.ts index 93bdaa4f4a1..86d674b4aed 100644 --- a/ts/features/itwallet/machine/eid/actions.ts +++ b/ts/features/itwallet/machine/eid/actions.ts @@ -189,7 +189,7 @@ export const createEidIssuanceActionsImplementation = ( eid = { ...eid, jwt: { - expiration: '2024-12-22T23:59:59Z', + expiration: "2024-12-22T23:59:59Z" } }; store.dispatch(itwCredentialsStore([eid])); diff --git a/ts/features/itwallet/machine/eid/machine.ts b/ts/features/itwallet/machine/eid/machine.ts index 421ba67f436..7e26d996f09 100644 --- a/ts/features/itwallet/machine/eid/machine.ts +++ b/ts/features/itwallet/machine/eid/machine.ts @@ -75,7 +75,7 @@ export const itwEidIssuanceMachine = setup({ setIsReissuing: assign(({ context }) => ({ ...context, isReissuing: true - })), + })) }, actors: { createWalletInstance: fromPromise(notImplemented), @@ -127,7 +127,7 @@ export const itwEidIssuanceMachine = setup({ "revoke-wallet-instance": { target: "WalletInstanceRevocation" }, - 'start-reissuing': { + "start-reissuing": { target: "UserIdentification", actions: "setIsReissuing" } @@ -289,7 +289,7 @@ export const itwEidIssuanceMachine = setup({ target: "#itwEidIssuanceMachine.Idle" }, { - target: "#itwEidIssuanceMachine.IpzsPrivacyAcceptance", + target: "#itwEidIssuanceMachine.IpzsPrivacyAcceptance" } ] } @@ -573,12 +573,12 @@ export const itwEidIssuanceMachine = setup({ on: { "add-to-wallet": [ { - guard: "isReissuing", + guard: "isReissuing", actions: [ "storeEidCredential", "setWalletInstanceToValid", "trackWalletInstanceCreation", - "navigateToWallet" + "navigateToWallet" ] }, { diff --git a/ts/features/itwallet/navigation/ItwParamsList.ts b/ts/features/itwallet/navigation/ItwParamsList.ts index 5b90ba6e275..ec1722a7e4c 100644 --- a/ts/features/itwallet/navigation/ItwParamsList.ts +++ b/ts/features/itwallet/navigation/ItwParamsList.ts @@ -14,7 +14,8 @@ export type ItwParamsList = { [ITW_ROUTES.DISCOVERY.IPZS_PRIVACY]: undefined; [ITW_ROUTES.DISCOVERY.ALREADY_ACTIVE_SCREEN]: undefined; // IDENTIFICATION - [ITW_ROUTES.IDENTIFICATION.MODE_SELECTION]: ItwIdentificationModeSelectionScreenNavigationParams; + [ITW_ROUTES.IDENTIFICATION + .MODE_SELECTION]: ItwIdentificationModeSelectionScreenNavigationParams; // IDENTIFICATION SPID [ITW_ROUTES.IDENTIFICATION.IDP_SELECTION]: undefined; [ITW_ROUTES.IDENTIFICATION.SPID.LOGIN]: undefined; diff --git a/ts/features/itwallet/navigation/routes.ts b/ts/features/itwallet/navigation/routes.ts index 2bd5672b37b..6315e98c88b 100644 --- a/ts/features/itwallet/navigation/routes.ts +++ b/ts/features/itwallet/navigation/routes.ts @@ -43,7 +43,7 @@ export const ITW_ROUTES = { CREDENTIAL_CARD_MODAL: "ITW_PRESENTATION_CREDENTIAL_CARD_MODAL", CREDENTIAL_FISCAL_CODE_MODAL: "ITW_PRESENTATION_CREDENTIAL_FISCAL_CODE_MODAL", - EID_VERIFICATION_EXPIRED: "ITW_PRESENTATION_EID_VERIFICATION_EXPIRED", + EID_VERIFICATION_EXPIRED: "ITW_PRESENTATION_EID_VERIFICATION_EXPIRED" } as const, PLAYGROUNDS: "ITW_PLAYGROUNDS" as const, IDENTITY_NOT_MATCHING_SCREEN: "ITW_IDENTITY_NOT_MATCHING_SCREEN" as const, diff --git a/ts/features/itwallet/presentation/screens/ItwPresentationEidVerificationExpiredScreen.tsx b/ts/features/itwallet/presentation/screens/ItwPresentationEidVerificationExpiredScreen.tsx index acae9212856..0f636d75c59 100644 --- a/ts/features/itwallet/presentation/screens/ItwPresentationEidVerificationExpiredScreen.tsx +++ b/ts/features/itwallet/presentation/screens/ItwPresentationEidVerificationExpiredScreen.tsx @@ -26,20 +26,26 @@ export const ItwPresentationEidVerificationExpiredScreen = () => { const bodyPropsArray: Array = useMemo( () => [ { - text: I18n.t("features.itWallet.presentation.eid.verificationExpired.contentStart"), + text: I18n.t( + "features.itWallet.presentation.eid.verificationExpired.contentStart" + ), style: { textAlign: "center" } }, { - text: I18n.t("features.itWallet.presentation.eid.verificationExpired.contentBold"), + text: I18n.t( + "features.itWallet.presentation.eid.verificationExpired.contentBold" + ), style: { textAlign: "center", fontWeight: "bold" } }, { - text: I18n.t("features.itWallet.presentation.eid.verificationExpired.contentEnd"), + text: I18n.t( + "features.itWallet.presentation.eid.verificationExpired.contentEnd" + ), style: { textAlign: "center" } From 38afaa36550a87bbe12a1f1d553574101c831c4e Mon Sep 17 00:00:00 2001 From: RiccardoMolinari95 Date: Mon, 23 Dec 2024 15:38:49 +0100 Subject: [PATCH 03/17] refactor: reintroduced store of real eid and credential and not mocked --- ts/features/itwallet/machine/credential/actions.ts | 12 +----------- ts/features/itwallet/machine/eid/actions.ts | 10 +--------- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/ts/features/itwallet/machine/credential/actions.ts b/ts/features/itwallet/machine/credential/actions.ts index 5b4dc3cef90..f5f1eaf9990 100644 --- a/ts/features/itwallet/machine/credential/actions.ts +++ b/ts/features/itwallet/machine/credential/actions.ts @@ -101,17 +101,7 @@ export default ( CredentialIssuanceEvents >) => { assert(context.credential, "credential is undefined"); - - let cred = context.credential; - - cred = { - ...cred, - jwt: { - expiration: "2024-12-22T23:59:59Z" - } - }; - - store.dispatch(itwCredentialsStore([cred])); + store.dispatch(itwCredentialsStore([context.credential])); }, flagCredentialAsRequested: ({ diff --git a/ts/features/itwallet/machine/eid/actions.ts b/ts/features/itwallet/machine/eid/actions.ts index 86d674b4aed..d7581cc2b7a 100644 --- a/ts/features/itwallet/machine/eid/actions.ts +++ b/ts/features/itwallet/machine/eid/actions.ts @@ -184,15 +184,7 @@ export const createEidIssuanceActionsImplementation = ( context }: ActionArgs) => { assert(context.eid, "eID is undefined"); - - let eid = context.eid; - eid = { - ...eid, - jwt: { - expiration: "2024-12-22T23:59:59Z" - } - }; - store.dispatch(itwCredentialsStore([eid])); + store.dispatch(itwCredentialsStore([context.eid])); }, requestAssistance: () => {}, From 503d15dcd70a1829fa0f4d4b6eed46af04c4189f Mon Sep 17 00:00:00 2001 From: RiccardoMolinari95 Date: Mon, 23 Dec 2024 17:08:21 +0100 Subject: [PATCH 04/17] test: add test eid reissuing --- .../machine/eid/__tests__/machine.test.ts | 137 +++++++++++++++++- 1 file changed, 136 insertions(+), 1 deletion(-) diff --git a/ts/features/itwallet/machine/eid/__tests__/machine.test.ts b/ts/features/itwallet/machine/eid/__tests__/machine.test.ts index c7d51a9c7ab..dddce76a1ad 100644 --- a/ts/features/itwallet/machine/eid/__tests__/machine.test.ts +++ b/ts/features/itwallet/machine/eid/__tests__/machine.test.ts @@ -92,7 +92,10 @@ describe("itwEidIssuanceMachine", () => { resetWalletInstance, trackWalletInstanceCreation, trackWalletInstanceRevocation, - onInit: assign(onInit) + onInit: assign(onInit), + setIsReissuing : assign({ + isReissuing: true + }) }, actors: { createWalletInstance: fromPromise(createWalletInstance), @@ -982,4 +985,136 @@ describe("itwEidIssuanceMachine", () => { expect(actor.getSnapshot().value).toStrictEqual("Idle"); }); + + it("Should obtain an eID (SPID), reissuing mode", async () => { + + //The wallet instance and attestation already exist + const initialContext = { + ...InitialContext, + integrityKeyTag: T_INTEGRITY_KEY, + walletInstanceAttestation: T_WIA, + }; + + const actor = createActor(mockedMachine); + actor.start(); + + actor.getSnapshot().context = initialContext; + + await waitFor(() => expect(onInit).toHaveBeenCalledTimes(1)); + + expect(actor.getSnapshot().value).toStrictEqual("Idle"); + expect(actor.getSnapshot().tags).toStrictEqual(new Set()); + + actor.send({ type: "start-reissuing" }); + + expect(actor.getSnapshot().value).toStrictEqual({ + UserIdentification: "ModeSelection" + }); + + expect(actor.getSnapshot().context).toStrictEqual({ + ...initialContext, + isReissuing: true + }); + + /** + * Choose SPID as identification mode + */ + + actor.send({ type: "select-identification-mode", mode: "spid" }); + + expect(actor.getSnapshot().value).toStrictEqual({ + UserIdentification: { + Spid: "IdpSelection" + } + }); + expect(actor.getSnapshot().tags).toStrictEqual(new Set()); + expect(navigateToIdpSelectionScreen).toHaveBeenCalledTimes(1); + + /** + * Choose first IDP in list for SPID identification + */ + + startAuthFlow.mockImplementation(() => Promise.resolve({})); + + requestEid.mockImplementation(() => + Promise.resolve(ItwStoredCredentialsMocks.eid) + ); + + issuedEidMatchesAuthenticatedUser.mockImplementation(() => true); + + actor.send({ type: "select-spid-idp", idp: idps[0] }); + + expect(actor.getSnapshot().value).toStrictEqual({ + UserIdentification: { + Spid: "StartingSpidAuthFlow" + } + }); + + expect(actor.getSnapshot().context).toStrictEqual({ + ...initialContext, + integrityKeyTag: T_INTEGRITY_KEY, + walletInstanceAttestation: T_WIA, + isReissuing: true, + identification: { + mode: "spid", + idpId: idps[0].id + } + }); + + expect(actor.getSnapshot().tags).toStrictEqual(new Set([ItwTags.Loading])); + + await waitFor(() => expect(startAuthFlow).toHaveBeenCalledTimes(1)); + + expect(actor.getSnapshot().value).toStrictEqual({ + UserIdentification: { + Spid: "CompletingSpidAuthFlow" + } + }); + + actor.send({ + type: "user-identification-completed", + authRedirectUrl: "http://test.it" + }); + + expect(actor.getSnapshot().value).toStrictEqual({ + Issuance: "RequestingEid" + }); + + expect(actor.getSnapshot().tags).toStrictEqual(new Set([ItwTags.Loading])); + expect(actor.getSnapshot().context).toMatchObject({ + authenticationContext: { + callbackUrl: "http://test.it" + } + }); + expect(navigateToEidPreviewScreen).toHaveBeenCalledTimes(1); + + // EID obtained + + await waitFor(() => + expect(actor.getSnapshot().value).toStrictEqual({ + Issuance: "DisplayingPreview" + }) + ); + + actor.send({ type: "add-to-wallet" }); + + expect(storeEidCredential).toHaveBeenCalledTimes(1); + expect(setWalletInstanceToValid).toHaveBeenCalledTimes(1); + expect(navigateToWallet).toHaveBeenCalledTimes(1); + + expect(actor.getSnapshot().context).toStrictEqual({ + ...initialContext, + integrityKeyTag: T_INTEGRITY_KEY, + walletInstanceAttestation: T_WIA, + isReissuing: true, + identification: { + mode: "spid", + idpId: idps[0].id + }, + authenticationContext: expect.objectContaining({ + callbackUrl: "http://test.it" + }), + eid: ItwStoredCredentialsMocks.eid + }); + }); }); From 4daa05be080bfe8f110f6eca86470a2c8ebc3a6d Mon Sep 17 00:00:00 2001 From: RiccardoMolinari95 Date: Mon, 23 Dec 2024 17:13:59 +0100 Subject: [PATCH 05/17] test: add tests for back button in UserIdentification: ModeSelection --- .../machine/eid/__tests__/machine.test.ts | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/ts/features/itwallet/machine/eid/__tests__/machine.test.ts b/ts/features/itwallet/machine/eid/__tests__/machine.test.ts index dddce76a1ad..3c5d4bc7bcd 100644 --- a/ts/features/itwallet/machine/eid/__tests__/machine.test.ts +++ b/ts/features/itwallet/machine/eid/__tests__/machine.test.ts @@ -1117,4 +1117,48 @@ describe("itwEidIssuanceMachine", () => { eid: ItwStoredCredentialsMocks.eid }); }); + + it("Should go back to Idle state if isReissuing is true", async () => { + const initialSnapshot: MachineSnapshot = createActor( + itwEidIssuanceMachine + ).getSnapshot(); + + const snapshot: MachineSnapshot = _.merge(undefined, initialSnapshot, { + value: { UserIdentification: "ModeSelection" }, + context: { + isReissuing: true + } + } as MachineSnapshot); + + const actor = createActor(mockedMachine, { + snapshot + }); + actor.start(); + + actor.send({ type: "back" }); + + expect(actor.getSnapshot().value).toStrictEqual("Idle"); + }); + + it("Should go back to IpzsPrivacyAcceptance state if isReissuing is false", async () => { + const initialSnapshot: MachineSnapshot = createActor( + itwEidIssuanceMachine + ).getSnapshot(); + + const snapshot: MachineSnapshot = _.merge(undefined, initialSnapshot, { + value: { UserIdentification: "ModeSelection" }, + context: { + isReissuing: false + } + } as MachineSnapshot); + + const actor = createActor(mockedMachine, { + snapshot + }); + actor.start(); + + actor.send({ type: "back" }); + + expect(actor.getSnapshot().value).toStrictEqual("IpzsPrivacyAcceptance"); + }); }); From 903cb6ce2bd1b85ff5d3dbf8f6aa02fe59776adb Mon Sep 17 00:00:00 2001 From: RiccardoMolinari95 Date: Mon, 23 Dec 2024 17:14:58 +0100 Subject: [PATCH 06/17] refactor: prettify --- .../machine/eid/__tests__/machine.test.ts | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/ts/features/itwallet/machine/eid/__tests__/machine.test.ts b/ts/features/itwallet/machine/eid/__tests__/machine.test.ts index 3c5d4bc7bcd..deec87b8774 100644 --- a/ts/features/itwallet/machine/eid/__tests__/machine.test.ts +++ b/ts/features/itwallet/machine/eid/__tests__/machine.test.ts @@ -93,7 +93,7 @@ describe("itwEidIssuanceMachine", () => { trackWalletInstanceCreation, trackWalletInstanceRevocation, onInit: assign(onInit), - setIsReissuing : assign({ + setIsReissuing: assign({ isReissuing: true }) }, @@ -987,14 +987,13 @@ describe("itwEidIssuanceMachine", () => { }); it("Should obtain an eID (SPID), reissuing mode", async () => { - //The wallet instance and attestation already exist const initialContext = { ...InitialContext, integrityKeyTag: T_INTEGRITY_KEY, - walletInstanceAttestation: T_WIA, + walletInstanceAttestation: T_WIA }; - + const actor = createActor(mockedMachine); actor.start(); @@ -1004,9 +1003,9 @@ describe("itwEidIssuanceMachine", () => { expect(actor.getSnapshot().value).toStrictEqual("Idle"); expect(actor.getSnapshot().tags).toStrictEqual(new Set()); - + actor.send({ type: "start-reissuing" }); - + expect(actor.getSnapshot().value).toStrictEqual({ UserIdentification: "ModeSelection" }); @@ -1122,21 +1121,21 @@ describe("itwEidIssuanceMachine", () => { const initialSnapshot: MachineSnapshot = createActor( itwEidIssuanceMachine ).getSnapshot(); - + const snapshot: MachineSnapshot = _.merge(undefined, initialSnapshot, { value: { UserIdentification: "ModeSelection" }, context: { isReissuing: true } } as MachineSnapshot); - + const actor = createActor(mockedMachine, { snapshot }); actor.start(); - + actor.send({ type: "back" }); - + expect(actor.getSnapshot().value).toStrictEqual("Idle"); }); @@ -1144,21 +1143,21 @@ describe("itwEidIssuanceMachine", () => { const initialSnapshot: MachineSnapshot = createActor( itwEidIssuanceMachine ).getSnapshot(); - + const snapshot: MachineSnapshot = _.merge(undefined, initialSnapshot, { value: { UserIdentification: "ModeSelection" }, context: { isReissuing: false } } as MachineSnapshot); - + const actor = createActor(mockedMachine, { snapshot }); actor.start(); - + actor.send({ type: "back" }); - + expect(actor.getSnapshot().value).toStrictEqual("IpzsPrivacyAcceptance"); }); }); From 50f94faaafd82e7d77fcb3eeb19b4a1e879ce8f5 Mon Sep 17 00:00:00 2001 From: RiccardoMolinari95 Date: Tue, 24 Dec 2024 14:46:10 +0100 Subject: [PATCH 07/17] fix lint --- .../screens/ItwIdentificationModeSelectionScreen.tsx | 3 +-- ts/features/itwallet/machine/eid/__tests__/machine.test.ts | 4 +++- ts/features/itwallet/navigation/ItwStackNavigator.tsx | 2 +- .../onboarding/screens/WalletCardOnboardingScreen.tsx | 2 +- .../screens/ItwPresentationEidVerificationExpiredScreen.tsx | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx b/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx index bda0496cdf2..22dfd7b9e3f 100644 --- a/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx +++ b/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx @@ -5,7 +5,7 @@ import { VStack } from "@pagopa/io-app-design-system"; import React, { useCallback, useMemo } from "react"; -import { useFocusEffect } from "@react-navigation/native"; +import { Route, useFocusEffect, useRoute } from "@react-navigation/native"; import I18n from "../../../../i18n"; import { useIOSelector } from "../../../../store/hooks"; import { cieFlowForDevServerEnabled } from "../../../cieLogin/utils"; @@ -17,7 +17,6 @@ import { import { itwDisabledIdentificationMethodsSelector } from "../../../../store/reducers/backendStatus/remoteConfig"; import { IOScrollViewWithLargeHeader } from "../../../../components/ui/IOScrollViewWithLargeHeader"; import { isCIEAuthenticationSupportedSelector } from "../../machine/eid/selectors"; -import { Route, useRoute } from "@react-navigation/native"; import { ITW_ROUTES } from "../../navigation/routes"; export type ItwIdentificationModeSelectionScreenNavigationParams = diff --git a/ts/features/itwallet/machine/eid/__tests__/machine.test.ts b/ts/features/itwallet/machine/eid/__tests__/machine.test.ts index 6eb452c5ce8..bf790811943 100644 --- a/ts/features/itwallet/machine/eid/__tests__/machine.test.ts +++ b/ts/features/itwallet/machine/eid/__tests__/machine.test.ts @@ -989,7 +989,7 @@ describe("itwEidIssuanceMachine", () => { }); it("Should obtain an eID (SPID), reissuing mode", async () => { - //The wallet instance and attestation already exist + // The wallet instance and attestation already exist const initialContext = { ...InitialContext, integrityKeyTag: T_INTEGRITY_KEY, @@ -999,6 +999,7 @@ describe("itwEidIssuanceMachine", () => { const actor = createActor(mockedMachine); actor.start(); + // eslint-disable-next-line functional/immutable-data actor.getSnapshot().context = initialContext; await waitFor(() => expect(onInit).toHaveBeenCalledTimes(1)); @@ -1091,6 +1092,7 @@ describe("itwEidIssuanceMachine", () => { // EID obtained + // eslint-disable-next-line sonarjs/no-identical-functions await waitFor(() => expect(actor.getSnapshot().value).toStrictEqual({ Issuance: "DisplayingPreview" diff --git a/ts/features/itwallet/navigation/ItwStackNavigator.tsx b/ts/features/itwallet/navigation/ItwStackNavigator.tsx index 6d1404208d1..75fd1f84237 100644 --- a/ts/features/itwallet/navigation/ItwStackNavigator.tsx +++ b/ts/features/itwallet/navigation/ItwStackNavigator.tsx @@ -40,9 +40,9 @@ import ItwCieIdLoginScreen from "../identification/screens/cieId/ItwCieIdLoginSc import { ItwPresentationCredentialFiscalCodeModal } from "../presentation/screens/ItwPresentationCredentialFiscalCodeModal"; import { ItwCredentialTrustmarkScreen } from "../trustmark/screens/ItwCredentialTrustmarkScreen"; import { ItwAlreadyActiveScreen } from "../discovery/screens/ItwAlreadyActiveScreen"; +import { ItwPresentationEidVerificationExpiredScreen } from "../presentation/screens/ItwPresentationEidVerificationExpiredScreen"; import { ItwParamsList } from "./ItwParamsList"; import { ITW_ROUTES } from "./routes"; -import { ItwPresentationEidVerificationExpiredScreen } from "../presentation/screens/ItwPresentationEidVerificationExpiredScreen"; const Stack = createStackNavigator(); diff --git a/ts/features/itwallet/onboarding/screens/WalletCardOnboardingScreen.tsx b/ts/features/itwallet/onboarding/screens/WalletCardOnboardingScreen.tsx index b7b9d7bf1c8..0a0eed54394 100644 --- a/ts/features/itwallet/onboarding/screens/WalletCardOnboardingScreen.tsx +++ b/ts/features/itwallet/onboarding/screens/WalletCardOnboardingScreen.tsx @@ -118,7 +118,7 @@ const ItwCredentialOnboardingSection = () => { }); } }, - [machineRef] + [machineRef, isWalletValid, navigation] ); return ( diff --git a/ts/features/itwallet/presentation/screens/ItwPresentationEidVerificationExpiredScreen.tsx b/ts/features/itwallet/presentation/screens/ItwPresentationEidVerificationExpiredScreen.tsx index 0f636d75c59..37b9e73ef33 100644 --- a/ts/features/itwallet/presentation/screens/ItwPresentationEidVerificationExpiredScreen.tsx +++ b/ts/features/itwallet/presentation/screens/ItwPresentationEidVerificationExpiredScreen.tsx @@ -1,9 +1,9 @@ import React, { useMemo } from "react"; +import { BodyProps } from "@pagopa/io-app-design-system"; import { OperationResultScreenContent } from "../../../../components/screens/OperationResultScreenContent"; import I18n from "../../../../i18n"; import { useIONavigation } from "../../../../navigation/params/AppParamsList"; import { useHeaderSecondLevel } from "../../../../hooks/useHeaderSecondLevel"; -import { BodyProps } from "@pagopa/io-app-design-system"; import { ITW_ROUTES } from "../../navigation/routes"; export const ItwPresentationEidVerificationExpiredScreen = () => { From 1ba545e32e56462ba707f3c5cac74dea6e3458c0 Mon Sep 17 00:00:00 2001 From: RiccardoMolinari95 Date: Fri, 3 Jan 2025 16:23:20 +0100 Subject: [PATCH 08/17] chore: check wia before start eid reisuuing flow --- ts/features/itwallet/machine/eid/actions.ts | 4 ++ ts/features/itwallet/machine/eid/guards.ts | 8 +++- ts/features/itwallet/machine/eid/machine.ts | 48 ++++++++++++++++----- 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/ts/features/itwallet/machine/eid/actions.ts b/ts/features/itwallet/machine/eid/actions.ts index 2572a537d9f..8d00851a7ea 100644 --- a/ts/features/itwallet/machine/eid/actions.ts +++ b/ts/features/itwallet/machine/eid/actions.ts @@ -220,6 +220,10 @@ export const createEidIssuanceActionsImplementation = ( trackItwDeactivated(store.getState()); }, + assignWalletInstanceAttestationToContext: assign(({ event }) => ({ + walletInstanceAttestation: event.output + })), + onInit: assign( () => { const state = store.getState(); diff --git a/ts/features/itwallet/machine/eid/guards.ts b/ts/features/itwallet/machine/eid/guards.ts index 78cb8f805f2..a05d799d853 100644 --- a/ts/features/itwallet/machine/eid/guards.ts +++ b/ts/features/itwallet/machine/eid/guards.ts @@ -12,6 +12,9 @@ type GuardsImplementationOptions = Partial<{ bypassIdentityMatch: boolean; }>; +const checkSessionExpired = ({ event }: { event: EidIssuanceEvents }) => + "error" in event && event.error instanceof ItwSessionExpiredError; + export const createEidIssuanceGuardsImplementation = ( store: ReturnType, options?: GuardsImplementationOptions @@ -35,7 +38,10 @@ export const createEidIssuanceGuardsImplementation = ( }, isSessionExpired: ({ event }: { event: EidIssuanceEvents }) => - "error" in event && event.error instanceof ItwSessionExpiredError, + checkSessionExpired({ event }), + + isReissuingAndSessionExpired: ({ context, event }: { context: Context, event: EidIssuanceEvents }) => + context.isReissuing === true && checkSessionExpired({ event }), hasValidWalletInstanceAttestation: ({ context }: { context: Context }) => pipe( diff --git a/ts/features/itwallet/machine/eid/machine.ts b/ts/features/itwallet/machine/eid/machine.ts index 0106185bd4f..a9be52993f2 100644 --- a/ts/features/itwallet/machine/eid/machine.ts +++ b/ts/features/itwallet/machine/eid/machine.ts @@ -56,6 +56,7 @@ export const itwEidIssuanceMachine = setup({ trackWalletInstanceRevocation: notImplemented, setFailure: assign(({ event }) => ({ failure: mapEventToFailure(event) })), onInit: notImplemented, + assignWalletInstanceAttestationToContext: notImplemented, /** * Save the final redirect url in the machine context for later reuse. * This action is the same for the three identification methods. @@ -95,6 +96,7 @@ export const itwEidIssuanceMachine = setup({ guards: { issuedEidMatchesAuthenticatedUser: notImplemented, isSessionExpired: notImplemented, + isReissuingAndSessionExpired: notImplemented, isOperationAborted: notImplemented, hasValidWalletInstanceAttestation: notImplemented, isNFCEnabled: ({ context }) => context.cieContext?.isNFCEnabled || false, @@ -129,7 +131,7 @@ export const itwEidIssuanceMachine = setup({ target: "WalletInstanceRevocation" }, "start-reissuing": { - target: "UserIdentification", + target: "CheckingWalletInstanceAttestation", actions: "setIsReissuing" } } @@ -154,6 +156,19 @@ export const itwEidIssuanceMachine = setup({ ] } }, + CheckingWalletInstanceAttestation: { + description: + "This is a state with the only purpose of checking the WIA and decide weather to get a new one or not and then proceed with the user identification", + always: [ + { + guard: not("hasValidWalletInstanceAttestation"), + target: "WalletInstanceAttestationObtainment" + }, + { + target: "UserIdentification" + } + ] + }, WalletInstanceCreation: { description: "This state generates the integrity hardware key and registers the wallet instance. The generated integrity hardware key is then stored and persisted to the redux store.", @@ -219,16 +234,29 @@ export const itwEidIssuanceMachine = setup({ invoke: { src: "getWalletAttestation", input: ({ context }) => ({ integrityKeyTag: context.integrityKeyTag }), - onDone: { - actions: [ - assign(({ event }) => ({ - walletInstanceAttestation: event.output - })), - { type: "storeWalletInstanceAttestation" } - ], - target: "IpzsPrivacyAcceptance" - }, + onDone: [ + { + guard: "isReissuing", + actions: [ + "assignWalletInstanceAttestationToContext", + { type: "storeWalletInstanceAttestation" } + ], + target: "UserIdentification" + }, + { + actions: [ + "assignWalletInstanceAttestationToContext", + { type: "storeWalletInstanceAttestation" } + ], + target: "IpzsPrivacyAcceptance" + } + ], onError: [ + { + guard: "isReissuingAndSessionExpired", + actions: ["handleSessionExpired", "closeIssuance"], + target: "#itwEidIssuanceMachine.Idle" + }, { guard: "isSessionExpired", actions: "handleSessionExpired", From c5177525841fc0beae1192d2705fa88fedb1df73 Mon Sep 17 00:00:00 2001 From: RiccardoMolinari95 Date: Fri, 3 Jan 2025 16:31:43 +0100 Subject: [PATCH 09/17] refactor: deleted assignWalletInstanceAttestationToContext action --- ts/features/itwallet/machine/eid/actions.ts | 4 ---- ts/features/itwallet/machine/eid/machine.ts | 9 ++++++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/ts/features/itwallet/machine/eid/actions.ts b/ts/features/itwallet/machine/eid/actions.ts index 8d00851a7ea..2572a537d9f 100644 --- a/ts/features/itwallet/machine/eid/actions.ts +++ b/ts/features/itwallet/machine/eid/actions.ts @@ -220,10 +220,6 @@ export const createEidIssuanceActionsImplementation = ( trackItwDeactivated(store.getState()); }, - assignWalletInstanceAttestationToContext: assign(({ event }) => ({ - walletInstanceAttestation: event.output - })), - onInit: assign( () => { const state = store.getState(); diff --git a/ts/features/itwallet/machine/eid/machine.ts b/ts/features/itwallet/machine/eid/machine.ts index a9be52993f2..cd496a1a432 100644 --- a/ts/features/itwallet/machine/eid/machine.ts +++ b/ts/features/itwallet/machine/eid/machine.ts @@ -56,7 +56,6 @@ export const itwEidIssuanceMachine = setup({ trackWalletInstanceRevocation: notImplemented, setFailure: assign(({ event }) => ({ failure: mapEventToFailure(event) })), onInit: notImplemented, - assignWalletInstanceAttestationToContext: notImplemented, /** * Save the final redirect url in the machine context for later reuse. * This action is the same for the three identification methods. @@ -238,14 +237,18 @@ export const itwEidIssuanceMachine = setup({ { guard: "isReissuing", actions: [ - "assignWalletInstanceAttestationToContext", + assign(({ event }) => ({ + walletInstanceAttestation: event.output + })), { type: "storeWalletInstanceAttestation" } ], target: "UserIdentification" }, { actions: [ - "assignWalletInstanceAttestationToContext", + assign(({ event }) => ({ + walletInstanceAttestation: event.output + })), { type: "storeWalletInstanceAttestation" } ], target: "IpzsPrivacyAcceptance" From d12f2494cd97a1aceb3e62a7f39a165123848ad2 Mon Sep 17 00:00:00 2001 From: RiccardoMolinari95 Date: Fri, 3 Jan 2025 16:51:40 +0100 Subject: [PATCH 10/17] fix: lint --- ts/features/itwallet/machine/eid/guards.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/features/itwallet/machine/eid/guards.ts b/ts/features/itwallet/machine/eid/guards.ts index a05d799d853..586ecd73fbd 100644 --- a/ts/features/itwallet/machine/eid/guards.ts +++ b/ts/features/itwallet/machine/eid/guards.ts @@ -40,7 +40,7 @@ export const createEidIssuanceGuardsImplementation = ( isSessionExpired: ({ event }: { event: EidIssuanceEvents }) => checkSessionExpired({ event }), - isReissuingAndSessionExpired: ({ context, event }: { context: Context, event: EidIssuanceEvents }) => + isReissuingAndSessionExpired: ({ context, event }: { context: Context; event: EidIssuanceEvents }) => context.isReissuing === true && checkSessionExpired({ event }), hasValidWalletInstanceAttestation: ({ context }: { context: Context }) => From e8d82bea67d94d271aabc1377c316fcf9572ed4d Mon Sep 17 00:00:00 2001 From: RiccardoMolinari95 Date: Fri, 3 Jan 2025 16:59:56 +0100 Subject: [PATCH 11/17] chore:prettify --- ts/features/itwallet/machine/eid/guards.ts | 9 +++++++-- ts/features/itwallet/machine/eid/machine.ts | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ts/features/itwallet/machine/eid/guards.ts b/ts/features/itwallet/machine/eid/guards.ts index 586ecd73fbd..b07e8ce70e7 100644 --- a/ts/features/itwallet/machine/eid/guards.ts +++ b/ts/features/itwallet/machine/eid/guards.ts @@ -40,8 +40,13 @@ export const createEidIssuanceGuardsImplementation = ( isSessionExpired: ({ event }: { event: EidIssuanceEvents }) => checkSessionExpired({ event }), - isReissuingAndSessionExpired: ({ context, event }: { context: Context; event: EidIssuanceEvents }) => - context.isReissuing === true && checkSessionExpired({ event }), + isReissuingAndSessionExpired: ({ + context, + event + }: { + context: Context; + event: EidIssuanceEvents; + }) => context.isReissuing === true && checkSessionExpired({ event }), hasValidWalletInstanceAttestation: ({ context }: { context: Context }) => pipe( diff --git a/ts/features/itwallet/machine/eid/machine.ts b/ts/features/itwallet/machine/eid/machine.ts index cd496a1a432..63e2374745c 100644 --- a/ts/features/itwallet/machine/eid/machine.ts +++ b/ts/features/itwallet/machine/eid/machine.ts @@ -242,7 +242,7 @@ export const itwEidIssuanceMachine = setup({ })), { type: "storeWalletInstanceAttestation" } ], - target: "UserIdentification" + target: "UserIdentification" }, { actions: [ @@ -251,7 +251,7 @@ export const itwEidIssuanceMachine = setup({ })), { type: "storeWalletInstanceAttestation" } ], - target: "IpzsPrivacyAcceptance" + target: "IpzsPrivacyAcceptance" } ], onError: [ From 7f44f959a7c5c07ba6366ced6518572da75f3e2b Mon Sep 17 00:00:00 2001 From: RiccardoMolinari95 Date: Fri, 3 Jan 2025 18:08:48 +0100 Subject: [PATCH 12/17] test: fix --- ts/features/itwallet/machine/eid/__tests__/machine.test.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ts/features/itwallet/machine/eid/__tests__/machine.test.ts b/ts/features/itwallet/machine/eid/__tests__/machine.test.ts index bf790811943..1cc35aa836d 100644 --- a/ts/features/itwallet/machine/eid/__tests__/machine.test.ts +++ b/ts/features/itwallet/machine/eid/__tests__/machine.test.ts @@ -64,6 +64,7 @@ describe("itwEidIssuanceMachine", () => { const trackWalletInstanceCreation = jest.fn(); const trackWalletInstanceRevocation = jest.fn(); const revokeWalletInstance = jest.fn(); + const isReissuingAndSessionExpired = jest.fn(); const mockedMachine = itwEidIssuanceMachine.provide({ actions: { @@ -119,7 +120,8 @@ describe("itwEidIssuanceMachine", () => { issuedEidMatchesAuthenticatedUser, isSessionExpired, isOperationAborted, - hasValidWalletInstanceAttestation + hasValidWalletInstanceAttestation, + isReissuingAndSessionExpired } }); @@ -1002,6 +1004,8 @@ describe("itwEidIssuanceMachine", () => { // eslint-disable-next-line functional/immutable-data actor.getSnapshot().context = initialContext; + hasValidWalletInstanceAttestation.mockImplementation(() => true); + await waitFor(() => expect(onInit).toHaveBeenCalledTimes(1)); expect(actor.getSnapshot().value).toStrictEqual("Idle"); From 2ca518f4bc988398916844ffb98a03c95fb143cf Mon Sep 17 00:00:00 2001 From: RiccardoMolinari95 Date: Wed, 8 Jan 2025 09:31:45 +0100 Subject: [PATCH 13/17] refactor: screen props in ItwIdentificationModeSelectionScreen --- .../ItwIdentificationModeSelectionScreen.tsx | 30 +++++++++---------- ts/features/itwallet/machine/eid/actions.ts | 3 +- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx b/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx index 22dfd7b9e3f..10fe59600b0 100644 --- a/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx +++ b/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx @@ -5,7 +5,7 @@ import { VStack } from "@pagopa/io-app-design-system"; import React, { useCallback, useMemo } from "react"; -import { Route, useFocusEffect, useRoute } from "@react-navigation/native"; +import { useFocusEffect } from "@react-navigation/native"; import I18n from "../../../../i18n"; import { useIOSelector } from "../../../../store/hooks"; import { cieFlowForDevServerEnabled } from "../../../cieLogin/utils"; @@ -17,15 +17,19 @@ import { import { itwDisabledIdentificationMethodsSelector } from "../../../../store/reducers/backendStatus/remoteConfig"; import { IOScrollViewWithLargeHeader } from "../../../../components/ui/IOScrollViewWithLargeHeader"; import { isCIEAuthenticationSupportedSelector } from "../../machine/eid/selectors"; -import { ITW_ROUTES } from "../../navigation/routes"; +import { IOStackNavigationRouteProps } from "../../../../navigation/params/AppParamsList"; +import { ItwParamsList } from "../../navigation/ItwParamsList"; -export type ItwIdentificationModeSelectionScreenNavigationParams = - | { - eidReissuing?: boolean; - } - | undefined; +export type ItwIdentificationModeSelectionScreenNavigationParams = { + eidReissuing?: boolean; +}; + +type ScreenProps = IOStackNavigationRouteProps< + ItwParamsList, + "ITW_IDENTIFICATION_MODE_SELECTION" +> -export const ItwIdentificationModeSelectionScreen = () => { +export const ItwIdentificationModeSelectionScreen = (params: ScreenProps) => { const machineRef = ItwEidIssuanceMachineContext.useActorRef(); const isCieAuthenticationSupported = ItwEidIssuanceMachineContext.useSelector( isCIEAuthenticationSupportedSelector @@ -52,15 +56,9 @@ export const ItwIdentificationModeSelectionScreen = () => { [isCieAuthenticationSupported] ); - const route = - useRoute< - Route< - typeof ITW_ROUTES.IDENTIFICATION.MODE_SELECTION, - ItwIdentificationModeSelectionScreenNavigationParams - > - >(); + const { eidReissuing } = params.route.params; - const { eidReissuing } = route.params || {}; + console.log("eidReissuing", eidReissuing); useFocusEffect( useCallback(() => { diff --git a/ts/features/itwallet/machine/eid/actions.ts b/ts/features/itwallet/machine/eid/actions.ts index 2572a537d9f..f25376362a7 100644 --- a/ts/features/itwallet/machine/eid/actions.ts +++ b/ts/features/itwallet/machine/eid/actions.ts @@ -49,7 +49,8 @@ export const createEidIssuanceActionsImplementation = ( navigateToIdentificationModeScreen: () => { navigation.navigate(ITW_ROUTES.MAIN, { - screen: ITW_ROUTES.IDENTIFICATION.MODE_SELECTION + screen: ITW_ROUTES.IDENTIFICATION.MODE_SELECTION, + params: { eidReissuing: false } }); }, From decb8aba7af5bda97bd24dcb0798f6b3c817fc85 Mon Sep 17 00:00:00 2001 From: RiccardoMolinari95 Date: Wed, 8 Jan 2025 09:32:38 +0100 Subject: [PATCH 14/17] chore: prettify --- .../screens/ItwIdentificationModeSelectionScreen.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx b/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx index 10fe59600b0..3dd3f0f5e65 100644 --- a/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx +++ b/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx @@ -27,7 +27,7 @@ export type ItwIdentificationModeSelectionScreenNavigationParams = { type ScreenProps = IOStackNavigationRouteProps< ItwParamsList, "ITW_IDENTIFICATION_MODE_SELECTION" -> +>; export const ItwIdentificationModeSelectionScreen = (params: ScreenProps) => { const machineRef = ItwEidIssuanceMachineContext.useActorRef(); @@ -56,7 +56,7 @@ export const ItwIdentificationModeSelectionScreen = (params: ScreenProps) => { [isCieAuthenticationSupported] ); - const { eidReissuing } = params.route.params; + const { eidReissuing } = params.route.params; console.log("eidReissuing", eidReissuing); From b72bffd9e31c9bdfe8474870a14ce648a7cf2595 Mon Sep 17 00:00:00 2001 From: RiccardoMolinari95 Date: Wed, 8 Jan 2025 09:35:05 +0100 Subject: [PATCH 15/17] chore: deleted console log --- .../screens/ItwIdentificationModeSelectionScreen.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx b/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx index 3dd3f0f5e65..b3d9f365225 100644 --- a/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx +++ b/ts/features/itwallet/identification/screens/ItwIdentificationModeSelectionScreen.tsx @@ -58,8 +58,6 @@ export const ItwIdentificationModeSelectionScreen = (params: ScreenProps) => { const { eidReissuing } = params.route.params; - console.log("eidReissuing", eidReissuing); - useFocusEffect( useCallback(() => { if (eidReissuing) { From 95f5372d597fefa512adb09505e65e50edd924dc Mon Sep 17 00:00:00 2001 From: RiccardoMolinari95 Date: Wed, 8 Jan 2025 10:22:06 +0100 Subject: [PATCH 16/17] test: fix ItwIdentificationModeSelectionScreen test --- ...IdentificationModeSelectionScreen.test.tsx | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/ts/features/itwallet/identification/screens/__tests__/ItwIdentificationModeSelectionScreen.test.tsx b/ts/features/itwallet/identification/screens/__tests__/ItwIdentificationModeSelectionScreen.test.tsx index 6ed8b90582c..034f14af4e2 100644 --- a/ts/features/itwallet/identification/screens/__tests__/ItwIdentificationModeSelectionScreen.test.tsx +++ b/ts/features/itwallet/identification/screens/__tests__/ItwIdentificationModeSelectionScreen.test.tsx @@ -15,6 +15,8 @@ import { ItwEidIssuanceMachineContext } from "../../../machine/provider"; import { itwEidIssuanceMachine } from "../../../machine/eid/machine"; import { ItwLifecycleState } from "../../../lifecycle/store/reducers"; import { ToolEnum } from "../../../../../../definitions/content/AssistanceToolConfig"; +import { IOStackNavigationProp } from "../../../../../navigation/params/AppParamsList"; +import { ItwParamsList } from "../../../navigation/ItwParamsList"; jest.mock("../../../../../config", () => ({ itwEnabled: true @@ -128,10 +130,29 @@ describe("ItwIdentificationModeSelectionScreen", () => { } }); + const mockNavigation = new Proxy( + {}, + { + get: (_, prop) => jest.fn() + } + ) as unknown as IOStackNavigationProp< + ItwParamsList, + "ITW_IDENTIFICATION_MODE_SELECTION" + >; + + const route = { + key: "ITW_IDENTIFICATION_MODE_SELECTION", + name: ITW_ROUTES.IDENTIFICATION.MODE_SELECTION, + params: {} + }; + return renderScreenWithNavigationStoreContext( () => ( - + ), ITW_ROUTES.IDENTIFICATION.MODE_SELECTION, From d19bcf823d40b1f910eab7ddeabeac308c8bc203 Mon Sep 17 00:00:00 2001 From: RiccardoMolinari95 Date: Wed, 8 Jan 2025 10:28:02 +0100 Subject: [PATCH 17/17] test: removed unused prop --- .../__tests__/ItwIdentificationModeSelectionScreen.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/features/itwallet/identification/screens/__tests__/ItwIdentificationModeSelectionScreen.test.tsx b/ts/features/itwallet/identification/screens/__tests__/ItwIdentificationModeSelectionScreen.test.tsx index 034f14af4e2..83d026db21d 100644 --- a/ts/features/itwallet/identification/screens/__tests__/ItwIdentificationModeSelectionScreen.test.tsx +++ b/ts/features/itwallet/identification/screens/__tests__/ItwIdentificationModeSelectionScreen.test.tsx @@ -133,7 +133,7 @@ describe("ItwIdentificationModeSelectionScreen", () => { const mockNavigation = new Proxy( {}, { - get: (_, prop) => jest.fn() + get: _ => jest.fn() } ) as unknown as IOStackNavigationProp< ItwParamsList,