diff --git a/examples/aml-check/package-lock.json b/examples/aml-check/package-lock.json index d3e718fb..e0220337 100644 --- a/examples/aml-check/package-lock.json +++ b/examples/aml-check/package-lock.json @@ -25,7 +25,7 @@ }, "../..": { "name": "yoti", - "version": "4.11.1", + "version": "4.12.0", "license": "MIT", "dependencies": { "form-data": "4.0.4", diff --git a/examples/digital-identity/package-lock.json b/examples/digital-identity/package-lock.json index e7240337..d4231b41 100644 --- a/examples/digital-identity/package-lock.json +++ b/examples/digital-identity/package-lock.json @@ -28,7 +28,7 @@ }, "../..": { "name": "yoti", - "version": "4.11.1", + "version": "4.12.0", "license": "MIT", "dependencies": { "form-data": "4.0.4", diff --git a/examples/idv-identity-checks/package-lock.json b/examples/idv-identity-checks/package-lock.json index e8ec9a8b..9a8fb66e 100644 --- a/examples/idv-identity-checks/package-lock.json +++ b/examples/idv-identity-checks/package-lock.json @@ -27,7 +27,7 @@ }, "../..": { "name": "yoti", - "version": "4.11.1", + "version": "4.12.0", "license": "MIT", "dependencies": { "form-data": "4.0.4", diff --git a/examples/idv-identity-checks/views/pages/partials/check.ejs b/examples/idv-identity-checks/views/pages/partials/check.ejs index c8b27843..2369e54a 100644 --- a/examples/idv-identity-checks/views/pages/partials/check.ejs +++ b/examples/idv-identity-checks/views/pages/partials/check.ejs @@ -114,6 +114,12 @@ formatString = function (value) { <%= breakdown.getResult(); %> <% } %> + + <% if (breakdown.getProcess()) { %> + Process + <%= breakdown.getProcess(); %> + <% } %> + <% if (breakdown.getDetails() && breakdown.getDetails().length > 0) { %> Details diff --git a/examples/idv/package-lock.json b/examples/idv/package-lock.json index 937c54bd..9dcdd010 100644 --- a/examples/idv/package-lock.json +++ b/examples/idv/package-lock.json @@ -12,7 +12,7 @@ "dotenv": "16.0.2", "ejs": "3.1.10", "express": "4.21.2", - "express-session": "1.18.1", + "express-session": "1.18.2", "yoti": "file:../.." }, "devDependencies": { @@ -28,7 +28,7 @@ }, "../..": { "name": "yoti", - "version": "4.11.1", + "version": "4.12.0", "license": "MIT", "dependencies": { "form-data": "4.0.4", @@ -1406,15 +1406,15 @@ } }, "node_modules/express-session": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.1.tgz", - "integrity": "sha512-a5mtTqEaZvBCL9A9aqkrtfz+3SMDhOVUnjafjo+s7A9Txkq+SVX2DLvSp1Zrv4uCXa3lMSK3viWnh9Gg07PBUA==", + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.2.tgz", + "integrity": "sha512-SZjssGQC7TzTs9rpPDuUrR23GNZ9+2+IkA/+IJWmvQilTr5OSliEHGF+D9scbIpdC6yGtTI0/VhaHoVes2AN/A==", "dependencies": { "cookie": "0.7.2", "cookie-signature": "1.0.7", "debug": "2.6.9", "depd": "~2.0.0", - "on-headers": "~1.0.2", + "on-headers": "~1.1.0", "parseurl": "~1.3.3", "safe-buffer": "5.2.1", "uid-safe": "~2.1.5" @@ -2455,9 +2455,9 @@ } }, "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "engines": { "node": ">= 0.8" } @@ -4238,15 +4238,15 @@ } }, "express-session": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.1.tgz", - "integrity": "sha512-a5mtTqEaZvBCL9A9aqkrtfz+3SMDhOVUnjafjo+s7A9Txkq+SVX2DLvSp1Zrv4uCXa3lMSK3viWnh9Gg07PBUA==", + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.2.tgz", + "integrity": "sha512-SZjssGQC7TzTs9rpPDuUrR23GNZ9+2+IkA/+IJWmvQilTr5OSliEHGF+D9scbIpdC6yGtTI0/VhaHoVes2AN/A==", "requires": { "cookie": "0.7.2", "cookie-signature": "1.0.7", "debug": "2.6.9", "depd": "~2.0.0", - "on-headers": "~1.0.2", + "on-headers": "~1.1.0", "parseurl": "~1.3.3", "safe-buffer": "5.2.1", "uid-safe": "~2.1.5" @@ -4993,9 +4993,9 @@ } }, "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==" }, "once": { "version": "1.4.0", diff --git a/examples/idv/package.json b/examples/idv/package.json index d7eb448e..275d5653 100644 --- a/examples/idv/package.json +++ b/examples/idv/package.json @@ -15,7 +15,7 @@ "dotenv": "16.0.2", "ejs": "3.1.10", "express": "4.21.2", - "express-session": "1.18.1", + "express-session": "1.18.2", "yoti": "file:../.." }, "devDependencies": { diff --git a/examples/idv/src/controllers/use-cases/index.js b/examples/idv/src/controllers/use-cases/index.js index 78f29412..5a028b58 100644 --- a/examples/idv/src/controllers/use-cases/index.js +++ b/examples/idv/src/controllers/use-cases/index.js @@ -5,6 +5,7 @@ const allowExpiredDocumentCheckController = require('./allow.expired.document.ch const faceComparisonCheckController = require('./face.comparison.check.controller'); const faceMatchCheckController = require('./face.match.check.controller'); const watchlistCheckController = require('./watchlist.check.controller'); +const suppressedScreensCheckController = require('./suppressed.screens.check.controller'); module.exports = { authenticityAndIdentityCheckController, @@ -14,4 +15,5 @@ module.exports = { faceComparisonCheckController, faceMatchCheckController, watchlistCheckController, + suppressedScreensCheckController, }; diff --git a/examples/idv/src/controllers/use-cases/suppressed.screens.check.controller.js b/examples/idv/src/controllers/use-cases/suppressed.screens.check.controller.js new file mode 100644 index 00000000..5f089c9f --- /dev/null +++ b/examples/idv/src/controllers/use-cases/suppressed.screens.check.controller.js @@ -0,0 +1,77 @@ +const { + IDVClient, + SessionSpecificationBuilder, + SdkConfigBuilder, + RequiredIdDocumentBuilder, + RequestedDocumentAuthenticityCheckBuilder, + RequestedTextExtractionTaskBuilder, +} = require('yoti'); +const config = require('../../../config'); + +/** + * Create an IDV session. + */ +async function createSession() { + const idvClient = new IDVClient( + config.YOTI_CLIENT_SDK_ID, + config.YOTI_PEM + ); + + const sessionSpec = new SessionSpecificationBuilder() + .withClientSessionTokenTtl(600) // 10 minutes + .withResourcesTtl(90000) // session TTL(10 minutes) + 24 hours(minimum required) + .withUserTrackingId('some-user-tracking-id') + .withRequestedCheck( + new RequestedDocumentAuthenticityCheckBuilder() + .withManualCheckFallback() + .build() + ) + .withRequestedTask( + new RequestedTextExtractionTaskBuilder() + .withManualCheckFallback() + .withChipDataDesired() + .withCreateExpandedDocumentFields(true) // default is false + .build() + ) + .withSdkConfig( + new SdkConfigBuilder() + .withAllowsCameraAndUpload() + .withPrimaryColour('#2d9fff') + .withSecondaryColour('#FFFFFF') + .withFontColour('#FFFFFF') + .withLocale('en-GB') + .withPresetIssuingCountry('GBR') + .withSuccessUrl(`${config.YOTI_APP_BASE_URL}/success`) + .withErrorUrl(`${config.YOTI_APP_BASE_URL}/error`) + .withAllowHandoff(true) + .withIdDocumentTextExtractionGenericRetries(3) + .withIdDocumentTextExtractionReclassificationRetries(3) + .withSuppressedScreens([ + 'ID_DOCUMENT_EDUCATION', + 'ID_DOCUMENT_REQUIREMENTS', + ]) + .build() + ) + .withRequiredDocument( + (new RequiredIdDocumentBuilder()).build() + ) + .build(); + + return idvClient.createSession(sessionSpec); +} + +module.exports = async (req, res) => { + try { + const session = await createSession(); + + req.session.IDV_SESSION_ID = session.getSessionId(); + req.session.IDV_SESSION_TOKEN = session.getClientSessionToken(); + + res.render('pages/session', { + sessionId: req.session.IDV_SESSION_ID, + iframeUrl: `${config.YOTI_IDV_IFRAME_URL}?sessionID=${req.session.IDV_SESSION_ID}&sessionToken=${req.session.IDV_SESSION_TOKEN}`, + }); + } catch (error) { + res.render('pages/error', { error }); + } +}; diff --git a/examples/idv/src/routes/use-cases-router.js b/examples/idv/src/routes/use-cases-router.js index c160b76c..17980820 100644 --- a/examples/idv/src/routes/use-cases-router.js +++ b/examples/idv/src/routes/use-cases-router.js @@ -14,6 +14,7 @@ const { faceComparisonCheckController, faceMatchCheckController, watchlistCheckController, + suppressedScreensCheckController, } = controllers.useCasesControllers; const caseIdToControllerMapping = { @@ -24,6 +25,7 @@ const caseIdToControllerMapping = { [Cases.FACE_COMPARISON]: faceComparisonCheckController, [Cases.FACE_MATCH]: faceMatchCheckController, [Cases.WATCHLIST]: watchlistCheckController, + [Cases.SUPPRESSED_SCREENS]: suppressedScreensCheckController, }; const casesEntries = [...CasesMap.entries()]; diff --git a/examples/idv/src/useCases.js b/examples/idv/src/useCases.js index 08fe31bf..edaaa3a3 100644 --- a/examples/idv/src/useCases.js +++ b/examples/idv/src/useCases.js @@ -6,6 +6,7 @@ const Cases = { FACE_COMPARISON: 'faceComparison', FACE_MATCH: 'faceMatch', WATCHLIST: 'watchlist', + SUPPRESSED_SCREENS: 'suppressedScreens', }; const CasesMap = new Map([ @@ -37,6 +38,10 @@ const CasesMap = new Map([ name: 'Watchlist check', path: '/watchlist-check', }], + [Cases.SUPPRESSED_SCREENS, { + name: 'Suppressed screens check', + path: '/suppressed-screens-check', + }], ]); module.exports = { diff --git a/examples/idv/views/pages/partials/check.ejs b/examples/idv/views/pages/partials/check.ejs index 1e241599..eebd857b 100644 --- a/examples/idv/views/pages/partials/check.ejs +++ b/examples/idv/views/pages/partials/check.ejs @@ -113,6 +113,12 @@ formatString = function (value) { <%= breakdown.getResult(); %> <% } %> + + <% if (breakdown.getProcess()) { %> + Process + <%= breakdown.getProcess(); %> + <% } %> + <% if (breakdown.getDetails() && breakdown.getDetails().length > 0) { %> Details diff --git a/examples/profile-identity-checks/package-lock.json b/examples/profile-identity-checks/package-lock.json index 7f215914..8d2b0505 100644 --- a/examples/profile-identity-checks/package-lock.json +++ b/examples/profile-identity-checks/package-lock.json @@ -28,7 +28,7 @@ }, "../..": { "name": "yoti", - "version": "4.11.1", + "version": "4.12.0", "license": "MIT", "dependencies": { "form-data": "4.0.4", diff --git a/examples/profile/package-lock.json b/examples/profile/package-lock.json index 7f215914..8d2b0505 100644 --- a/examples/profile/package-lock.json +++ b/examples/profile/package-lock.json @@ -28,7 +28,7 @@ }, "../..": { "name": "yoti", - "version": "4.11.1", + "version": "4.12.0", "license": "MIT", "dependencies": { "form-data": "4.0.4", diff --git a/package-lock.json b/package-lock.json index b6fda183..26438a0e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "yoti", - "version": "4.11.1", + "version": "4.12.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "yoti", - "version": "4.11.1", + "version": "4.12.0", "license": "MIT", "dependencies": { "form-data": "4.0.4", diff --git a/package.json b/package.json index c40a7cf0..71f86128 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "yoti", - "version": "4.11.1", + "version": "4.12.0", "description": "Yoti NodeJS SDK for back-end integration", "author": "Yoti LTD (https://www.yoti.com/developers)", "license": "MIT", diff --git a/sonar-project.properties b/sonar-project.properties index 061265a5..5ee1cb86 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -3,7 +3,7 @@ sonar.organization = getyoti sonar.projectKey = getyoti:node sonar.projectName = Node SDK -sonar.projectVersion = 4.11.0 +sonar.projectVersion = 4.12.0 sonar.exclusions=tests/**,examples/**,node_modules/**,coverage/** sonar.javascript.lcov.reportPaths=coverage/lcov.info sonar.verbose = true diff --git a/src/idv_service/session/create/sdk.config.builder.js b/src/idv_service/session/create/sdk.config.builder.js index e1d142cb..6fda7b32 100644 --- a/src/idv_service/session/create/sdk.config.builder.js +++ b/src/idv_service/session/create/sdk.config.builder.js @@ -264,6 +264,20 @@ class SdkConfigBuilder { return this; } + /** + * Sets the suppressed screens on the builder + * + * @param {string[]} screens + * + * @returns {this} + */ + withSuppressedScreens(screens) { + Validation.notNullOrEmpty(screens, 'suppressedScreens'); + Validation.isArrayOfStrings(screens, 'suppressedScreens'); + this.suppressedScreens = screens; + return this; + } + /** * Builds the {@link SdkConfig} using the values supplied to the builder * @@ -283,7 +297,8 @@ class SdkConfigBuilder { this.biometricConsentFlow, this.allowHandoff, this.attemptsConfiguration, - this.brandId + this.brandId, + this.suppressedScreens ); } } diff --git a/src/idv_service/session/create/sdk.config.js b/src/idv_service/session/create/sdk.config.js index 027d1515..35cb69fb 100644 --- a/src/idv_service/session/create/sdk.config.js +++ b/src/idv_service/session/create/sdk.config.js @@ -30,6 +30,8 @@ class SdkConfig { * The attempts configuration * @param {string} brandId * The brandID for the client + * @param {string[]} suppressedScreens + * The list of suppressed screens */ constructor( allowedCaptureMethods, @@ -44,7 +46,8 @@ class SdkConfig { biometricConsentFlow, allowHandoff, attemptsConfiguration, - brandId + brandId, + suppressedScreens ) { Validation.isString(allowedCaptureMethods, 'allowedCaptureMethods', true); /** @private */ @@ -99,6 +102,13 @@ class SdkConfig { Validation.isString(brandId, 'brandId', true); /** @private */ this.brandId = brandId; + + if (suppressedScreens) { + Validation.notNullOrEmpty(suppressedScreens, 'suppressedScreens'); + Validation.isArrayOfStrings(suppressedScreens, 'suppressedScreens'); + /** @private */ + this.suppressedScreens = suppressedScreens; + } } /** @@ -119,6 +129,7 @@ class SdkConfig { allow_handoff: this.allowHandoff, attempts_configuration: this.attemptsConfiguration, brand_id: this.brandId, + suppressed_screens: this.suppressedScreens, }; } } diff --git a/src/idv_service/session/retrieve/breakdown.response.js b/src/idv_service/session/retrieve/breakdown.response.js index 7f32d547..c1f78421 100644 --- a/src/idv_service/session/retrieve/breakdown.response.js +++ b/src/idv_service/session/retrieve/breakdown.response.js @@ -13,6 +13,10 @@ class BreakdownResponse { /** @private */ this.result = breakdown.result; + Validation.isString(breakdown.process, 'process', true); + /** @private */ + this.process = breakdown.process; + if (breakdown.details) { Validation.isArrayOfType(breakdown.details, Object, 'details'); /** @private */ @@ -37,6 +41,13 @@ class BreakdownResponse { return this.result; } + /** + * @returns {string|undefined} Likely 'AUTOMATED' or 'EXPERT_REVIEW' + */ + getProcess() { + return this.process; + } + /** * @returns {DetailsResponse[]} */ diff --git a/tests/idv_service/session/create/sdk.config.builder.test.js b/tests/idv_service/session/create/sdk.config.builder.test.js index ccc00756..e074712b 100644 --- a/tests/idv_service/session/create/sdk.config.builder.test.js +++ b/tests/idv_service/session/create/sdk.config.builder.test.js @@ -17,6 +17,7 @@ describe('SdkConfigBuilder', () => { .withBiometricConsentFlow('some-flow') .withAllowHandoff(true) .withBrandId('some-brand-identifier') + .withSuppressedScreens(['SCREEN_1', 'SCREEN_3']) .build(); const expectedJson = JSON.stringify({ @@ -32,6 +33,7 @@ describe('SdkConfigBuilder', () => { biometric_consent_flow: 'some-flow', allow_handoff: true, brand_id: 'some-brand-identifier', + suppressed_screens: ['SCREEN_1', 'SCREEN_3'], }); expect(JSON.stringify(sdkConfig)).toBe(expectedJson); diff --git a/tests/idv_service/session/retrieve/breakdown.response.spec.js b/tests/idv_service/session/retrieve/breakdown.response.spec.js index 6fd32b13..2d61fab2 100644 --- a/tests/idv_service/session/retrieve/breakdown.response.spec.js +++ b/tests/idv_service/session/retrieve/breakdown.response.spec.js @@ -9,6 +9,7 @@ describe('BreakdownResponse', () => { sub_check: 'some-sub-check', result: 'some-result', details: [{}], + process: 'AUTOMATED', }); }); @@ -24,6 +25,12 @@ describe('BreakdownResponse', () => { }); }); + describe('#getProcess', () => { + it('should return process', () => { + expect(breakdownResponse.getProcess()).toBe('AUTOMATED'); + }); + }); + describe('#getDetails', () => { describe('when details are available', () => { it('should return array of details', () => { diff --git a/types/src/idv_service/session/create/sdk.config.builder.d.ts b/types/src/idv_service/session/create/sdk.config.builder.d.ts index c2bf3652..d0b41659 100644 --- a/types/src/idv_service/session/create/sdk.config.builder.d.ts +++ b/types/src/idv_service/session/create/sdk.config.builder.d.ts @@ -172,6 +172,15 @@ declare class SdkConfigBuilder { */ withBrandId(brandId: string): this; brandId: string; + /** + * Sets the suppressed screens on the builder + * + * @param {string[]} screens + * + * @returns {this} + */ + withSuppressedScreens(screens: string[]): this; + suppressedScreens: string[]; /** * Builds the {@link SdkConfig} using the values supplied to the builder * diff --git a/types/src/idv_service/session/create/sdk.config.d.ts b/types/src/idv_service/session/create/sdk.config.d.ts index e0884857..8611eae8 100644 --- a/types/src/idv_service/session/create/sdk.config.d.ts +++ b/types/src/idv_service/session/create/sdk.config.d.ts @@ -27,8 +27,10 @@ declare class SdkConfig { * The attempts configuration * @param {string} brandId * The brandID for the client + * @param {string[]} suppressedScreens + * The list of suppressed screens */ - constructor(allowedCaptureMethods: string, primaryColour: string, secondaryColour: string, fontColour: string, locale: string, presetIssuingCountry: string, successUrl: string, errorUrl: string, privacyPolicyUrl: string, biometricConsentFlow: string, allowHandoff: boolean, attemptsConfiguration: object, brandId: string); + constructor(allowedCaptureMethods: string, primaryColour: string, secondaryColour: string, fontColour: string, locale: string, presetIssuingCountry: string, successUrl: string, errorUrl: string, privacyPolicyUrl: string, biometricConsentFlow: string, allowHandoff: boolean, attemptsConfiguration: object, brandId: string, suppressedScreens: string[]); /** @private */ private allowedCaptureMethods; /** @private */ @@ -55,6 +57,8 @@ declare class SdkConfig { private attemptsConfiguration; /** @private */ private brandId; + /** @private */ + private suppressedScreens; /** * Returns serialized data for JSON.stringify() */ @@ -72,5 +76,6 @@ declare class SdkConfig { allow_handoff: boolean; attempts_configuration: any; brand_id: string; + suppressed_screens: string[]; }; } diff --git a/types/src/idv_service/session/retrieve/breakdown.response.d.ts b/types/src/idv_service/session/retrieve/breakdown.response.d.ts index e51fb05a..1073775c 100644 --- a/types/src/idv_service/session/retrieve/breakdown.response.d.ts +++ b/types/src/idv_service/session/retrieve/breakdown.response.d.ts @@ -6,6 +6,8 @@ declare class BreakdownResponse { /** @private */ private result; /** @private */ + private process; + /** @private */ private details; /** * @returns {string} @@ -15,6 +17,10 @@ declare class BreakdownResponse { * @returns {string} */ getResult(): string; + /** + * @returns {string|undefined} Likely 'AUTOMATED' or 'EXPERT_REVIEW' + */ + getProcess(): string | undefined; /** * @returns {DetailsResponse[]} */