From b57af95e754fe88716cd4ccdf4daca5e3d83977a Mon Sep 17 00:00:00 2001 From: Harsh Vardhan Date: Thu, 28 Sep 2023 16:21:36 +0530 Subject: [PATCH 01/20] feat(INJI-205): handle errors in OIDC flow in issuerMachine - `internet not available` on network request failure to issuer - generic error message on other errors in the flow - OIDC flow cancel error message Signed-off-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> --- machines/issuersMachine.ts | 64 +++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 8 deletions(-) diff --git a/machines/issuersMachine.ts b/machines/issuersMachine.ts index 1ddf71b164..f519cc0d09 100644 --- a/machines/issuersMachine.ts +++ b/machines/issuersMachine.ts @@ -22,10 +22,12 @@ import { } from '../types/VC/EsignetMosipVC/vc'; import {CACHED_API} from '../shared/api'; +const TIMEOUT_SEC = 10; + const model = createModel( { issuers: [] as issuerType[], - selectedIssuer: [] as issuerType[], + selectedIssuer: {} as issuerType, tokenResponse: {} as AuthorizeResult, errorMessage: '' as string, loadingReason: 'displayIssuers' as string, @@ -56,7 +58,7 @@ export const Issuer_Tab_Ref_Id = 'issuersMachine'; export const Issuers_Key_Ref = 'OpenId4VCI'; export const IssuersMachine = model.createMachine( { - /** @xstate-layout N4IgpgJg5mDOIC5QEtawK5gE6wLIEMBjAC2QDswA6AG1QBcBJNTHAYggHsLLY786qqDNjxFS3WrybCcAbQAMAXUSgADh1jI6yLipAAPRAEYA7PMomj8gJwAWeSYAcTgMy2TJgDQgAnsZPWlLYArC5GAEzWEfKRtka2AL4J3kIsoiTkVLBg1GCE2mRQ0iysACIA8gDqAHIAMuUAgqUA+gBqDA3NDKUKykgg6prauv2GCMHuFo7W8sET8i4x1uHefgimJpTWoRHWJrYuc9YAbEkpzCIEGdzZufnkRRdYrADKAKK1bwDCACpvLQwXi8AKpvABKvT0gy0OjIejGE02Thmc3si0iK18iEcRiC1nxJxR22OjhcZxAqUuYkyPByeQKjxkZUBuEBL0h-Whwzho0QiKmKPm6OWq0Q4X2QXkx3C0uCOKM0pcJnJlJwV3EWTp+WK2HYXCyfAElFV6Q1tLujCeHLUGhhI1AY2mx0oRmCxyMjgcJMi8VF6xM4Uo4QWRjc2xMcqVp2SFKepppqmwADMOFgALYNdB0Yip5AAL34sNYDWBPwAEuUwQwAFr-a0DW3c+HGBaOILHeSOWwkj3hYIKv34rYmY4TUeOZzSxzR84yePcRNYFPpzPZ3MF7msMHfN4MVr-Zo-coAaTe1XrXNhzfW4VvlEW3YVMRcexlfo2Wx2kX2h2C20SMYmuqNIwHQXxYJAYBkNo+DUAAYlgHBpjqzycDchqCHGwHcKB4GQdByCwQhSEoRejZXry6zuG2yy9scSq0bY75WEGMpytM+wONsZLkmQHAQHAehAdSFBQuR9oGIgAC0xx+jJKpYSJghkFoYlDBRDqIMctiUB2EyOPpMzhM4mJrH2gTLHs8jxI44T2K6ClzthVCSJac5qXaPKaQgtimWK1lBJExwzF24QuMGtgAbOaTOea9IPChHlNpRLi2ZQ-Zur5o7PlEslYggwa4r5JwBFlLijvsjkxUpcXak8SUaZJCARi4Lq2F28izGEna2e+dgugExwmKl7hmFKVVUtcVCLsuGZZjmWD5oWEmXhJYxWCxtkxGiRjLJYjh+oVgUlXYMrlcElWAYpU2ULhEECQRRGIch9WcuJXlNfECqBR6MTOHYZgHflwZtkNVkxGdrbhBNao1cgEC5A1a2IC1bUdV1VgTn5BV7JQWOksENhyk4RhJEkQA */ + /** @xstate-layout N4IgpgJg5mDOIC5QEtawK5gE6wLIEMBjAC2QDswA6CVABwBt8BPASTUxwGIIB7Cy8gDceAayqoM2PEVL8asBszaScCIT0L4ALsj4BtAAwBdQ0cShaPWMh19zIAB6IAjAA4ALAE5KAZgCsBs4A7D4ATABs7j4GngA0IEyI4X6hlO7hQUFemc5+Pp4+AL6F8RIc0iTkVPKKrOxSnNhYPFiUiloAZi0AtgL1OASVcnSMdSqwamTCmrZkpqb2ltaz9k4Ibl6+AcFhkdFxCS5B4ZQp4c4GBqF+fkGhQX7hxaX9FbJUTS2cACoASgCaAH0AIIAcWBLAAcgskCAljZdGRVi4CkE0s4oqFLqFPM5nJ5QvFEghXM5KG4Qu4Hp4YkFckFniAylJBu9KJ8sJxfgBRADK3O+gO5v1+AHlfjCLFYEXZYWtrhjKOEaUFXJ4aa5Qu5CYcEJ4TuEfD4qRc-ASDAFXIzmQMZFV2VhmlhQj8ASDwVDJXDpSs5YgfOFLpQDNF3K5Ih5woGgkTEK5XD5KAmPAZ3AYstF49bXqz7RyXTz+YLhWKJcZFj7EciEAGgyHU+Gw+lo7GEKrXGl1UFAncjddPNnxrn+ByfK6gWCIdDy7D4b7QGtawZg6HG5GW7rnBE-Kdcp4zXTqe5B+Vhx9HS0x4WBUKReKvXOq36a4Hl-WwxHm+nW3ju+Sco8IQ0pEDIlEyOZ2vwsBgPQYCEDoZBQMoHCcAAIqKADqkIADKisCqGAiwqEPpWsoLogoShMESZGg8uShGqOKtrciY+EENKUTijyPE8YE2m89rQbB8HkEh-ScPy2HcgAwt83IESwvK8gAqsKJHLE+5EIAq7hKiqaoalqOrEh4unuFuPgeH4+LnJkJ4spB1Q8AA7mQ9A8PgEDIdg0l8B0yBQNwfDiFMojiBBQxOa57med5WC+WQ-lQJM0zaIi8wzlKGlkY4-rpmiW7sYayoGOcPg-lcHYBKqKSXPuzgZPZtqRdQLluR5Xn9AlSWNBerTtF0WC9PxZ6tdFHVxd1AUpRoaX6MY6kykiz7RJk5L3PqAbAc45W6q4IaUJkBSUVtkSBE1An8LQ2CDd0wLoFoxAtMgABec1kEF-DqGIfRDo5bQ3T092Pc9b2zDNMzpQtmXetly1aUuK4Np+Ubfpu7h5OSx36uEVlmn4F2jddWC3cDT1YK9729U6bSMJ0PS-ae-3E6TD3k5T4PqJD80mDDj45YugZkmxpWeO4GM0jcP61kmfhUuEET6hZhP-SQcEiAA0mATAAAr4MgnLSQAEjJGuAhr3JAjrEJlmYs6kfDuU1lRlBGYGyQBOmmo-luZK+5ZxXWftVp8RFbJq4Qmva3rBucMbpvm5bgLWywErOHbWVLdWYRkm7pU3JcqrGXG+Q0fuVFRuxYYDqHf0tTAFBYNoYBa7r+ucrwX2hT9I3-Q32DN63MdYBD70ZRnsNZ8+FzRK7YtagU1n6qVrY0rp8bhnLxzKikKv12AjeD9H7efSFwg92H9r903Wgt8fBuj7M8zpxWcPVjPy44tqXj+DZK+6jVJMCtcYEnFgqGuLw65sl4ONTy0ksCQAPjofA9BYCnwEN3cKUD7QwPanAhBEAkHIBQRMLmY9oYT35o7NYGxvD+B7LsKIMRWxZHXqVBibEzSeAeKBSBTMWq4JihAeBiCyDINQdTFotNtC3UZg5ARbUhEiMIWI4hqDH5Q15pQh278PB0O2CECITCDjEjxK4HcGNcb3GVLiFIoQ97QMUR1ZRRCSFx2BJCaS3JsKLXnE7WhWwGFGP2K2BMBUMb5W7DifODj7SCGwMgDoTBRIuNUSg9B30sH8LZPEimSSUkENcfQDRPNfGaSdjpPSXt1QGE1NqVsfZyTmTYriHGtTjSxP4LkxJyTEKpPEZI-qdNZG9xat0-JfTClpOKWQp+FDX5Ty0pUkqqoal1OLggJeh06RRjTKVCMvDwLYK+hAWCcdRS4B1lJOSxE+Y6OfFEM0lB9JhFTDEcW0tUieE3sqMI2osQhz4fItkyBTlgHcZ47xZSBb+m7CcFI6QLgRHDJkVsVilRf2+eqSyxoa5gTIDwQh8BYSjPeAsvxawAC04RWzUs6dUEYShXjkvKTQrwZJzFRm+SA5UO0fyPF8ArK4PgMTBFxI1Wu2S8x9RZTC7SGJlx5EsvudiW4-DhlXmidIYDK4ivec4elDonShFldQ-0YREw2JnnsTUERQkHTxJceM3z8QXGPJK4F0qnQ+FNdnC1elcQhhtZRGlm4NiHVcEeEVGJKIEw9c1NkQk4IITEioX1z4K47kuOLdMe4MxopCIdYI+1AjBBxBAo5Uq5BONil1PyAV01LLuLnTUPKrjJHtTuG4+obg3EiNcQ5pL7QsyBmzUG71G1O2VcuEIRUqK5CjEaVepVTiGiNMkQ04t1SGojlHNuBtJ1rHqZuXN2yTpajyMcayhrr5H33VgQ9SQwinEjamfIOI3UbJLc8lFBJuxUkeBWod1bYHCKmeI4lmcKUuCbK7TUx14wWjhaEvEzyzSBGuOW3Ghrxm9KgP0tRj7tLvPWniNMuQRUat1NG12YR1R2ItDiLIhrYBaGeohIj9wXYMWRcvbcrZQil32gxO4ctIz6nsfGy64gwVEfyHLckuNjhhmxNw6WiZKLpmNGmHhjzDWdzAERjGuQkwPGVJG8ytT3AVQ7Guna3zalnDlsUYoQA */ predictableActionArguments: true, preserveActionOrder: true, id: Issuer_Tab_Ref_Id, @@ -95,6 +97,32 @@ export const IssuersMachine = model.createMachine( }, }, }, + error2: { + description: 'reaches here when issuer config is not available', + on: { + TRY_AGAIN: { + actions: 'resetError', + target: 'downloadCredentials', + }, + RESET_ERROR: { + actions: 'resetError', + target: 'idle', + }, + }, + }, + error3: { + description: 'reaches here when auth callback fails', + on: { + TRY_AGAIN: { + actions: 'resetError', + target: 'downloadCredentials', + }, + RESET_ERROR: { + actions: 'resetError', + target: 'idle', + }, + }, + }, selectingIssuer: { description: 'waits for the user to select any issuer', on: { @@ -114,6 +142,10 @@ export const IssuersMachine = model.createMachine( actions: 'setSelectedIssuers', target: 'performAuthorization', }, + onError: { + actions: 'setError', + target: 'error2', + }, }, }, performAuthorization: { @@ -125,10 +157,21 @@ export const IssuersMachine = model.createMachine( actions: ['setTokenResponse', 'getKeyPairFromStore', 'loadKeyPair'], target: 'checkKeyPair', }, - onError: { - actions: [() => console.log('error in invokeAuth - ', event.data)], - target: 'downloadCredentials', - }, + onError: [ + { + cond: (_, event) => event.data.error !== 'User cancelled flow', + actions: [ + (_, event) => console.log('error in invokeAuth - ', event.data), + 'setError', + ], + target: 'error3', + }, + { + cond: (_, event) => + event.data.error !== 'Invalid token specified', + target: 'downloadCredentials', + }, + ], }, }, checkKeyPair: { @@ -173,8 +216,8 @@ export const IssuersMachine = model.createMachine( target: 'verifyingCredential', }, onError: { - actions: event => - console.log(' error occured in downloadCredential', event), + actions: 'setError', + target: 'error3', }, }, on: { @@ -238,6 +281,10 @@ export const IssuersMachine = model.createMachine( setError: model.assign({ errorMessage: (_, event) => { console.log('Error while fetching issuers ', event.data.message); + if (event.data.message === 'User cancelled flow') { + // not an error if user has pressed back button or closes the tab + return ''; + } return event.data.message === 'Network request failed' ? 'noInternetConnection' : 'generic'; @@ -386,6 +433,7 @@ export const IssuersMachine = model.createMachine( return credential; }, invokeAuthorization: async context => { + console.log('ISSUER: ', context.selectedIssuer); const response = await authorize(context.selectedIssuer); return response; }, From 256c036371746d11d8a8d5ee00b7ae8d710ac016 Mon Sep 17 00:00:00 2001 From: Harsh Vardhan Date: Thu, 28 Sep 2023 16:24:40 +0530 Subject: [PATCH 02/20] feat(INJI-205): add support for request timeout for OIDC Signed-off-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> --- shared/GlobalContext.ts | 22 +++++++++++----------- shared/request.ts | 26 ++++++++++++++++---------- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/shared/GlobalContext.ts b/shared/GlobalContext.ts index d93dca3afc..43be0f4aaa 100644 --- a/shared/GlobalContext.ts +++ b/shared/GlobalContext.ts @@ -1,14 +1,14 @@ -import { createContext } from 'react'; -import { ActorRefFrom, InterpreterFrom } from 'xstate'; -import { activityLogMachine } from '../machines/activityLog'; -import { appMachine } from '../machines/app'; -import { authMachine } from '../machines/auth'; -import { requestMachine } from '../machines/bleShare/request/requestMachine'; -import { scanMachine } from '../machines/bleShare/scan/scanMachine'; -import { settingsMachine } from '../machines/settings'; -import { storeMachine } from '../machines/store'; -import { vcMachine } from '../machines/vc'; -import { revokeVidsMachine } from '../machines/revoke'; +import {createContext} from 'react'; +import {ActorRefFrom, InterpreterFrom} from 'xstate'; +import {activityLogMachine} from '../machines/activityLog'; +import {appMachine} from '../machines/app'; +import {authMachine} from '../machines/auth'; +import {requestMachine} from '../machines/bleShare/request/requestMachine'; +import {scanMachine} from '../machines/bleShare/scan/scanMachine'; +import {settingsMachine} from '../machines/settings'; +import {storeMachine} from '../machines/store'; +import {vcMachine} from '../machines/vc'; +import {revokeVidsMachine} from '../machines/revoke'; export const GlobalContext = createContext({} as GlobalServices); diff --git a/shared/request.ts b/shared/request.ts index 16a0837c30..ef901b493c 100644 --- a/shared/request.ts +++ b/shared/request.ts @@ -18,6 +18,7 @@ export async function request( method: HTTP_METHOD, path: `/${string}`, body?: Record, + timeout?: undefined | number, host = MIMOTO_BASE_URL, ) { const headers = { @@ -25,12 +26,20 @@ export async function request( }; if (path.includes('residentmobileapp')) headers['X-AppId'] = __AppId.getValue(); - - const response = await fetch(host + path, { - method, - headers, - body: JSON.stringify(body), - }); + let response; + if (timeout === undefined) { + response = await fetch(host + path, { + method, + headers, + body: JSON.stringify(body), + }); + } else { + response = Promise.race([ + fetch(host + path, {method, headers, body: JSON.stringify(body)}), + (_: any, reject: (arg0: Error) => void) => + setTimeout(() => reject(new Error('request timeout')), timeout * 1000), + ]); + } const jsonResponse = await response.json(); @@ -38,10 +47,7 @@ export async function request( let backendUrl = host + path; let errorMessage = jsonResponse.message || jsonResponse.error; console.error( - 'The backend API ' + - backendUrl + - ' returned error code 400 with message --> ' + - errorMessage, + `The backend API ${backendUrl} returned error code ${response.status} with message --> ${errorMessage}`, ); throw new Error(errorMessage); } From 53c540d4270787cf2633ce8bf2a46092d01a3e98 Mon Sep 17 00:00:00 2001 From: Harsh Vardhan Date: Thu, 5 Oct 2023 12:48:11 +0530 Subject: [PATCH 03/20] refactor(INJI-205): improve oidc error handling granular level changes: - merged error states - move to a two-step issuer-ID assign of issuer from issuerScreen to state machine - improved OIDC cancel flow handling for android/iOS openid platform libs Co-authored-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> Signed-off-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> --- machines/auth.typegen.ts | 22 ++-- machines/issuersMachine.ts | 114 +++++++++--------- machines/issuersMachine.typegen.ts | 182 ++++++++++++----------------- machines/store.typegen.ts | 124 ++++++++------------ shared/request.ts | 2 +- 5 files changed, 193 insertions(+), 251 deletions(-) diff --git a/machines/auth.typegen.ts b/machines/auth.typegen.ts index 3843a6d7cb..71a4e6dc39 100644 --- a/machines/auth.typegen.ts +++ b/machines/auth.typegen.ts @@ -2,8 +2,8 @@ export interface Typegen0 { '@@xstate/typegen': true; - 'internalEvents': { - '': { type: '' }; + internalEvents: { + '': {type: ''}; 'done.invoke.auth.authorized:invocation[0]': { type: 'done.invoke.auth.authorized:invocation[0]'; data: unknown; @@ -14,19 +14,19 @@ export interface Typegen0 { data: unknown; __tip: 'See the XState TS docs to learn how to strongly type this.'; }; - 'xstate.init': { type: 'xstate.init' }; + 'xstate.init': {type: 'xstate.init'}; }; - 'invokeSrcNameMap': { + invokeSrcNameMap: { downloadFaceSdkModel: 'done.invoke.auth.authorized:invocation[0]'; generatePasscodeSalt: 'done.invoke.auth.introSlider:invocation[0]'; }; - 'missingImplementations': { + missingImplementations: { actions: never; delays: never; guards: never; services: never; }; - 'eventsCausingActions': { + eventsCausingActions: { requestStoredContext: 'xstate.init'; setBiometrics: 'SETUP_BIOMETRICS'; setContext: 'STORE_RESPONSE'; @@ -40,18 +40,18 @@ export interface Typegen0 { | 'done.invoke.auth.authorized:invocation[0]' | 'done.invoke.auth.introSlider:invocation[0]'; }; - 'eventsCausingDelays': {}; - 'eventsCausingGuards': { + eventsCausingDelays: {}; + eventsCausingGuards: { hasBiometricSet: ''; hasData: 'STORE_RESPONSE'; hasLanguageset: ''; hasPasscodeSet: ''; }; - 'eventsCausingServices': { + eventsCausingServices: { downloadFaceSdkModel: 'LOGIN' | 'SETUP_PASSCODE'; generatePasscodeSalt: 'SELECT'; }; - 'matchesStates': + matchesStates: | 'authorized' | 'checkingAuth' | 'init' @@ -60,5 +60,5 @@ export interface Typegen0 { | 'savingDefaults' | 'settingUp' | 'unauthorized'; - 'tags': never; + tags: never; } diff --git a/machines/issuersMachine.ts b/machines/issuersMachine.ts index f519cc0d09..b8e75e817e 100644 --- a/machines/issuersMachine.ts +++ b/machines/issuersMachine.ts @@ -2,7 +2,6 @@ import {authorize, AuthorizeResult} from 'react-native-app-auth'; import {assign, EventFrom, send, sendParent, StateFrom} from 'xstate'; import {createModel} from 'xstate/lib/model'; import {MY_VCS_STORE_KEY} from '../shared/constants'; -import {request} from '../shared/request'; import {StoreEvents} from './store'; import {AppServices} from '../shared/GlobalContext'; import { @@ -24,9 +23,18 @@ import {CACHED_API} from '../shared/api'; const TIMEOUT_SEC = 10; +// OIDCErrors is a collection of external errors from the OpenID library or the issuer +enum OIDCErrors { + OIDC_FLOW_CANCELLED_ANDROID = 'User cancelled flow', + OIDC_FLOW_CANCELLED_IOS = 'org.openid.appauth.general error -3', + + INVALID_TOKEN_SPECIFIED = 'Invalid token specified', +} + const model = createModel( { issuers: [] as issuerType[], + tempSelectedIssuer: '' as string, selectedIssuer: {} as issuerType, tokenResponse: {} as AuthorizeResult, errorMessage: '' as string, @@ -58,7 +66,7 @@ export const Issuer_Tab_Ref_Id = 'issuersMachine'; export const Issuers_Key_Ref = 'OpenId4VCI'; export const IssuersMachine = model.createMachine( { - /** @xstate-layout N4IgpgJg5mDOIC5QEtawK5gE6wLIEMBjAC2QDswA6CVABwBt8BPASTUxwGIIB7Cy8gDceAayqoM2PEVL8asBszaScCIT0L4ALsj4BtAAwBdQ0cShaPWMh19zIAB6IAjAA4ALAE5KAZgCsBs4A7D4ATABs7j4GngA0IEyI4X6hlO7hQUFemc5+Pp4+AL6F8RIc0iTkVPKKrOxSnNhYPFiUiloAZi0AtgL1OASVcnSMdSqwamTCmrZkpqb2ltaz9k4Ibl6+AcFhkdFxCS5B4ZQp4c4GBqF+fkGhQX7hxaX9FbJUTS2cACoASgCaAH0AIIAcWBLAAcgskCAljZdGRVi4CkE0s4oqFLqFPM5nJ5QvFEghXM5KG4Qu4Hp4YkFckFniAylJBu9KJ8sJxfgBRADK3O+gO5v1+AHlfjCLFYEXZYWtrhjKOEaUFXJ4aa5Qu5CYcEJ4TuEfD4qRc-ASDAFXIzmQMZFV2VhmlhQj8ASDwVDJXDpSs5YgfOFLpQDNF3K5Ih5woGgkTEK5XD5KAmPAZ3AYstF49bXqz7RyXTz+YLhWKJcZFj7EciEAGgyHU+Gw+lo7GEKrXGl1UFAncjddPNnxrn+ByfK6gWCIdDy7D4b7QGtawZg6HG5GW7rnBE-Kdcp4zXTqe5B+Vhx9HS0x4WBUKReKvXOq36a4Hl-WwxHm+nW3ju+Sco8IQ0pEDIlEyOZ2vwsBgPQYCEDoZBQMoHCcAAIqKADqkIADKisCqGAiwqEPpWsoLogoShMESZGg8uShGqOKtrciY+EENKUTijyPE8YE2m89rQbB8HkEh-ScPy2HcgAwt83IESwvK8gAqsKJHLE+5EIAq7hKiqaoalqOrEh4unuFuPgeH4+LnJkJ4spB1Q8AA7mQ9A8PgEDIdg0l8B0yBQNwfDiFMojiBBQxOa57med5WC+WQ-lQJM0zaIi8wzlKGlkY4-rpmiW7sYayoGOcPg-lcHYBKqKSXPuzgZPZtqRdQLluR5Xn9AlSWNBerTtF0WC9PxZ6tdFHVxd1AUpRoaX6MY6kykiz7RJk5L3PqAbAc45W6q4IaUJkBSUVtkSBE1An8LQ2CDd0wLoFoxAtMgABec1kEF-DqGIfRDo5bQ3T092Pc9b2zDNMzpQtmXetly1aUuK4Np+Ubfpu7h5OSx36uEVlmn4F2jddWC3cDT1YK9729U6bSMJ0PS-ae-3E6TD3k5T4PqJD80mDDj45YugZkmxpWeO4GM0jcP61kmfhUuEET6hZhP-SQcEiAA0mATAAAr4MgnLSQAEjJGuAhr3JAjrEJlmYs6kfDuU1lRlBGYGyQBOmmo-luZK+5ZxXWftVp8RFbJq4Qmva3rBucMbpvm5bgLWywErOHbWVLdWYRkm7pU3JcqrGXG+Q0fuVFRuxYYDqHf0tTAFBYNoYBa7r+ucrwX2hT9I3-Q32DN63MdYBD70ZRnsNZ8+FzRK7YtagU1n6qVrY0rp8bhnLxzKikKv12AjeD9H7efSFwg92H9r903Wgt8fBuj7M8zpxWcPVjPy44tqXj+DZK+6jVJMCtcYEnFgqGuLw65sl4ONTy0ksCQAPjofA9BYCnwEN3cKUD7QwPanAhBEAkHIBQRMLmY9oYT35o7NYGxvD+B7LsKIMRWxZHXqVBibEzSeAeKBSBTMWq4JihAeBiCyDINQdTFotNtC3UZg5ARbUhEiMIWI4hqDH5Q15pQh278PB0O2CECITCDjEjxK4HcGNcb3GVLiFIoQ97QMUR1ZRRCSFx2BJCaS3JsKLXnE7WhWwGFGP2K2BMBUMb5W7DifODj7SCGwMgDoTBRIuNUSg9B30sH8LZPEimSSUkENcfQDRPNfGaSdjpPSXt1QGE1NqVsfZyTmTYriHGtTjSxP4LkxJyTEKpPEZI-qdNZG9xat0-JfTClpOKWQp+FDX5Ty0pUkqqoal1OLggJeh06RRjTKVCMvDwLYK+hAWCcdRS4B1lJOSxE+Y6OfFEM0lB9JhFTDEcW0tUieE3sqMI2osQhz4fItkyBTlgHcZ47xZSBb+m7CcFI6QLgRHDJkVsVilRf2+eqSyxoa5gTIDwQh8BYSjPeAsvxawAC04RWzUs6dUEYShXjkvKTQrwZJzFRm+SA5UO0fyPF8ArK4PgMTBFxI1Wu2S8x9RZTC7SGJlx5EsvudiW4-DhlXmidIYDK4ivec4elDonShFldQ-0YREw2JnnsTUERQkHTxJceM3z8QXGPJK4F0qnQ+FNdnC1elcQhhtZRGlm4NiHVcEeEVGJKIEw9c1NkQk4IITEioX1z4K47kuOLdMe4MxopCIdYI+1AjBBxBAo5Uq5BONil1PyAV01LLuLnTUPKrjJHtTuG4+obg3EiNcQ5pL7QsyBmzUG71G1O2VcuEIRUqK5CjEaVepVTiGiNMkQ04t1SGojlHNuBtJ1rHqZuXN2yTpajyMcayhrr5H33VgQ9SQwinEjamfIOI3UbJLc8lFBJuxUkeBWod1bYHCKmeI4lmcKUuCbK7TUx14wWjhaEvEzyzSBGuOW3Ghrxm9KgP0tRj7tLvPWniNMuQRUat1NG12YR1R2ItDiLIhrYBaGeohIj9wXYMWRcvbcrZQil32gxO4ctIz6nsfGy64gwVEfyHLckuNjhhmxNw6WiZKLpmNGmHhjzDWdzAERjGuQkwPGVJG8ytT3AVQ7Guna3zalnDlsUYoQA */ + /** @xstate-layout N4IgpgJg5mDOIC5QEtawK5gE6wLIEMBjAC2QDswA6CVABwBt8BPASTUxwGIIB7Cy8gDceAayqoM2PEVL8asBszaScCIT0L4ALsj4BtAAwBdQ0cShaPWMh19zIAB6IATAHYAHAFZK7gGwBmd2cARgBOdwNgvwAaECZEV18DSmdfdw8ogBZQ-wN-TwBfAtiJDmkScip5RVZ2KU5sLB4sSkUtADNmgFsBOpwCCrk6RlqVWDUyYU1bMlNTe0trGfsnBDcvHwCgsIio31j4tf9fFINI4MTPfMzXT2cikr7y2SpG5s4AFQAlAE0AfQAggBxAEsABy8yQIEWNl0ZBWiEywX8rkomXyvlCOQ8Bn2cUQnnSKSRbixnkyvl8zn8DxApSkAxelDeWE+v0BIPBemCZihMOWUNWmQM6MoVIMflCd2CAX8B0QoVcwRSnkxrnRkUyd1CtPp-RklWZWCarK+AFEAMpmj5-M1fL4AeS+kIsVlhdkFiKSyRue1cEvSvlc8oQnlcqMS6OOziCaT8uqejMNLOcbP+wNBEOMCzdAtAq3JJxlioizk8oWCyMyIeCnjOaPcwQloQM-tcbl8CbGSf4Kc45qtNrtjud2b5ubhCNDFMoxZxZYrVZrrnylHCOOyEVCAWCXbKPaosDA9DAhB0ZCgyg4nAAIg6AOpggAyDoBN7+LBvLuhE49+cQ-jBJkmSUP4NxgU2-iBEGnghiuPpNr4haeGEZJ7gyBr8EeJ5nuQl59JwVpPmaADCHxmu+LAWhaACqdrfvyk6eggYFIqcwGZGW2pas4IY3MkzitukNzUli-g6sUdKJphVQ8AA7mQ9A8PgEBXtgJF8O0yBQNwfDiJMojiNJgyyQpSkqWpWAaWQWlQBMUzaHCcxjq6SxMf+LHAcqgkcVxzihDxIYoqikoomckFUhJjzdjJ1DyYpymqX01m2Q0xrNK0jAdN0vQxSZcVmYllkpdp9kaI5+jGAxv7wsxwqiuKkrSrKfG5GiEqtiu6rkjchSSXqzyGrQ2CdFgXQAugWjEM0yAAF4VWQun8OoYi5fusXDVgo3jZN01YHNC1ldMTlVS5P5uX+jgEjOc6luWlZgTW1yUIkjbpChvgXGW6H6vlm3bRNU0zfNMxpSamXaNta0YX9I3dIDe0HTMR0Lc5vKue6tUeYWs5qndi6PfiCCNrO6SpEkfh1k2mQ-YN-D-fDu3AwtYMZW0UMDQerRw2NCPM8j6jHZVJg8jmF1Y1d05FnjBgLg91ZEzKVIvWW-HerWbi01zJCniIADSYBMAACvgyCsiRAASpF638etmv8RugqO6PnZjU7BKkzgvaqzicb7qrCu4NZXP4oESpS+QBWkdxa7FOuEPrhsm2bnCW9btv238jssM6ovjuL7ue97VJ+1qviB09WqUHW4ZKhcSpR7H+UwBQWDaGABvG6brK8MtBmrZzsUt9g7ed8nWAozMaNi27zFhEqPhCRSqTZLioRPRclCtlSlwijsnb9cZTLD23Wgd0n3dLfpwgD0fhon6PF9m5PJ0iy7jGXas8-KhEHjL+XLZMQ1h2FvOsvVKSKjrDSQ+eUmS8EKipEiWBIBgDIDofA9BYBXwEP3IysDDTwISog5BEBUHoMwS-YW1UC7MXWN4PwgQQjhEiDERW2pZyCVlhKP+Xgm5wPiuZCASCUFoOQBgrBLIIbZTGtDX6-CEFCJIWQsRFDBao1Ou-GqU46GbEYTsFheJDiVlrGuVIKJjiBClJSPhBCBGJWEaQ0R4jU4AjBCRM0T5qGzw8johh2xmF7BDF4L2SR2yU0imBPq0V1r5UENgZA7QmB4QccojB2CVp4JiUyOJ+1EnJKUU4+glDZgaJnnmSWrFvIimAn5AKdwnpJDXGBMsSskLAVcDY-gOSElJIvCkwprMWjsxyoPWJ8S8l9IKeQ4p0987eIqV5diNTPDcXqWwzI7hq7lyRMcaOgkolSXwctCAJ5U4OlwEbYi5EvxnQ-hLIUfhkj+GcL7SktwzhQWDkGdqgQKRBCCHkdwnTxAnLAC4txHivHlKFOXL2dxjhbnaZ9WCisgKbMrHcAwoRqT7PcEC2kZAeCkPgFCUZLwynuUlgAWkMYgKl3gsSMqZcy6B0SYZwOGEoJ4FLP4uE4pssKCL-L7zlETJUXsogRD+S0pINMYFZOTOlLAPL7mImeSBICIp3BYm1eWYMRMwybPLHcIIFZnn3HleyxVJpnAqvdiuUCZY-DpA9h7QIy5qRb3EqkN6r05VsrkYabCp5zz4RUHa5iuQKzVwuFiIMlZIiE0OO4Nq6oAobK1OWMxwKCpEKSioEqUAI0eQRRGW4n1OLNLxfqw4JIXrATOBsps7YPY5oZrzJm+0QaUruVOTiwc-CgXbJ9FNFJhQHwDXTKg8dE5dzNsWyWipQ4oWjK9KkEcaxjq9divFKJGxQJzQ-M+Y9u4Lq-mGDVZxPrhhyJ9EUT1cRihWWcKU-pdgdMtYGuQdjiEiPISSjG0K+VlhetuJIHtSTAU3UEFI2qYyEnJBBKKhyFVdPGb0qA-TyFnoAlwsUYFEhlhCBuYOlY0QrICimoClIZQ5tgFoGaF4cMsTSGW1UQFqT8vSDWH11dX3UkxJ9NwFrJ1c2QKC5jNxEgvRRJBUsxYvmoi2HkXIHZy4ftE7FXuYBmNUxOP5WWjZK2KhrYgWsooDBQNyAw-yH6ihAA */ predictableActionArguments: true, preserveActionOrder: true, id: Issuer_Tab_Ref_Id, @@ -75,7 +83,7 @@ export const IssuersMachine = model.createMachine( invoke: { src: 'downloadIssuersList', onDone: { - actions: ['setIssuers'], + actions: ['setIssuers', 'unsetLoadingReason'], target: 'selectingIssuer', }, onError: { @@ -87,36 +95,17 @@ export const IssuersMachine = model.createMachine( error: { description: 'reaches here when any error happens', on: { - TRY_AGAIN: { - actions: 'resetError', - target: 'displayIssuers', - }, - RESET_ERROR: { - actions: 'resetError', - target: 'idle', - }, - }, - }, - error2: { - description: 'reaches here when issuer config is not available', - on: { - TRY_AGAIN: { - actions: 'resetError', - target: 'downloadCredentials', - }, - RESET_ERROR: { - actions: 'resetError', - target: 'idle', - }, - }, - }, - error3: { - description: 'reaches here when auth callback fails', - on: { - TRY_AGAIN: { - actions: 'resetError', - target: 'downloadCredentials', - }, + TRY_AGAIN: [ + { + cond: 'shouldFetchIssuerAgain', + actions: ['setLoadingIssuer', 'resetError'], + target: 'displayIssuers', + }, + { + actions: 'resetError', + target: 'checkKeyPair', + }, + ], RESET_ERROR: { actions: 'resetError', target: 'idle', @@ -130,6 +119,8 @@ export const IssuersMachine = model.createMachine( actions: sendParent('DOWNLOAD_ID'), }, SELECTED_ISSUER: { + // set the issuer obj from the issuerStore + actions: 'updateTmpSelectedIssuer', target: 'downloadIssuerConfig', }, }, @@ -144,7 +135,7 @@ export const IssuersMachine = model.createMachine( }, onError: { actions: 'setError', - target: 'error2', + target: 'error', }, }, }, @@ -159,17 +150,16 @@ export const IssuersMachine = model.createMachine( }, onError: [ { - cond: (_, event) => event.data.error !== 'User cancelled flow', + cond: 'isOIDCflowCancelled', + actions: 'resetError', + target: 'selectingIssuer', + }, + { actions: [ - (_, event) => console.log('error in invokeAuth - ', event.data), 'setError', + (_, event) => console.log('error in invokeAuth - ', event.data), ], - target: 'error3', - }, - { - cond: (_, event) => - event.data.error !== 'Invalid token specified', - target: 'downloadCredentials', + target: 'error', }, ], }, @@ -217,7 +207,7 @@ export const IssuersMachine = model.createMachine( }, onError: { actions: 'setError', - target: 'error3', + target: 'error', }, }, on: { @@ -277,21 +267,18 @@ export const IssuersMachine = model.createMachine( issuers: (_, event) => event.data, loadingReason: null, }), - + unsetLoadingReason: model.assign({ + loadingReason: null, + }), setError: model.assign({ errorMessage: (_, event) => { console.log('Error while fetching issuers ', event.data.message); - if (event.data.message === 'User cancelled flow') { - // not an error if user has pressed back button or closes the tab - return ''; - } return event.data.message === 'Network request failed' ? 'noInternetConnection' : 'generic'; }, loadingReason: null, }), - resetError: model.assign({ errorMessage: '', }), @@ -315,7 +302,9 @@ export const IssuersMachine = model.createMachine( to: context => context.serviceRefs.store, }, ), - + setLoadingIssuer: model.assign({ + loadingReason: 'displayIssuers', + }), storeVerifiableCredentialMeta: send( context => StoreEvents.PREPEND(MY_VCS_STORE_KEY, getVCMetadata(context)), @@ -363,6 +352,9 @@ export const IssuersMachine = model.createMachine( setSelectedIssuers: model.assign({ selectedIssuer: (_, event) => event.data, }), + updateTmpSelectedIssuer: model.assign({ + tempSelectedIssuer: (_, event) => event.id, + }), setTokenResponse: model.assign({ tokenResponse: (_, event) => event.data, loadingReason: 'settingUp', @@ -410,11 +402,9 @@ export const IssuersMachine = model.createMachine( downloadIssuersList: async () => { return await CACHED_API.fetchIssuers(); }, - - downloadIssuerConfig: async (_, event) => { - return await CACHED_API.fetchIssuerConfig(event.id); + downloadIssuerConfig: async (context, _) => { + return await CACHED_API.fetchIssuerConfig(context.tempSelectedIssuer); }, - downloadCredential: async context => { const body = await getBody(context); const response = await fetch( @@ -433,7 +423,6 @@ export const IssuersMachine = model.createMachine( return credential; }, invokeAuthorization: async context => { - console.log('ISSUER: ', context.selectedIssuer); const response = await authorize(context.selectedIssuer); return response; }, @@ -456,6 +445,21 @@ export const IssuersMachine = model.createMachine( hasKeyPair: context => { return context.publicKey != null; }, + isOIDCflowCancelled: (_, event) => { + // iOS & Android have different error strings for user cancelled flow + const err = [ + OIDCErrors.OIDC_FLOW_CANCELLED_ANDROID, + OIDCErrors.OIDC_FLOW_CANCELLED_IOS, + ]; + return ( + !!event.data && + typeof event.data.toString === 'function' && + err.some(e => event.data.toString().includes(e)) + ); + }, + shouldFetchIssuerAgain: context => context.selectedIssuer !== null, + invalidTokenSpecified: (_, event) => + event.data.error !== OIDCErrors.INVALID_TOKEN_SPECIFIED, isCustomSecureKeystore: () => isCustomSecureKeystore(), }, }, diff --git a/machines/issuersMachine.typegen.ts b/machines/issuersMachine.typegen.ts index b07dc261d3..416a7bb3fd 100644 --- a/machines/issuersMachine.typegen.ts +++ b/machines/issuersMachine.typegen.ts @@ -1,109 +1,75 @@ -// This file was automatically generated. Edits will be overwritten -export interface Typegen0 { - '@@xstate/typegen': true; - internalEvents: { - 'done.invoke.issuersMachine.displayIssuers:invocation[0]': { - type: 'done.invoke.issuersMachine.displayIssuers:invocation[0]'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'done.invoke.issuersMachine.downloadCredentials:invocation[0]': { - type: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]': { - type: 'done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'done.invoke.issuersMachine.generateKeyPair:invocation[0]': { - type: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'done.invoke.issuersMachine.performAuthorization:invocation[0]': { - type: 'done.invoke.issuersMachine.performAuthorization:invocation[0]'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'done.invoke.issuersMachine.verifyingCredential:invocation[0]': { - type: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'error.platform.issuersMachine.displayIssuers:invocation[0]': { - type: 'error.platform.issuersMachine.displayIssuers:invocation[0]'; - data: unknown; - }; - 'error.platform.issuersMachine.performAuthorization:invocation[0]': { - type: 'error.platform.issuersMachine.performAuthorization:invocation[0]'; - data: unknown; - }; - 'xstate.init': {type: 'xstate.init'}; - }; - invokeSrcNameMap: { - downloadCredential: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]'; - downloadIssuerConfig: 'done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]'; - downloadIssuersList: 'done.invoke.issuersMachine.displayIssuers:invocation[0]'; - generateKeyPair: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; - invokeAuthorization: 'done.invoke.issuersMachine.performAuthorization:invocation[0]'; - verifyCredential: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'; - }; - missingImplementations: { - actions: never; - delays: never; - guards: never; - services: never; - }; - eventsCausingActions: { - getKeyPairFromStore: 'done.invoke.issuersMachine.performAuthorization:invocation[0]'; - loadKeyPair: 'done.invoke.issuersMachine.performAuthorization:invocation[0]'; - logDownloaded: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'; - resetError: 'RESET_ERROR' | 'TRY_AGAIN'; - setCredentialWrapper: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]'; - setError: 'error.platform.issuersMachine.displayIssuers:invocation[0]'; - setIssuers: 'done.invoke.issuersMachine.displayIssuers:invocation[0]'; - setPrivateKey: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; - setPublicKey: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; - setSelectedIssuers: 'done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]'; - setTokenResponse: 'done.invoke.issuersMachine.performAuthorization:invocation[0]'; - setVerifiableCredential: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]'; - storeKeyPair: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; - storeVcMetaContext: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'; - storeVcsContext: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'; - storeVerifiableCredentialData: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'; - storeVerifiableCredentialMeta: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'; - }; - eventsCausingDelays: {}; - eventsCausingGuards: { - hasKeyPair: 'CHECK_KEY_PAIR'; - isCustomSecureKeystore: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; - }; - eventsCausingServices: { - downloadCredential: - | 'CHECK_KEY_PAIR' - | 'done.invoke.issuersMachine.generateKeyPair:invocation[0]' - | 'error.platform.issuersMachine.performAuthorization:invocation[0]'; - downloadIssuerConfig: 'SELECTED_ISSUER'; - downloadIssuersList: 'TRY_AGAIN' | 'xstate.init'; - generateKeyPair: 'CHECK_KEY_PAIR'; - invokeAuthorization: 'done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]'; - verifyCredential: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]'; - }; - matchesStates: - | 'checkKeyPair' - | 'displayIssuers' - | 'done' - | 'downloadCredentials' - | 'downloadIssuerConfig' - | 'error' - | 'generateKeyPair' - | 'idle' - | 'performAuthorization' - | 'selectingIssuer' - | 'storing' - | 'verifyingCredential'; - tags: never; -} + // This file was automatically generated. Edits will be overwritten + + export interface Typegen0 { + '@@xstate/typegen': true; + internalEvents: { + "done.invoke.issuersMachine.displayIssuers:invocation[0]": { type: "done.invoke.issuersMachine.displayIssuers:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"done.invoke.issuersMachine.downloadCredentials:invocation[0]": { type: "done.invoke.issuersMachine.downloadCredentials:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]": { type: "done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"done.invoke.issuersMachine.generateKeyPair:invocation[0]": { type: "done.invoke.issuersMachine.generateKeyPair:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"done.invoke.issuersMachine.performAuthorization:invocation[0]": { type: "done.invoke.issuersMachine.performAuthorization:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"done.invoke.issuersMachine.verifyingCredential:invocation[0]": { type: "done.invoke.issuersMachine.verifyingCredential:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"error.platform.issuersMachine.displayIssuers:invocation[0]": { type: "error.platform.issuersMachine.displayIssuers:invocation[0]"; data: unknown }; +"error.platform.issuersMachine.downloadCredentials:invocation[0]": { type: "error.platform.issuersMachine.downloadCredentials:invocation[0]"; data: unknown }; +"error.platform.issuersMachine.downloadIssuerConfig:invocation[0]": { type: "error.platform.issuersMachine.downloadIssuerConfig:invocation[0]"; data: unknown }; +"error.platform.issuersMachine.performAuthorization:invocation[0]": { type: "error.platform.issuersMachine.performAuthorization:invocation[0]"; data: unknown }; +"xstate.init": { type: "xstate.init" }; + }; + invokeSrcNameMap: { + "downloadCredential": "done.invoke.issuersMachine.downloadCredentials:invocation[0]"; +"downloadIssuerConfig": "done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]"; +"downloadIssuersList": "done.invoke.issuersMachine.displayIssuers:invocation[0]"; +"generateKeyPair": "done.invoke.issuersMachine.generateKeyPair:invocation[0]"; +"invokeAuthorization": "done.invoke.issuersMachine.performAuthorization:invocation[0]"; +"verifyCredential": "done.invoke.issuersMachine.verifyingCredential:invocation[0]"; + }; + missingImplementations: { + actions: never; + delays: never; + guards: never; + services: never; + }; + eventsCausingActions: { + "getKeyPairFromStore": "done.invoke.issuersMachine.performAuthorization:invocation[0]"; +"loadKeyPair": "done.invoke.issuersMachine.performAuthorization:invocation[0]"; +"logDownloaded": "done.invoke.issuersMachine.verifyingCredential:invocation[0]"; +"resetError": "RESET_ERROR" | "TRY_AGAIN" | "error.platform.issuersMachine.performAuthorization:invocation[0]"; +"setCredentialWrapper": "done.invoke.issuersMachine.downloadCredentials:invocation[0]"; +"setError": "error.platform.issuersMachine.displayIssuers:invocation[0]" | "error.platform.issuersMachine.downloadCredentials:invocation[0]" | "error.platform.issuersMachine.downloadIssuerConfig:invocation[0]" | "error.platform.issuersMachine.performAuthorization:invocation[0]"; +"setIssuers": "done.invoke.issuersMachine.displayIssuers:invocation[0]"; +"setLoadingIssuer": "TRY_AGAIN"; +"setPrivateKey": "done.invoke.issuersMachine.generateKeyPair:invocation[0]"; +"setPublicKey": "done.invoke.issuersMachine.generateKeyPair:invocation[0]"; +"setSelectedIssuers": "done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]"; +"setTokenResponse": "done.invoke.issuersMachine.performAuthorization:invocation[0]"; +"setVerifiableCredential": "done.invoke.issuersMachine.downloadCredentials:invocation[0]"; +"storeKeyPair": "done.invoke.issuersMachine.generateKeyPair:invocation[0]"; +"storeVcMetaContext": "done.invoke.issuersMachine.verifyingCredential:invocation[0]"; +"storeVcsContext": "done.invoke.issuersMachine.verifyingCredential:invocation[0]"; +"storeVerifiableCredentialData": "done.invoke.issuersMachine.verifyingCredential:invocation[0]"; +"storeVerifiableCredentialMeta": "done.invoke.issuersMachine.verifyingCredential:invocation[0]"; +"unsetLoadingReason": "done.invoke.issuersMachine.displayIssuers:invocation[0]"; +"updateTmpSelectedIssuer": "SELECTED_ISSUER"; + }; + eventsCausingDelays: { + + }; + eventsCausingGuards: { + "hasKeyPair": "CHECK_KEY_PAIR"; +"isCustomSecureKeystore": "done.invoke.issuersMachine.generateKeyPair:invocation[0]"; +"isOIDCflowCancelled": "error.platform.issuersMachine.performAuthorization:invocation[0]"; +"shouldFetchIssuerAgain": "TRY_AGAIN"; + }; + eventsCausingServices: { + "downloadCredential": "CHECK_KEY_PAIR" | "done.invoke.issuersMachine.generateKeyPair:invocation[0]"; +"downloadIssuerConfig": "SELECTED_ISSUER"; +"downloadIssuersList": "TRY_AGAIN" | "xstate.init"; +"generateKeyPair": "CHECK_KEY_PAIR"; +"invokeAuthorization": "done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]"; +"verifyCredential": "done.invoke.issuersMachine.downloadCredentials:invocation[0]"; + }; + matchesStates: "checkKeyPair" | "displayIssuers" | "done" | "downloadCredentials" | "downloadIssuerConfig" | "error" | "generateKeyPair" | "idle" | "performAuthorization" | "selectingIssuer" | "storing" | "verifyingCredential"; + tags: never; + } + \ No newline at end of file diff --git a/machines/store.typegen.ts b/machines/store.typegen.ts index c689d514de..8657894994 100644 --- a/machines/store.typegen.ts +++ b/machines/store.typegen.ts @@ -1,77 +1,49 @@ -// This file was automatically generated. Edits will be overwritten -export interface Typegen0 { - '@@xstate/typegen': true; - 'internalEvents': { - 'done.invoke._store': { - type: 'done.invoke._store'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'done.invoke.store.resettingStorage:invocation[0]': { - type: 'done.invoke.store.resettingStorage:invocation[0]'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'error.platform._store': { type: 'error.platform._store'; data: unknown }; - 'xstate.init': { type: 'xstate.init' }; - }; - 'invokeSrcNameMap': { - checkStorageInitialisedOrNot: 'done.invoke.store.checkStorageInitialisation:invocation[0]'; - clear: 'done.invoke.store.resettingStorage:invocation[0]'; - generateEncryptionKey: 'done.invoke.store.generatingEncryptionKey:invocation[0]'; - getEncryptionKey: 'done.invoke.store.gettingEncryptionKey:invocation[0]'; - hasAndroidEncryptionKey: 'done.invoke.store.checkEncryptionKey:invocation[0]'; - store: 'done.invoke._store'; - }; - 'missingImplementations': { - actions: 'logKey'; - delays: never; - guards: never; - services: never; - }; - 'eventsCausingActions': { - forwardStoreRequest: - | 'APPEND' - | 'CLEAR' - | 'GET' - | 'PREPEND' - | 'REMOVE' - | 'REMOVE_ITEMS' - | 'REMOVE_VC_METADATA' - | 'SET' - | 'UPDATE'; - logKey: 'KEY_RECEIVED'; - notifyParent: - | 'KEY_RECEIVED' - | 'READY' - | 'done.invoke.store.resettingStorage:invocation[0]'; - resetIsTamperedVc: 'RESET_IS_TAMPERED'; - setEncryptionKey: 'KEY_RECEIVED'; - setIsTamperedVc: 'TAMPERED_VC'; - }; - 'eventsCausingDelays': {}; - 'eventsCausingGuards': { - isCustomSecureKeystore: 'KEY_RECEIVED'; - }; - 'eventsCausingServices': { - checkStorageInitialisedOrNot: 'ERROR'; - clear: 'KEY_RECEIVED'; - generateEncryptionKey: 'ERROR' | 'IGNORE' | 'READY'; - getEncryptionKey: 'TRY_AGAIN'; - hasAndroidEncryptionKey: never; - store: - | 'KEY_RECEIVED' - | 'READY' - | 'done.invoke.store.resettingStorage:invocation[0]'; - }; - 'matchesStates': - | 'checkEncryptionKey' - | 'checkStorageInitialisation' - | 'failedReadingKey' - | 'generatingEncryptionKey' - | 'gettingEncryptionKey' - | 'ready' - | 'resettingStorage'; - 'tags': never; -} + // This file was automatically generated. Edits will be overwritten + + export interface Typegen0 { + '@@xstate/typegen': true; + internalEvents: { + "done.invoke._store": { type: "done.invoke._store"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"done.invoke.store.resettingStorage:invocation[0]": { type: "done.invoke.store.resettingStorage:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"error.platform._store": { type: "error.platform._store"; data: unknown }; +"xstate.init": { type: "xstate.init" }; + }; + invokeSrcNameMap: { + "checkStorageInitialisedOrNot": "done.invoke.store.checkStorageInitialisation:invocation[0]"; +"clear": "done.invoke.store.resettingStorage:invocation[0]"; +"generateEncryptionKey": "done.invoke.store.generatingEncryptionKey:invocation[0]"; +"getEncryptionKey": "done.invoke.store.gettingEncryptionKey:invocation[0]"; +"hasAndroidEncryptionKey": "done.invoke.store.checkEncryptionKey:invocation[0]"; +"store": "done.invoke._store"; + }; + missingImplementations: { + actions: "logKey"; + delays: never; + guards: never; + services: never; + }; + eventsCausingActions: { + "forwardStoreRequest": "APPEND" | "CLEAR" | "GET" | "PREPEND" | "REMOVE" | "REMOVE_ITEMS" | "REMOVE_VC_METADATA" | "SET" | "UPDATE"; +"logKey": "KEY_RECEIVED"; +"notifyParent": "KEY_RECEIVED" | "READY" | "done.invoke.store.resettingStorage:invocation[0]"; +"setEncryptionKey": "KEY_RECEIVED"; + }; + eventsCausingDelays: { + + }; + eventsCausingGuards: { + "isCustomSecureKeystore": "KEY_RECEIVED"; + }; + eventsCausingServices: { + "checkStorageInitialisedOrNot": "ERROR"; +"clear": "KEY_RECEIVED"; +"generateEncryptionKey": "ERROR" | "IGNORE" | "READY"; +"getEncryptionKey": "TRY_AGAIN"; +"hasAndroidEncryptionKey": never; +"store": "KEY_RECEIVED" | "READY" | "done.invoke.store.resettingStorage:invocation[0]"; + }; + matchesStates: "checkEncryptionKey" | "checkStorageInitialisation" | "failedReadingKey" | "generatingEncryptionKey" | "gettingEncryptionKey" | "ready" | "resettingStorage"; + tags: never; + } + \ No newline at end of file diff --git a/shared/request.ts b/shared/request.ts index ef901b493c..ae002d749c 100644 --- a/shared/request.ts +++ b/shared/request.ts @@ -18,8 +18,8 @@ export async function request( method: HTTP_METHOD, path: `/${string}`, body?: Record, - timeout?: undefined | number, host = MIMOTO_BASE_URL, + timeout?: undefined | number, ) { const headers = { 'Content-Type': 'application/json', From 84715a3dd2524d5c3b70b4165f98076b0a468b43 Mon Sep 17 00:00:00 2001 From: Harsh Vardhan Date: Fri, 6 Oct 2023 12:23:37 +0530 Subject: [PATCH 04/20] refactor(INJI-205): Check Internet before OIDC AuthZ Co-authored-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> Signed-off-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> --- machines/activityLog.typegen.ts | 22 ++--- .../request/requestMachine.typegen.ts | 6 +- machines/issuersMachine.ts | 56 ++++++++++++- machines/issuersMachine.typegen.ts | 18 +++-- machines/settings.typegen.ts | 6 +- machines/store.typegen.ts | 80 ++++++++++++++++++- 6 files changed, 161 insertions(+), 27 deletions(-) diff --git a/machines/activityLog.typegen.ts b/machines/activityLog.typegen.ts index 686854d097..a21e978730 100644 --- a/machines/activityLog.typegen.ts +++ b/machines/activityLog.typegen.ts @@ -2,31 +2,31 @@ export interface Typegen0 { '@@xstate/typegen': true; - 'internalEvents': { - 'xstate.init': { type: 'xstate.init' }; + internalEvents: { + 'xstate.init': {type: 'xstate.init'}; }; - 'invokeSrcNameMap': {}; - 'missingImplementations': { + invokeSrcNameMap: {}; + missingImplementations: { actions: never; delays: never; guards: never; services: never; }; - 'eventsCausingActions': { + eventsCausingActions: { loadActivities: 'REFRESH' | 'xstate.init'; prependActivity: 'STORE_RESPONSE'; setActivities: 'STORE_RESPONSE'; storeActivity: 'LOG_ACTIVITY'; }; - 'eventsCausingDelays': {}; - 'eventsCausingGuards': {}; - 'eventsCausingServices': {}; - 'matchesStates': + eventsCausingDelays: {}; + eventsCausingGuards: {}; + eventsCausingServices: {}; + matchesStates: | 'init' | 'ready' | 'ready.idle' | 'ready.logging' | 'ready.refreshing' - | { ready?: 'idle' | 'logging' | 'refreshing' }; - 'tags': never; + | {ready?: 'idle' | 'logging' | 'refreshing'}; + tags: never; } diff --git a/machines/bleShare/request/requestMachine.typegen.ts b/machines/bleShare/request/requestMachine.typegen.ts index 3ed41328a8..4a8b103887 100644 --- a/machines/bleShare/request/requestMachine.typegen.ts +++ b/machines/bleShare/request/requestMachine.typegen.ts @@ -66,11 +66,11 @@ export interface Typegen0 { prependReceivedVc: 'VC_RESPONSE'; registerLoggers: | 'DISCONNECT' - | 'DISMISS' + | 'RESET' | 'xstate.after(DESTROY_TIMEOUT)#request.clearingConnection'; removeLoggers: | 'DISCONNECT' - | 'DISMISS' + | 'RESET' | 'SCREEN_BLUR' | 'xstate.after(DESTROY_TIMEOUT)#request.clearingConnection' | 'xstate.init'; @@ -105,7 +105,7 @@ export interface Typegen0 { eventsCausingServices: { advertiseDevice: | 'DISCONNECT' - | 'DISMISS' + | 'RESET' | 'xstate.after(DESTROY_TIMEOUT)#request.clearingConnection'; checkBluetoothService: 'NEARBY_ENABLED'; checkNearByDevicesPermission: diff --git a/machines/issuersMachine.ts b/machines/issuersMachine.ts index b8e75e817e..644e06125d 100644 --- a/machines/issuersMachine.ts +++ b/machines/issuersMachine.ts @@ -4,6 +4,7 @@ import {createModel} from 'xstate/lib/model'; import {MY_VCS_STORE_KEY} from '../shared/constants'; import {StoreEvents} from './store'; import {AppServices} from '../shared/GlobalContext'; +import NetInfo from '@react-native-community/netinfo'; import { generateKeys, isCustomSecureKeystore, @@ -66,7 +67,7 @@ export const Issuer_Tab_Ref_Id = 'issuersMachine'; export const Issuers_Key_Ref = 'OpenId4VCI'; export const IssuersMachine = model.createMachine( { - /** @xstate-layout N4IgpgJg5mDOIC5QEtawK5gE6wLIEMBjAC2QDswA6CVABwBt8BPASTUxwGIIB7Cy8gDceAayqoM2PEVL8asBszaScCIT0L4ALsj4BtAAwBdQ0cShaPWMh19zIAB6IATAHYAHAFZK7gGwBmd2cARgBOdwNgvwAaECZEV18DSmdfdw8ogBZQ-wN-TwBfAtiJDmkScip5RVZ2KU5sLB4sSkUtADNmgFsBOpwCCrk6RlqVWDUyYU1bMlNTe0trGfsnBDcvHwCgsIio31j4tf9fFINI4MTPfMzXT2cikr7y2SpG5s4AFQAlAE0AfQAggBxAEsABy8yQIEWNl0ZBWiEywX8rkomXyvlCOQ8Bn2cUQnnSKSRbixnkyvl8zn8DxApSkAxelDeWE+v0BIPBemCZihMOWUNWmQM6MoVIMflCd2CAX8B0QoVcwRSnkxrnRkUyd1CtPp-RklWZWCarK+AFEAMpmj5-M1fL4AeS+kIsVlhdkFiKSyRue1cEvSvlc8oQnlcqMS6OOziCaT8uqejMNLOcbP+wNBEOMCzdAtAq3JJxlioizk8oWCyMyIeCnjOaPcwQloQM-tcbl8CbGSf4Kc45qtNrtjud2b5ubhCNDFMoxZxZYrVZrrnylHCOOyEVCAWCXbKPaosDA9DAhB0ZCgyg4nAAIg6AOpggAyDoBN7+LBvLuhE49+cQ-jBJkmSUP4NxgU2-iBEGnghiuPpNr4haeGEZJ7gyBr8EeJ5nuQl59JwVpPmaADCHxmu+LAWhaACqdrfvyk6eggYFIqcwGZGW2pas4IY3MkzitukNzUli-g6sUdKJphVQ8AA7mQ9A8PgEBXtgJF8O0yBQNwfDiJMojiNJgyyQpSkqWpWAaWQWlQBMUzaHCcxjq6SxMf+LHAcqgkcVxzihDxIYoqikoomckFUhJjzdjJ1DyYpymqX01m2Q0xrNK0jAdN0vQxSZcVmYllkpdp9kaI5+jGAxv7wsxwqiuKkrSrKfG5GiEqtiu6rkjchSSXqzyGrQ2CdFgXQAugWjEM0yAAF4VWQun8OoYi5fusXDVgo3jZN01YHNC1ldMTlVS5P5uX+jgEjOc6luWlZgTW1yUIkjbpChvgXGW6H6vlm3bRNU0zfNMxpSamXaNta0YX9I3dIDe0HTMR0Lc5vKue6tUeYWs5qndi6PfiCCNrO6SpEkfh1k2mQ-YN-D-fDu3AwtYMZW0UMDQerRw2NCPM8j6jHZVJg8jmF1Y1d05FnjBgLg91ZEzKVIvWW-HerWbi01zJCniIADSYBMAACvgyCsiRAASpF638etmv8RugqO6PnZjU7BKkzgvaqzicb7qrCu4NZXP4oESpS+QBWkdxa7FOuEPrhsm2bnCW9btv238jssM6ovjuL7ue97VJ+1qviB09WqUHW4ZKhcSpR7H+UwBQWDaGABvG6brK8MtBmrZzsUt9g7ed8nWAozMaNi27zFhEqPhCRSqTZLioRPRclCtlSlwijsnb9cZTLD23Wgd0n3dLfpwgD0fhon6PF9m5PJ0iy7jGXas8-KhEHjL+XLZMQ1h2FvOsvVKSKjrDSQ+eUmS8EKipEiWBIBgDIDofA9BYBXwEP3IysDDTwISog5BEBUHoMwS-YW1UC7MXWN4PwgQQjhEiDERW2pZyCVlhKP+Xgm5wPiuZCASCUFoOQBgrBLIIbZTGtDX6-CEFCJIWQsRFDBao1Ou-GqU46GbEYTsFheJDiVlrGuVIKJjiBClJSPhBCBGJWEaQ0R4jU4AjBCRM0T5qGzw8johh2xmF7BDF4L2SR2yU0imBPq0V1r5UENgZA7QmB4QccojB2CVp4JiUyOJ+1EnJKUU4+glDZgaJnnmSWrFvIimAn5AKdwnpJDXGBMsSskLAVcDY-gOSElJIvCkwprMWjsxyoPWJ8S8l9IKeQ4p0987eIqV5diNTPDcXqWwzI7hq7lyRMcaOgkolSXwctCAJ5U4OlwEbYi5EvxnQ-hLIUfhkj+GcL7SktwzhQWDkGdqgQKRBCCHkdwnTxAnLAC4txHivHlKFOXL2dxjhbnaZ9WCisgKbMrHcAwoRqT7PcEC2kZAeCkPgFCUZLwynuUlgAWkMYgKl3gsSMqZcy6B0SYZwOGEoJ4FLP4uE4pssKCL-L7zlETJUXsogRD+S0pINMYFZOTOlLAPL7mImeSBICIp3BYm1eWYMRMwybPLHcIIFZnn3HleyxVJpnAqvdiuUCZY-DpA9h7QIy5qRb3EqkN6r05VsrkYabCp5zz4RUHa5iuQKzVwuFiIMlZIiE0OO4Nq6oAobK1OWMxwKCpEKSioEqUAI0eQRRGW4n1OLNLxfqw4JIXrATOBsps7YPY5oZrzJm+0QaUruVOTiwc-CgXbJ9FNFJhQHwDXTKg8dE5dzNsWyWipQ4oWjK9KkEcaxjq9divFKJGxQJzQ-M+Y9u4Lq-mGDVZxPrhhyJ9EUT1cRihWWcKU-pdgdMtYGuQdjiEiPISSjG0K+VlhetuJIHtSTAU3UEFI2qYyEnJBBKKhyFVdPGb0qA-TyFnoAlwsUYFEhlhCBuYOlY0QrICimoClIZQ5tgFoGaF4cMsTSGW1UQFqT8vSDWH11dX3UkxJ9NwFrJ1c2QKC5jNxEgvRRJBUsxYvmoi2HkXIHZy4ftE7FXuYBmNUxOP5WWjZK2KhrYgWsooDBQNyAw-yH6ihAA */ + /** @xstate-layout N4IgpgJg5mDOIC5QEtawK5gE6wLIEMBjAC2QDswA6CVABwBt8BPASTUxwGIIB7Cy8gDceAayqoM2PEVL8asBszaScCIT0L4ALsj4BtAAwBdQ0cShaPWMh19zIAB6IALAEYAnJWfuAzM4BsAKwAHN7BwQDsfgA0IEyIAEw+Ea6UBgkRwT7uEekGrhHOAL5FsRIc0iTkVPKKrOxSnNhYPFiUiloAZq0AtgINOARVcnSM9SqwamTCmrZkpqb2ltZz9k4Izgme3n5Boe7hUc6x8QgJ3gZpgT6BgRH+yYWBJWUDlbJUza2cACoASgBNAD6AEEAOIglgAOUWSBAyxsujIaxcWy8vgCITCkRicUSIQSlGyCQMETu7n84QKLxA5SkQw+lC+WF+gNBEOhelcZjhCNWcPWrgSJ0QQppdMGMmqTKwLRZ-2B4MhMISPIsVkRdgFooMvjS-jc9wezl1ARFZwiCUClFcN3czmcKWuPnFbwZ0uZnD+AFEAMren5A71-P4AeT+sPVKyRKIQrgMwX8lASCWCgVcgW8lt15oyEU8CSCloz6WcN38rom7v4sDA9DAhB0ZCgyg4nAAIqGAOpQgAyoZB7aBLHbkfhGv5oHWPgMBmclEigQM-lTVpyc9z+R8yfzriyPhTS4zlYq1aotfrjfILYGnH9ve9AGEft6hyxfb6AKrBsd8mPahBAmFPEEB8VwhS8XVkgKA5dXcE96SlOQeAAdzIegeHwCBW2wR8+E6ZAoG4PhxGmURxDdJCalQ9DMOwgY8LIAioCmGZtCRBZjCWCd-ynUVgNOMVSlpSjhmotCMKwnCsEY5imllVp2kYLpen6KsqOoGjJPolRZMI1iNHY-RjF-HitT4jYUwXZwgMpFMfHCGcIlze15zuFdghyA5UweBDJTEygSAbEQWDILRsAoLRiP4dQxEC4hgtC8KsEi0zo3MxxRVuQlLUCdxdUzbIhX8c14w8Iky1ucI1zTYI-PeaUgsIEKwoisAot4GKyLipqWuS1LuW49LkQA4I0SFdxwOXO1-HSUrbUuLZSX8XwMn8Vwy3qs94sS1qUva+S5SU7RuiwPpeqStqtDSzURos4IIMpB5i1moCHPNSbgi8QIDXcPLcltDIto0i69simU5QSVlFQ5GEuN5My7syuNkiTfJJvyDwiyCUrZ2tPwbimoDMhuYGAtobBTp6EF0C0YhWmQAAvIyyGi0jhDiiUGv4CmsCpmm6YZ5m5gM2YOJM+Go1u2NbJtFbJoyN7U3cc0V2tbxXH8FdHSPe0ycZXn+dp+msCZlnDsUjoqbU08NMN3oBZNs2RfUMXjJMSXx2GmXNbl9wFbJJJlfNB6bUiLYbiW-KIgifXpXts7HaF83mWOlSzptxDycph3jeTl2yLd+YTMGhHvYA64k01-2hUDg9PNK5J52CAwZ3TQpwNj4Sue23qAGkwCYAAFfBkBZR8AAknz7oE++9YEh8hCNPb-DLBTnKuPD+h15cKc0qptDaMcibxnm70TGX7weR7HzhJ+n2f56BReWAjUupcnZH4x8Tf-czAJ-Z7xAskS4YFiQeXOJ5F0591IBRgBQLA2gwAD2HqPFknV2bkUzv5Rk8DsBIJQTfLAosWacTVF7aWAECjZEoPlTy6Z1o5HOOaPwqRqoOQyGNTMKY478DwYg8KhC0FswEN1CisDcFgAQQQ6+aCSFzAWO-Chn9BRRE8HQv6msPCWmOCBFMhI0xBH8DHMkOQyS8PErRLCj4sCQCkTofA9BYAiNiuI22AVeASTojYuxYVkCOMmK7UhEtyGryRusGyER9SWgpIVCkYFAi5j3EmG4CZW4OSbsUGB7jGSeKsRAHxEB7H+KcRbNoVtVI9w0nk7ShTikBPkeLD2oTEaxkidErYQQyzxIzLmThlBKSrQzJsKkFjNJeOsbYopfiAl3xBFCR83pew3RUS4R0HTYndIeL0kCe4ogVSyB4ByMcNpjMENgZAnQmDXjqTM+gLixHYO5lQc5psrk3KmfU+gjT3YrN4l-eMnguF3HOAkDMDlEl6ITFXYxDosjnCONA14EjpSvMudc5styHH3NThUjOVSApoveZiz5dyfnF2aUNShFkppAqtCCzY4K0x9IMNafMDCDgPBJAeMZyAID1jvqGXAQ8HwvlHCvVpVC1ZeG5VsVMUQ9l9JNAM5wY0W6pnjJEXl-KwBzIWUsv5a9RTSs2K3OVOJFV6NtKkG4eVUytx+jymkZAeBFPgHCAlHwqWrIQAAWh-uaX1ZIw6WnuJVKIK0EhjNqGMaS7qP7-PWJaXMP0okmhTPmGOFJ4wVmyVnRkzJvWJsQC3IFOQNqJkKPmG4uZMiXF1JSTYhZ0i7DGReBsTYbwqCLUauMu4iRUh+pmIUG0km2gGQURMqNNibTzTg6UNS6LST0lAHt4TEDGJcoWWhI6xreACGSXNyKcmNQSs1S6+0tBrtjGGgZU6XqsqSMEc0ZJtwFRNAUHeGYz7Hvzae3a-V2oQ1aAka9VCwVROhS3PKfhlwFA+mNZMjxcgORskkI9IkUU8xzonPOpthb-LCW0gSoofB+C8GNFaLd4zLhjmMq+qCx5gYsoehcMcbi7g2imVW5H0yqrGjcPwlo6pzueZQfhMjGNYGY1-PwhISQFGeoJlILCwJeHWhmBVFahK-vnchCZBTSXYvjco4tCAch9LU7Va48ZHSUjORc4lUAsUlJk+sQZyYqrrgNFrZ9VrKR3uMR5TWZGf5tq0AzZsbnSO+0NNkNwbhHKQsEv7bcar8pgW8FsUI2r6zRZRhmNIMdVy5Dyuqyz84AhPXsqqlI0aSL5ZgjawdXSR26NOCmX2WxHS6k-Xxs+JQgA */ predictableActionArguments: true, preserveActionOrder: true, id: Issuer_Tab_Ref_Id, @@ -97,11 +98,15 @@ export const IssuersMachine = model.createMachine( on: { TRY_AGAIN: [ { - cond: 'shouldFetchIssuerAgain', + // come from displayIssuers + description: 'not fetched issuers config yet', + cond: 'shouldFetchIssuerConfigAgain', + // check if issuers' has 0 length actions: ['setLoadingIssuer', 'resetError'], target: 'displayIssuers', }, { + // check if selectedIssuers is empty object actions: 'resetError', target: 'checkKeyPair', }, @@ -131,7 +136,8 @@ export const IssuersMachine = model.createMachine( src: 'downloadIssuerConfig', onDone: { actions: 'setSelectedIssuers', - target: 'performAuthorization', + // TODO: move checkInternet before downloadIssuerConfig + target: 'checkInternet', }, onError: { actions: 'setError', @@ -139,6 +145,37 @@ export const IssuersMachine = model.createMachine( }, }, }, + checkInternet: { + description: 'checks internet before opening the web view', + invoke: { + src: 'checkInternet', + id: 'checkInternet', + onDone: [ + { + cond: 'isInternetConnected', + target: 'performAuthorization', + }, + { + actions: 'setNoInternet', + target: '#issuersMachine.checkInternet.error2', + }, + ], + onError: { + actions: () => console.log('checkInternet error caught'), + target: '.error2', + }, + }, + states: { + error2: { + entry: () => console.log('child error state entered'), + on: { + TRY_AGAIN: { + target: '#issuersMachine.checkInternet', + }, + }, + }, + }, + }, performAuthorization: { description: 'invokes the issuers authorization endpoint and gets the access token', @@ -267,6 +304,9 @@ export const IssuersMachine = model.createMachine( issuers: (_, event) => event.data, loadingReason: null, }), + setNoInternet: model.assign({ + errorMessage: 'noInternetConnection', + }), unsetLoadingReason: model.assign({ loadingReason: null, }), @@ -402,6 +442,7 @@ export const IssuersMachine = model.createMachine( downloadIssuersList: async () => { return await CACHED_API.fetchIssuers(); }, + checkInternet: async () => await NetInfo.fetch(), downloadIssuerConfig: async (context, _) => { return await CACHED_API.fetchIssuerConfig(context.tempSelectedIssuer); }, @@ -445,6 +486,9 @@ export const IssuersMachine = model.createMachine( hasKeyPair: context => { return context.publicKey != null; }, + isInternetConnected: (_, event) => !!event.data.isConnected, + returnTrue: () => true, + returnFalse: () => false, isOIDCflowCancelled: (_, event) => { // iOS & Android have different error strings for user cancelled flow const err = [ @@ -457,7 +501,11 @@ export const IssuersMachine = model.createMachine( err.some(e => event.data.toString().includes(e)) ); }, - shouldFetchIssuerAgain: context => context.selectedIssuer !== null, + // failed to download all issuer from mimoto + shouldFetchIssuersAgain: context => context.issuers.length === 0, + // failed to download the selected issuer config from mimoto + shouldFetchIssuerConfigAgain: context => + Object.keys(context.selectedIssuer).length === 0, invalidTokenSpecified: (_, event) => event.data.error !== OIDCErrors.INVALID_TOKEN_SPECIFIED, isCustomSecureKeystore: () => isCustomSecureKeystore(), diff --git a/machines/issuersMachine.typegen.ts b/machines/issuersMachine.typegen.ts index 416a7bb3fd..e57a2c7c22 100644 --- a/machines/issuersMachine.typegen.ts +++ b/machines/issuersMachine.typegen.ts @@ -4,12 +4,14 @@ export interface Typegen0 { '@@xstate/typegen': true; internalEvents: { - "done.invoke.issuersMachine.displayIssuers:invocation[0]": { type: "done.invoke.issuersMachine.displayIssuers:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; + "done.invoke.checkInternet": { type: "done.invoke.checkInternet"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"done.invoke.issuersMachine.displayIssuers:invocation[0]": { type: "done.invoke.issuersMachine.displayIssuers:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; "done.invoke.issuersMachine.downloadCredentials:invocation[0]": { type: "done.invoke.issuersMachine.downloadCredentials:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; "done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]": { type: "done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; "done.invoke.issuersMachine.generateKeyPair:invocation[0]": { type: "done.invoke.issuersMachine.generateKeyPair:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; "done.invoke.issuersMachine.performAuthorization:invocation[0]": { type: "done.invoke.issuersMachine.performAuthorization:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; "done.invoke.issuersMachine.verifyingCredential:invocation[0]": { type: "done.invoke.issuersMachine.verifyingCredential:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"error.platform.checkInternet": { type: "error.platform.checkInternet"; data: unknown }; "error.platform.issuersMachine.displayIssuers:invocation[0]": { type: "error.platform.issuersMachine.displayIssuers:invocation[0]"; data: unknown }; "error.platform.issuersMachine.downloadCredentials:invocation[0]": { type: "error.platform.issuersMachine.downloadCredentials:invocation[0]"; data: unknown }; "error.platform.issuersMachine.downloadIssuerConfig:invocation[0]": { type: "error.platform.issuersMachine.downloadIssuerConfig:invocation[0]"; data: unknown }; @@ -17,7 +19,8 @@ "xstate.init": { type: "xstate.init" }; }; invokeSrcNameMap: { - "downloadCredential": "done.invoke.issuersMachine.downloadCredentials:invocation[0]"; + "checkInternet": "done.invoke.checkInternet"; +"downloadCredential": "done.invoke.issuersMachine.downloadCredentials:invocation[0]"; "downloadIssuerConfig": "done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]"; "downloadIssuersList": "done.invoke.issuersMachine.displayIssuers:invocation[0]"; "generateKeyPair": "done.invoke.issuersMachine.generateKeyPair:invocation[0]"; @@ -39,6 +42,7 @@ "setError": "error.platform.issuersMachine.displayIssuers:invocation[0]" | "error.platform.issuersMachine.downloadCredentials:invocation[0]" | "error.platform.issuersMachine.downloadIssuerConfig:invocation[0]" | "error.platform.issuersMachine.performAuthorization:invocation[0]"; "setIssuers": "done.invoke.issuersMachine.displayIssuers:invocation[0]"; "setLoadingIssuer": "TRY_AGAIN"; +"setNoInternet": "done.invoke.checkInternet"; "setPrivateKey": "done.invoke.issuersMachine.generateKeyPair:invocation[0]"; "setPublicKey": "done.invoke.issuersMachine.generateKeyPair:invocation[0]"; "setSelectedIssuers": "done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]"; @@ -58,18 +62,20 @@ eventsCausingGuards: { "hasKeyPair": "CHECK_KEY_PAIR"; "isCustomSecureKeystore": "done.invoke.issuersMachine.generateKeyPair:invocation[0]"; +"isInternetConnected": "done.invoke.checkInternet"; "isOIDCflowCancelled": "error.platform.issuersMachine.performAuthorization:invocation[0]"; -"shouldFetchIssuerAgain": "TRY_AGAIN"; +"shouldFetchIssuerConfigAgain": "TRY_AGAIN"; }; eventsCausingServices: { - "downloadCredential": "CHECK_KEY_PAIR" | "done.invoke.issuersMachine.generateKeyPair:invocation[0]"; + "checkInternet": "done.invoke.checkInternet" | "done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]"; +"downloadCredential": "CHECK_KEY_PAIR" | "done.invoke.issuersMachine.generateKeyPair:invocation[0]"; "downloadIssuerConfig": "SELECTED_ISSUER"; "downloadIssuersList": "TRY_AGAIN" | "xstate.init"; "generateKeyPair": "CHECK_KEY_PAIR"; -"invokeAuthorization": "done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]"; +"invokeAuthorization": "done.invoke.checkInternet"; "verifyCredential": "done.invoke.issuersMachine.downloadCredentials:invocation[0]"; }; - matchesStates: "checkKeyPair" | "displayIssuers" | "done" | "downloadCredentials" | "downloadIssuerConfig" | "error" | "generateKeyPair" | "idle" | "performAuthorization" | "selectingIssuer" | "storing" | "verifyingCredential"; + matchesStates: "checkInternet" | "checkInternet.error2" | "checkKeyPair" | "displayIssuers" | "done" | "downloadCredentials" | "downloadIssuerConfig" | "error" | "generateKeyPair" | "idle" | "performAuthorization" | "selectingIssuer" | "storing" | "verifyingCredential" | { "checkInternet"?: "error2"; }; tags: never; } \ No newline at end of file diff --git a/machines/settings.typegen.ts b/machines/settings.typegen.ts index e616d17f17..31ee28ed65 100644 --- a/machines/settings.typegen.ts +++ b/machines/settings.typegen.ts @@ -32,12 +32,13 @@ export interface Typegen0 { | 'done.invoke.settings.resetInjiProps:invocation[0]' | 'error.platform.settings.resetInjiProps:invocation[0]'; requestStoredContext: 'xstate.init'; - resetCredentialRegistry: 'CANCEL' | 'UPDATE_CREDENTIAL_REGISTRY'; + resetCredentialRegistry: 'CANCEL' | 'UPDATE_MIMOTO_HOST'; setContext: 'STORE_RESPONSE'; storeContext: | 'ACCEPT_HARDWARE_SUPPORT_NOT_EXISTS' | 'STORE_RESPONSE' | 'TOGGLE_BIOMETRIC_UNLOCK' + | 'UPDATE_ESIGNET_HOST' | 'UPDATE_NAME' | 'UPDATE_VC_LABEL' | 'done.invoke.settings.resetInjiProps:invocation[0]'; @@ -46,6 +47,7 @@ export interface Typegen0 { updateCredentialRegistryResponse: 'error.platform.settings.resetInjiProps:invocation[0]'; updateCredentialRegistrySuccess: 'done.invoke.settings.resetInjiProps:invocation[0]'; updateDefaults: 'STORE_RESPONSE'; + updateEsignetHostUrl: 'UPDATE_ESIGNET_HOST'; updateName: 'UPDATE_NAME'; updatePartialDefaults: 'STORE_RESPONSE'; updateUserShownWithHardwareKeystoreNotExists: 'ACCEPT_HARDWARE_SUPPORT_NOT_EXISTS'; @@ -57,7 +59,7 @@ export interface Typegen0 { hasPartialData: 'STORE_RESPONSE'; }; eventsCausingServices: { - resetInjiProps: 'UPDATE_CREDENTIAL_REGISTRY'; + resetInjiProps: 'UPDATE_MIMOTO_HOST'; }; matchesStates: | 'idle' diff --git a/machines/store.typegen.ts b/machines/store.typegen.ts index 8657894994..804f958af5 100644 --- a/machines/store.typegen.ts +++ b/machines/store.typegen.ts @@ -1,4 +1,5 @@ +<<<<<<< HEAD // This file was automatically generated. Edits will be overwritten export interface Typegen0 { @@ -46,4 +47,81 @@ matchesStates: "checkEncryptionKey" | "checkStorageInitialisation" | "failedReadingKey" | "generatingEncryptionKey" | "gettingEncryptionKey" | "ready" | "resettingStorage"; tags: never; } - \ No newline at end of file + +======= +export interface Typegen0 { + '@@xstate/typegen': true; + internalEvents: { + 'done.invoke._store': { + type: 'done.invoke._store'; + data: unknown; + __tip: 'See the XState TS docs to learn how to strongly type this.'; + }; + 'done.invoke.store.resettingStorage:invocation[0]': { + type: 'done.invoke.store.resettingStorage:invocation[0]'; + data: unknown; + __tip: 'See the XState TS docs to learn how to strongly type this.'; + }; + 'error.platform._store': {type: 'error.platform._store'; data: unknown}; + 'xstate.init': {type: 'xstate.init'}; + }; + invokeSrcNameMap: { + checkStorageInitialisedOrNot: 'done.invoke.store.checkStorageInitialisation:invocation[0]'; + clear: 'done.invoke.store.resettingStorage:invocation[0]'; + generateEncryptionKey: 'done.invoke.store.generatingEncryptionKey:invocation[0]'; + getEncryptionKey: 'done.invoke.store.gettingEncryptionKey:invocation[0]'; + hasAndroidEncryptionKey: 'done.invoke.store.checkEncryptionKey:invocation[0]'; + store: 'done.invoke._store'; + }; + missingImplementations: { + actions: 'logKey'; + delays: never; + guards: never; + services: never; + }; + eventsCausingActions: { + forwardStoreRequest: + | 'APPEND' + | 'CLEAR' + | 'GET' + | 'PREPEND' + | 'REMOVE' + | 'REMOVE_ITEMS' + | 'REMOVE_VC_METADATA' + | 'SET' + | 'UPDATE'; + logKey: 'KEY_RECEIVED'; + notifyParent: + | 'KEY_RECEIVED' + | 'READY' + | 'done.invoke.store.resettingStorage:invocation[0]'; + resetIsTamperedVc: 'RESET_IS_TAMPERED'; + setEncryptionKey: 'KEY_RECEIVED'; + setIsTamperedVc: 'TAMPERED_VC'; + }; + eventsCausingDelays: {}; + eventsCausingGuards: { + isCustomSecureKeystore: 'KEY_RECEIVED'; + }; + eventsCausingServices: { + checkStorageInitialisedOrNot: 'ERROR'; + clear: 'KEY_RECEIVED'; + generateEncryptionKey: 'ERROR' | 'IGNORE' | 'READY'; + getEncryptionKey: 'TRY_AGAIN'; + hasAndroidEncryptionKey: never; + store: + | 'KEY_RECEIVED' + | 'READY' + | 'done.invoke.store.resettingStorage:invocation[0]'; + }; + matchesStates: + | 'checkEncryptionKey' + | 'checkStorageInitialisation' + | 'failedReadingKey' + | 'generatingEncryptionKey' + | 'gettingEncryptionKey' + | 'ready' + | 'resettingStorage'; + tags: never; +} +>>>>>>> 5b53b069 (refactor(INJI-205): Check Internet before OIDC AuthZ) From 39e51a56095be0f64d791d91729a2a02bf2dea2c Mon Sep 17 00:00:00 2001 From: Harsh Vardhan Date: Fri, 6 Oct 2023 18:35:43 +0530 Subject: [PATCH 05/20] refactor(INJI-205): remove redundant error state Co-authored-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> Signed-off-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> --- machines/issuersMachine.ts | 37 ++++++++---------------------- machines/issuersMachine.typegen.ts | 10 ++++---- 2 files changed, 14 insertions(+), 33 deletions(-) diff --git a/machines/issuersMachine.ts b/machines/issuersMachine.ts index 644e06125d..e8f19ae1cd 100644 --- a/machines/issuersMachine.ts +++ b/machines/issuersMachine.ts @@ -98,17 +98,15 @@ export const IssuersMachine = model.createMachine( on: { TRY_AGAIN: [ { - // come from displayIssuers description: 'not fetched issuers config yet', - cond: 'shouldFetchIssuerConfigAgain', - // check if issuers' has 0 length + cond: 'shouldFetchIssuersAgain', actions: ['setLoadingIssuer', 'resetError'], target: 'displayIssuers', }, { - // check if selectedIssuers is empty object - actions: 'resetError', - target: 'checkKeyPair', + description: 'not fetched issuers config yet', + actions: ['setLoadingIssuer', 'resetError'], + target: 'downloadIssuerConfig', }, ], RESET_ERROR: { @@ -156,23 +154,13 @@ export const IssuersMachine = model.createMachine( target: 'performAuthorization', }, { - actions: 'setNoInternet', - target: '#issuersMachine.checkInternet.error2', + actions: ['setNoInternet', 'unsetLoadingReason'], + target: 'error', }, ], onError: { actions: () => console.log('checkInternet error caught'), - target: '.error2', - }, - }, - states: { - error2: { - entry: () => console.log('child error state entered'), - on: { - TRY_AGAIN: { - target: '#issuersMachine.checkInternet', - }, - }, + target: 'error', }, }, }, @@ -188,7 +176,7 @@ export const IssuersMachine = model.createMachine( onError: [ { cond: 'isOIDCflowCancelled', - actions: 'resetError', + actions: ['resetError', 'unsetLoadingReason'], target: 'selectingIssuer', }, { @@ -464,8 +452,7 @@ export const IssuersMachine = model.createMachine( return credential; }, invokeAuthorization: async context => { - const response = await authorize(context.selectedIssuer); - return response; + return await authorize(context.selectedIssuer); }, generateKeyPair: async context => { if (!isCustomSecureKeystore()) { @@ -487,8 +474,6 @@ export const IssuersMachine = model.createMachine( return context.publicKey != null; }, isInternetConnected: (_, event) => !!event.data.isConnected, - returnTrue: () => true, - returnFalse: () => false, isOIDCflowCancelled: (_, event) => { // iOS & Android have different error strings for user cancelled flow const err = [ @@ -501,11 +486,7 @@ export const IssuersMachine = model.createMachine( err.some(e => event.data.toString().includes(e)) ); }, - // failed to download all issuer from mimoto shouldFetchIssuersAgain: context => context.issuers.length === 0, - // failed to download the selected issuer config from mimoto - shouldFetchIssuerConfigAgain: context => - Object.keys(context.selectedIssuer).length === 0, invalidTokenSpecified: (_, event) => event.data.error !== OIDCErrors.INVALID_TOKEN_SPECIFIED, isCustomSecureKeystore: () => isCustomSecureKeystore(), diff --git a/machines/issuersMachine.typegen.ts b/machines/issuersMachine.typegen.ts index e57a2c7c22..8ef6eb4992 100644 --- a/machines/issuersMachine.typegen.ts +++ b/machines/issuersMachine.typegen.ts @@ -53,7 +53,7 @@ "storeVcsContext": "done.invoke.issuersMachine.verifyingCredential:invocation[0]"; "storeVerifiableCredentialData": "done.invoke.issuersMachine.verifyingCredential:invocation[0]"; "storeVerifiableCredentialMeta": "done.invoke.issuersMachine.verifyingCredential:invocation[0]"; -"unsetLoadingReason": "done.invoke.issuersMachine.displayIssuers:invocation[0]"; +"unsetLoadingReason": "done.invoke.checkInternet" | "done.invoke.issuersMachine.displayIssuers:invocation[0]" | "error.platform.issuersMachine.performAuthorization:invocation[0]"; "updateTmpSelectedIssuer": "SELECTED_ISSUER"; }; eventsCausingDelays: { @@ -64,18 +64,18 @@ "isCustomSecureKeystore": "done.invoke.issuersMachine.generateKeyPair:invocation[0]"; "isInternetConnected": "done.invoke.checkInternet"; "isOIDCflowCancelled": "error.platform.issuersMachine.performAuthorization:invocation[0]"; -"shouldFetchIssuerConfigAgain": "TRY_AGAIN"; +"shouldFetchIssuersAgain": "TRY_AGAIN"; }; eventsCausingServices: { - "checkInternet": "done.invoke.checkInternet" | "done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]"; + "checkInternet": "done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]"; "downloadCredential": "CHECK_KEY_PAIR" | "done.invoke.issuersMachine.generateKeyPair:invocation[0]"; -"downloadIssuerConfig": "SELECTED_ISSUER"; +"downloadIssuerConfig": "SELECTED_ISSUER" | "TRY_AGAIN"; "downloadIssuersList": "TRY_AGAIN" | "xstate.init"; "generateKeyPair": "CHECK_KEY_PAIR"; "invokeAuthorization": "done.invoke.checkInternet"; "verifyCredential": "done.invoke.issuersMachine.downloadCredentials:invocation[0]"; }; - matchesStates: "checkInternet" | "checkInternet.error2" | "checkKeyPair" | "displayIssuers" | "done" | "downloadCredentials" | "downloadIssuerConfig" | "error" | "generateKeyPair" | "idle" | "performAuthorization" | "selectingIssuer" | "storing" | "verifyingCredential" | { "checkInternet"?: "error2"; }; + matchesStates: "checkInternet" | "checkKeyPair" | "displayIssuers" | "done" | "downloadCredentials" | "downloadIssuerConfig" | "error" | "generateKeyPair" | "idle" | "performAuthorization" | "selectingIssuer" | "storing" | "verifyingCredential"; tags: never; } \ No newline at end of file From 017009f4dca30fdfafd8b0bee66d5dbe81b71f4e Mon Sep 17 00:00:00 2001 From: Harsh Vardhan Date: Mon, 9 Oct 2023 11:49:12 +0530 Subject: [PATCH 06/20] feat(INJI-205): use AbortController's signal timeout this feature was added in [RN 0.60](https://github.com/react-native-community/releases/blob/master/CHANGELOG.md#v0600) Signed-off-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> --- shared/request.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/shared/request.ts b/shared/request.ts index ae002d749c..cdf1acebb0 100644 --- a/shared/request.ts +++ b/shared/request.ts @@ -3,7 +3,7 @@ import { VerifiableCredential, } from '../types/VC/ExistingMosipVC/vc'; import {__AppId} from './GlobalVariables'; -import {HOST, MIMOTO_BASE_URL} from './constants'; +import {MIMOTO_BASE_URL} from './constants'; export type HTTP_METHOD = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE'; @@ -34,11 +34,16 @@ export async function request( body: JSON.stringify(body), }); } else { - response = Promise.race([ - fetch(host + path, {method, headers, body: JSON.stringify(body)}), - (_: any, reject: (arg0: Error) => void) => - setTimeout(() => reject(new Error('request timeout')), timeout * 1000), - ]); + let controller = new AbortController(); + setTimeout(() => { + controller.abort(); + }, timeout * 1000); + response = await fetch(host + path, { + method, + headers, + body: JSON.stringify(body), + signal: controller.signal, + }); } const jsonResponse = await response.json(); From fcf4204d93a4f2c7f0f867cc6a971b43d64cb2f8 Mon Sep 17 00:00:00 2001 From: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> Date: Mon, 9 Oct 2023 11:57:27 +0530 Subject: [PATCH 07/20] refactor(INJI-205): rename variable and remove redundant comments Signed-off-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> --- machines/issuersMachine.ts | 14 +- machines/issuersMachine.typegen.ts | 224 ++++++++++++++++++----------- 2 files changed, 150 insertions(+), 88 deletions(-) diff --git a/machines/issuersMachine.ts b/machines/issuersMachine.ts index e8f19ae1cd..1d5a08e667 100644 --- a/machines/issuersMachine.ts +++ b/machines/issuersMachine.ts @@ -35,7 +35,7 @@ enum OIDCErrors { const model = createModel( { issuers: [] as issuerType[], - tempSelectedIssuer: '' as string, + selectedIssuerId: '' as string, selectedIssuer: {} as issuerType, tokenResponse: {} as AuthorizeResult, errorMessage: '' as string, @@ -122,8 +122,7 @@ export const IssuersMachine = model.createMachine( actions: sendParent('DOWNLOAD_ID'), }, SELECTED_ISSUER: { - // set the issuer obj from the issuerStore - actions: 'updateTmpSelectedIssuer', + actions: 'updateSelectedIssuerId', target: 'downloadIssuerConfig', }, }, @@ -134,7 +133,6 @@ export const IssuersMachine = model.createMachine( src: 'downloadIssuerConfig', onDone: { actions: 'setSelectedIssuers', - // TODO: move checkInternet before downloadIssuerConfig target: 'checkInternet', }, onError: { @@ -300,7 +298,7 @@ export const IssuersMachine = model.createMachine( }), setError: model.assign({ errorMessage: (_, event) => { - console.log('Error while fetching issuers ', event.data.message); + console.log('Error occured ', event.data.message); return event.data.message === 'Network request failed' ? 'noInternetConnection' : 'generic'; @@ -380,8 +378,8 @@ export const IssuersMachine = model.createMachine( setSelectedIssuers: model.assign({ selectedIssuer: (_, event) => event.data, }), - updateTmpSelectedIssuer: model.assign({ - tempSelectedIssuer: (_, event) => event.id, + updateSelectedIssuerId: model.assign({ + selectedIssuerId: (_, event) => event.id, }), setTokenResponse: model.assign({ tokenResponse: (_, event) => event.data, @@ -432,7 +430,7 @@ export const IssuersMachine = model.createMachine( }, checkInternet: async () => await NetInfo.fetch(), downloadIssuerConfig: async (context, _) => { - return await CACHED_API.fetchIssuerConfig(context.tempSelectedIssuer); + return await CACHED_API.fetchIssuerConfig(context.selectedIssuerId); }, downloadCredential: async context => { const body = await getBody(context); diff --git a/machines/issuersMachine.typegen.ts b/machines/issuersMachine.typegen.ts index 8ef6eb4992..9243b16463 100644 --- a/machines/issuersMachine.typegen.ts +++ b/machines/issuersMachine.typegen.ts @@ -1,81 +1,145 @@ +// This file was automatically generated. Edits will be overwritten - // This file was automatically generated. Edits will be overwritten - - export interface Typegen0 { - '@@xstate/typegen': true; - internalEvents: { - "done.invoke.checkInternet": { type: "done.invoke.checkInternet"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; -"done.invoke.issuersMachine.displayIssuers:invocation[0]": { type: "done.invoke.issuersMachine.displayIssuers:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; -"done.invoke.issuersMachine.downloadCredentials:invocation[0]": { type: "done.invoke.issuersMachine.downloadCredentials:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; -"done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]": { type: "done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; -"done.invoke.issuersMachine.generateKeyPair:invocation[0]": { type: "done.invoke.issuersMachine.generateKeyPair:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; -"done.invoke.issuersMachine.performAuthorization:invocation[0]": { type: "done.invoke.issuersMachine.performAuthorization:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; -"done.invoke.issuersMachine.verifyingCredential:invocation[0]": { type: "done.invoke.issuersMachine.verifyingCredential:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; -"error.platform.checkInternet": { type: "error.platform.checkInternet"; data: unknown }; -"error.platform.issuersMachine.displayIssuers:invocation[0]": { type: "error.platform.issuersMachine.displayIssuers:invocation[0]"; data: unknown }; -"error.platform.issuersMachine.downloadCredentials:invocation[0]": { type: "error.platform.issuersMachine.downloadCredentials:invocation[0]"; data: unknown }; -"error.platform.issuersMachine.downloadIssuerConfig:invocation[0]": { type: "error.platform.issuersMachine.downloadIssuerConfig:invocation[0]"; data: unknown }; -"error.platform.issuersMachine.performAuthorization:invocation[0]": { type: "error.platform.issuersMachine.performAuthorization:invocation[0]"; data: unknown }; -"xstate.init": { type: "xstate.init" }; - }; - invokeSrcNameMap: { - "checkInternet": "done.invoke.checkInternet"; -"downloadCredential": "done.invoke.issuersMachine.downloadCredentials:invocation[0]"; -"downloadIssuerConfig": "done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]"; -"downloadIssuersList": "done.invoke.issuersMachine.displayIssuers:invocation[0]"; -"generateKeyPair": "done.invoke.issuersMachine.generateKeyPair:invocation[0]"; -"invokeAuthorization": "done.invoke.issuersMachine.performAuthorization:invocation[0]"; -"verifyCredential": "done.invoke.issuersMachine.verifyingCredential:invocation[0]"; - }; - missingImplementations: { - actions: never; - delays: never; - guards: never; - services: never; - }; - eventsCausingActions: { - "getKeyPairFromStore": "done.invoke.issuersMachine.performAuthorization:invocation[0]"; -"loadKeyPair": "done.invoke.issuersMachine.performAuthorization:invocation[0]"; -"logDownloaded": "done.invoke.issuersMachine.verifyingCredential:invocation[0]"; -"resetError": "RESET_ERROR" | "TRY_AGAIN" | "error.platform.issuersMachine.performAuthorization:invocation[0]"; -"setCredentialWrapper": "done.invoke.issuersMachine.downloadCredentials:invocation[0]"; -"setError": "error.platform.issuersMachine.displayIssuers:invocation[0]" | "error.platform.issuersMachine.downloadCredentials:invocation[0]" | "error.platform.issuersMachine.downloadIssuerConfig:invocation[0]" | "error.platform.issuersMachine.performAuthorization:invocation[0]"; -"setIssuers": "done.invoke.issuersMachine.displayIssuers:invocation[0]"; -"setLoadingIssuer": "TRY_AGAIN"; -"setNoInternet": "done.invoke.checkInternet"; -"setPrivateKey": "done.invoke.issuersMachine.generateKeyPair:invocation[0]"; -"setPublicKey": "done.invoke.issuersMachine.generateKeyPair:invocation[0]"; -"setSelectedIssuers": "done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]"; -"setTokenResponse": "done.invoke.issuersMachine.performAuthorization:invocation[0]"; -"setVerifiableCredential": "done.invoke.issuersMachine.downloadCredentials:invocation[0]"; -"storeKeyPair": "done.invoke.issuersMachine.generateKeyPair:invocation[0]"; -"storeVcMetaContext": "done.invoke.issuersMachine.verifyingCredential:invocation[0]"; -"storeVcsContext": "done.invoke.issuersMachine.verifyingCredential:invocation[0]"; -"storeVerifiableCredentialData": "done.invoke.issuersMachine.verifyingCredential:invocation[0]"; -"storeVerifiableCredentialMeta": "done.invoke.issuersMachine.verifyingCredential:invocation[0]"; -"unsetLoadingReason": "done.invoke.checkInternet" | "done.invoke.issuersMachine.displayIssuers:invocation[0]" | "error.platform.issuersMachine.performAuthorization:invocation[0]"; -"updateTmpSelectedIssuer": "SELECTED_ISSUER"; - }; - eventsCausingDelays: { - - }; - eventsCausingGuards: { - "hasKeyPair": "CHECK_KEY_PAIR"; -"isCustomSecureKeystore": "done.invoke.issuersMachine.generateKeyPair:invocation[0]"; -"isInternetConnected": "done.invoke.checkInternet"; -"isOIDCflowCancelled": "error.platform.issuersMachine.performAuthorization:invocation[0]"; -"shouldFetchIssuersAgain": "TRY_AGAIN"; - }; - eventsCausingServices: { - "checkInternet": "done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]"; -"downloadCredential": "CHECK_KEY_PAIR" | "done.invoke.issuersMachine.generateKeyPair:invocation[0]"; -"downloadIssuerConfig": "SELECTED_ISSUER" | "TRY_AGAIN"; -"downloadIssuersList": "TRY_AGAIN" | "xstate.init"; -"generateKeyPair": "CHECK_KEY_PAIR"; -"invokeAuthorization": "done.invoke.checkInternet"; -"verifyCredential": "done.invoke.issuersMachine.downloadCredentials:invocation[0]"; - }; - matchesStates: "checkInternet" | "checkKeyPair" | "displayIssuers" | "done" | "downloadCredentials" | "downloadIssuerConfig" | "error" | "generateKeyPair" | "idle" | "performAuthorization" | "selectingIssuer" | "storing" | "verifyingCredential"; - tags: never; - } - \ No newline at end of file +export interface Typegen0 { + '@@xstate/typegen': true; + internalEvents: { + 'done.invoke.checkInternet': { + type: 'done.invoke.checkInternet'; + data: unknown; + __tip: 'See the XState TS docs to learn how to strongly type this.'; + }; + 'done.invoke.issuersMachine.displayIssuers:invocation[0]': { + type: 'done.invoke.issuersMachine.displayIssuers:invocation[0]'; + data: unknown; + __tip: 'See the XState TS docs to learn how to strongly type this.'; + }; + 'done.invoke.issuersMachine.downloadCredentials:invocation[0]': { + type: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]'; + data: unknown; + __tip: 'See the XState TS docs to learn how to strongly type this.'; + }; + 'done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]': { + type: 'done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]'; + data: unknown; + __tip: 'See the XState TS docs to learn how to strongly type this.'; + }; + 'done.invoke.issuersMachine.generateKeyPair:invocation[0]': { + type: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; + data: unknown; + __tip: 'See the XState TS docs to learn how to strongly type this.'; + }; + 'done.invoke.issuersMachine.performAuthorization:invocation[0]': { + type: 'done.invoke.issuersMachine.performAuthorization:invocation[0]'; + data: unknown; + __tip: 'See the XState TS docs to learn how to strongly type this.'; + }; + 'done.invoke.issuersMachine.verifyingCredential:invocation[0]': { + type: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'; + data: unknown; + __tip: 'See the XState TS docs to learn how to strongly type this.'; + }; + 'error.platform.checkInternet': { + type: 'error.platform.checkInternet'; + data: unknown; + }; + 'error.platform.issuersMachine.displayIssuers:invocation[0]': { + type: 'error.platform.issuersMachine.displayIssuers:invocation[0]'; + data: unknown; + }; + 'error.platform.issuersMachine.downloadCredentials:invocation[0]': { + type: 'error.platform.issuersMachine.downloadCredentials:invocation[0]'; + data: unknown; + }; + 'error.platform.issuersMachine.downloadIssuerConfig:invocation[0]': { + type: 'error.platform.issuersMachine.downloadIssuerConfig:invocation[0]'; + data: unknown; + }; + 'error.platform.issuersMachine.performAuthorization:invocation[0]': { + type: 'error.platform.issuersMachine.performAuthorization:invocation[0]'; + data: unknown; + }; + 'xstate.init': {type: 'xstate.init'}; + }; + invokeSrcNameMap: { + checkInternet: 'done.invoke.checkInternet'; + downloadCredential: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]'; + downloadIssuerConfig: 'done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]'; + downloadIssuersList: 'done.invoke.issuersMachine.displayIssuers:invocation[0]'; + generateKeyPair: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; + invokeAuthorization: 'done.invoke.issuersMachine.performAuthorization:invocation[0]'; + verifyCredential: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'; + }; + missingImplementations: { + actions: never; + delays: never; + guards: never; + services: never; + }; + eventsCausingActions: { + getKeyPairFromStore: 'done.invoke.issuersMachine.performAuthorization:invocation[0]'; + loadKeyPair: 'done.invoke.issuersMachine.performAuthorization:invocation[0]'; + logDownloaded: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'; + resetError: + | 'RESET_ERROR' + | 'TRY_AGAIN' + | 'error.platform.issuersMachine.performAuthorization:invocation[0]'; + setCredentialWrapper: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]'; + setError: + | 'error.platform.issuersMachine.displayIssuers:invocation[0]' + | 'error.platform.issuersMachine.downloadCredentials:invocation[0]' + | 'error.platform.issuersMachine.downloadIssuerConfig:invocation[0]' + | 'error.platform.issuersMachine.performAuthorization:invocation[0]'; + setIssuers: 'done.invoke.issuersMachine.displayIssuers:invocation[0]'; + setLoadingIssuer: 'TRY_AGAIN'; + setNoInternet: 'done.invoke.checkInternet'; + setPrivateKey: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; + setPublicKey: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; + setSelectedIssuers: 'done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]'; + setTokenResponse: 'done.invoke.issuersMachine.performAuthorization:invocation[0]'; + setVerifiableCredential: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]'; + storeKeyPair: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; + storeVcMetaContext: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'; + storeVcsContext: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'; + storeVerifiableCredentialData: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'; + storeVerifiableCredentialMeta: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'; + unsetLoadingReason: + | 'done.invoke.checkInternet' + | 'done.invoke.issuersMachine.displayIssuers:invocation[0]' + | 'error.platform.issuersMachine.performAuthorization:invocation[0]'; + updateSelectedIssuerId: 'SELECTED_ISSUER'; + }; + eventsCausingDelays: {}; + eventsCausingGuards: { + hasKeyPair: 'CHECK_KEY_PAIR'; + isCustomSecureKeystore: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; + isInternetConnected: 'done.invoke.checkInternet'; + isOIDCflowCancelled: 'error.platform.issuersMachine.performAuthorization:invocation[0]'; + shouldFetchIssuersAgain: 'TRY_AGAIN'; + }; + eventsCausingServices: { + checkInternet: 'done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]'; + downloadCredential: + | 'CHECK_KEY_PAIR' + | 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; + downloadIssuerConfig: 'SELECTED_ISSUER' | 'TRY_AGAIN'; + downloadIssuersList: 'TRY_AGAIN' | 'xstate.init'; + generateKeyPair: 'CHECK_KEY_PAIR'; + invokeAuthorization: 'done.invoke.checkInternet'; + verifyCredential: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]'; + }; + matchesStates: + | 'checkInternet' + | 'checkKeyPair' + | 'displayIssuers' + | 'done' + | 'downloadCredentials' + | 'downloadIssuerConfig' + | 'error' + | 'generateKeyPair' + | 'idle' + | 'performAuthorization' + | 'selectingIssuer' + | 'storing' + | 'verifyingCredential'; + tags: never; +} From de7dfedea8c267ab26bd5d606e774a1779b94ca5 Mon Sep 17 00:00:00 2001 From: Harsh Vardhan Date: Mon, 9 Oct 2023 12:40:32 +0530 Subject: [PATCH 08/20] feat(INJI-205): handle invalid OIDC configs error Co-authored-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> Signed-off-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> --- machines/issuersMachine.ts | 30 ++++++++++++++++++++++++++++-- machines/issuersMachine.typegen.ts | 3 +++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/machines/issuersMachine.ts b/machines/issuersMachine.ts index 1d5a08e667..7c86e5681d 100644 --- a/machines/issuersMachine.ts +++ b/machines/issuersMachine.ts @@ -30,6 +30,7 @@ enum OIDCErrors { OIDC_FLOW_CANCELLED_IOS = 'org.openid.appauth.general error -3', INVALID_TOKEN_SPECIFIED = 'Invalid token specified', + OIDC_CONFIG_ERROR_PREFIX = 'Config error', } const model = createModel( @@ -39,6 +40,7 @@ const model = createModel( selectedIssuer: {} as issuerType, tokenResponse: {} as AuthorizeResult, errorMessage: '' as string, + rawError: '' as string, loadingReason: 'displayIssuers' as string, verifiableCredential: null as VerifiableCredential | null, credentialWrapper: {} as CredentialWrapper, @@ -103,6 +105,11 @@ export const IssuersMachine = model.createMachine( actions: ['setLoadingIssuer', 'resetError'], target: 'displayIssuers', }, + { + cond: 'isRawErrorOIDCConfigError', + actions: 'resetError', + target: 'selectingIssuer', + }, { description: 'not fetched issuers config yet', actions: ['setLoadingIssuer', 'resetError'], @@ -177,6 +184,11 @@ export const IssuersMachine = model.createMachine( actions: ['resetError', 'unsetLoadingReason'], target: 'selectingIssuer', }, + { + cond: 'isOIDCConfigError', + actions: ['setError', 'setOIDCConfigRawError'], + target: 'error', + }, { actions: [ 'setError', @@ -305,8 +317,15 @@ export const IssuersMachine = model.createMachine( }, loadingReason: null, }), + setOIDCConfigRawError: model.assign({ + rawError: (_, event) => + typeof event.data.toString === 'function' + ? event.data.toString() + : '', + }), resetError: model.assign({ errorMessage: '', + rawError: '', }), loadKeyPair: assign({ @@ -484,9 +503,16 @@ export const IssuersMachine = model.createMachine( err.some(e => event.data.toString().includes(e)) ); }, + isOIDCConfigError: (_, event) => { + return ( + !!event.data && + typeof event.data.toString === 'function' && + event.data.toString().includes(OIDCErrors.OIDC_CONFIG_ERROR_PREFIX) + ); + }, + isRawErrorOIDCConfigError: (context, _) => + context.rawError.includes(OIDCErrors.OIDC_CONFIG_ERROR_PREFIX), shouldFetchIssuersAgain: context => context.issuers.length === 0, - invalidTokenSpecified: (_, event) => - event.data.error !== OIDCErrors.INVALID_TOKEN_SPECIFIED, isCustomSecureKeystore: () => isCustomSecureKeystore(), }, }, diff --git a/machines/issuersMachine.typegen.ts b/machines/issuersMachine.typegen.ts index 9243b16463..2a5c575151 100644 --- a/machines/issuersMachine.typegen.ts +++ b/machines/issuersMachine.typegen.ts @@ -92,6 +92,7 @@ export interface Typegen0 { setIssuers: 'done.invoke.issuersMachine.displayIssuers:invocation[0]'; setLoadingIssuer: 'TRY_AGAIN'; setNoInternet: 'done.invoke.checkInternet'; + setOIDCConfigRawError: 'error.platform.issuersMachine.performAuthorization:invocation[0]'; setPrivateKey: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; setPublicKey: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; setSelectedIssuers: 'done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]'; @@ -113,7 +114,9 @@ export interface Typegen0 { hasKeyPair: 'CHECK_KEY_PAIR'; isCustomSecureKeystore: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; isInternetConnected: 'done.invoke.checkInternet'; + isOIDCConfigError: 'error.platform.issuersMachine.performAuthorization:invocation[0]'; isOIDCflowCancelled: 'error.platform.issuersMachine.performAuthorization:invocation[0]'; + isRawErrorOIDCConfigError: 'TRY_AGAIN'; shouldFetchIssuersAgain: 'TRY_AGAIN'; }; eventsCausingServices: { From 8e16ca02c169d06faa5a0d941bf1f24fcd09f7eb Mon Sep 17 00:00:00 2001 From: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> Date: Mon, 9 Oct 2023 17:19:55 +0530 Subject: [PATCH 09/20] feat(INJI-205): handle timeout error for vc download via issuer the timeout is kept as 30 seconds Co-authored-by: Harsh Vardhan Signed-off-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> --- machines/issuersMachine.ts | 49 ++++++++++++++++++++++-------- machines/issuersMachine.typegen.ts | 3 ++ shared/request.ts | 31 +++++++++++++------ 3 files changed, 61 insertions(+), 22 deletions(-) diff --git a/machines/issuersMachine.ts b/machines/issuersMachine.ts index 7c86e5681d..0e1d6a7050 100644 --- a/machines/issuersMachine.ts +++ b/machines/issuersMachine.ts @@ -21,8 +21,9 @@ import { VerifiableCredential, } from '../types/VC/EsignetMosipVC/vc'; import {CACHED_API} from '../shared/api'; +import {request} from '../shared/request'; -const TIMEOUT_SEC = 10; +const VC_DOWNLOAD_TIMEOUT = 30; // OIDCErrors is a collection of external errors from the OpenID library or the issuer enum OIDCErrors { @@ -33,6 +34,8 @@ enum OIDCErrors { OIDC_CONFIG_ERROR_PREFIX = 'Config error', } +const REQUEST_TIMEDOUT = 'request timedout'; + const model = createModel( { issuers: [] as issuerType[], @@ -110,6 +113,11 @@ export const IssuersMachine = model.createMachine( actions: 'resetError', target: 'selectingIssuer', }, + { + cond: 'isRawErrorTimeoutError', + actions: ['resetError'], + target: 'selectingIssuer', + }, { description: 'not fetched issuers config yet', actions: ['setLoadingIssuer', 'resetError'], @@ -240,10 +248,17 @@ export const IssuersMachine = model.createMachine( actions: ['setVerifiableCredential', 'setCredentialWrapper'], target: 'verifyingCredential', }, - onError: { - actions: 'setError', - target: 'error', - }, + onError: [ + { + cond: 'isVCdownloadTimeout', + actions: ['setOIDCRawError', 'setError'], + target: 'error', + }, + { + actions: 'setError', + target: 'error', + }, + ], }, on: { CANCEL: { @@ -323,6 +338,12 @@ export const IssuersMachine = model.createMachine( ? event.data.toString() : '', }), + setOIDCRawError: model.assign({ + rawError: (_, event) => event.data.message, + }), + setRawError: model.assign({ + rawError: (_, event) => event.data, + }), resetError: model.assign({ errorMessage: '', rawError: '', @@ -453,16 +474,16 @@ export const IssuersMachine = model.createMachine( }, downloadCredential: async context => { const body = await getBody(context); - const response = await fetch( + const response = await request( + 'POST', context.selectedIssuer.serviceConfiguration.credentialEndpoint, + body, + '', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Authorization: 'Bearer ' + context.tokenResponse?.accessToken, - }, - body: JSON.stringify(body), + 'Content-Type': 'application/json', + Authorization: 'Bearer ' + context.tokenResponse?.accessToken, }, + VC_DOWNLOAD_TIMEOUT, ); let credential = await response.json(); credential = updateCredentialInformation(context, credential); @@ -510,8 +531,12 @@ export const IssuersMachine = model.createMachine( event.data.toString().includes(OIDCErrors.OIDC_CONFIG_ERROR_PREFIX) ); }, + isVCdownloadTimeout: (_, event) => + event.data.message === 'request timedout', isRawErrorOIDCConfigError: (context, _) => context.rawError.includes(OIDCErrors.OIDC_CONFIG_ERROR_PREFIX), + isRawErrorTimeoutError: (context, _) => + context.rawError.includes(REQUEST_TIMEDOUT), shouldFetchIssuersAgain: context => context.issuers.length === 0, isCustomSecureKeystore: () => isCustomSecureKeystore(), }, diff --git a/machines/issuersMachine.typegen.ts b/machines/issuersMachine.typegen.ts index 2a5c575151..15575669fa 100644 --- a/machines/issuersMachine.typegen.ts +++ b/machines/issuersMachine.typegen.ts @@ -93,6 +93,7 @@ export interface Typegen0 { setLoadingIssuer: 'TRY_AGAIN'; setNoInternet: 'done.invoke.checkInternet'; setOIDCConfigRawError: 'error.platform.issuersMachine.performAuthorization:invocation[0]'; + setOIDCRawError: 'error.platform.issuersMachine.downloadCredentials:invocation[0]'; setPrivateKey: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; setPublicKey: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; setSelectedIssuers: 'done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]'; @@ -117,6 +118,8 @@ export interface Typegen0 { isOIDCConfigError: 'error.platform.issuersMachine.performAuthorization:invocation[0]'; isOIDCflowCancelled: 'error.platform.issuersMachine.performAuthorization:invocation[0]'; isRawErrorOIDCConfigError: 'TRY_AGAIN'; + isRawErrorTimeoutError: 'TRY_AGAIN'; + isVCdownloadTimeout: 'error.platform.issuersMachine.downloadCredentials:invocation[0]'; shouldFetchIssuersAgain: 'TRY_AGAIN'; }; eventsCausingServices: { diff --git a/shared/request.ts b/shared/request.ts index cdf1acebb0..99e965d6ef 100644 --- a/shared/request.ts +++ b/shared/request.ts @@ -19,11 +19,11 @@ export async function request( path: `/${string}`, body?: Record, host = MIMOTO_BASE_URL, + headers: Record = { + 'Content-Type': 'application/json', + }, timeout?: undefined | number, ) { - const headers = { - 'Content-Type': 'application/json', - }; if (path.includes('residentmobileapp')) headers['X-AppId'] = __AppId.getValue(); let response; @@ -31,19 +31,30 @@ export async function request( response = await fetch(host + path, { method, headers, - body: JSON.stringify(body), + body: body ? JSON.stringify(body) : undefined, }); } else { + console.log(`making a web request to ${host + path}`); let controller = new AbortController(); setTimeout(() => { controller.abort(); }, timeout * 1000); - response = await fetch(host + path, { - method, - headers, - body: JSON.stringify(body), - signal: controller.signal, - }); + try { + response = await fetch(host + path, { + method, + headers, + body: body ? JSON.stringify(body) : undefined, + signal: controller.signal, + }); + } catch (error) { + console.log( + `Error occurred while making request: ${host + path}: ${error}`, + ); + if (error.name === 'AbortError') { + throw new Error('request timedout'); + } + throw error; + } } const jsonResponse = await response.json(); From 198ac72f2087b8174dd9c8c9865a23bfe271f4d4 Mon Sep 17 00:00:00 2001 From: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> Date: Mon, 9 Oct 2023 18:30:51 +0530 Subject: [PATCH 10/20] refactor(INJI-205): remove redundant storing of error message and type Co-authored-by: Harsh Vardhan Signed-off-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> --- machines/issuersMachine.ts | 57 ++++++++++------------ machines/issuersMachine.typegen.ts | 6 +-- screens/Issuers/IssuerScreenController.tsx | 4 +- screens/Issuers/IssuersScreen.tsx | 20 +++++--- 4 files changed, 42 insertions(+), 45 deletions(-) diff --git a/machines/issuersMachine.ts b/machines/issuersMachine.ts index 0e1d6a7050..ffd7d4b8c4 100644 --- a/machines/issuersMachine.ts +++ b/machines/issuersMachine.ts @@ -34,7 +34,7 @@ enum OIDCErrors { OIDC_CONFIG_ERROR_PREFIX = 'Config error', } -const REQUEST_TIMEDOUT = 'request timedout'; +const REQUEST_TIMEDOUT = 'requestTimedOut'; const model = createModel( { @@ -43,7 +43,6 @@ const model = createModel( selectedIssuer: {} as issuerType, tokenResponse: {} as AuthorizeResult, errorMessage: '' as string, - rawError: '' as string, loadingReason: 'displayIssuers' as string, verifiableCredential: null as VerifiableCredential | null, credentialWrapper: {} as CredentialWrapper, @@ -109,15 +108,10 @@ export const IssuersMachine = model.createMachine( target: 'displayIssuers', }, { - cond: 'isRawErrorOIDCConfigError', + cond: 'canSelectIssuerAgain', actions: 'resetError', target: 'selectingIssuer', }, - { - cond: 'isRawErrorTimeoutError', - actions: ['resetError'], - target: 'selectingIssuer', - }, { description: 'not fetched issuers config yet', actions: ['setLoadingIssuer', 'resetError'], @@ -194,7 +188,7 @@ export const IssuersMachine = model.createMachine( }, { cond: 'isOIDCConfigError', - actions: ['setError', 'setOIDCConfigRawError'], + actions: ['setOIDCConfigError'], target: 'error', }, { @@ -251,7 +245,7 @@ export const IssuersMachine = model.createMachine( onError: [ { cond: 'isVCdownloadTimeout', - actions: ['setOIDCRawError', 'setError'], + actions: ['setError'], target: 'error', }, { @@ -326,27 +320,23 @@ export const IssuersMachine = model.createMachine( setError: model.assign({ errorMessage: (_, event) => { console.log('Error occured ', event.data.message); - return event.data.message === 'Network request failed' - ? 'noInternetConnection' - : 'generic'; + const error = event.data.message; + switch (error) { + case 'Network request failed': + return 'noInternetConnection'; + case 'request timedout': + return REQUEST_TIMEDOUT; + default: + return 'generic'; + } }, loadingReason: null, }), - setOIDCConfigRawError: model.assign({ - rawError: (_, event) => - typeof event.data.toString === 'function' - ? event.data.toString() - : '', - }), - setOIDCRawError: model.assign({ - rawError: (_, event) => event.data.message, - }), - setRawError: model.assign({ - rawError: (_, event) => event.data, + setOIDCConfigError: model.assign({ + errorMessage: (_, event) => event.data.toString(), }), resetError: model.assign({ errorMessage: '', - rawError: '', }), loadKeyPair: assign({ @@ -533,10 +523,12 @@ export const IssuersMachine = model.createMachine( }, isVCdownloadTimeout: (_, event) => event.data.message === 'request timedout', - isRawErrorOIDCConfigError: (context, _) => - context.rawError.includes(OIDCErrors.OIDC_CONFIG_ERROR_PREFIX), - isRawErrorTimeoutError: (context, _) => - context.rawError.includes(REQUEST_TIMEDOUT), + canSelectIssuerAgain: (context, _) => { + return ( + context.errorMessage.includes(OIDCErrors.OIDC_CONFIG_ERROR_PREFIX) || + context.errorMessage.includes(REQUEST_TIMEDOUT) + ); + }, shouldFetchIssuersAgain: context => context.issuers.length === 0, isCustomSecureKeystore: () => isCustomSecureKeystore(), }, @@ -549,8 +541,11 @@ export function selectIssuers(state: State) { return state.context.issuers; } -export function selectErrorMessage(state: State) { - return state.context.errorMessage; +export function selectErrorMessageType(state: State) { + return state.context.errorMessage === '' || + state.context.errorMessage === 'noInternetConnection' + ? state.context.errorMessage + : 'generic'; } export function selectLoadingReason(state: State) { diff --git a/machines/issuersMachine.typegen.ts b/machines/issuersMachine.typegen.ts index 15575669fa..1c7a4bc459 100644 --- a/machines/issuersMachine.typegen.ts +++ b/machines/issuersMachine.typegen.ts @@ -92,8 +92,7 @@ export interface Typegen0 { setIssuers: 'done.invoke.issuersMachine.displayIssuers:invocation[0]'; setLoadingIssuer: 'TRY_AGAIN'; setNoInternet: 'done.invoke.checkInternet'; - setOIDCConfigRawError: 'error.platform.issuersMachine.performAuthorization:invocation[0]'; - setOIDCRawError: 'error.platform.issuersMachine.downloadCredentials:invocation[0]'; + setOIDCConfigError: 'error.platform.issuersMachine.performAuthorization:invocation[0]'; setPrivateKey: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; setPublicKey: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; setSelectedIssuers: 'done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]'; @@ -112,13 +111,12 @@ export interface Typegen0 { }; eventsCausingDelays: {}; eventsCausingGuards: { + canSelectIssuerAgain: 'TRY_AGAIN'; hasKeyPair: 'CHECK_KEY_PAIR'; isCustomSecureKeystore: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; isInternetConnected: 'done.invoke.checkInternet'; isOIDCConfigError: 'error.platform.issuersMachine.performAuthorization:invocation[0]'; isOIDCflowCancelled: 'error.platform.issuersMachine.performAuthorization:invocation[0]'; - isRawErrorOIDCConfigError: 'TRY_AGAIN'; - isRawErrorTimeoutError: 'TRY_AGAIN'; isVCdownloadTimeout: 'error.platform.issuersMachine.downloadCredentials:invocation[0]'; shouldFetchIssuersAgain: 'TRY_AGAIN'; }; diff --git a/screens/Issuers/IssuerScreenController.tsx b/screens/Issuers/IssuerScreenController.tsx index 63f10d4ec9..a22129f4af 100644 --- a/screens/Issuers/IssuerScreenController.tsx +++ b/screens/Issuers/IssuerScreenController.tsx @@ -2,7 +2,7 @@ import {useSelector} from '@xstate/react'; import { IssuerScreenTabEvents, IssuersMachine, - selectErrorMessage, + selectErrorMessageType, selectIsDone, selectIsDownloadCredentials, selectIsIdle, @@ -18,7 +18,7 @@ export function useIssuerScreenController({route, navigation}) { return { issuers: useSelector(service, selectIssuers), - errorMessage: useSelector(service, selectErrorMessage), + errorMessageType: useSelector(service, selectErrorMessageType), isDownloadingCredentials: useSelector(service, selectIsDownloadCredentials), isDone: useSelector(service, selectIsDone), isIdle: useSelector(service, selectIsIdle), diff --git a/screens/Issuers/IssuersScreen.tsx b/screens/Issuers/IssuersScreen.tsx index 3e969cb250..be530174a7 100644 --- a/screens/Issuers/IssuersScreen.tsx +++ b/screens/Issuers/IssuersScreen.tsx @@ -19,7 +19,7 @@ export const IssuersScreen: React.FC< const {t} = useTranslation('IssuersScreen'); useLayoutEffect(() => { - if (controller.loadingReason || controller.errorMessage) { + if (controller.loadingReason || controller.errorMessageType) { props.navigation.setOptions({ headerShown: false, }); @@ -39,7 +39,11 @@ export const IssuersScreen: React.FC< if (controller.isStoring) { props.navigation.goBack(); } - }, [controller.loadingReason, controller.errorMessage, controller.isStoring]); + }, [ + controller.loadingReason, + controller.errorMessageType, + controller.isStoring, + ]); const onPressHandler = (id: string) => { if (id !== 'UIN, VID, AID') { @@ -50,7 +54,7 @@ export const IssuersScreen: React.FC< }; const isGenericError = () => { - return controller.errorMessage === 'generic'; + return controller.errorMessageType === 'generic'; }; const goBack = () => { @@ -125,12 +129,12 @@ export const IssuersScreen: React.FC< )} - {controller.errorMessage && ( + {controller.errorMessageType && ( Date: Mon, 9 Oct 2023 19:04:24 +0530 Subject: [PATCH 11/20] refactor(INJI-205): move loadingReason update to diff action Co-authored-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> Signed-off-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> --- machines/issuersMachine.ts | 42 +++++++++++++++++------------- machines/issuersMachine.typegen.ts | 6 ++++- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/machines/issuersMachine.ts b/machines/issuersMachine.ts index ffd7d4b8c4..7116eb0875 100644 --- a/machines/issuersMachine.ts +++ b/machines/issuersMachine.ts @@ -92,7 +92,7 @@ export const IssuersMachine = model.createMachine( target: 'selectingIssuer', }, onError: { - actions: ['setError'], + actions: ['setError', 'unsetLoadingReason'], target: 'error', }, }, @@ -145,7 +145,7 @@ export const IssuersMachine = model.createMachine( target: 'checkInternet', }, onError: { - actions: 'setError', + actions: ['setError', 'unsetLoadingReason'], target: 'error', }, }, @@ -177,7 +177,12 @@ export const IssuersMachine = model.createMachine( invoke: { src: 'invokeAuthorization', onDone: { - actions: ['setTokenResponse', 'getKeyPairFromStore', 'loadKeyPair'], + actions: [ + 'setTokenResponse', + 'setTokenLoadingReason', + 'getKeyPairFromStore', + 'loadKeyPair', + ], target: 'checkKeyPair', }, onError: [ @@ -194,6 +199,7 @@ export const IssuersMachine = model.createMachine( { actions: [ 'setError', + 'unsetLoadingReason', (_, event) => console.log('error in invokeAuth - ', event.data), ], target: 'error', @@ -223,11 +229,16 @@ export const IssuersMachine = model.createMachine( src: 'generateKeyPair', onDone: [ { - actions: ['setPublicKey', 'setPrivateKey', 'storeKeyPair'], + actions: [ + 'setPublicKey', + 'setDownloadingCreds', + 'setPrivateKey', + 'storeKeyPair', + ], target: 'downloadCredentials', }, { - actions: ['setPublicKey', 'storeKeyPair'], + actions: ['setPublicKey', 'setDownloadingCreds', 'storeKeyPair'], cond: 'isCustomSecureKeystore', target: 'downloadCredentials', }, @@ -244,12 +255,7 @@ export const IssuersMachine = model.createMachine( }, onError: [ { - cond: 'isVCdownloadTimeout', - actions: ['setError'], - target: 'error', - }, - { - actions: 'setError', + actions: ['setError', 'unsetLoadingReason'], target: 'error', }, ], @@ -309,11 +315,16 @@ export const IssuersMachine = model.createMachine( actions: { setIssuers: model.assign({ issuers: (_, event) => event.data, - loadingReason: null, }), setNoInternet: model.assign({ errorMessage: 'noInternetConnection', }), + setDownloadingCreds: model.assign({ + loadingReason: 'downloadingCredentials', + }), + setTokenLoadingReason: model.assign({ + loadingReason: 'settingUp', + }), unsetLoadingReason: model.assign({ loadingReason: null, }), @@ -330,7 +341,6 @@ export const IssuersMachine = model.createMachine( return 'generic'; } }, - loadingReason: null, }), setOIDCConfigError: model.assign({ errorMessage: (_, event) => event.data.toString(), @@ -413,7 +423,6 @@ export const IssuersMachine = model.createMachine( }), setTokenResponse: model.assign({ tokenResponse: (_, event) => event.data, - loadingReason: 'settingUp', }), setVerifiableCredential: model.assign({ verifiableCredential: (_, event) => { @@ -432,11 +441,10 @@ export const IssuersMachine = model.createMachine( } return event.data as string; }, - loadingReason: 'downloadingCredentials', }), setPrivateKey: assign({ - privateKey: (context, event) => (event.data as KeyPair).private, + privateKey: (_, event) => (event.data as KeyPair).private, }), logDownloaded: send( @@ -521,8 +529,6 @@ export const IssuersMachine = model.createMachine( event.data.toString().includes(OIDCErrors.OIDC_CONFIG_ERROR_PREFIX) ); }, - isVCdownloadTimeout: (_, event) => - event.data.message === 'request timedout', canSelectIssuerAgain: (context, _) => { return ( context.errorMessage.includes(OIDCErrors.OIDC_CONFIG_ERROR_PREFIX) || diff --git a/machines/issuersMachine.typegen.ts b/machines/issuersMachine.typegen.ts index 1c7a4bc459..4df2823500 100644 --- a/machines/issuersMachine.typegen.ts +++ b/machines/issuersMachine.typegen.ts @@ -84,6 +84,7 @@ export interface Typegen0 { | 'TRY_AGAIN' | 'error.platform.issuersMachine.performAuthorization:invocation[0]'; setCredentialWrapper: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]'; + setDownloadingCreds: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; setError: | 'error.platform.issuersMachine.displayIssuers:invocation[0]' | 'error.platform.issuersMachine.downloadCredentials:invocation[0]' @@ -96,6 +97,7 @@ export interface Typegen0 { setPrivateKey: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; setPublicKey: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; setSelectedIssuers: 'done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]'; + setTokenLoadingReason: 'done.invoke.issuersMachine.performAuthorization:invocation[0]'; setTokenResponse: 'done.invoke.issuersMachine.performAuthorization:invocation[0]'; setVerifiableCredential: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]'; storeKeyPair: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; @@ -106,6 +108,9 @@ export interface Typegen0 { unsetLoadingReason: | 'done.invoke.checkInternet' | 'done.invoke.issuersMachine.displayIssuers:invocation[0]' + | 'error.platform.issuersMachine.displayIssuers:invocation[0]' + | 'error.platform.issuersMachine.downloadCredentials:invocation[0]' + | 'error.platform.issuersMachine.downloadIssuerConfig:invocation[0]' | 'error.platform.issuersMachine.performAuthorization:invocation[0]'; updateSelectedIssuerId: 'SELECTED_ISSUER'; }; @@ -117,7 +122,6 @@ export interface Typegen0 { isInternetConnected: 'done.invoke.checkInternet'; isOIDCConfigError: 'error.platform.issuersMachine.performAuthorization:invocation[0]'; isOIDCflowCancelled: 'error.platform.issuersMachine.performAuthorization:invocation[0]'; - isVCdownloadTimeout: 'error.platform.issuersMachine.downloadCredentials:invocation[0]'; shouldFetchIssuersAgain: 'TRY_AGAIN'; }; eventsCausingServices: { From bcd500f9a4c59a30dc915397f72df1f2b756a40c Mon Sep 17 00:00:00 2001 From: Harsh Vardhan Date: Tue, 10 Oct 2023 13:20:33 +0530 Subject: [PATCH 12/20] refactor(INJI-205): rename state actions & extract consts Co-authored-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> Signed-off-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> --- machines/issuersMachine.ts | 55 ++++++++++++++---------------- machines/issuersMachine.typegen.ts | 16 ++++----- shared/openId4VCI/Utils.ts | 17 +++++++++ 3 files changed, 50 insertions(+), 38 deletions(-) diff --git a/machines/issuersMachine.ts b/machines/issuersMachine.ts index 7116eb0875..becb9397f4 100644 --- a/machines/issuersMachine.ts +++ b/machines/issuersMachine.ts @@ -14,7 +14,15 @@ import {KeyPair} from 'react-native-rsa-native'; import {ActivityLogEvents} from './activityLog'; import {log} from 'xstate/lib/actions'; import {verifyCredential} from '../shared/vcjs/verifyCredential'; -import {getBody, getIdentifier} from '../shared/openId4VCI/Utils'; +import { + getBody, + getIdentifier, + ErrorMessage, + NETWORK_REQUEST_FAILED, + REQUEST_TIMEOUT, + VC_DOWNLOAD_TIMEOUT, + OIDCErrors, +} from '../shared/openId4VCI/Utils'; import {VCMetadata} from '../shared/VCMetadata'; import { CredentialWrapper, @@ -23,19 +31,6 @@ import { import {CACHED_API} from '../shared/api'; import {request} from '../shared/request'; -const VC_DOWNLOAD_TIMEOUT = 30; - -// OIDCErrors is a collection of external errors from the OpenID library or the issuer -enum OIDCErrors { - OIDC_FLOW_CANCELLED_ANDROID = 'User cancelled flow', - OIDC_FLOW_CANCELLED_IOS = 'org.openid.appauth.general error -3', - - INVALID_TOKEN_SPECIFIED = 'Invalid token specified', - OIDC_CONFIG_ERROR_PREFIX = 'Config error', -} - -const REQUEST_TIMEDOUT = 'requestTimedOut'; - const model = createModel( { issuers: [] as issuerType[], @@ -88,11 +83,11 @@ export const IssuersMachine = model.createMachine( invoke: { src: 'downloadIssuersList', onDone: { - actions: ['setIssuers', 'unsetLoadingReason'], + actions: ['setIssuers', 'resetLoadingReason'], target: 'selectingIssuer', }, onError: { - actions: ['setError', 'unsetLoadingReason'], + actions: ['setError', 'resetLoadingReason'], target: 'error', }, }, @@ -131,7 +126,7 @@ export const IssuersMachine = model.createMachine( actions: sendParent('DOWNLOAD_ID'), }, SELECTED_ISSUER: { - actions: 'updateSelectedIssuerId', + actions: 'setSelectedIssuerId', target: 'downloadIssuerConfig', }, }, @@ -145,7 +140,7 @@ export const IssuersMachine = model.createMachine( target: 'checkInternet', }, onError: { - actions: ['setError', 'unsetLoadingReason'], + actions: ['setError', 'resetLoadingReason'], target: 'error', }, }, @@ -161,7 +156,7 @@ export const IssuersMachine = model.createMachine( target: 'performAuthorization', }, { - actions: ['setNoInternet', 'unsetLoadingReason'], + actions: ['setNoInternet', 'resetLoadingReason'], target: 'error', }, ], @@ -188,7 +183,7 @@ export const IssuersMachine = model.createMachine( onError: [ { cond: 'isOIDCflowCancelled', - actions: ['resetError', 'unsetLoadingReason'], + actions: ['resetError', 'resetLoadingReason'], target: 'selectingIssuer', }, { @@ -199,7 +194,7 @@ export const IssuersMachine = model.createMachine( { actions: [ 'setError', - 'unsetLoadingReason', + 'resetLoadingReason', (_, event) => console.log('error in invokeAuth - ', event.data), ], target: 'error', @@ -255,7 +250,7 @@ export const IssuersMachine = model.createMachine( }, onError: [ { - actions: ['setError', 'unsetLoadingReason'], + actions: ['setError', 'resetLoadingReason'], target: 'error', }, ], @@ -317,7 +312,7 @@ export const IssuersMachine = model.createMachine( issuers: (_, event) => event.data, }), setNoInternet: model.assign({ - errorMessage: 'noInternetConnection', + errorMessage: ErrorMessage.NO_INTERNET, }), setDownloadingCreds: model.assign({ loadingReason: 'downloadingCredentials', @@ -325,7 +320,7 @@ export const IssuersMachine = model.createMachine( setTokenLoadingReason: model.assign({ loadingReason: 'settingUp', }), - unsetLoadingReason: model.assign({ + resetLoadingReason: model.assign({ loadingReason: null, }), setError: model.assign({ @@ -333,12 +328,12 @@ export const IssuersMachine = model.createMachine( console.log('Error occured ', event.data.message); const error = event.data.message; switch (error) { - case 'Network request failed': - return 'noInternetConnection'; - case 'request timedout': - return REQUEST_TIMEDOUT; + case NETWORK_REQUEST_FAILED: + return ErrorMessage.NO_INTERNET; + case REQUEST_TIMEOUT: + return ErrorMessage.REQUEST_TIMEDOUT; default: - return 'generic'; + return ErrorMessage.GENERIC; } }, }), @@ -418,7 +413,7 @@ export const IssuersMachine = model.createMachine( setSelectedIssuers: model.assign({ selectedIssuer: (_, event) => event.data, }), - updateSelectedIssuerId: model.assign({ + setSelectedIssuerId: model.assign({ selectedIssuerId: (_, event) => event.id, }), setTokenResponse: model.assign({ diff --git a/machines/issuersMachine.typegen.ts b/machines/issuersMachine.typegen.ts index 4df2823500..663cd44bc9 100644 --- a/machines/issuersMachine.typegen.ts +++ b/machines/issuersMachine.typegen.ts @@ -83,6 +83,13 @@ export interface Typegen0 { | 'RESET_ERROR' | 'TRY_AGAIN' | 'error.platform.issuersMachine.performAuthorization:invocation[0]'; + resetLoadingReason: + | 'done.invoke.checkInternet' + | 'done.invoke.issuersMachine.displayIssuers:invocation[0]' + | 'error.platform.issuersMachine.displayIssuers:invocation[0]' + | 'error.platform.issuersMachine.downloadCredentials:invocation[0]' + | 'error.platform.issuersMachine.downloadIssuerConfig:invocation[0]' + | 'error.platform.issuersMachine.performAuthorization:invocation[0]'; setCredentialWrapper: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]'; setDownloadingCreds: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; setError: @@ -96,6 +103,7 @@ export interface Typegen0 { setOIDCConfigError: 'error.platform.issuersMachine.performAuthorization:invocation[0]'; setPrivateKey: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; setPublicKey: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; + setSelectedIssuerId: 'SELECTED_ISSUER'; setSelectedIssuers: 'done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]'; setTokenLoadingReason: 'done.invoke.issuersMachine.performAuthorization:invocation[0]'; setTokenResponse: 'done.invoke.issuersMachine.performAuthorization:invocation[0]'; @@ -105,14 +113,6 @@ export interface Typegen0 { storeVcsContext: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'; storeVerifiableCredentialData: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'; storeVerifiableCredentialMeta: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'; - unsetLoadingReason: - | 'done.invoke.checkInternet' - | 'done.invoke.issuersMachine.displayIssuers:invocation[0]' - | 'error.platform.issuersMachine.displayIssuers:invocation[0]' - | 'error.platform.issuersMachine.downloadCredentials:invocation[0]' - | 'error.platform.issuersMachine.downloadIssuerConfig:invocation[0]' - | 'error.platform.issuersMachine.performAuthorization:invocation[0]'; - updateSelectedIssuerId: 'SELECTED_ISSUER'; }; eventsCausingDelays: {}; eventsCausingGuards: { diff --git a/shared/openId4VCI/Utils.ts b/shared/openId4VCI/Utils.ts index 5d9e290e96..5c750d7c92 100644 --- a/shared/openId4VCI/Utils.ts +++ b/shared/openId4VCI/Utils.ts @@ -92,3 +92,20 @@ export const getJWT = async context => { throw e; } }; +export const VC_DOWNLOAD_TIMEOUT = 30; +// OIDCErrors is a collection of external errors from the OpenID library or the issuer +export enum OIDCErrors { + OIDC_FLOW_CANCELLED_ANDROID = 'User cancelled flow', + OIDC_FLOW_CANCELLED_IOS = 'org.openid.appauth.general error -3', + + INVALID_TOKEN_SPECIFIED = 'Invalid token specified', + OIDC_CONFIG_ERROR_PREFIX = 'Config error', +} +// ErrorMessage is the type of error message shown in the UI +export enum ErrorMessage { + NO_INTERNET = 'noInternetConnection', + GENERIC = 'generic', + REQUEST_TIMEDOUT = 'requestTimedOut', +} +export const NETWORK_REQUEST_FAILED = 'Network request failed'; +export const REQUEST_TIMEOUT = 'request timedout'; From d9077ff88dcaf6c4e98787503156f4d2e2a6827c Mon Sep 17 00:00:00 2001 From: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> Date: Tue, 10 Oct 2023 15:06:41 +0530 Subject: [PATCH 13/20] fix(INJI-205): reference errormessages from util in issuersMachine Signed-off-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> --- machines/issuersMachine.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/machines/issuersMachine.ts b/machines/issuersMachine.ts index becb9397f4..215f1850f1 100644 --- a/machines/issuersMachine.ts +++ b/machines/issuersMachine.ts @@ -17,11 +17,11 @@ import {verifyCredential} from '../shared/vcjs/verifyCredential'; import { getBody, getIdentifier, - ErrorMessage, NETWORK_REQUEST_FAILED, REQUEST_TIMEOUT, VC_DOWNLOAD_TIMEOUT, OIDCErrors, + ErrorMessage, } from '../shared/openId4VCI/Utils'; import {VCMetadata} from '../shared/VCMetadata'; import { @@ -312,7 +312,7 @@ export const IssuersMachine = model.createMachine( issuers: (_, event) => event.data, }), setNoInternet: model.assign({ - errorMessage: ErrorMessage.NO_INTERNET, + errorMessage: () => ErrorMessage.NO_INTERNET, }), setDownloadingCreds: model.assign({ loadingReason: 'downloadingCredentials', @@ -527,7 +527,7 @@ export const IssuersMachine = model.createMachine( canSelectIssuerAgain: (context, _) => { return ( context.errorMessage.includes(OIDCErrors.OIDC_CONFIG_ERROR_PREFIX) || - context.errorMessage.includes(REQUEST_TIMEDOUT) + context.errorMessage.includes(ErrorMessage.REQUEST_TIMEDOUT) ); }, shouldFetchIssuersAgain: context => context.issuers.length === 0, From 6192c222928dda0011ba311663a3af2ea3b2c990 Mon Sep 17 00:00:00 2001 From: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> Date: Tue, 10 Oct 2023 16:19:29 +0530 Subject: [PATCH 14/20] refactor(INJI-205): move common error const to consts file Co-authored-by: Harsh Vardhan Signed-off-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> --- machines/issuersMachine.ts | 5 ++--- shared/constants.ts | 3 +++ shared/openId4VCI/Utils.ts | 2 -- shared/request.ts | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/machines/issuersMachine.ts b/machines/issuersMachine.ts index 215f1850f1..cddce5ad09 100644 --- a/machines/issuersMachine.ts +++ b/machines/issuersMachine.ts @@ -17,12 +17,11 @@ import {verifyCredential} from '../shared/vcjs/verifyCredential'; import { getBody, getIdentifier, - NETWORK_REQUEST_FAILED, - REQUEST_TIMEOUT, VC_DOWNLOAD_TIMEOUT, OIDCErrors, ErrorMessage, } from '../shared/openId4VCI/Utils'; +import {NETWORK_REQUEST_FAILED, REQUEST_TIMEOUT} from '../shared/constants'; import {VCMetadata} from '../shared/VCMetadata'; import { CredentialWrapper, @@ -430,7 +429,7 @@ export const IssuersMachine = model.createMachine( }, }), setPublicKey: assign({ - publicKey: (context, event) => { + publicKey: (_, event) => { if (!isCustomSecureKeystore()) { return (event.data as KeyPair).public; } diff --git a/shared/constants.ts b/shared/constants.ts index c194a6c77f..cce9377d04 100644 --- a/shared/constants.ts +++ b/shared/constants.ts @@ -68,3 +68,6 @@ export const argon2iConfigForUinVid: Argon2iConfig = { export const argon2iSalt = '1234567891011121314151617181920212223242526272829303132333435363'; + +export const NETWORK_REQUEST_FAILED = 'Network request failed'; +export const REQUEST_TIMEOUT = 'request timedout'; diff --git a/shared/openId4VCI/Utils.ts b/shared/openId4VCI/Utils.ts index 5c750d7c92..d47aa93b2d 100644 --- a/shared/openId4VCI/Utils.ts +++ b/shared/openId4VCI/Utils.ts @@ -107,5 +107,3 @@ export enum ErrorMessage { GENERIC = 'generic', REQUEST_TIMEDOUT = 'requestTimedOut', } -export const NETWORK_REQUEST_FAILED = 'Network request failed'; -export const REQUEST_TIMEOUT = 'request timedout'; diff --git a/shared/request.ts b/shared/request.ts index 99e965d6ef..a7c45092c5 100644 --- a/shared/request.ts +++ b/shared/request.ts @@ -3,7 +3,7 @@ import { VerifiableCredential, } from '../types/VC/ExistingMosipVC/vc'; import {__AppId} from './GlobalVariables'; -import {MIMOTO_BASE_URL} from './constants'; +import {MIMOTO_BASE_URL, REQUEST_TIMEOUT} from './constants'; export type HTTP_METHOD = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE'; @@ -51,7 +51,7 @@ export async function request( `Error occurred while making request: ${host + path}: ${error}`, ); if (error.name === 'AbortError') { - throw new Error('request timedout'); + throw new Error(REQUEST_TIMEOUT); } throw error; } From a81f27a145cae81cfd89997b404480d99490948e Mon Sep 17 00:00:00 2001 From: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> Date: Tue, 10 Oct 2023 16:27:42 +0530 Subject: [PATCH 15/20] refactor(INJI-205): rename action names Co-authored-by: Harsh Vardhan Signed-off-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> --- machines/issuersMachine.ts | 24 ++++++++++++++---------- machines/issuersMachine.typegen.ts | 6 +++--- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/machines/issuersMachine.ts b/machines/issuersMachine.ts index cddce5ad09..518b378b1c 100644 --- a/machines/issuersMachine.ts +++ b/machines/issuersMachine.ts @@ -98,7 +98,7 @@ export const IssuersMachine = model.createMachine( { description: 'not fetched issuers config yet', cond: 'shouldFetchIssuersAgain', - actions: ['setLoadingIssuer', 'resetError'], + actions: ['setLoadingReasonAsDisplayIssuers', 'resetError'], target: 'displayIssuers', }, { @@ -108,7 +108,7 @@ export const IssuersMachine = model.createMachine( }, { description: 'not fetched issuers config yet', - actions: ['setLoadingIssuer', 'resetError'], + actions: ['setLoadingReasonAsDisplayIssuers', 'resetError'], target: 'downloadIssuerConfig', }, ], @@ -173,7 +173,7 @@ export const IssuersMachine = model.createMachine( onDone: { actions: [ 'setTokenResponse', - 'setTokenLoadingReason', + 'setLoadingReasonAsSettingUp', 'getKeyPairFromStore', 'loadKeyPair', ], @@ -225,14 +225,18 @@ export const IssuersMachine = model.createMachine( { actions: [ 'setPublicKey', - 'setDownloadingCreds', + 'setLoadingReasonAsDownloadingCreds', 'setPrivateKey', 'storeKeyPair', ], target: 'downloadCredentials', }, { - actions: ['setPublicKey', 'setDownloadingCreds', 'storeKeyPair'], + actions: [ + 'setPublicKey', + 'setLoadingReasonAsDownloadingCreds', + 'storeKeyPair', + ], cond: 'isCustomSecureKeystore', target: 'downloadCredentials', }, @@ -313,10 +317,13 @@ export const IssuersMachine = model.createMachine( setNoInternet: model.assign({ errorMessage: () => ErrorMessage.NO_INTERNET, }), - setDownloadingCreds: model.assign({ + setLoadingReasonAsDisplayIssuers: model.assign({ + loadingReason: 'displayIssuers', + }), + setLoadingReasonAsDownloadingCreds: model.assign({ loadingReason: 'downloadingCredentials', }), - setTokenLoadingReason: model.assign({ + setLoadingReasonAsSettingUp: model.assign({ loadingReason: 'settingUp', }), resetLoadingReason: model.assign({ @@ -362,9 +369,6 @@ export const IssuersMachine = model.createMachine( to: context => context.serviceRefs.store, }, ), - setLoadingIssuer: model.assign({ - loadingReason: 'displayIssuers', - }), storeVerifiableCredentialMeta: send( context => StoreEvents.PREPEND(MY_VCS_STORE_KEY, getVCMetadata(context)), diff --git a/machines/issuersMachine.typegen.ts b/machines/issuersMachine.typegen.ts index 663cd44bc9..31a693231c 100644 --- a/machines/issuersMachine.typegen.ts +++ b/machines/issuersMachine.typegen.ts @@ -91,21 +91,21 @@ export interface Typegen0 { | 'error.platform.issuersMachine.downloadIssuerConfig:invocation[0]' | 'error.platform.issuersMachine.performAuthorization:invocation[0]'; setCredentialWrapper: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]'; - setDownloadingCreds: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; setError: | 'error.platform.issuersMachine.displayIssuers:invocation[0]' | 'error.platform.issuersMachine.downloadCredentials:invocation[0]' | 'error.platform.issuersMachine.downloadIssuerConfig:invocation[0]' | 'error.platform.issuersMachine.performAuthorization:invocation[0]'; setIssuers: 'done.invoke.issuersMachine.displayIssuers:invocation[0]'; - setLoadingIssuer: 'TRY_AGAIN'; + setLoadingReasonAsDisplayIssuers: 'TRY_AGAIN'; + setLoadingReasonAsDownloadingCreds: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; + setLoadingReasonAsSettingUp: 'done.invoke.issuersMachine.performAuthorization:invocation[0]'; setNoInternet: 'done.invoke.checkInternet'; setOIDCConfigError: 'error.platform.issuersMachine.performAuthorization:invocation[0]'; setPrivateKey: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; setPublicKey: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; setSelectedIssuerId: 'SELECTED_ISSUER'; setSelectedIssuers: 'done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]'; - setTokenLoadingReason: 'done.invoke.issuersMachine.performAuthorization:invocation[0]'; setTokenResponse: 'done.invoke.issuersMachine.performAuthorization:invocation[0]'; setVerifiableCredential: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]'; storeKeyPair: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; From eb7396ec1043db43f27ff3454fa35cf020116233 Mon Sep 17 00:00:00 2001 From: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> Date: Tue, 10 Oct 2023 18:15:48 +0530 Subject: [PATCH 16/20] feat(INJI-205): move to prev screen on back btn press in error screen Co-authored-by: Harsh Vardhan Signed-off-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> --- machines/issuersMachine.ts | 5 +++-- machines/issuersMachine.typegen.ts | 1 - screens/Issuers/IssuersScreen.tsx | 35 ++++++++++++++++++------------ 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/machines/issuersMachine.ts b/machines/issuersMachine.ts index 518b378b1c..c28e2bb4b3 100644 --- a/machines/issuersMachine.ts +++ b/machines/issuersMachine.ts @@ -86,7 +86,8 @@ export const IssuersMachine = model.createMachine( target: 'selectingIssuer', }, onError: { - actions: ['setError', 'resetLoadingReason'], + //loadingReason is not reset here so that we go to previous(Home) screen on back button press of error screen + actions: ['setError'], target: 'error', }, }, @@ -114,7 +115,7 @@ export const IssuersMachine = model.createMachine( ], RESET_ERROR: { actions: 'resetError', - target: 'idle', + target: 'selectingIssuer', }, }, }, diff --git a/machines/issuersMachine.typegen.ts b/machines/issuersMachine.typegen.ts index 31a693231c..fcffc9755e 100644 --- a/machines/issuersMachine.typegen.ts +++ b/machines/issuersMachine.typegen.ts @@ -86,7 +86,6 @@ export interface Typegen0 { resetLoadingReason: | 'done.invoke.checkInternet' | 'done.invoke.issuersMachine.displayIssuers:invocation[0]' - | 'error.platform.issuersMachine.displayIssuers:invocation[0]' | 'error.platform.issuersMachine.downloadCredentials:invocation[0]' | 'error.platform.issuersMachine.downloadIssuerConfig:invocation[0]' | 'error.platform.issuersMachine.performAuthorization:invocation[0]'; diff --git a/screens/Issuers/IssuersScreen.tsx b/screens/Issuers/IssuersScreen.tsx index be530174a7..07fa901d99 100644 --- a/screens/Issuers/IssuersScreen.tsx +++ b/screens/Issuers/IssuersScreen.tsx @@ -58,10 +58,14 @@ export const IssuersScreen: React.FC< }; const goBack = () => { - controller.RESET_ERROR(); - setTimeout(() => { + if ( + controller.errorMessageType && + controller.loadingReason === 'displayIssuers' + ) { props.navigation.goBack(); - }, 0); + } else { + controller.RESET_ERROR(); + } }; const getImage = () => { @@ -82,6 +86,20 @@ export const IssuersScreen: React.FC< ); }; + if (controller.errorMessageType) { + return ( + + ); + } + if (controller.loadingReason) { return ( )} - {controller.errorMessageType && ( - - )} ); }; From 41755bcda7a14b87867977ebab05ff9aa709c3f4 Mon Sep 17 00:00:00 2001 From: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> Date: Tue, 10 Oct 2023 18:38:07 +0530 Subject: [PATCH 17/20] feat(INJI-205): use openId4VCIDownloadVCTimeout from config Co-authored-by: Harsh Vardhan Signed-off-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> --- shared/InitialConfig.ts | 1 + shared/commonprops/commonProps.ts | 8 ++++++++ shared/openId4VCI/Utils.ts | 4 +++- shared/request.ts | 6 +++--- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/shared/InitialConfig.ts b/shared/InitialConfig.ts index 44b37075d9..3f0b65c4d8 100644 --- a/shared/InitialConfig.ts +++ b/shared/InitialConfig.ts @@ -17,5 +17,6 @@ export const INITIAL_CONFIG = { warningDomainName: '', aboutInjiUrl: 'https://docs.mosip.io/inji', faceSdkModelUrl: '', + openId4VCIDownloadVCTimeout: '30000', }, }; diff --git a/shared/commonprops/commonProps.ts b/shared/commonprops/commonProps.ts index 1a48ae07e2..f5ec9efd09 100644 --- a/shared/commonprops/commonProps.ts +++ b/shared/commonprops/commonProps.ts @@ -10,6 +10,14 @@ export default async function getAllConfigurations(host = undefined) { return await CACHED_API.getAllProperties(); } +export function getConfig(key: string): string { + let value: string = ''; + getAllConfigurations() + .then(resp => (value = resp[key])) + .catch(() => (value = '')); + return value; +} + export async function downloadModel() { try { var injiProp = await getAllConfigurations(); diff --git a/shared/openId4VCI/Utils.ts b/shared/openId4VCI/Utils.ts index d47aa93b2d..91d3abf961 100644 --- a/shared/openId4VCI/Utils.ts +++ b/shared/openId4VCI/Utils.ts @@ -5,6 +5,7 @@ import {isIOS} from '../constants'; import pem2jwk from 'simple-pem2jwk'; import {Issuers_Key_Ref} from '../../machines/issuersMachine'; import {ENABLE_OPENID_FOR_VC} from 'react-native-dotenv'; +import {getConfig} from '../commonprops/commonProps'; export const OpenId4VCIProtocol = 'OpenId4VCIProtocol'; export const isOpenId4VCIEnabled = () => { @@ -92,7 +93,8 @@ export const getJWT = async context => { throw e; } }; -export const VC_DOWNLOAD_TIMEOUT = 30; +export const VC_DOWNLOAD_TIMEOUT = + Number(getConfig('openId4VCIDownloadVCTimeout')) || 30000; // OIDCErrors is a collection of external errors from the OpenID library or the issuer export enum OIDCErrors { OIDC_FLOW_CANCELLED_ANDROID = 'User cancelled flow', diff --git a/shared/request.ts b/shared/request.ts index a7c45092c5..5ea47bfd66 100644 --- a/shared/request.ts +++ b/shared/request.ts @@ -22,12 +22,12 @@ export async function request( headers: Record = { 'Content-Type': 'application/json', }, - timeout?: undefined | number, + timeoutMillis?: undefined | number, ) { if (path.includes('residentmobileapp')) headers['X-AppId'] = __AppId.getValue(); let response; - if (timeout === undefined) { + if (timeoutMillis === undefined) { response = await fetch(host + path, { method, headers, @@ -38,7 +38,7 @@ export async function request( let controller = new AbortController(); setTimeout(() => { controller.abort(); - }, timeout * 1000); + }, timeoutMillis); try { response = await fetch(host + path, { method, From 9d3c9c2f97f79b5c037dd3625ca946804e9ac738 Mon Sep 17 00:00:00 2001 From: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> Date: Tue, 10 Oct 2023 18:39:59 +0530 Subject: [PATCH 18/20] feat(INJI-205): toggle on openID for VC Co-authored-by: Harsh Vardhan Signed-off-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> --- .env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env b/.env index d055ca21fc..6ff684b9d5 100644 --- a/.env +++ b/.env @@ -21,4 +21,4 @@ DEBUG_MODE=false APPLICATION_LANGUAGE=en #Toggle for openID for VC -ENABLE_OPENID_FOR_VC=false +ENABLE_OPENID_FOR_VC=true From 25c2bd639fa4f897deb7b300d989dbf792f7264b Mon Sep 17 00:00:00 2001 From: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> Date: Tue, 10 Oct 2023 18:59:51 +0530 Subject: [PATCH 19/20] refactor(INJI-205): use extracted error constant to avoid hardcoding Signed-off-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> --- machines/issuersMachine.ts | 4 ++-- screens/Issuers/IssuersScreen.tsx | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/machines/issuersMachine.ts b/machines/issuersMachine.ts index c28e2bb4b3..ca4d11f0a7 100644 --- a/machines/issuersMachine.ts +++ b/machines/issuersMachine.ts @@ -548,9 +548,9 @@ export function selectIssuers(state: State) { export function selectErrorMessageType(state: State) { return state.context.errorMessage === '' || - state.context.errorMessage === 'noInternetConnection' + state.context.errorMessage === ErrorMessage.NO_INTERNET ? state.context.errorMessage - : 'generic'; + : ErrorMessage.GENERIC; } export function selectLoadingReason(state: State) { diff --git a/screens/Issuers/IssuersScreen.tsx b/screens/Issuers/IssuersScreen.tsx index 07fa901d99..398cb31998 100644 --- a/screens/Issuers/IssuersScreen.tsx +++ b/screens/Issuers/IssuersScreen.tsx @@ -11,6 +11,7 @@ import {HomeRouteProps} from '../../routes/main'; import {useIssuerScreenController} from './IssuerScreenController'; import {Loader} from '../../components/ui/Loader'; import testIDProps, {removeWhiteSpace} from '../../shared/commonUtil'; +import {ErrorMessage} from '../../shared/openId4VCI/Utils'; export const IssuersScreen: React.FC< HomeRouteProps | RootRouteProps @@ -54,7 +55,7 @@ export const IssuersScreen: React.FC< }; const isGenericError = () => { - return controller.errorMessageType === 'generic'; + return controller.errorMessageType === ErrorMessage.GENERIC; }; const goBack = () => { From 2e91aefb4dd5bb72d15a5b9097513b8c2be8b1b5 Mon Sep 17 00:00:00 2001 From: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> Date: Tue, 10 Oct 2023 19:39:34 +0530 Subject: [PATCH 20/20] fix(INJI-205): vcDownloadTimeout config fetch Co-authored-by: Harsh Vardhan Signed-off-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> --- machines/issuersMachine.ts | 11 ++++++----- machines/issuersMachine.typegen.ts | 2 +- shared/commonprops/commonProps.ts | 8 -------- shared/openId4VCI/Utils.ts | 11 ++++++++--- 4 files changed, 15 insertions(+), 17 deletions(-) diff --git a/machines/issuersMachine.ts b/machines/issuersMachine.ts index ca4d11f0a7..876535a308 100644 --- a/machines/issuersMachine.ts +++ b/machines/issuersMachine.ts @@ -17,7 +17,7 @@ import {verifyCredential} from '../shared/vcjs/verifyCredential'; import { getBody, getIdentifier, - VC_DOWNLOAD_TIMEOUT, + vcDownloadTimeout, OIDCErrors, ErrorMessage, } from '../shared/openId4VCI/Utils'; @@ -226,7 +226,7 @@ export const IssuersMachine = model.createMachine( { actions: [ 'setPublicKey', - 'setLoadingReasonAsDownloadingCreds', + 'setLoadingReasonAsDownloadingCredentials', 'setPrivateKey', 'storeKeyPair', ], @@ -235,7 +235,7 @@ export const IssuersMachine = model.createMachine( { actions: [ 'setPublicKey', - 'setLoadingReasonAsDownloadingCreds', + 'setLoadingReasonAsDownloadingCredentials', 'storeKeyPair', ], cond: 'isCustomSecureKeystore', @@ -321,7 +321,7 @@ export const IssuersMachine = model.createMachine( setLoadingReasonAsDisplayIssuers: model.assign({ loadingReason: 'displayIssuers', }), - setLoadingReasonAsDownloadingCreds: model.assign({ + setLoadingReasonAsDownloadingCredentials: model.assign({ loadingReason: 'downloadingCredentials', }), setLoadingReasonAsSettingUp: model.assign({ @@ -471,6 +471,7 @@ export const IssuersMachine = model.createMachine( }, downloadCredential: async context => { const body = await getBody(context); + const downloadTimeout = await vcDownloadTimeout(); const response = await request( 'POST', context.selectedIssuer.serviceConfiguration.credentialEndpoint, @@ -480,7 +481,7 @@ export const IssuersMachine = model.createMachine( 'Content-Type': 'application/json', Authorization: 'Bearer ' + context.tokenResponse?.accessToken, }, - VC_DOWNLOAD_TIMEOUT, + downloadTimeout, ); let credential = await response.json(); credential = updateCredentialInformation(context, credential); diff --git a/machines/issuersMachine.typegen.ts b/machines/issuersMachine.typegen.ts index fcffc9755e..9d9bb364e6 100644 --- a/machines/issuersMachine.typegen.ts +++ b/machines/issuersMachine.typegen.ts @@ -97,7 +97,7 @@ export interface Typegen0 { | 'error.platform.issuersMachine.performAuthorization:invocation[0]'; setIssuers: 'done.invoke.issuersMachine.displayIssuers:invocation[0]'; setLoadingReasonAsDisplayIssuers: 'TRY_AGAIN'; - setLoadingReasonAsDownloadingCreds: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; + setLoadingReasonAsDownloadingCredentials: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'; setLoadingReasonAsSettingUp: 'done.invoke.issuersMachine.performAuthorization:invocation[0]'; setNoInternet: 'done.invoke.checkInternet'; setOIDCConfigError: 'error.platform.issuersMachine.performAuthorization:invocation[0]'; diff --git a/shared/commonprops/commonProps.ts b/shared/commonprops/commonProps.ts index f5ec9efd09..1a48ae07e2 100644 --- a/shared/commonprops/commonProps.ts +++ b/shared/commonprops/commonProps.ts @@ -10,14 +10,6 @@ export default async function getAllConfigurations(host = undefined) { return await CACHED_API.getAllProperties(); } -export function getConfig(key: string): string { - let value: string = ''; - getAllConfigurations() - .then(resp => (value = resp[key])) - .catch(() => (value = '')); - return value; -} - export async function downloadModel() { try { var injiProp = await getAllConfigurations(); diff --git a/shared/openId4VCI/Utils.ts b/shared/openId4VCI/Utils.ts index 91d3abf961..30c46017bb 100644 --- a/shared/openId4VCI/Utils.ts +++ b/shared/openId4VCI/Utils.ts @@ -5,7 +5,7 @@ import {isIOS} from '../constants'; import pem2jwk from 'simple-pem2jwk'; import {Issuers_Key_Ref} from '../../machines/issuersMachine'; import {ENABLE_OPENID_FOR_VC} from 'react-native-dotenv'; -import {getConfig} from '../commonprops/commonProps'; +import getAllConfigurations from '../commonprops/commonProps'; export const OpenId4VCIProtocol = 'OpenId4VCIProtocol'; export const isOpenId4VCIEnabled = () => { @@ -93,8 +93,13 @@ export const getJWT = async context => { throw e; } }; -export const VC_DOWNLOAD_TIMEOUT = - Number(getConfig('openId4VCIDownloadVCTimeout')) || 30000; + +export const vcDownloadTimeout = async (): Promise => { + const response = await getAllConfigurations(); + + return Number(response['openId4VCIDownloadVCTimeout']) || 30000; +}; + // OIDCErrors is a collection of external errors from the OpenID library or the issuer export enum OIDCErrors { OIDC_FLOW_CANCELLED_ANDROID = 'User cancelled flow',