Files
inji-wallet/machines/VerifiableCredential/VCItemMachine/VCItemMachine.ts
KiruthikaJeyashankar 003cc156c2 [INJIMOB-1192] onboarding of new issuer is affecting the existing issuers (#1476)
* [INJIMOB-1192] : use wellknown response instead of mimoto issuer config.
-- Remove hardcoding for sunbird issuer in vc activation and verification flow.
-- Render idType from wellknown response
-- Remove UIN/VID from default add-on fields

Signed-off-by: Swati Goel <meet2swati@gmail.com>

* [INJIMOB-1192] : fix propType and some refactoring

Signed-off-by: Swati Goel <meet2swati@gmail.com>

* [INJIMOB-1192] : add credentialType in VcMetadata

Signed-off-by: Swati Goel <meet2swati@gmail.com>

* [INJIMOB-1192] fix vc download via issuer flow due to credentialType mismatch

Co-authored-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>
Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com>

* [INJIMOB-1192] rename supported list of credential type in issuers model

Co-authored-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>
Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com>

* [INJIMOB-1192] display id type in history based on wellknown for issuers VC

Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com>

* [INJIMOB-1192] fix id type not shown for VC activation

Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com>

* [INJIMOB-1192] remove unused credentialType field from VCMetaData

Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com>

* [INJIMOB-1192] set default idType for logging activity

Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com>

* [INJIMOB-1192] move vc item machine events into model

Events should not be exported to other packages for direct use so that Xstate's createModel() can decorate the function appropriately

Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com>

* [INJIMOB-1192] show verify banner id type from wellknown

Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com>

* [INJIMOB-1192] refactor duplication and unused code

Co-authored-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>
Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com>

* [INJIMOB-1192] remove unused displayId in metadata

Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com>

* [INJIMOB-1192] revert the dimensions of camera scanner to old values to support face liveness verification

Co-authored-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com>
Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-1192] remove unused code & debug logs

Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com>

* [INJIMOB-1192] fix failing test cases

Co-authored-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com>
Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-1192] remove unused translations

Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com>

---------

Signed-off-by: Swati Goel <meet2swati@gmail.com>
Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com>
Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>
Co-authored-by: Swati Goel <meet2swati@gmail.com>
Co-authored-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>
2024-06-04 16:37:54 +05:30

646 lines
22 KiB
TypeScript

import {AppServices} from '../../../shared/GlobalContext';
import {VCMetadata} from '../../../shared/VCMetadata';
import {assign, EventFrom, send} from 'xstate';
import {log} from 'xstate/lib/actions';
import {VCItemActions} from './VCItemActions';
import {VCItemGaurds} from './VCItemGaurds';
import {VCItemServices} from './VCItemServices';
import {VCItemModel} from './VCItemModel';
import {BannerStatusType} from '../../../components/BannerNotification';
const machineName = 'vc-item-machine';
const model = VCItemModel;
export const VCItemEvents = model.events;
export const VCItemMachine = model.createMachine(
{
predictableActionArguments: true,
preserveActionOrder: true,
tsTypes: {} as import('./VCItemMachine.typegen').Typegen0,
schema: {
context: model.initialContext,
events: {} as EventFrom<typeof model>,
},
description:
'This machine is spawned for every VC downloaded, and tracks its lifecycle.',
id: machineName,
type: 'parallel',
states: {
vcUtilitiesState: {
on: {
REFRESH: {
target: '.loadVc',
},
UPDATE_VC_METADATA: {
actions: 'setVcMetadata',
},
},
initial: 'loadVc',
states: {
loadVc: {
initial: 'loadVcFromContext',
states: {
loadVcFromContext: {
entry: ['requestVcContext'],
description: 'Fetch the VC data from the Memory.',
on: {
GET_VC_RESPONSE: [
{
actions: ['setContext'],
cond: 'hasCredentialAndWellknown',
target: '.fetchWellknown',
},
{
actions: ['setContext'],
cond: 'hasCredential',
target: `#vc-item-machine.vcUtilitiesState.idle`,
},
{
actions: 'addVcToInProgressDownloads',
target: 'loadVcFromServer',
},
],
TAMPERED_VC: {
target: '#vc-item-machine.vcUtilitiesState.idle',
},
},
initial: 'idle',
states: {
idle: {},
fetchWellknown: {
invoke: {
src: 'fetchIssuerWellknown',
onDone: {
actions: 'updateWellknownResponse',
target: `#vc-item-machine.vcUtilitiesState.idle`,
},
},
},
},
},
loadVcFromServer: {
description:
"Download VC data from the server. Uses polling method to check when it's available.",
initial: 'loadDownloadLimitConfig',
states: {
loadDownloadLimitConfig: {
invoke: {
src: 'loadDownloadLimitConfig',
onDone: {
actions: ['setMaxDownloadCount', 'setDownloadInterval'],
target: 'verifyingDownloadLimitExpiry',
},
},
},
verifyingDownloadLimitExpiry: {
entry: ['incrementDownloadCounter'],
invoke: {
src: 'checkDownloadExpiryLimit',
onDone: {
target: 'checkingStatus',
},
onError: {
actions: [
log((_, event) => (event.data as Error).message),
'sendDownloadLimitExpire',
],
},
},
},
checkingStatus: {
invoke: {
src: 'checkStatus',
id: 'checkStatus',
},
on: {
POLL: {
actions: send('POLL_STATUS', {to: 'checkStatus'}),
},
DOWNLOAD_READY: {
target: 'downloadingCredential',
},
FAILED: {
actions: 'sendDownloadLimitExpire',
},
},
},
downloadingCredential: {
invoke: {
src: 'downloadCredential',
id: 'downloadCredential',
onError: {
actions: [
'sendDownloadingFailedToVcMeta',
'removeVcFromInProgressDownloads',
],
},
},
on: {
POLL: [
{
cond: 'isDownloadAllowed',
actions: [
send('POLL_DOWNLOAD', {to: 'downloadCredential'}),
'incrementDownloadCounter',
],
},
{
target: 'verifyingDownloadLimitExpiry',
},
],
CREDENTIAL_DOWNLOADED: {
actions: 'setContext',
target:
'#vc-item-machine.vcUtilitiesState.verifyingCredential',
},
},
},
savingFailed: {
entry: ['removeVcMetaDataFromStorage'],
initial: 'idle',
states: {
idle: {},
viewingVc: {},
},
on: {
DISMISS: {
actions: ['removeVcMetaDataFromVcMachineContext'],
target: '.viewingVc',
},
},
},
},
},
},
},
walletBinding: {
initial: 'showBindingWarning',
states: {
showBindingWarning: {
on: {
CONFIRM: {
actions: 'sendActivationStartEvent',
target: 'requestingBindingOTP',
},
CANCEL: [
{
cond: context => context.isMachineInKebabPopupState,
target: '#vc-item-machine.vcUtilitiesState.kebabPopUp',
},
{
target: '#vc-item-machine.vcUtilitiesState.idle',
},
],
},
},
requestingBindingOTP: {
invoke: {
src: 'requestBindingOTP',
onDone: [
{
target: 'acceptingBindingOTP',
actions: ['setCommunicationDetails'],
},
],
onError: [
{
actions: [
'setErrorAsWalletBindingError',
'sendWalletBindingErrorEvent',
'logWalletBindingFailure',
],
target: 'showingWalletBindingError',
},
],
},
},
showingWalletBindingError: {
on: {
CANCEL: [
{
cond: context => context.isMachineInKebabPopupState,
actions: ['unSetError'],
target: '#vc-item-machine.vcUtilitiesState.kebabPopUp',
},
{
actions: ['unSetError'],
target: '#vc-item-machine.vcUtilitiesState.idle',
},
],
},
},
acceptingBindingOTP: {
entry: ['unSetOTP'],
on: {
INPUT_OTP: {
target: 'addKeyPair',
actions: ['setOTP'],
},
DISMISS: [
{
cond: context => context.isMachineInKebabPopupState,
target: '#vc-item-machine.vcUtilitiesState.kebabPopUp',
actions: [
'sendUserCancelledActivationFailedEndEvent',
'unSetOTP',
'unSetBindingTransactionId',
],
},
{
target: '#vc-item-machine.vcUtilitiesState.idle',
actions: [
'sendUserCancelledActivationFailedEndEvent',
'unSetOTP',
'unSetBindingTransactionId',
],
},
],
RESEND_OTP: {
target: '.resendOTP',
},
},
initial: 'idle',
states: {
idle: {},
resendOTP: {
invoke: {
src: 'requestBindingOTP',
onDone: {
target:
'#vc-item-machine.vcUtilitiesState.walletBinding.acceptingBindingOTP',
actions: ['setCommunicationDetails'],
},
onError: {
actions: [
'setErrorAsWalletBindingError',
'sendWalletBindingErrorEvent',
],
target:
'#vc-item-machine.vcUtilitiesState.walletBinding.showingWalletBindingError',
},
},
},
},
},
addKeyPair: {
invoke: {
src: 'generateKeyPair',
onDone: [
{
cond: 'isCustomSecureKeystore',
target: 'addingWalletBindingId',
actions: ['setPublicKey'],
},
{
target: 'addingWalletBindingId',
actions: ['setPublicKey', 'setPrivateKey'],
},
],
onError: [
{
actions: [
'setErrorAsWalletBindingError',
'sendWalletBindingErrorEvent',
'logWalletBindingFailure',
],
target: 'showingWalletBindingError',
},
],
},
},
addingWalletBindingId: {
invoke: {
src: 'addWalletBindingId',
onDone: [
{
cond: 'isCustomSecureKeystore',
target: 'updatingContextVariables',
actions: ['setWalletBindingResponse'],
},
{
target: 'updatingPrivateKey',
/*The walletBindingResponse is used for conditional rendering in wallet binding. response and use it in updatingPrivateKey state*/
actions: ['setWalletBindingResponse'],
},
],
onError: [
{
actions: [
'setErrorAsWalletBindingError',
'sendWalletBindingErrorEvent',
'logWalletBindingFailure',
],
target: 'showingWalletBindingError',
},
],
},
},
updatingPrivateKey: {
invoke: {
src: 'updatePrivateKey',
onDone: {
target: 'updatingContextVariables',
},
onError: {
actions: [
'setErrorAsWalletBindingError',
'sendWalletBindingErrorEvent',
'logWalletBindingFailure',
],
target: 'showingWalletBindingError',
},
},
},
updatingContextVariables: {
entry: [
'setThumbprintForWalletBindingId',
'storeContext',
'resetPrivateKey',
'storeVcInContext',
'unSetError',
'sendActivationSuccessEvent',
'logWalletBindingSuccess',
send('SHOW_BINDING_STATUS'),
],
on: {
SHOW_BINDING_STATUS: [
{
cond: context => context.isMachineInKebabPopupState,
actions: 'sendWalletBindingSuccess',
target: '#vc-item-machine.vcUtilitiesState.kebabPopUp',
},
{
actions: 'sendWalletBindingSuccess',
target: '#vc-item-machine.vcUtilitiesState.idle',
},
],
},
},
},
},
kebabPopUp: {
entry: assign({isMachineInKebabPopupState: () => true}),
exit: 'resetIsMachineInKebabPopupState',
on: {
DISMISS: {
target: '#vc-item-machine.vcUtilitiesState.idle',
},
ADD_WALLET_BINDING_ID: {
target: '#vc-item-machine.vcUtilitiesState.walletBinding',
},
PIN_CARD: {
target: '.pinCard',
actions: 'setPinCard',
},
SHOW_ACTIVITY: {
target:
'#vc-item-machine.vcUtilitiesState.kebabPopUp.showActivities',
},
REMOVE: {
actions: 'setVcKey',
target:
'#vc-item-machine.vcUtilitiesState.kebabPopUp.removeWallet',
},
CLOSE_VC_MODAL: {
actions: ['closeViewVcModal'],
target: '#vc-item-machine.vcUtilitiesState.idle',
},
},
initial: 'idle',
states: {
idle: {},
pinCard: {
entry: 'updateVcMetadata',
always: {
target: '#vc-item-machine.vcUtilitiesState.idle',
},
},
showActivities: {
entry: 'resetIsMachineInKebabPopupState',
on: {
DISMISS: '#vc-item-machine.vcUtilitiesState.idle',
},
},
removeWallet: {
entry: 'resetIsMachineInKebabPopupState',
on: {
CONFIRM: {
target: 'removingVc',
},
CANCEL: {
target: '#vc-item-machine.vcUtilitiesState.idle',
},
},
},
removingVc: {
entry: 'removeVcItem',
on: {
STORE_RESPONSE: {
actions: [
'closeViewVcModal',
'refreshAllVcs',
'logRemovedVc',
],
target: 'triggerAutoBackup',
},
},
},
triggerAutoBackup: {
invoke: {
src: 'isUserSignedAlready',
onDone: [
{
cond: 'isSignedIn',
actions: [
'sendBackupEvent',
'refreshAllVcs',
'logRemovedVc',
],
target: '#vc-item-machine.vcUtilitiesState.idle',
},
{
actions: ['refreshAllVcs', 'logRemovedVc'],
target: '#vc-item-machine.vcUtilitiesState.idle',
},
],
},
},
},
},
verifyingCredential: {
invoke: {
src: 'verifyCredential',
onDone: {
actions: ['setIsVerified', 'storeContext'],
},
onError: [
{
cond: 'isVerificationPendingBecauseOfNetworkIssue',
actions: ['resetIsVerified', 'storeContext'],
},
{
actions: ['setErrorAsVerificationError'],
target: '.handleVCVerificationFailure',
},
],
},
on: {
STORE_RESPONSE: {
actions: [
'storeVcInContext',
'updateVcMetadata',
'logDownloaded',
'sendTelemetryEvents',
'removeVcFromInProgressDownloads',
],
target: '.triggerAutoBackupForVcDownload',
},
STORE_ERROR: {
target:
'#vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.savingFailed',
},
},
initial: 'idle',
states: {
idle: {},
triggerAutoBackupForVcDownload: {
invoke: {
src: 'isUserSignedAlready',
onDone: [
{
cond: 'isSignedIn',
actions: ['sendBackupEvent'],
target: `#vc-item-machine.vcUtilitiesState.idle`,
},
{
target: `#vc-item-machine.vcUtilitiesState.idle`,
},
],
},
},
handleVCVerificationFailure: {
entry: [
'removeVcMetaDataFromStorage',
'removeVcFromInProgressDownloads',
],
on: {
STORE_RESPONSE: {
actions: ['sendVerificationError'],
},
},
},
},
},
idle: {
on: {
DISMISS: {
target:
'#vc-item-machine.vcUtilitiesState.loadVc.loadVcFromContext',
},
KEBAB_POPUP: {
target: 'kebabPopUp',
},
ADD_WALLET_BINDING_ID: {
target: '#vc-item-machine.vcUtilitiesState.walletBinding',
},
PIN_CARD: {
target: '#vc-item-machine.vcUtilitiesState.kebabPopUp.pinCard',
actions: 'setPinCard',
},
},
},
},
},
verifyState: {
on: {
VERIFY: {
target: '#vc-item-machine.verifyState.verifyingCredential',
},
RESET_VERIFICATION_STATUS: {
actions: [
'resetVerificationStatus',
'removeVerificationStatusFromVcMeta',
],
},
},
initial: 'idle',
states: {
idle: {},
verifyingCredential: {
entry: send({
type: 'SET_VERIFICATION_STATUS',
response: {statusType: BannerStatusType.IN_PROGRESS},
}),
invoke: {
src: 'verifyCredential',
onDone: {
actions: ['setIsVerified', 'storeContext'],
},
onError: [
{
cond: 'isVerificationPendingBecauseOfNetworkIssue',
actions: ['resetIsVerified', 'storeContext'],
},
],
},
after: {
500: [
{
actions: 'showVerificationBannerStatus',
},
],
},
on: {
STORE_RESPONSE: {
actions: [
'setVerificationStatus',
'sendVerificationStatusToVcMeta',
'updateVcMetadata',
],
target: 'verificationCompleted',
},
SET_VERIFICATION_STATUS: {
actions: 'setVerificationStatus',
},
SHOW_VERIFICATION_STATUS_BANNER: {
actions: [
'setVerificationStatus',
'showVerificationBannerStatus',
],
},
//TO-DO: Handle if some error is thrown when storing verified status into storage
STORE_ERROR: {},
},
},
verificationCompleted: {
entry: 'showVerificationBannerStatus',
on: {
REMOVE_VERIFICATION_STATUS_BANNER: {
actions: 'resetVerificationStatus',
},
},
},
},
},
},
},
{
actions: VCItemActions(model),
services: VCItemServices(model),
guards: VCItemGaurds(),
},
);
export const createVCItemMachine = (
serviceRefs: AppServices,
vcMetadata: VCMetadata,
) => {
return VCItemMachine.withContext({
...VCItemMachine.context,
serviceRefs,
vcMetadata,
});
};