Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(IT Wallet): [SIW-1824] Show alert if wallet instance is revoked #6547

Open
wants to merge 38 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
f1fc15b
chore: add to wallet instance state also revocation props, initialize…
RiccardoMolinari95 Dec 10, 2024
50ec519
chore: add hook to display alert when wi is revoked, add test
RiccardoMolinari95 Dec 12, 2024
4e3857f
refactor: moved update wi status after reset
RiccardoMolinari95 Dec 13, 2024
c7694d0
refactor: deleted env ITW_MINIMUM_INTEGRITY_REQUIREMENTS and instead …
RiccardoMolinari95 Dec 13, 2024
19d9176
refactor: create type WalletInstanceStatus and WalletInstanceRevocati…
RiccardoMolinari95 Dec 13, 2024
7071c48
chore: fix test
RiccardoMolinari95 Dec 13, 2024
8582fb7
Merge commit 'a6a71349f95d7b8cb01262d578ae83f9c25b74d1' into SIW-1824…
RiccardoMolinari95 Dec 13, 2024
40bb43c
refactor: create selector folder for wallet instance, add test Wallet…
RiccardoMolinari95 Dec 13, 2024
efee04b
Merge branch 'master' into SIW-1824-alert-after-wi-revocation
RiccardoMolinari95 Dec 13, 2024
cdb4447
Merge branch 'master' into SIW-1824-alert-after-wi-revocation
RiccardoMolinari95 Dec 16, 2024
dd2346a
Merge branch 'master' into SIW-1824-alert-after-wi-revocation
RiccardoMolinari95 Dec 16, 2024
e20bee2
refactor: removed unused env
RiccardoMolinari95 Dec 16, 2024
0d1a844
Merge branch 'master' into SIW-1824-alert-after-wi-revocation
RiccardoMolinari95 Dec 16, 2024
06939b7
chore: typo
RiccardoMolinari95 Dec 17, 2024
260a57a
chore: typo
RiccardoMolinari95 Dec 17, 2024
e37c2fc
Merge branch 'master' into SIW-1824-alert-after-wi-revocation
RiccardoMolinari95 Dec 17, 2024
1728866
chore: add revocation object in wallet instance global state, includi…
RiccardoMolinari95 Dec 17, 2024
54168ff
test: update snapshot
RiccardoMolinari95 Dec 17, 2024
9a2fefc
refactor: revocation state moved alert shown
RiccardoMolinari95 Dec 17, 2024
2c2b0c3
test: update snapshot
RiccardoMolinari95 Dec 17, 2024
72bf28c
Merge branch 'master' into SIW-1824-alert-after-wi-revocation
RiccardoMolinari95 Dec 17, 2024
c788250
chore: add FAQ link url for NEW_WALLET_INSTANCE_CREATED alert
RiccardoMolinari95 Dec 17, 2024
e03ed75
Merge branch 'master' into SIW-1824-alert-after-wi-revocation
RiccardoMolinari95 Dec 17, 2024
0c6fc9b
Merge branch 'master' into SIW-1824-alert-after-wi-revocation
RiccardoMolinari95 Dec 18, 2024
bfb16f4
Merge branch 'master' into SIW-1824-alert-after-wi-revocation
RiccardoMolinari95 Dec 18, 2024
24e0e5f
Merge branch 'master' into SIW-1824-alert-after-wi-revocation
RiccardoMolinari95 Dec 18, 2024
b6fa8d4
refactor: refactor wi revocation alert
RiccardoMolinari95 Dec 18, 2024
8ddd9ed
chore: not persist wallet instance status
RiccardoMolinari95 Dec 18, 2024
70ec8cb
chore: persist wallet instance status, deleted itwWalletInstanceSetAl…
RiccardoMolinari95 Dec 18, 2024
545a54f
Merge branch 'master' into SIW-1824-alert-after-wi-revocation
RiccardoMolinari95 Dec 18, 2024
fe44716
fix: lint
RiccardoMolinari95 Dec 18, 2024
2ee86b0
refactor: prettify
RiccardoMolinari95 Dec 18, 2024
dfa16d8
refactor: openWebUrl instead linking
RiccardoMolinari95 Dec 18, 2024
bb5fcfa
Merge branch 'master' into SIW-1824-alert-after-wi-revocation
RiccardoMolinari95 Dec 18, 2024
d92a539
Merge branch 'master' into SIW-1824-alert-after-wi-revocation
RiccardoMolinari95 Dec 19, 2024
1261408
refactor
RiccardoMolinari95 Dec 19, 2024
84ce577
Merge branch 'master' into SIW-1824-alert-after-wi-revocation
RiccardoMolinari95 Dec 19, 2024
fe8f6bc
Merge branch 'master' into SIW-1824-alert-after-wi-revocation
RiccardoMolinari95 Dec 19, 2024
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
4 changes: 1 addition & 3 deletions .env.local
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,4 @@ ITW_BYPASS_IDENTITY_MATCH=YES
# Use the test environment for the IDP hint for both CIE and SPID
ITW_IDP_HINT_TEST=YES
# IPZS Privacy Policy URL
ITW_IPZS_PRIVACY_URL='https://io.italia.it/informativa-ipzs'
# ITW Documents on IO URL
ITW_DOCUMENTS_ON_IO_URL='https://io.italia.it/documenti-su-io'
ITW_IPZS_PRIVACY_URL='https://io.italia.it/informativa-ipzs'
4 changes: 1 addition & 3 deletions .env.production
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,4 @@ ITW_BYPASS_IDENTITY_MATCH=NO
# Use the test environment for the IDP hint for both CIE and SPID
ITW_IDP_HINT_TEST=NO
# IPZS Privacy Policy URL
ITW_IPZS_PRIVACY_URL='https://io.italia.it/informativa-ipzs'
# ITW Documents on IO URL
ITW_DOCUMENTS_ON_IO_URL='https://io.italia.it/documenti-su-io'
ITW_IPZS_PRIVACY_URL='https://io.italia.it/informativa-ipzs'
14 changes: 14 additions & 0 deletions locales/en/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3550,6 +3550,20 @@ features:
title: Dicci cosa ne pensi
content: Raccontaci la tua esperienza con la funzionalità Documenti su IO.
action: Inizia
walletInstanceRevoked:
alert:
cta: Scopri di più
closeButton: Chiudi
closeButtonAlt: Ho capito
revokedByWalletProvider:
title: Documenti su IO è stata disattivata
content: Per verificare i requisiti richiesti per continuare a usare la funzionalità sul tuo dispositivo, premi "Scopri di più".
newWalletInstanceCreated:
title: Documenti su IO è stata disattivata su questo dispositivo
content: Puoi usare i tuoi documenti su IO su un solo dispositivo alla volta per ragioni di sicurezza.
revokedByUser:
title: Hai disattivato Documenti su IO
content: Se cambi idea, potrai riattivare Documenti su IO in futuro.
support:
ticketList:
noTicket:
Expand Down
14 changes: 14 additions & 0 deletions locales/it/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3550,6 +3550,20 @@ features:
title: Dicci cosa ne pensi
content: Raccontaci la tua esperienza con la funzionalità Documenti su IO.
action: Inizia
walletInstanceRevoked:
alert:
cta: Scopri di più
closeButton: Chiudi
closeButtonAlt: Ho capito
revokedByWalletProvider:
title: Documenti su IO è stata disattivata
content: Per verificare i requisiti richiesti per continuare a usare la funzionalità sul tuo dispositivo, premi "Scopri di più".
newWalletInstanceCreated:
title: Documenti su IO è stata disattivata su questo dispositivo
content: Puoi usare i tuoi documenti su IO su un solo dispositivo alla volta per ragioni di sicurezza.
revokedByUser:
title: Hai disattivato Documenti su IO
content: Se cambi idea, potrai riattivare Documenti su IO in futuro.
support:
ticketList:
noTicket:
Expand Down
5 changes: 0 additions & 5 deletions ts/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,3 @@ export const itwIpzsPrivacyUrl: string = pipe(
t.string.decode,
E.getOrElse(() => "https://io.italia.it/informativa-ipzs")
);
export const itwDocumentsOnIOUrl: string = pipe(
Config.ITW_DOCUMENTS_ON_IO_URL,
t.string.decode,
E.getOrElse(() => "https://io.italia.it/documenti-su-io")
);
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ exports[`featuresPersistor should match snapshot 1`] = `
},
"walletInstance": {
"attestation": undefined,
"isRevoked": false,
"revocationReason": undefined,
},
},
"landingBanners": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ exports[`itWalletReducer should match snapshot [if this test fails, remember to
},
"walletInstance": {
"attestation": undefined,
"isRevoked": false,
"revocationReason": undefined,
},
}
`;
19 changes: 18 additions & 1 deletion ts/features/itwallet/common/utils/itwTypesUtils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { Credential, Trust } from "@pagopa/io-react-native-wallet";
import {
Credential,
Trust,
WalletInstance
} from "@pagopa/io-react-native-wallet";

/**
* Alias type for the return type of the start issuance flow operation.
Expand Down Expand Up @@ -43,6 +47,19 @@ export type ParsedStatusAttestation = Awaited<
ReturnType<typeof Credential.Status.verifyAndParseStatusAttestation>
>["parsedStatusAttestation"]["payload"];

/**
* Alias for the WalletInstanceStatus type
*/
export type WalletInstanceStatus = Awaited<
ReturnType<typeof WalletInstance.getWalletInstanceStatus>
>;

/**
* Alias for the WalletInstanceRevocationReason type
*/
export type WalletInstanceRevocationReason =
WalletInstanceStatus["revocation_reason"];

export type StoredStatusAttestation =
| {
credentialStatus: "valid";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import { getWalletInstanceStatus } from "../../../common/utils/itwAttestationUti
import { StoredCredential } from "../../../common/utils/itwTypesUtils";
import { sessionTokenSelector } from "../../../../../store/reducers/authentication";
import { handleWalletInstanceResetSaga } from "../handleWalletInstanceResetSaga";
import { itwIsWalletInstanceAttestationValidSelector } from "../../../walletInstance/store/reducers";
import { ensureIntegrityServiceIsReady } from "../../../common/utils/itwIntegrityUtils";
import { itwIntegrityServiceReadySelector } from "../../../issuance/store/selectors";
import { itwIsWalletInstanceAttestationValidSelector } from "../../../walletInstance/store/selectors";

jest.mock("@pagopa/io-react-native-crypto", () => ({
deleteKey: jest.fn
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ensureIntegrityServiceIsReady } from "../../common/utils/itwIntegrityUt
import { itwIntegrityKeyTagSelector } from "../../issuance/store/selectors";
import { itwLifecycleIsOperationalOrValid } from "../store/selectors";
import { itwIntegritySetServiceIsReady } from "../../issuance/store/actions";
import { itwUpdateWalletInstanceStatus } from "../../walletInstance/store/actions";
import { handleWalletInstanceResetSaga } from "./handleWalletInstanceResetSaga";

export function* getStatusOrResetWalletInstance(integrityKeyTag: string) {
Expand All @@ -23,6 +24,9 @@ export function* getStatusOrResetWalletInstance(integrityKeyTag: string) {
if (walletInstanceStatus.is_revoked) {
yield* call(handleWalletInstanceResetSaga);
}

// Update wallet instance status
yield* put(itwUpdateWalletInstanceStatus(walletInstanceStatus));
}

/**
Expand Down
2 changes: 1 addition & 1 deletion ts/features/itwallet/machine/credential/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
import { itwCredentialsStore } from "../../credentials/store/actions";
import { ITW_ROUTES } from "../../navigation/routes";
import { itwWalletInstanceAttestationStore } from "../../walletInstance/store/actions";
import { itwWalletInstanceAttestationSelector } from "../../walletInstance/store/reducers";
import { itwWalletInstanceAttestationSelector } from "../../walletInstance/store/selectors";
import { Context } from "./context";
import { CredentialIssuanceEvents } from "./events";

Expand Down
2 changes: 1 addition & 1 deletion ts/features/itwallet/machine/eid/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import {
trackSaveCredentialSuccess,
updateITWStatusAndIDProperties
} from "../../analytics";
import { itwWalletInstanceAttestationSelector } from "../../walletInstance/store/reducers";
import { itwIntegrityKeyTagSelector } from "../../issuance/store/selectors";
import { itwWalletInstanceAttestationSelector } from "../../walletInstance/store/selectors";
import { Context } from "./context";
import { EidIssuanceEvents } from "./events";

Expand Down
2 changes: 1 addition & 1 deletion ts/features/itwallet/trustmark/machine/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useIONavigation } from "../../../../navigation/params/AppParamsList";
import { checkCurrentSession } from "../../../../store/actions/authentication";
import { useIOStore } from "../../../../store/hooks";
import { itwCredentialByTypeSelector } from "../../credentials/store/selectors";
import { itwWalletInstanceAttestationSelector } from "../../walletInstance/store/reducers";
import { itwWalletInstanceAttestationSelector } from "../../walletInstance/store/selectors";
import { Context } from "./context";

export const createItwTrustmarkActionsImplementation = (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { Alert, AlertButton, Linking } from "react-native";
import React from "react";
import { IOToast } from "@pagopa/io-app-design-system";
import I18n from "../../../../i18n";
import { WalletInstanceRevocationReason } from "../../common/utils/itwTypesUtils";

const closeButtonText = I18n.t(
"features.itWallet.walletInstanceRevoked.alert.closeButton"
);
const alertCtaText = I18n.t(
"features.itWallet.walletInstanceRevoked.alert.cta"
);

const itwMinIntergityReqUrl = "https://io.italia.it/documenti-su-io/faq/#n1_12";
Copy link
Collaborator

Choose a reason for hiding this comment

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

Typo: Intergity.


/**
* Hook to monitor wallet instance status and display alerts if revoked.
* @param walletInstanceStatus - The status of the wallet instance, including whether it is revoked and the reason for revocation.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* @param walletInstanceStatus - The status of the wallet instance, including whether it is revoked and the reason for revocation.

*/
export const useItwWalletInstanceRevocationAlert = (walletInstanceStatus: {
isRevoked: boolean;
revocationReason?: WalletInstanceRevocationReason;
}) => {
React.useEffect(() => {
if (walletInstanceStatus.isRevoked) {
showWalletRevocationAlert(walletInstanceStatus.revocationReason);
}
}, [walletInstanceStatus]);
};

/**
* Displays an alert based on the revocation reason.
*/
const showWalletRevocationAlert = (
revocationReason?: WalletInstanceRevocationReason
) => {
switch (revocationReason) {
case "CERTIFICATE_REVOKED_BY_ISSUER":
showAlert(
I18n.t(
"features.itWallet.walletInstanceRevoked.alert.revokedByWalletProvider.title"
),
I18n.t(
"features.itWallet.walletInstanceRevoked.alert.revokedByWalletProvider.content"
),
[
{ text: closeButtonText },
{
text: alertCtaText,
onPress: () => {
Linking.openURL(itwMinIntergityReqUrl).catch(() => {
IOToast.error(I18n.t("global.genericError"));
});
}
}
]
);
break;

case "NEW_WALLET_INSTANCE_CREATED":
showAlert(
I18n.t(
"features.itWallet.walletInstanceRevoked.alert.newWalletInstanceCreated.title"
),
I18n.t(
"features.itWallet.walletInstanceRevoked.alert.newWalletInstanceCreated.content"
),
[
{ text: closeButtonText },
{
text: alertCtaText,
onPress: () => {
// TODO: Add the correct URL
Linking.openURL("").catch(() => {
IOToast.error(I18n.t("global.genericError"));
});
}
}
]
);
break;
case "REVOKED_BY_USER":
showAlert(
I18n.t(
"features.itWallet.walletInstanceRevoked.alert.revokedByUser.title"
),
I18n.t(
"features.itWallet.walletInstanceRevoked.alert.revokedByUser.content"
),
[
{
text: I18n.t(
"features.itWallet.walletInstanceRevoked.alert.closeButtonAlt"
)
}
]
);
break;
default:
break;
}
};

const showAlert = (
title: string,
message: string,
buttons: Array<AlertButton> = [{ text: closeButtonText }]
) => {
Alert.alert(title, message, buttons);
};
Comment on lines +103 to +109
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we really need this? Why not using directly Alert.alert?

14 changes: 11 additions & 3 deletions ts/features/itwallet/walletInstance/store/actions/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ActionType, createStandardAction } from "typesafe-actions";
import { WalletInstanceStatus } from "../../../common/utils/itwTypesUtils";

/**
* This action stores the Wallet Instance Attestation
Expand All @@ -7,6 +8,13 @@ export const itwWalletInstanceAttestationStore = createStandardAction(
"ITW_WALLET_INSTANCE_ATTESTATION_STORE"
)<string>();

export type ItwWalletInstanceActions = ActionType<
typeof itwWalletInstanceAttestationStore
>;
/**
* This action update the Wallet Instance Status
*/
export const itwUpdateWalletInstanceStatus = createStandardAction(
"ITW_WALLET_INSTANCE_STATUS_UPDATE"
)<WalletInstanceStatus>();

export type ItwWalletInstanceActions =
| ActionType<typeof itwWalletInstanceAttestationStore>
| ActionType<typeof itwUpdateWalletInstanceStatus>;
38 changes: 19 additions & 19 deletions ts/features/itwallet/walletInstance/store/reducers/index.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import * as O from "fp-ts/lib/Option";
import { flow } from "fp-ts/lib/function";
import { PersistConfig, persistReducer } from "redux-persist";
import { createSelector } from "reselect";
import { getType } from "typesafe-actions";
import { Action } from "../../../../../store/actions/types";
import { GlobalState } from "../../../../../store/reducers/types";
import itwCreateSecureStorage from "../../../common/store/storages/itwSecureStorage";
import { isWalletInstanceAttestationValid } from "../../../common/utils/itwAttestationUtils";
import { itwLifecycleStoresReset } from "../../../lifecycle/store/actions";
import { itwWalletInstanceAttestationStore } from "../actions";
import {
itwWalletInstanceAttestationStore,
itwUpdateWalletInstanceStatus
} from "../actions";
import { WalletInstanceRevocationReason } from "../../../common/utils/itwTypesUtils";

export type ItwWalletInstanceState = {
attestation: string | undefined;
isRevoked: boolean;
revocationReason?: WalletInstanceRevocationReason;
};

export const itwWalletInstanceInitialState: ItwWalletInstanceState = {
attestation: undefined
attestation: undefined,
isRevoked: false,
revocationReason: undefined
};

const CURRENT_REDUX_ITW_WALLET_INSTANCE_STORE_VERSION = -1;
Expand All @@ -27,10 +30,19 @@ const reducer = (
switch (action.type) {
case getType(itwWalletInstanceAttestationStore): {
return {
...state,
attestation: action.payload
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
...state,

I think it's correct to reset the state when we save a new WI: if there is already a status stored, it is for sure referred to a past WI.
What do you think?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Absolutely! Thanks for the suggestion

};
}

case getType(itwUpdateWalletInstanceStatus): {
return {
...state,
isRevoked: action.payload.is_revoked,
revocationReason: action.payload.revocation_reason
};
}

case getType(itwLifecycleStoresReset):
return { ...itwWalletInstanceInitialState };

Expand All @@ -50,16 +62,4 @@ const persistedReducer = persistReducer(
reducer
);

export const itwWalletInstanceAttestationSelector = (state: GlobalState) =>
state.features.itWallet.walletInstance.attestation;

export const itwIsWalletInstanceAttestationValidSelector = createSelector(
itwWalletInstanceAttestationSelector,
flow(
O.fromNullable,
O.map(isWalletInstanceAttestationValid),
O.getOrElse(() => false)
)
);

export default persistedReducer;
Loading
Loading