From acf91ad4d8bad97b217f6c31cd163412d3bb29bd Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Mon, 11 Nov 2024 18:06:50 +0700 Subject: [PATCH 1/8] feat: enable storage service encrypted endpoint --- app-config.json | 17 +----------- .../mock-app/src/constants/app-config.json | 17 +----------- .../src/__tests__/aggregationEvent.test.ts | 22 +++++++++------ .../epcisEvents/associationEvent.test.ts | 11 ++++++-- .../__tests__/epcisEvents/objectEvent.test.ts | 11 ++++++-- .../transformationEventOnly.test.ts | 11 ++++++-- .../src/__tests__/linkResolver.test.ts | 6 +++++ .../services/src/__tests__/processDPP.test.ts | 21 ++++++++++----- ...processDigitalConformityCredential.test.ts | 11 ++++++-- .../processDigitalFacilityRecord.test.ts | 11 ++++++-- .../processDigitalIdentityAnchor.test.ts | 11 ++++++-- .../services/src/__tests__/storage.test.ts | 6 +---- .../src/__tests__/transactionEvent.test.ts | 27 ++++++++++--------- .../src/__tests__/transformationEvent.test.ts | 22 ++++++++++----- .../src/epcisEvents/aggregationEvent.ts | 8 +++--- .../src/epcisEvents/associationEvent.ts | 8 +++--- .../services/src/epcisEvents/objectEvent.ts | 8 +++--- .../src/epcisEvents/transactionEvent.ts | 8 +++--- .../src/epcisEvents/transformationEvent.ts | 15 +++++++---- .../epcisEvents/transformationEventOnly.ts | 8 +++--- packages/services/src/linkResolver.service.ts | 8 +++--- packages/services/src/processDPP.service.ts | 8 +++--- ...cessDigitalConformityCredential.service.ts | 8 +++--- .../processDigitalFacilityRecord.service.ts | 8 +++--- .../processDigitalIdentityAnchor.service.ts | 9 ++++--- packages/services/src/storage.service.ts | 3 +-- packages/services/src/types/storage.ts | 1 - 27 files changed, 182 insertions(+), 122 deletions(-) diff --git a/app-config.json b/app-config.json index 0a43e4e3..b9efaa86 100644 --- a/app-config.json +++ b/app-config.json @@ -688,9 +688,8 @@ "linkRegisterPath": "/api/resolver" }, "storage": { - "url": "http://localhost:3334/v1/documents", + "url": "http://localhost:3334/v1/credentials", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -904,7 +903,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -1844,7 +1842,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -2022,7 +2019,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -2204,7 +2200,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -2386,7 +2381,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -2589,7 +2583,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -3091,7 +3084,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -3509,7 +3501,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -4173,7 +4164,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -4387,7 +4377,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -5061,7 +5050,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -5275,7 +5263,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -5949,7 +5936,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -6163,7 +6149,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { diff --git a/packages/mock-app/src/constants/app-config.json b/packages/mock-app/src/constants/app-config.json index 0a43e4e3..b9efaa86 100644 --- a/packages/mock-app/src/constants/app-config.json +++ b/packages/mock-app/src/constants/app-config.json @@ -688,9 +688,8 @@ "linkRegisterPath": "/api/resolver" }, "storage": { - "url": "http://localhost:3334/v1/documents", + "url": "http://localhost:3334/v1/credentials", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -904,7 +903,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -1844,7 +1842,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -2022,7 +2019,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -2204,7 +2200,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -2386,7 +2381,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -2589,7 +2583,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -3091,7 +3084,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -3509,7 +3501,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -4173,7 +4164,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -4387,7 +4377,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -5061,7 +5050,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -5275,7 +5263,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -5949,7 +5936,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -6163,7 +6149,6 @@ "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { diff --git a/packages/services/src/__tests__/aggregationEvent.test.ts b/packages/services/src/__tests__/aggregationEvent.test.ts index 42d7720c..d402d487 100644 --- a/packages/services/src/__tests__/aggregationEvent.test.ts +++ b/packages/services/src/__tests__/aggregationEvent.test.ts @@ -5,8 +5,9 @@ import { ITraceabilityEventContext } from '../types/types'; import { Result } from '../types/validateContext'; import * as validateContext from '../validateContext'; import { processAggregationEvent } from '../epcisEvents'; -import { publicAPI } from '../utils/httpService'; import { aggregationEventMock } from './mocks/constants'; +import { constructVerifyURL } from '../utils/helpers'; +import { issueVC } from '../vckit.service'; jest.mock('../vckit.service', () => ({ issueVC: jest.fn(), @@ -27,6 +28,10 @@ jest.mock('../linkResolver.service', () => ({ epcisLinkType: 'gs1:epcis', }, })); +jest.mock('../utils/helpers', () => ({ + ...jest.requireActual('../utils/helpers'), + constructVerifyURL: jest.fn(), +})); describe('processAggregationEvent', () => { const { parentItem, aggregationVCMock, uploadedAggregationEventLinkMock, aggregationEventDLRMock } = @@ -59,7 +64,8 @@ describe('processAggregationEvent', () => { it('should process aggregation event', async () => { (vckitService.issueVC as jest.Mock).mockImplementationOnce(() => aggregationVCMock); (vckitService.decodeEnvelopedVC as jest.Mock).mockReturnValue(aggregationVCMock); - (uploadData as jest.Mock).mockResolvedValueOnce(aggregationEventDLRMock); + (uploadData as jest.Mock).mockResolvedValueOnce({ uri: 'https://exampleStorage.com/vc.json', key: '123', hash: 'ABC123' }); + (constructVerifyURL as jest.Mock).mockReturnValueOnce('http://localhost/event/1234'); jest .spyOn(validateContext, 'validateTraceabilityEventContext') @@ -138,7 +144,7 @@ describe('processAggregationEvent', () => { qualifierPath: '/10/ABC123', elementString: '01012345678910ABC123', }); - jest.spyOn(publicAPI, 'post').mockRejectedValueOnce("Can't issue VC"); + (issueVC as jest.Mock).mockRejectedValueOnce(new Error("Can't issue VC")); await processAggregationEvent(aggregationEvent, invalidIssuerContext); } catch (e) { @@ -156,6 +162,7 @@ describe('processAggregationEvent', () => { }; (vckitService.issueVC as jest.Mock).mockImplementationOnce(() => aggregationVCMock); (vckitService.decodeEnvelopedVC as jest.Mock).mockReturnValue(aggregationVCMock); + (uploadData as jest.Mock).mockRejectedValueOnce(new Error('Invalid storage provider')); jest .spyOn(validateContext, 'validateTraceabilityEventContext') @@ -168,7 +175,6 @@ describe('processAggregationEvent', () => { qualifierPath: '/10/ABC123', elementString: '01012345678910ABC123', }); - jest.spyOn(publicAPI, 'put').mockRejectedValueOnce('Invalid storage provider'); await processAggregationEvent(aggregationEvent, invalidStorageContext); } catch (e) { @@ -188,9 +194,8 @@ describe('processAggregationEvent', () => { (vckitService.issueVC as jest.Mock).mockImplementationOnce(() => aggregationVCMock); (vckitService.decodeEnvelopedVC as jest.Mock).mockReturnValue(aggregationVCMock); - (uploadData as jest.Mock).mockImplementation(({ url, _data, path }) => { - return `${url}/${path}`; - }); + (uploadData as jest.Mock).mockResolvedValueOnce({ uri: 'https://exampleStorage.com/vc.json', key: '123', hash: 'ABC123' }); + (constructVerifyURL as jest.Mock).mockReturnValueOnce('http://localhost/event/1234'); jest .spyOn(validateContext, 'validateTraceabilityEventContext') @@ -223,7 +228,8 @@ describe('processAggregationEvent', () => { }; (vckitService.issueVC as jest.Mock).mockImplementationOnce(() => aggregationVCMock); - (uploadData as jest.Mock).mockResolvedValueOnce('https://exampleStorage.com/vc.json'); + (uploadData as jest.Mock).mockResolvedValueOnce({ uri: 'https://exampleStorage.com/vc.json', key: '123', hash: 'ABC123' }); + (constructVerifyURL as jest.Mock).mockReturnValueOnce('http://localhost/event/1234'); jest .spyOn(validateContext, 'validateTraceabilityEventContext') diff --git a/packages/services/src/__tests__/epcisEvents/associationEvent.test.ts b/packages/services/src/__tests__/epcisEvents/associationEvent.test.ts index fb26a72a..7910daa8 100644 --- a/packages/services/src/__tests__/epcisEvents/associationEvent.test.ts +++ b/packages/services/src/__tests__/epcisEvents/associationEvent.test.ts @@ -7,6 +7,7 @@ import { ITraceabilityEventContext } from '../../types'; import { Result } from '../../types/validateContext'; import * as validateContext from '../../validateContext'; import { traceabilityEventContext as context } from '../mocks/constants'; +import { constructVerifyURL } from '../../utils/helpers'; jest.mock('../../vckit.service', () => ({ issueVC: jest.fn(), @@ -27,6 +28,10 @@ jest.mock('../../linkResolver.service', () => ({ epcisLinkType: 'epcis', }, })); +jest.mock('../../utils/helpers', () => ({ + ...jest.requireActual('../../utils/helpers'), + constructVerifyURL: jest.fn(), +})); describe('processAssociationEvent', () => { const associationEvent: ITraceabilityEvent = { @@ -131,7 +136,8 @@ describe('processAssociationEvent', () => { (vckitService.issueVC as jest.Mock).mockImplementation(() => ({ credentialSubject: { id: 'https://example.com/123' }, })); - (uploadData as jest.Mock).mockResolvedValue('https://exampleStorage.com/vc.json'); + (uploadData as jest.Mock).mockResolvedValueOnce({ uri: 'https://exampleStorage.com/vc.json', key: '123', hash: 'ABC123' }); + (constructVerifyURL as jest.Mock).mockReturnValueOnce('http://localhost/event/1234'); jest .spyOn(validateContext, 'validateTraceabilityEventContext') @@ -208,7 +214,8 @@ describe('processAssociationEvent', () => { (vckitService.issueVC as jest.Mock).mockImplementation(() => ({ credentialSubject: { id: 'https://example.com/123' }, })); - (uploadData as jest.Mock).mockResolvedValue('https://exampleStorage.com/vc.json'); + (uploadData as jest.Mock).mockResolvedValueOnce({ uri: 'https://exampleStorage.com/vc.json', key: '123', hash: 'ABC123' }); + (constructVerifyURL as jest.Mock).mockReturnValueOnce('http://localhost/event/1234'); jest .spyOn(validateContext, 'validateTraceabilityEventContext') diff --git a/packages/services/src/__tests__/epcisEvents/objectEvent.test.ts b/packages/services/src/__tests__/epcisEvents/objectEvent.test.ts index db953b63..a2e4d9ca 100644 --- a/packages/services/src/__tests__/epcisEvents/objectEvent.test.ts +++ b/packages/services/src/__tests__/epcisEvents/objectEvent.test.ts @@ -7,6 +7,7 @@ import { ITraceabilityEventContext } from '../../types'; import { Result } from '../../types/validateContext'; import * as validateContext from '../../validateContext'; import { traceabilityEventContext as context } from '../mocks/constants'; +import { constructVerifyURL } from '../../utils/helpers'; jest.mock('../../vckit.service', () => ({ issueVC: jest.fn(), @@ -27,6 +28,10 @@ jest.mock('../../linkResolver.service', () => ({ epcisLinkType: 'epcis', }, })); +jest.mock('../../utils/helpers', () => ({ + ...jest.requireActual('../../utils/helpers'), + constructVerifyURL: jest.fn(), +})); describe('processObjectEvent', () => { const objectEvent: ITraceabilityEvent = { @@ -66,7 +71,8 @@ describe('processObjectEvent', () => { (vckitService.decodeEnvelopedVC as jest.Mock).mockReturnValue({ credentialSubject: { id: 'https://example.com/123' }, }); - (uploadData as jest.Mock).mockResolvedValue('https://exampleStorage.com/vc.json'); + (uploadData as jest.Mock).mockResolvedValueOnce({ uri: 'https://exampleStorage.com/vc.json', key: '123', hash: 'ABC123' }); + (constructVerifyURL as jest.Mock).mockReturnValueOnce('http://localhost/event/1234'); jest .spyOn(validateContext, 'validateTraceabilityEventContext') @@ -141,7 +147,8 @@ describe('processObjectEvent', () => { (vckitService.issueVC as jest.Mock).mockImplementation(() => ({ credentialSubject: { id: 'https://example.com/123' }, })); - (uploadData as jest.Mock).mockResolvedValue('https://exampleStorage.com/vc.json'); + (uploadData as jest.Mock).mockResolvedValueOnce({ uri: 'https://exampleStorage.com/vc.json', key: '123', hash: 'ABC123' }); + (constructVerifyURL as jest.Mock).mockReturnValueOnce('http://localhost/event/1234'); jest .spyOn(validateContext, 'validateTraceabilityEventContext') diff --git a/packages/services/src/__tests__/epcisEvents/transformationEventOnly.test.ts b/packages/services/src/__tests__/epcisEvents/transformationEventOnly.test.ts index 72d16b70..79c0c60a 100644 --- a/packages/services/src/__tests__/epcisEvents/transformationEventOnly.test.ts +++ b/packages/services/src/__tests__/epcisEvents/transformationEventOnly.test.ts @@ -7,6 +7,7 @@ import { ITraceabilityEventContext } from '../../types'; import { Result } from '../../types/validateContext'; import * as validateContext from '../../validateContext'; import { traceabilityEventContext as context } from '../mocks/constants'; +import { constructVerifyURL } from '../../utils/helpers'; jest.mock('../../vckit.service', () => ({ issueVC: jest.fn(), @@ -27,6 +28,10 @@ jest.mock('../../linkResolver.service', () => ({ epcisLinkType: 'epcis', }, })); +jest.mock('../../utils/helpers', () => ({ + ...jest.requireActual('../../utils/helpers'), + constructVerifyURL: jest.fn(), +})); describe('processTransformationEventOnly', () => { const transformationEvent: ITraceabilityEvent = { @@ -155,7 +160,8 @@ describe('processTransformationEventOnly', () => { (vckitService.decodeEnvelopedVC as jest.Mock).mockReturnValue({ credentialSubject: { id: 'https://example.com/123' }, }); - (uploadData as jest.Mock).mockResolvedValue('https://exampleStorage.com/vc.json'); + (uploadData as jest.Mock).mockResolvedValueOnce({ uri: 'https://exampleStorage.com/vc.json', key: '123', hash: 'ABC123' }); + (constructVerifyURL as jest.Mock).mockReturnValueOnce('https://example.com/verify?q=https://exampleStorage.com/vc.json&key123&hash=ABC123'); jest .spyOn(validateContext, 'validateTraceabilityEventContext') @@ -232,7 +238,8 @@ describe('processTransformationEventOnly', () => { (vckitService.issueVC as jest.Mock).mockImplementation(() => ({ credentialSubject: { id: 'https://example.com/123' }, })); - (uploadData as jest.Mock).mockResolvedValue('https://exampleStorage.com/vc.json'); + (uploadData as jest.Mock).mockResolvedValueOnce({ uri: 'https://exampleStorage.com/vc.json', key: '123', hash: 'ABC123' }); + (constructVerifyURL as jest.Mock).mockReturnValueOnce('https://example.com/verify?q=https://exampleStorage.com/vc.json&key123&hash=ABC123'); jest .spyOn(validateContext, 'validateTraceabilityEventContext') diff --git a/packages/services/src/__tests__/linkResolver.test.ts b/packages/services/src/__tests__/linkResolver.test.ts index 9c7f639e..a349a654 100644 --- a/packages/services/src/__tests__/linkResolver.test.ts +++ b/packages/services/src/__tests__/linkResolver.test.ts @@ -30,6 +30,7 @@ describe('create link resolve service', () => { const mockValue = { eventLink: 'https://localhost/epcis-transformation-event/1234', + eventVerifyLink: 'https://verify.com/dev/verifyCredential?q=https://localhost/epcis-transformation-event/1234&key=123&hash=abcde123', identificationKeyType: IdentificationKeyType.nlisid, identificationKey: 'gtin-key', itemDescription: 'EPCIS transformation event VC', @@ -43,6 +44,7 @@ describe('create link resolve service', () => { const resolverUrl = await registerLinkResolver( mockValue.eventLink, + mockValue.eventVerifyLink, mockValue.identificationKeyType, mockValue.identificationKey, mockValue.itemDescription, @@ -73,6 +75,7 @@ describe('create link resolve service', () => { const mockValue = { eventLink: 'https://localhost/epcis-transformation-event/1234', + eventVerifyLink: 'https://verify.com/dev/verifyCredential?q=https://localhost/epcis-transformation-event/1234&key=123&hash=abcde123', identificationKeyType: IdentificationKeyType.nlisid, identificationKey: 'gtin-key', itemDescription: 'EPCIS transformation event VC', @@ -86,6 +89,7 @@ describe('create link resolve service', () => { const resolverUrl = await registerLinkResolver( mockValue.eventLink, + mockValue.eventVerifyLink, mockValue.identificationKeyType, mockValue.identificationKey, mockValue.itemDescription, @@ -117,6 +121,7 @@ describe('create link resolve service', () => { const mockValue = { eventLink: 'https://localhost/epcis-transformation-event/1234', + eventVerifyLink: 'https://verify.com/dev/verifyCredential?q=https://localhost/epcis-transformation-event/1234&key=123&hash=abcde123', identificationKeyType: IdentificationKeyType.nlisid, identificationKey: 'gtin-key', itemDescription: 'EPCIS transformation event VC', @@ -130,6 +135,7 @@ describe('create link resolve service', () => { const resolverUrl = await registerLinkResolver( mockValue.eventLink, + mockValue.eventVerifyLink, mockValue.identificationKeyType, mockValue.identificationKey, mockValue.itemDescription, diff --git a/packages/services/src/__tests__/processDPP.test.ts b/packages/services/src/__tests__/processDPP.test.ts index 517010ed..0f68062f 100644 --- a/packages/services/src/__tests__/processDPP.test.ts +++ b/packages/services/src/__tests__/processDPP.test.ts @@ -3,6 +3,7 @@ import { issueVC, contextDefault, decodeEnvelopedVC } from '../vckit.service'; import { uploadData } from '../storage.service'; import { registerLinkResolver, IdentificationKeyType, LinkType } from '../linkResolver.service'; import { contextDPP, dataDPP } from './mocks/constants'; +import { constructVerifyURL } from '../utils/helpers'; jest.mock('../vckit.service', () => ({ issueVC: jest.fn(), @@ -27,6 +28,10 @@ jest.mock('../linkResolver.service', () => ({ epcisLinkType: 'gs1:epcis', }, })); +jest.mock('../utils/helpers', () => ({ + ...jest.requireActual('../utils/helpers'), + constructVerifyURL: jest.fn(), +})); describe('processDPP', () => { describe('successful case', () => { @@ -60,13 +65,14 @@ describe('processDPP', () => { }); it('should call process DPP', async () => { - (uploadData as jest.Mock).mockImplementation(({ url, _data, path }) => { - return `${url}/${dataDPP.data.herd.identifier}`; - }); + const mockVerifyURL = 'https://example.com/vc.json'; + (uploadData as jest.Mock).mockResolvedValueOnce({ uri: 'https://exampleStorage.com/vc.json', key: '123', hash: 'ABC123' }); + (constructVerifyURL as jest.Mock).mockReturnValueOnce(mockVerifyURL); - (registerLinkResolver as jest.Mock).mockImplementation( + (registerLinkResolver as jest.Mock).mockImplementationOnce( ( url, + verifyURL, identificationKeyType: IdentificationKeyType, identificationKey: string, linkTitle, @@ -99,6 +105,7 @@ describe('processDPP', () => { const dlrContext = contextDPP.dlr; expect(registerLinkResolver).toHaveBeenCalledWith( expect.any(String), + mockVerifyURL, dppContext.dlrIdentificationKeyType, dataDPP.data.herd.identifier, dppContext.dlrLinkTitle, @@ -122,13 +129,13 @@ describe('processDPP', () => { }, }; - (uploadData as jest.Mock).mockImplementation(({ url, _data, path }) => { - return `${url}/${dataDPP.data.herd.identifier}`; - }); + (uploadData as jest.Mock).mockResolvedValueOnce({ uri: 'https://exampleStorage.com/vc.json', key: '123', hash: 'ABC123' }); + (constructVerifyURL as jest.Mock).mockReturnValueOnce('https://example.com/vc.json'); (registerLinkResolver as jest.Mock).mockImplementation( ( url, + verifyURL, identificationKeyType: IdentificationKeyType, identificationKey: string, linkTitle, diff --git a/packages/services/src/__tests__/processDigitalConformityCredential.test.ts b/packages/services/src/__tests__/processDigitalConformityCredential.test.ts index a4a5a304..4f7f679a 100644 --- a/packages/services/src/__tests__/processDigitalConformityCredential.test.ts +++ b/packages/services/src/__tests__/processDigitalConformityCredential.test.ts @@ -6,6 +6,7 @@ import * as validateContext from '../validateContext'; import { IDigitalConformityCredentialContext } from '../types'; import { processDigitalConformityCredential } from '../processDigitalConformityCredential.service'; import { digitalConformityCredentialContext as context } from './mocks/constants'; +import { constructVerifyURL } from '../utils/helpers'; jest.mock('../vckit.service', () => ({ issueVC: jest.fn(), @@ -26,6 +27,10 @@ jest.mock('../linkResolver.service', () => ({ epcisLinkType: 'epcis', }, })); +jest.mock('../utils/helpers', () => ({ + ...jest.requireActual('../utils/helpers'), + constructVerifyURL: jest.fn(), +})); describe('processDigitalConformityCredential', () => { const digitalConformityCredentialData = { @@ -41,7 +46,8 @@ describe('processDigitalConformityCredential', () => { (vckitService.issueVC as jest.Mock).mockImplementation(() => ({ credentialSubject: { id: 'https://example.com/123' }, })); - (uploadData as jest.Mock).mockResolvedValue('https://exampleStorage.com/vc.json'); + (uploadData as jest.Mock).mockResolvedValueOnce({ uri: 'https://exampleStorage.com/vc.json', key: '123', hash: 'ABC123' }); + (constructVerifyURL as jest.Mock).mockReturnValueOnce('https://example.com/vc.json'); jest .spyOn(validateContext, 'validateDigitalConformityCredentialContext') @@ -113,7 +119,8 @@ describe('processDigitalConformityCredential', () => { (vckitService.issueVC as jest.Mock).mockImplementation(() => ({ credentialSubject: { id: 'https://example.com/123' }, })); - (uploadData as jest.Mock).mockResolvedValue('https://exampleStorage.com/vc.json'); + (uploadData as jest.Mock).mockResolvedValueOnce({ uri: 'https://exampleStorage.com/vc.json', key: '123', hash: 'ABC123' }); + (constructVerifyURL as jest.Mock).mockReturnValueOnce('https://example.com/vc.json'); jest.spyOn(validateContext, 'validateDigitalConformityCredentialContext').mockReturnValueOnce({ ok: true, diff --git a/packages/services/src/__tests__/processDigitalFacilityRecord.test.ts b/packages/services/src/__tests__/processDigitalFacilityRecord.test.ts index a8a2e732..8df46c75 100644 --- a/packages/services/src/__tests__/processDigitalFacilityRecord.test.ts +++ b/packages/services/src/__tests__/processDigitalFacilityRecord.test.ts @@ -6,6 +6,7 @@ import * as validateContext from '../validateContext'; import { IDigitalFacilityRecordContext } from '../types'; import { processDigitalFacilityRecord } from '../processDigitalFacilityRecord.service'; import { digitalFacilityRecordContext as context } from './mocks/constants'; +import { constructVerifyURL } from '../utils/helpers'; jest.mock('../vckit.service', () => ({ issueVC: jest.fn(), @@ -26,6 +27,10 @@ jest.mock('../linkResolver.service', () => ({ epcisLinkType: 'epcis', }, })); +jest.mock('../utils/helpers', () => ({ + ...jest.requireActual('../utils/helpers'), + constructVerifyURL: jest.fn(), +})); describe('processDigitalFacilityRecord', () => { const digitalFacilityRecordData = { @@ -41,7 +46,8 @@ describe('processDigitalFacilityRecord', () => { (vckitService.issueVC as jest.Mock).mockImplementation(() => ({ credentialSubject: { id: 'https://example.com/123' }, })); - (uploadData as jest.Mock).mockResolvedValue('https://exampleStorage.com/vc.json'); + (uploadData as jest.Mock).mockResolvedValueOnce({ uri: 'https://exampleStorage.com/vc.json', key: '123', hash: 'ABC123' }); + (constructVerifyURL as jest.Mock).mockReturnValueOnce('http://localhost/event/1234'); jest .spyOn(validateContext, 'validateDigitalFacilityRecordContext') @@ -113,7 +119,8 @@ describe('processDigitalFacilityRecord', () => { (vckitService.issueVC as jest.Mock).mockImplementation(() => ({ credentialSubject: { id: 'https://example.com/123' }, })); - (uploadData as jest.Mock).mockResolvedValue('https://exampleStorage.com/vc.json'); + (uploadData as jest.Mock).mockResolvedValueOnce({ uri: 'https://exampleStorage.com/vc.json', key: '123', hash: 'ABC123' }); + (constructVerifyURL as jest.Mock).mockReturnValueOnce('http://localhost/event/1234'); jest .spyOn(validateContext, 'validateDigitalFacilityRecordContext') diff --git a/packages/services/src/__tests__/processDigitalIdentityAnchor.test.ts b/packages/services/src/__tests__/processDigitalIdentityAnchor.test.ts index 92f9e22b..2b1abc0c 100644 --- a/packages/services/src/__tests__/processDigitalIdentityAnchor.test.ts +++ b/packages/services/src/__tests__/processDigitalIdentityAnchor.test.ts @@ -6,6 +6,7 @@ import * as validateContext from '../validateContext'; import { IDigitalIdentityAnchorContext } from '../types'; import { processDigitalIdentityAnchor } from '../processDigitalIdentityAnchor.service'; import { digitalIdentityAnchorContext as context } from './mocks/constants'; +import { constructVerifyURL } from '../utils/helpers'; jest.mock('../vckit.service', () => ({ issueVC: jest.fn(), @@ -26,6 +27,10 @@ jest.mock('../linkResolver.service', () => ({ epcisLinkType: 'epcis', }, })); +jest.mock('../utils/helpers', () => ({ + ...jest.requireActual('../utils/helpers'), + constructVerifyURL: jest.fn(), +})); describe('processDigitalIdentityAnchor', () => { const digitalIdentityAnchorData = { @@ -44,7 +49,8 @@ describe('processDigitalIdentityAnchor', () => { (vckitService.decodeEnvelopedVC as jest.Mock).mockReturnValue({ credentialSubject: { id: 'https://example.com/123' }, }); - (uploadData as jest.Mock).mockResolvedValue('https://exampleStorage.com/vc.json'); + (uploadData as jest.Mock).mockResolvedValueOnce({ uri: 'https://exampleStorage.com/vc.json', key: '123', hash: 'ABC123' }); + (constructVerifyURL as jest.Mock).mockReturnValueOnce('http://localhost/event/1234'); jest .spyOn(validateContext, 'validateDigitalIdentityAnchorContext') @@ -116,7 +122,8 @@ describe('processDigitalIdentityAnchor', () => { (vckitService.issueVC as jest.Mock).mockImplementation(() => ({ credentialSubject: { id: 'https://example.com/123' }, })); - (uploadData as jest.Mock).mockResolvedValue('https://exampleStorage.com/vc.json'); + (uploadData as jest.Mock).mockResolvedValueOnce({ uri: 'https://exampleStorage.com/vc.json', key: '123', hash: 'ABC123' }); + (constructVerifyURL as jest.Mock).mockReturnValueOnce('http://localhost/event/1234'); jest .spyOn(validateContext, 'validateDigitalIdentityAnchorContext') diff --git a/packages/services/src/__tests__/storage.test.ts b/packages/services/src/__tests__/storage.test.ts index fd33cd74..cf62f6f1 100644 --- a/packages/services/src/__tests__/storage.test.ts +++ b/packages/services/src/__tests__/storage.test.ts @@ -1,4 +1,4 @@ -import { storageService } from '../storage.service'; +import { storageService, uploadData } from '../storage.service'; import { publicAPI } from '../utils/httpService'; jest.mock('../utils/httpService', () => ({ @@ -36,7 +36,6 @@ describe('storage service', () => { params: { data: credentialPayload, path: path, - resultPath: '', }, }); expect(url).toEqual({ @@ -74,7 +73,6 @@ describe('storage service', () => { params: { data: {}, path: 'bachelorDegree/vc.json', - resultPath: '', }, }); } catch (error) { @@ -90,7 +88,6 @@ describe('storage service', () => { params: { data: {}, path: 'bachelorDegree/vc.json', - resultPath: '', }, options: { method: 'PUT', @@ -107,7 +104,6 @@ describe('storage service', () => { await storageService({ url: 'https://storage.com', params: { - resultPath: '', }, options: { //@ts-ignore diff --git a/packages/services/src/__tests__/transactionEvent.test.ts b/packages/services/src/__tests__/transactionEvent.test.ts index 5735646f..99ba8607 100644 --- a/packages/services/src/__tests__/transactionEvent.test.ts +++ b/packages/services/src/__tests__/transactionEvent.test.ts @@ -7,6 +7,8 @@ import { Result } from '../types/validateContext'; import { ITraceabilityEventContext } from '../types/types'; import { publicAPI } from '../utils/httpService'; import { transactionEventMock } from './mocks/constants'; +import { constructVerifyURL } from '../utils/helpers'; +import { issueVC } from '../vckit.service'; jest.mock('../vckit.service', () => ({ issueVC: jest.fn(), @@ -30,6 +32,10 @@ jest.mock('../linkResolver.service', () => ({ jest.mock('../epcisEvents/helpers', () => ({ deleteValuesFromLocalStorageByKeyPath: jest.fn(), })); +jest.mock('../utils/helpers', () => ({ + ...jest.requireActual('../utils/helpers'), + constructVerifyURL: jest.fn(), +})); describe('processTransactionEvent', () => { const { nlisidMock, transactionEventDLRMock, transactionVCMock } = transactionEventMock; @@ -60,9 +66,7 @@ describe('processTransactionEvent', () => { dlr: { dlrAPIUrl: 'http://exampleDLR.com', dlrAPIKey: 'test-key' }, storage: { url: 'https://storage.dlr.com', - params: { - resultPath: '', - }, + params: {}, }, identifierKeyPath: '/0/transaction/identifier', localStorageParams: { storageKey: 'transaction', keyPath: '/transaction/type' }, @@ -71,9 +75,8 @@ describe('processTransactionEvent', () => { it('should process transaction event', async () => { (vckitService.issueVC as jest.Mock).mockImplementationOnce(() => transactionVCMock); (vckitService.decodeEnvelopedVC as jest.Mock).mockReturnValue(transactionVCMock); - (uploadData as jest.Mock).mockImplementation(({ url, _data, path }) => { - return `${url}/${path}`; - }); + (uploadData as jest.Mock).mockResolvedValueOnce({ uri: 'https://exampleStorage.com/vc.json', key: '123', hash: 'ABC123' }); + (constructVerifyURL as jest.Mock).mockReturnValueOnce('http://localhost/event/1234'); jest .spyOn(validateContext, 'validateTraceabilityEventContext') @@ -136,7 +139,7 @@ describe('processTransactionEvent', () => { jest .spyOn(validateContext, 'validateTraceabilityEventContext') .mockReturnValueOnce({ ok: true, value: context } as unknown as Result); - jest.spyOn(publicAPI, 'post').mockRejectedValueOnce("Can't issue VC"); + (issueVC as jest.Mock).mockRejectedValueOnce(new Error("Can't issue VC")); await processTransactionEvent(transactionEvent, invalidIssuerContext); } catch (e) { @@ -158,7 +161,7 @@ describe('processTransactionEvent', () => { jest .spyOn(validateContext, 'validateTraceabilityEventContext') .mockReturnValueOnce({ ok: true, value: context } as unknown as Result); - jest.spyOn(publicAPI, 'post').mockRejectedValueOnce('Invalid storage provider'); + (uploadData as jest.Mock).mockRejectedValueOnce(new Error('Invalid storage provider')); await processTransactionEvent(transactionEvent, invalidStorageContext); } catch (e) { @@ -176,7 +179,8 @@ describe('processTransactionEvent', () => { dlr: { ...context.dlr, dlrAPIUrl: 'http://invalid-dlr.com' }, }; (vckitService.issueVC as jest.Mock).mockImplementationOnce(() => transactionVCMock); - (uploadData as jest.Mock).mockResolvedValueOnce('https://storage.com/vc.json'); + (uploadData as jest.Mock).mockResolvedValueOnce({ uri: 'https://exampleStorage.com/vc.json', key: '123', hash: 'ABC123' }); + (constructVerifyURL as jest.Mock).mockReturnValueOnce('http://localhost/event/1234'); jest .spyOn(validateContext, 'validateTraceabilityEventContext') .mockReturnValueOnce({ ok: true, value: context } as unknown as Result); @@ -203,9 +207,8 @@ describe('processTransactionEvent', () => { }; (vckitService.issueVC as jest.Mock).mockImplementationOnce(() => transactionVCMock); - (uploadData as jest.Mock).mockImplementation(({ url, _data, path }) => { - return `${url}/${path}`; - }); + (uploadData as jest.Mock).mockResolvedValueOnce({ uri: 'https://exampleStorage.com/vc.json', key: '123', hash: 'ABC123' }); + (constructVerifyURL as jest.Mock).mockReturnValueOnce('http://localhost/event/1234'); jest .spyOn(validateContext, 'validateTraceabilityEventContext') .mockReturnValueOnce({ ok: true, value: contextWithHeaders } as unknown as Result); diff --git a/packages/services/src/__tests__/transformationEvent.test.ts b/packages/services/src/__tests__/transformationEvent.test.ts index 97cbec40..be97cfa5 100644 --- a/packages/services/src/__tests__/transformationEvent.test.ts +++ b/packages/services/src/__tests__/transformationEvent.test.ts @@ -8,7 +8,7 @@ import { uploadData } from '../storage.service'; import { registerLinkResolver, IdentificationKeyType } from '../linkResolver.service'; import { IEntityIssue } from '../types'; import { contextTransformationEvent, dataTransformationEvent } from './mocks/constants'; -import { generateUUID } from '../utils'; +import { constructVerifyURL, generateUUID } from '../utils'; jest.mock('../vckit.service', () => ({ issueVC: jest.fn(), @@ -33,6 +33,10 @@ jest.mock('../linkResolver.service', () => ({ epcisLinkType: 'gs1:epcis', }, })); +jest.mock('../utils', () => ({ + ...jest.requireActual('../utils'), + constructVerifyURL: jest.fn(), +})); describe('Transformation event', () => { describe('successful case', () => { @@ -111,8 +115,9 @@ describe('Transformation event', () => { }); it('should upload vc and return link to the uploaded json file', async () => { - let expectResult = 'http://localhost/epcis-transformation-event/1234'; - (uploadData as jest.Mock).mockResolvedValue(expectResult); + let expectResult = { uri: 'http://localhost/epcis-transformation-event/1234', key: '123', hash: 'ABC123' }; + (uploadData as jest.Mock).mockResolvedValueOnce(expectResult); + (constructVerifyURL as jest.Mock).mockReturnValueOnce('http://localhost/event/1234'); const mockVc = { '@context': ['https://www.w3.org/2018/credentials/v1'], type: ['VerifiableCredential', 'MockEvent'], @@ -196,12 +201,14 @@ describe('Transformation event', () => { }); it('should call registerLinkResolver transformation event', async () => { - (uploadData as jest.Mock).mockImplementation(({ url, _data, path }) => { - return `${url}/${path}`; - }); + (uploadData as jest.Mock) + .mockResolvedValueOnce({ uri: 'http://localhost/epcis-transformation-event/1234', key: '123', hash: 'ABC123' }) + .mockResolvedValueOnce({ uri: 'http://localhost/dpp-event/1234', key: '123', hash: 'ABC123' }); + (constructVerifyURL as jest.Mock).mockReturnValueOnce('http://localhost/event/1234'); (registerLinkResolver as jest.Mock).mockImplementation( ( url, + verifyURL, identificationKeyType: IdentificationKeyType, identificationKey: string, linkTitle, @@ -367,6 +374,9 @@ describe('Transformation event', () => { }); it('should throw error when context is empty productTransformation field', async () => { + (uploadData as jest.Mock) + .mockResolvedValueOnce({ uri: 'http://localhost/transformation-event/1234', key: '123', hash: 'ABC123' }) + .mockResolvedValueOnce({ uri: 'http://localhost/dpp/1234', key: '123', hash: 'ABC123' }); const newContext = { ...contextTransformationEvent, productTransformation: [], diff --git a/packages/services/src/epcisEvents/aggregationEvent.ts b/packages/services/src/epcisEvents/aggregationEvent.ts index 902818fa..55202fe8 100644 --- a/packages/services/src/epcisEvents/aggregationEvent.ts +++ b/packages/services/src/epcisEvents/aggregationEvent.ts @@ -3,7 +3,7 @@ import { uploadData } from '../storage.service.js'; import { LinkType, getLinkResolverIdentifier, registerLinkResolver } from '../linkResolver.service.js'; import { IService } from '../types/IService.js'; import { ITraceabilityEvent, ITraceabilityEventContext } from '../types'; -import { constructIdentifierString, generateUUID } from '../utils/helpers.js'; +import { constructIdentifierString, constructVerifyURL, generateUUID } from '../utils/helpers.js'; import { validateTraceabilityEventContext } from '../validateContext.js'; import { EPCISBusinessStepCode, EPCISEventAction, EPCISEventDisposition, EPCISEventType } from '../types/epcis.js'; @@ -41,10 +41,12 @@ export const processAggregationEvent: IService = async ( }); const decodedEnvelopedVC = decodeEnvelopedVC(aggregationVC); - const aggregationVCLink = await uploadData(storage, aggregationVC, credentialId); + const { uri, key, hash } = await uploadData(storage, aggregationVC, credentialId); + const verifyURL = constructVerifyURL({ uri, key, hash }); const aggregationLinkResolver = await registerLinkResolver( - aggregationVCLink, + uri, + verifyURL, traceabilityEvent.dlrIdentificationKeyType, identifier, traceabilityEvent.dlrLinkTitle, diff --git a/packages/services/src/epcisEvents/associationEvent.ts b/packages/services/src/epcisEvents/associationEvent.ts index 1061c53b..6ac447d7 100644 --- a/packages/services/src/epcisEvents/associationEvent.ts +++ b/packages/services/src/epcisEvents/associationEvent.ts @@ -2,7 +2,7 @@ import { VerifiableCredential } from '@vckit/core-types'; import { registerLinkResolver, LinkType, getLinkResolverIdentifier } from '../linkResolver.service.js'; import { uploadData } from '../storage.service.js'; import { IService } from '../types/IService.js'; -import { constructIdentifierString, generateUUID } from '../utils/helpers.js'; +import { constructIdentifierString, constructVerifyURL, generateUUID } from '../utils/helpers.js'; import { decodeEnvelopedVC, issueVC } from '../vckit.service.js'; import { ITraceabilityEvent, ITraceabilityEventContext } from '../types/index.js'; import { validateTraceabilityEventContext } from '../validateContext.js'; @@ -50,10 +50,12 @@ export const processAssociationEvent: IService = async ( }); const decodedEnvelopedVC = decodeEnvelopedVC(associationEventVc); - const associationEventVcUrl = await uploadData(storage, associationEventVc, credentialId); + const { uri, key, hash } = await uploadData(storage, associationEventVc, credentialId); + const verifyURL = constructVerifyURL({ uri, key, hash }); const associationEventLinkResolver = await registerLinkResolver( - associationEventVcUrl, + uri, + verifyURL, traceabilityEvent.dlrIdentificationKeyType, associationEventIdentifier, traceabilityEvent.dlrLinkTitle, diff --git a/packages/services/src/epcisEvents/objectEvent.ts b/packages/services/src/epcisEvents/objectEvent.ts index 8459c3b1..a672ebb3 100644 --- a/packages/services/src/epcisEvents/objectEvent.ts +++ b/packages/services/src/epcisEvents/objectEvent.ts @@ -2,7 +2,7 @@ import { VerifiableCredential } from '@vckit/core-types'; import { registerLinkResolver, LinkType, getLinkResolverIdentifier } from '../linkResolver.service.js'; import { uploadData } from '../storage.service.js'; import { IService } from '../types/IService.js'; -import { constructIdentifierString, generateUUID } from '../utils/helpers.js'; +import { constructIdentifierString, constructVerifyURL, generateUUID } from '../utils/helpers.js'; import { decodeEnvelopedVC, issueVC } from '../vckit.service.js'; import { ITraceabilityEvent, ITraceabilityEventContext } from '../types/index.js'; import { validateTraceabilityEventContext } from '../validateContext.js'; @@ -50,10 +50,12 @@ export const processObjectEvent: IService = async ( }); const decodedEnvelopedVC = decodeEnvelopedVC(objectEventVc); - const objectEventVcUrl = await uploadData(storage, objectEventVc, credentialId); + const { uri, key, hash } = await uploadData(storage, objectEventVc, credentialId); + const verifyURL = constructVerifyURL({ uri, key, hash }); const objectEventLinkResolver = await registerLinkResolver( - objectEventVcUrl, + uri, + verifyURL, traceabilityEvent.dlrIdentificationKeyType, objectEventIdentifier, traceabilityEvent.dlrLinkTitle, diff --git a/packages/services/src/epcisEvents/transactionEvent.ts b/packages/services/src/epcisEvents/transactionEvent.ts index a3438519..b6f4f6da 100644 --- a/packages/services/src/epcisEvents/transactionEvent.ts +++ b/packages/services/src/epcisEvents/transactionEvent.ts @@ -2,7 +2,7 @@ import { VerifiableCredential } from '@vckit/core-types'; import { IService, ITraceabilityEvent, ITraceabilityEventContext } from '../types/index.js'; import { decodeEnvelopedVC, issueVC } from '../vckit.service.js'; import { uploadData } from '../storage.service.js'; -import { constructIdentifierString, generateUUID } from '../utils/helpers.js'; +import { constructIdentifierString, constructVerifyURL, generateUUID } from '../utils/helpers.js'; import { LinkType, getLinkResolverIdentifier, registerLinkResolver } from '../linkResolver.service.js'; import { validateTraceabilityEventContext } from '../validateContext.js'; import { deleteValuesFromLocalStorageByKeyPath } from './helpers.js'; @@ -40,10 +40,12 @@ export const processTransactionEvent: IService = async ( }); const decodedEnvelopedVC = decodeEnvelopedVC(vc); - const vcUrl = await uploadData(storage, vc, credentialId); + const { uri, key, hash } = await uploadData(storage, vc, credentialId); + const verifyURL = constructVerifyURL({ uri, key, hash }); const linkResolver = await registerLinkResolver( - vcUrl, + uri, + verifyURL, traceabilityEvent.dlrIdentificationKeyType, identifier, traceabilityEvent.dlrLinkTitle, diff --git a/packages/services/src/epcisEvents/transformationEvent.ts b/packages/services/src/epcisEvents/transformationEvent.ts index b0d06d8b..db892e90 100644 --- a/packages/services/src/epcisEvents/transformationEvent.ts +++ b/packages/services/src/epcisEvents/transformationEvent.ts @@ -16,6 +16,7 @@ import { IConstructObjectParameters, allowedIndexKeys, constructObject, + constructVerifyURL, generateCurrentDatetime, generateUUID, randomIntegerString, @@ -56,7 +57,8 @@ export const processTransformationEvent: IService = async ( const decodedEnvelopedVC = decodeEnvelopedVC(epcisVc); const storageContext = context.storage; - const transformantionEventLink = await uploadVC(transformationEventCredentialId, epcisVc, storageContext); + const uploadedTransformationEvent = await uploadVC(transformationEventCredentialId, epcisVc, storageContext); + const transformationEventVerifyURL = constructVerifyURL(uploadedTransformationEvent); const dppContext = context.dpp; @@ -78,7 +80,8 @@ export const processTransformationEvent: IService = async ( getLinkResolverIdentifier(`${productID as string}21${randomIntegerString(9)}`); const transformationEventLinkResolver = await registerLinkResolver( - transformantionEventLink, + uploadedTransformationEvent.uri, + transformationEventVerifyURL, epcisTransformationEventContext.dlrIdentificationKeyType, transformationEventIdentifier, epcisTransformationEventContext.dlrLinkTitle, @@ -99,11 +102,13 @@ export const processTransformationEvent: IService = async ( const dppId = generateUUID(); const dpp = await issueDPP(vcKitContext, dppContext, dppCredential, dppId, transformationEventData); - const DPPLink = await uploadVC(dppId, dpp, storageContext); + const uploadedDPP = await uploadVC(dppId, dpp, storageContext); + const dppVerifyURL = constructVerifyURL(uploadedDPP); const { identifier, qualifierPath } = getLinkResolverIdentifier(productID); await registerLinkResolver( - DPPLink, + uploadedDPP.uri, + dppVerifyURL, dppContext.dlrIdentificationKeyType, identifier, dppContext.dlrLinkTitle, @@ -117,7 +122,7 @@ export const processTransformationEvent: IService = async ( }), ); - return { vc: epcisVc, decodedEnvelopedVC, linkResolver: transformantionEventLink }; + return { vc: epcisVc, decodedEnvelopedVC, linkResolver: transformationEventVerifyURL }; } catch (error: any) { throw new Error(error); } diff --git a/packages/services/src/epcisEvents/transformationEventOnly.ts b/packages/services/src/epcisEvents/transformationEventOnly.ts index 55013c1a..bc097da5 100644 --- a/packages/services/src/epcisEvents/transformationEventOnly.ts +++ b/packages/services/src/epcisEvents/transformationEventOnly.ts @@ -2,7 +2,7 @@ import { VerifiableCredential } from '@vckit/core-types'; import { registerLinkResolver, LinkType, getLinkResolverIdentifier } from '../linkResolver.service.js'; import { uploadData } from '../storage.service.js'; import { IService } from '../types/IService.js'; -import { constructIdentifierString, generateUUID } from '../utils/helpers.js'; +import { constructIdentifierString, constructVerifyURL, generateUUID } from '../utils/helpers.js'; import { decodeEnvelopedVC, issueVC } from '../vckit.service.js'; import { ITraceabilityEvent, ITraceabilityEventContext } from '../types/index.js'; import { validateTraceabilityEventContext } from '../validateContext.js'; @@ -50,10 +50,12 @@ export const processTransformationEventOnly: IService = async ( }); const decodedEnvelopedVC = decodeEnvelopedVC(transformationEventVc); - const transformationEventVcUrl = await uploadData(storage, transformationEventVc, credentialId); + const { uri, key, hash } = await uploadData(storage, transformationEventVc, credentialId); + const verifyURL = constructVerifyURL({ uri, key, hash }); const transformationEventLinkResolver = await registerLinkResolver( - transformationEventVcUrl, + uri, + verifyURL, traceabilityEvent.dlrIdentificationKeyType, transformationEventIdentifier, traceabilityEvent.dlrLinkTitle, diff --git a/packages/services/src/linkResolver.service.ts b/packages/services/src/linkResolver.service.ts index a60d8fe0..24b20fd6 100644 --- a/packages/services/src/linkResolver.service.ts +++ b/packages/services/src/linkResolver.service.ts @@ -175,6 +175,7 @@ export const constructLinkResolver = ( export const registerLinkResolver = async ( url: string, + verifyURL: string, identificationKeyType: IdentificationKeyType, identificationKey: string, linkTitle: string, @@ -191,9 +192,7 @@ export const registerLinkResolver = async ( identificationKey: identificationKey, itemDescription: linkTitle, }; - const query = encodeURIComponent(JSON.stringify({ payload: { uri: url } })); - const queryString = `q=${query}`; - const verificationPassportPage = `${verificationPage}/?${queryString}`; + const linkResponses: ILinkResponse[] = [ { linkType: `${namespace}:${LinkType.verificationLinkType}`, @@ -210,7 +209,7 @@ export const registerLinkResolver = async ( { linkType: `${namespace}:${linkType}`, linkTitle: linkTitle, - targetUrl: verificationPassportPage, + targetUrl: verifyURL, mimeType: MimeType.textHtml, defaultLinkType: true, defaultIanaLanguage: true, @@ -223,7 +222,6 @@ export const registerLinkResolver = async ( namespace, linkResolver, linkResponses, - queryString, dlrAPIKey, qualifierPath: qualifierPath ?? '/', responseLinkType, diff --git a/packages/services/src/processDPP.service.ts b/packages/services/src/processDPP.service.ts index 62ab14a9..b43c122d 100644 --- a/packages/services/src/processDPP.service.ts +++ b/packages/services/src/processDPP.service.ts @@ -1,6 +1,6 @@ import { W3CVerifiableCredential } from '@vckit/core-types'; import { IDppContext, IService } from './types/index.js'; -import { constructIdentifierString, generateUUID } from './utils/helpers.js'; +import { constructIdentifierString, constructVerifyURL, generateUUID } from './utils/helpers.js'; import { uploadData } from './storage.service.js'; import { decodeEnvelopedVC, issueVC } from './vckit.service.js'; @@ -44,11 +44,13 @@ export const processDPP: IService = async (data: any, context: IDppContext): Pro const decodedEnvelopedVC = decodeEnvelopedVC(vc); const storageContext = context.storage; - const vcUrl = await uploadData(storageContext, vc, credentialId); + const { uri, key, hash } = await uploadData(storageContext, vc, credentialId); + const verifyURL = constructVerifyURL({ uri, key, hash }); const linkResolverContext = context.dlr; const linkResolver = await registerLinkResolver( - vcUrl, + uri, + verifyURL, dppContext.dlrIdentificationKeyType, identifier, dppContext.dlrLinkTitle, diff --git a/packages/services/src/processDigitalConformityCredential.service.ts b/packages/services/src/processDigitalConformityCredential.service.ts index ba8395c0..9fb5df9e 100644 --- a/packages/services/src/processDigitalConformityCredential.service.ts +++ b/packages/services/src/processDigitalConformityCredential.service.ts @@ -2,7 +2,7 @@ import { VerifiableCredential } from '@vckit/core-types'; import { registerLinkResolver, LinkType, getLinkResolverIdentifier } from './linkResolver.service.js'; import { uploadData } from './storage.service.js'; import { IService } from './types/IService.js'; -import { constructIdentifierString, generateUUID } from './utils/helpers.js'; +import { constructIdentifierString, constructVerifyURL, generateUUID } from './utils/helpers.js'; import { decodeEnvelopedVC, issueVC } from './vckit.service.js'; import { ITraceabilityEvent, IDigitalConformityCredentialContext } from './types/index.js'; import { validateDigitalConformityCredentialContext } from './validateContext.js'; @@ -50,10 +50,12 @@ export const processDigitalConformityCredential: IService = async ( const decodedEnvelopedVC = decodeEnvelopedVC(vc); - const vcUrl = await uploadData(storage, vc, credentialId); + const { uri, key, hash } = await uploadData(storage, vc, credentialId); + const verifyURL = constructVerifyURL({ uri, key, hash }); const linkResolver = await registerLinkResolver( - vcUrl, + uri, + verifyURL, digitalConformityCredential.dlrIdentificationKeyType, identifier, digitalConformityCredential.dlrLinkTitle, diff --git a/packages/services/src/processDigitalFacilityRecord.service.ts b/packages/services/src/processDigitalFacilityRecord.service.ts index 994558f8..0dc14d61 100644 --- a/packages/services/src/processDigitalFacilityRecord.service.ts +++ b/packages/services/src/processDigitalFacilityRecord.service.ts @@ -2,7 +2,7 @@ import { VerifiableCredential } from '@vckit/core-types'; import { registerLinkResolver, LinkType, getLinkResolverIdentifier } from './linkResolver.service.js'; import { uploadData } from './storage.service.js'; import { IService } from './types/IService.js'; -import { constructIdentifierString, generateUUID } from './utils/helpers.js'; +import { constructIdentifierString, constructVerifyURL, generateUUID } from './utils/helpers.js'; import { decodeEnvelopedVC, issueVC } from './vckit.service.js'; import { ITraceabilityEvent, IDigitalFacilityRecordContext } from './types/index.js'; import { validateDigitalFacilityRecordContext } from './validateContext.js'; @@ -50,10 +50,12 @@ export const processDigitalFacilityRecord: IService = async ( const decodedEnvelopedVC = decodeEnvelopedVC(vc); - const vcUrl = await uploadData(storage, vc, credentialId); + const { uri, key, hash } = await uploadData(storage, vc, credentialId); + const verifyURL = constructVerifyURL({ uri, key, hash }); const linkResolver = await registerLinkResolver( - vcUrl, + uri, + verifyURL, digitalFacilityRecord.dlrIdentificationKeyType, identifier, digitalFacilityRecord.dlrLinkTitle, diff --git a/packages/services/src/processDigitalIdentityAnchor.service.ts b/packages/services/src/processDigitalIdentityAnchor.service.ts index c9e4336e..d2f803bc 100644 --- a/packages/services/src/processDigitalIdentityAnchor.service.ts +++ b/packages/services/src/processDigitalIdentityAnchor.service.ts @@ -2,7 +2,7 @@ import { VerifiableCredential } from '@vckit/core-types'; import { registerLinkResolver, LinkType, getLinkResolverIdentifier } from './linkResolver.service.js'; import { uploadData } from './storage.service.js'; import { IService } from './types/IService.js'; -import { constructIdentifierString, generateUUID } from './utils/helpers.js'; +import { constructIdentifierString, constructVerifyURL, generateUUID } from './utils/helpers.js'; import { decodeEnvelopedVC, issueVC } from './vckit.service.js'; import { ITraceabilityEvent, IDigitalIdentityAnchorContext } from './types/index.js'; import { validateDigitalIdentityAnchorContext } from './validateContext.js'; @@ -49,10 +49,13 @@ export const processDigitalIdentityAnchor: IService = async ( }); const decodedEnvelopedVC = decodeEnvelopedVC(vc); - const vcUrl = await uploadData(storage, vc, credentialId); + + const { uri, key, hash } = await uploadData(storage, vc, credentialId); + const verifyURL = constructVerifyURL({ uri, key, hash }); const linkResolver = await registerLinkResolver( - vcUrl, + uri, + verifyURL, digitalIdentityAnchor.dlrIdentificationKeyType, identifier, digitalIdentityAnchor.dlrLinkTitle, diff --git a/packages/services/src/storage.service.ts b/packages/services/src/storage.service.ts index d199383c..8f61067f 100644 --- a/packages/services/src/storage.service.ts +++ b/packages/services/src/storage.service.ts @@ -1,5 +1,4 @@ import { IStorageService, IUploadData } from './types/storage.js'; -import { getValueByPath } from './utils/helpers.js'; import { publicAPI } from './utils/httpService.js'; export const storageService: IStorageService = async (config) => { @@ -35,5 +34,5 @@ export const uploadData: IUploadData = async (storage, data, id) => { options: storage.options, }); - return getValueByPath(result, storage.params.resultPath); + return result; }; diff --git a/packages/services/src/types/storage.ts b/packages/services/src/types/storage.ts index 73ca0c4e..262deb70 100644 --- a/packages/services/src/types/storage.ts +++ b/packages/services/src/types/storage.ts @@ -4,7 +4,6 @@ export type StorageServiceOptions = { }; export type StorageServiceParams = { - resultPath: string; [key: string]: any; }; From bb3c1e1e606f4b677c525494af5442a661df83a3 Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Tue, 12 Nov 2024 13:45:58 +0700 Subject: [PATCH 2/8] chore: remove resultPath propety in docs and unit tests --- documentation/docs/mock-apps/common/storage.md | 2 -- .../components/conformity-credential.md | 1 - .../mock-apps/configuration/service-config.md | 1 - .../docs/mock-apps/conformity-credential.md | 1 - documentation/docs/mock-apps/services/index.md | 1 - .../services/process-aggregation-event.md | 1 - .../services/process-association-event.md | 1 - .../process-digital-conformity-credential.md | 1 - .../process-digital-facility-record.md | 1 - .../process-digital-identity-anchor.md | 1 - .../docs/mock-apps/services/process-dpp.md | 1 - .../mock-apps/services/process-object-event.md | 1 - .../services/process-traceability-event.md | 1 - .../services/process-transaction-event.md | 1 - .../process-transformation-event-only.md | 1 - .../services/process-transformation-event.md | 1 - .../__tests__/ConformityCredential.test.tsx | 8 ++------ .../src/__tests__/ConformityUtils.test.tsx | 8 ++------ .../services/src/__tests__/mocks/constants.ts | 18 ++++++------------ .../services/src/__tests__/storage.test.ts | 1 - .../src/__tests__/transformationEvent.test.ts | 2 +- 21 files changed, 11 insertions(+), 43 deletions(-) diff --git a/documentation/docs/mock-apps/common/storage.md b/documentation/docs/mock-apps/common/storage.md index 69725eaa..f1da5512 100644 --- a/documentation/docs/mock-apps/common/storage.md +++ b/documentation/docs/mock-apps/common/storage.md @@ -18,7 +18,6 @@ The `Storage` object is responsible for managing the configuration of the [Stora "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { @@ -46,7 +45,6 @@ The `params` object contains specific parameters for the storage service. | Property | Required | Description | Type | | ---------- | -------- | -------------------------------------------------------------------- | ------ | | bucket | Yes | The name of the storage bucket | String | -| resultPath | Yes | The path where the result (e.g., URI) will be stored in the response | String | ### options diff --git a/documentation/docs/mock-apps/components/conformity-credential.md b/documentation/docs/mock-apps/components/conformity-credential.md index ac6707f7..d5215c5a 100644 --- a/documentation/docs/mock-apps/components/conformity-credential.md +++ b/documentation/docs/mock-apps/components/conformity-credential.md @@ -55,7 +55,6 @@ The ConformityCredential component allows users to request and manage conformity "storedCredentialsConfig": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { diff --git a/documentation/docs/mock-apps/configuration/service-config.md b/documentation/docs/mock-apps/configuration/service-config.md index 0490f9e8..3f7affa6 100644 --- a/documentation/docs/mock-apps/configuration/service-config.md +++ b/documentation/docs/mock-apps/configuration/service-config.md @@ -65,7 +65,6 @@ graph TD "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { diff --git a/documentation/docs/mock-apps/conformity-credential.md b/documentation/docs/mock-apps/conformity-credential.md index 12bd353f..c2f00a67 100644 --- a/documentation/docs/mock-apps/conformity-credential.md +++ b/documentation/docs/mock-apps/conformity-credential.md @@ -180,7 +180,6 @@ Example config snippet: "storedCredentialsConfig": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { diff --git a/documentation/docs/mock-apps/services/index.md b/documentation/docs/mock-apps/services/index.md index 390788c3..012e62ac 100644 --- a/documentation/docs/mock-apps/services/index.md +++ b/documentation/docs/mock-apps/services/index.md @@ -76,7 +76,6 @@ graph TD "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { diff --git a/documentation/docs/mock-apps/services/process-aggregation-event.md b/documentation/docs/mock-apps/services/process-aggregation-event.md index b744a765..fb6c409d 100644 --- a/documentation/docs/mock-apps/services/process-aggregation-event.md +++ b/documentation/docs/mock-apps/services/process-aggregation-event.md @@ -62,7 +62,6 @@ P-->>C: Return VC and resolver URL "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { diff --git a/documentation/docs/mock-apps/services/process-association-event.md b/documentation/docs/mock-apps/services/process-association-event.md index 356da11a..ef8ab7f2 100644 --- a/documentation/docs/mock-apps/services/process-association-event.md +++ b/documentation/docs/mock-apps/services/process-association-event.md @@ -65,7 +65,6 @@ P-->>C: Return association event VC and resolver URL "url": "https://storage.example.com/upload", "params": { "bucket": "bucket-name", - "resultPath": "/url" } }, "dlr": { diff --git a/documentation/docs/mock-apps/services/process-digital-conformity-credential.md b/documentation/docs/mock-apps/services/process-digital-conformity-credential.md index bdda50d9..560f2c62 100644 --- a/documentation/docs/mock-apps/services/process-digital-conformity-credential.md +++ b/documentation/docs/mock-apps/services/process-digital-conformity-credential.md @@ -65,7 +65,6 @@ P-->>C: Return digital conformity credential VC and resolver URL "url": "https://storage.example.com/upload", "params": { "bucket": "bucket-name", - "resultPath": "/url" } }, "dlr": { diff --git a/documentation/docs/mock-apps/services/process-digital-facility-record.md b/documentation/docs/mock-apps/services/process-digital-facility-record.md index ab47d54c..0b82a04f 100644 --- a/documentation/docs/mock-apps/services/process-digital-facility-record.md +++ b/documentation/docs/mock-apps/services/process-digital-facility-record.md @@ -62,7 +62,6 @@ P-->>C: Return digital facility record VC and resolver URL "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { diff --git a/documentation/docs/mock-apps/services/process-digital-identity-anchor.md b/documentation/docs/mock-apps/services/process-digital-identity-anchor.md index 1cb0d1de..10a977e4 100644 --- a/documentation/docs/mock-apps/services/process-digital-identity-anchor.md +++ b/documentation/docs/mock-apps/services/process-digital-identity-anchor.md @@ -62,7 +62,6 @@ P-->>C: Return digital identity anchor VC and resolver URL "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { diff --git a/documentation/docs/mock-apps/services/process-dpp.md b/documentation/docs/mock-apps/services/process-dpp.md index 46e3733c..19baba9a 100644 --- a/documentation/docs/mock-apps/services/process-dpp.md +++ b/documentation/docs/mock-apps/services/process-dpp.md @@ -85,7 +85,6 @@ P-->>C: Return VC and resolver URL "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { diff --git a/documentation/docs/mock-apps/services/process-object-event.md b/documentation/docs/mock-apps/services/process-object-event.md index 56ed55c9..05adeee1 100644 --- a/documentation/docs/mock-apps/services/process-object-event.md +++ b/documentation/docs/mock-apps/services/process-object-event.md @@ -62,7 +62,6 @@ P-->>C: Return object event VC and resolver URL "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { diff --git a/documentation/docs/mock-apps/services/process-traceability-event.md b/documentation/docs/mock-apps/services/process-traceability-event.md index 63a7759d..fed488e8 100644 --- a/documentation/docs/mock-apps/services/process-traceability-event.md +++ b/documentation/docs/mock-apps/services/process-traceability-event.md @@ -56,7 +56,6 @@ P-->>C: Return event VC and resolver URL "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { diff --git a/documentation/docs/mock-apps/services/process-transaction-event.md b/documentation/docs/mock-apps/services/process-transaction-event.md index 27c7bdeb..00b20c94 100644 --- a/documentation/docs/mock-apps/services/process-transaction-event.md +++ b/documentation/docs/mock-apps/services/process-transaction-event.md @@ -64,7 +64,6 @@ P-->>C: Return VC and resolver URL "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { diff --git a/documentation/docs/mock-apps/services/process-transformation-event-only.md b/documentation/docs/mock-apps/services/process-transformation-event-only.md index 840e0981..59d463d7 100644 --- a/documentation/docs/mock-apps/services/process-transformation-event-only.md +++ b/documentation/docs/mock-apps/services/process-transformation-event-only.md @@ -65,7 +65,6 @@ P-->>C: Return transformation event VC and resolver URL "url": "https://storage.example.com/upload", "params": { "bucket": "bucket-name", - "resultPath": "/url" } }, "dlr": { diff --git a/documentation/docs/mock-apps/services/process-transformation-event.md b/documentation/docs/mock-apps/services/process-transformation-event.md index 98dfa48d..95b841ee 100644 --- a/documentation/docs/mock-apps/services/process-transformation-event.md +++ b/documentation/docs/mock-apps/services/process-transformation-event.md @@ -75,7 +75,6 @@ P-->>C: Return EPCIS VC "storage": { "url": "http://localhost:3334/v1/documents", "params": { - "resultPath": "/uri", "bucket": "verifiable-credentials" }, "options": { diff --git a/packages/components/src/__tests__/ConformityCredential.test.tsx b/packages/components/src/__tests__/ConformityCredential.test.tsx index 28d29313..d66b270c 100644 --- a/packages/components/src/__tests__/ConformityCredential.test.tsx +++ b/packages/components/src/__tests__/ConformityCredential.test.tsx @@ -44,9 +44,7 @@ describe('ConformityCredential', () => { const storedCredentialsConfig = { url: 'https://example.com', - params: { - resultPath: '', - }, + params: {}, }; render( @@ -82,9 +80,7 @@ describe('ConformityCredential', () => { const storedCredentialsConfig = { url: 'https://example.com', - params: { - resultPath: '', - }, + params: {}, }; it('should save credential as string when trigger onClickStorageCredential function', async () => { diff --git a/packages/components/src/__tests__/ConformityUtils.test.tsx b/packages/components/src/__tests__/ConformityUtils.test.tsx index 13b3635c..fe41a054 100644 --- a/packages/components/src/__tests__/ConformityUtils.test.tsx +++ b/packages/components/src/__tests__/ConformityUtils.test.tsx @@ -4,9 +4,7 @@ describe('checkStoredCredentials', () => { it('should return the stored credentials if they are valid', () => { const storedCredentials = { url: 'https://example.com', - params: { - resultPath: '', - }, + params: {}, }; const result = checkStoredCredentialsConfig(storedCredentials); @@ -23,9 +21,7 @@ describe('checkStoredCredentials', () => { it('should throw an error if the stored credentials url is invalid', () => { const storedCredentials = { url: '', - params: { - resultPath: '', - }, + params: {}, }; const result = checkStoredCredentialsConfig(storedCredentials); diff --git a/packages/services/src/__tests__/mocks/constants.ts b/packages/services/src/__tests__/mocks/constants.ts index 078a3361..0ec3614d 100644 --- a/packages/services/src/__tests__/mocks/constants.ts +++ b/packages/services/src/__tests__/mocks/constants.ts @@ -48,7 +48,7 @@ export const contextTransformationEvent = { storage: { url: 'https://storage.example.com', params: { - resultPath: '', + bucket: 'transformation-event-bucket', }, }, productTransformation: { @@ -149,7 +149,7 @@ export const contextDPP = { storage: { url: 'https://storage.example.com', params: { - resultPath: '', + bucket: 'dpp-bucket', }, }, identifierKeyPath: '/herd/identifier', @@ -230,7 +230,7 @@ export const traceabilityEventContext = { storage: { url: 'https://storage.example.com/upload', params: { - resultPath: '/url', + bucket: 'traceability-event-bucket', }, }, dlr: { @@ -263,9 +263,7 @@ export const digitalIdentityAnchorContext = { }, storage: { url: 'https://storage.example.com', - params: { - resultPath: '', - }, + params: {}, }, identifierKeyPath: '/id', }; @@ -291,9 +289,7 @@ export const digitalFacilityRecordContext = { }, storage: { url: 'https://storage.example.com', - params: { - resultPath: '', - }, + params: {}, }, identifierKeyPath: '/id', }; @@ -319,9 +315,7 @@ export const digitalConformityCredentialContext = { }, storage: { url: 'https://storage.example.com', - params: { - resultPath: '', - }, + params: {}, }, identifierKeyPath: '/id', }; diff --git a/packages/services/src/__tests__/storage.test.ts b/packages/services/src/__tests__/storage.test.ts index cf62f6f1..462a4391 100644 --- a/packages/services/src/__tests__/storage.test.ts +++ b/packages/services/src/__tests__/storage.test.ts @@ -54,7 +54,6 @@ describe('storage service', () => { params: { data: credentialPayload, path: path, - resultPath: '/url', }, options: { method: 'PUT', diff --git a/packages/services/src/__tests__/transformationEvent.test.ts b/packages/services/src/__tests__/transformationEvent.test.ts index be97cfa5..b8dca1a2 100644 --- a/packages/services/src/__tests__/transformationEvent.test.ts +++ b/packages/services/src/__tests__/transformationEvent.test.ts @@ -135,7 +135,7 @@ describe('Transformation event', () => { }; const filename = 'epcis-transformation-event/1234'; - const urlUpload = await uploadVC(filename, mockVc, { url: 'http://localhost', params: { resultPath: '' } }); + const urlUpload = await uploadVC(filename, mockVc, { url: 'http://localhost', params: {} }); expect(urlUpload).toEqual(expectResult); }); From aad749b52843ace7c962506b059d43e2e34d0a2e Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Tue, 12 Nov 2024 14:52:03 +0700 Subject: [PATCH 3/8] docs: update verify-app documentation to describe the decryption process --- documentation/docs/mock-apps/common/verify-link.md | 5 +++-- documentation/docs/mock-apps/verify-app.md | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/documentation/docs/mock-apps/common/verify-link.md b/documentation/docs/mock-apps/common/verify-link.md index f410f6f9..fff95dc9 100644 --- a/documentation/docs/mock-apps/common/verify-link.md +++ b/documentation/docs/mock-apps/common/verify-link.md @@ -31,15 +31,16 @@ The general structure of the verify link is as follows: ### Decoded (Human-readable) Example: ``` -http://localhost:3001/verify?q={payload:{uri:http://localhost:3001/conformity-credentials/steel-mill-1-emissions.json}} +http://localhost:3001/verify?q={payload:{uri:'http://localhost:3001/conformity-credentials/steel-mill-1-emissions.json', key:'secret', hash:'595d8d20c586c6f55f8a758f294674fa85069db5c518a0f4cbbd3fd61f46522f'}} ``` ### Encoded (URL-safe) Example: ``` http://localhost:3001/verify?q%3D%7Bpayload%3A%7Buri%3Ahttp%3A%2F%2Flocalhost%3A3001%2Fconformity-credentials%2Fsteel-mill-1-emissions.json%7D%7D +http://localhost:3001/verify?q%3D%7B%22payload%22%3A%7B%22uri%22%3A%22http%3A%2F%2Flocalhost%3A3001%2Fconformity-credentials%2Fsteel-mill-1-emissions.json%22%2C%22key%22%3A%22secret%22%2C%22hash%22%3A%22595d8d20c586c6f55f8a758f294674fa85069db5c518a0f4cbbd3fd61f46522f%22%7D%7D ``` ### Production Example: ``` -https://www.example.com/verify?q=%7B%22payload%22%3A%7B%22uri%22%3A%22https%3A%2F%2Fstorage.googleapis.com%2Fverifiable-credentials%2Fconformity-credentials%2Ftop-line-steel-dcc.json%22%7D%7D +https://www.example.com/verify?q=%7B%22payload%22%3A%7B%22uri%22%3A%22https%3A%2F%2Fstorage.googleapis.com%2Fverifiable-credentials%2Fconformity-credentials%2Ftop-line-steel-dcc.json%22%2C%22key%22%3A%22secret%22%2C%22hash%22%3A%22595d8d20c586c6f55f8a758f294674fa85069db5c518a0f4cbbd3fd61f46522f%22%7D%7D ``` \ No newline at end of file diff --git a/documentation/docs/mock-apps/verify-app.md b/documentation/docs/mock-apps/verify-app.md index 651d1850..364c8282 100644 --- a/documentation/docs/mock-apps/verify-app.md +++ b/documentation/docs/mock-apps/verify-app.md @@ -43,3 +43,7 @@ To ensure the integrity of the credential, a hash value is included in the verif Upon retrieval of the credential, the application will compute its hash and compare it with the provided value in the URL. If the computed hash matches the provided hash, the credential is considered valid and unaltered. The hash is optional and can be omitted from the verification link. If the hash is not provided, the credential will not be validated against it. + +## Decryption (if required) + +If the credential is encrypted, the decryption key is included in the verification link. The application will use this key to decrypt the credential before proceeding with the verification process. \ No newline at end of file From f9d45b422fa162e544b9cbe3c864b2f565bd1046 Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Tue, 12 Nov 2024 16:58:23 +0700 Subject: [PATCH 4/8] test: add additional test case for the constructVerifyURL function --- packages/services/src/__tests__/helpers.test.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/services/src/__tests__/helpers.test.ts b/packages/services/src/__tests__/helpers.test.ts index 85f41a26..74490f62 100644 --- a/packages/services/src/__tests__/helpers.test.ts +++ b/packages/services/src/__tests__/helpers.test.ts @@ -294,6 +294,15 @@ describe('constructVerifyURL', () => { expect(result).toBe(expectedURL); }); + it('should construct the correct verify URL with URI and hash', () => { + const uri = 'http://example.com/credential'; + const hash = 'someHash'; + const result = constructVerifyURL({ uri, hash }); + + const expectedURL = 'http://localhost:3000/verify?q=%7B%22payload%22%3A%7B%22uri%22%3A%22http%3A%2F%2Fexample.com%2Fcredential%22%2C%22hash%22%3A%22someHash%22%7D%7D'; + expect(result).toBe(expectedURL); + }); + it('should construct the correct verify URL with URI, key, and hash', () => { const uri = 'http://example.com/credential'; const key = 'someKey'; From 706a7a9bc15883feeaf4f124838baf1c051d0668 Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Tue, 12 Nov 2024 17:06:17 +0700 Subject: [PATCH 5/8] test: add additional test case for the constructVerifyURL function --- packages/services/src/__tests__/helpers.test.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/services/src/__tests__/helpers.test.ts b/packages/services/src/__tests__/helpers.test.ts index 74490f62..294911d8 100644 --- a/packages/services/src/__tests__/helpers.test.ts +++ b/packages/services/src/__tests__/helpers.test.ts @@ -303,6 +303,15 @@ describe('constructVerifyURL', () => { expect(result).toBe(expectedURL); }); + it('should construct the correct verify URL with URI and key', () => { + const uri = 'http://example.com/credential'; + const key = 'someKey'; + const result = constructVerifyURL({ uri, key }); + + const expectedURL = 'http://localhost:3000/verify?q=%7B%22payload%22%3A%7B%22uri%22%3A%22http%3A%2F%2Fexample.com%2Fcredential%22%2C%22key%22%3A%22someKey%22%7D%7D'; + expect(result).toBe(expectedURL); + }); + it('should construct the correct verify URL with URI, key, and hash', () => { const uri = 'http://example.com/credential'; const key = 'someKey'; From e50a8956f79ac5517e002ac531383fc39b20d505 Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Tue, 12 Nov 2024 18:13:04 +0700 Subject: [PATCH 6/8] chore: update mock data --- packages/services/src/__tests__/linkResolver.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/services/src/__tests__/linkResolver.test.ts b/packages/services/src/__tests__/linkResolver.test.ts index a349a654..4c24aa90 100644 --- a/packages/services/src/__tests__/linkResolver.test.ts +++ b/packages/services/src/__tests__/linkResolver.test.ts @@ -30,7 +30,7 @@ describe('create link resolve service', () => { const mockValue = { eventLink: 'https://localhost/epcis-transformation-event/1234', - eventVerifyLink: 'https://verify.com/dev/verifyCredential?q=https://localhost/epcis-transformation-event/1234&key=123&hash=abcde123', + eventVerifyLink: 'https%3A%2F%2Fverify.com%2Fdev%2FverifyCredential%3Fq%3Dhttps%3A%2F%2Flocalhost%2Fepcis-transformation-event%2F1234%26key%3D123%26hash%3Dabcde123', identificationKeyType: IdentificationKeyType.nlisid, identificationKey: 'gtin-key', itemDescription: 'EPCIS transformation event VC', @@ -75,7 +75,7 @@ describe('create link resolve service', () => { const mockValue = { eventLink: 'https://localhost/epcis-transformation-event/1234', - eventVerifyLink: 'https://verify.com/dev/verifyCredential?q=https://localhost/epcis-transformation-event/1234&key=123&hash=abcde123', + eventVerifyLink: 'https%3A%2F%2Fverify.com%2Fdev%2FverifyCredential%3Fq%3Dhttps%3A%2F%2Flocalhost%2Fepcis-transformation-event%2F1234%26key%3D123%26hash%3Dabcde123', identificationKeyType: IdentificationKeyType.nlisid, identificationKey: 'gtin-key', itemDescription: 'EPCIS transformation event VC', @@ -121,7 +121,7 @@ describe('create link resolve service', () => { const mockValue = { eventLink: 'https://localhost/epcis-transformation-event/1234', - eventVerifyLink: 'https://verify.com/dev/verifyCredential?q=https://localhost/epcis-transformation-event/1234&key=123&hash=abcde123', + eventVerifyLink: 'https%3A%2F%2Fverify.com%2Fdev%2FverifyCredential%3Fq%3Dhttps%3A%2F%2Flocalhost%2Fepcis-transformation-event%2F1234%26key%3D123%26hash%3Dabcde123', identificationKeyType: IdentificationKeyType.nlisid, identificationKey: 'gtin-key', itemDescription: 'EPCIS transformation event VC', From 99a3c23e081b0cbced536ccf890aa71fc76aba24 Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Wed, 13 Nov 2024 15:40:10 +0700 Subject: [PATCH 7/8] chore: update scanning page to use the textHtml mime type link set --- packages/mock-app/src/pages/Scanning.tsx | 6 ++---- packages/services/src/linkResolver.service.ts | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/mock-app/src/pages/Scanning.tsx b/packages/mock-app/src/pages/Scanning.tsx index 2b70855c..a1b18895 100644 --- a/packages/mock-app/src/pages/Scanning.tsx +++ b/packages/mock-app/src/pages/Scanning.tsx @@ -43,10 +43,8 @@ const Scanning = () => { }; const redirectToVerifyPage = (verifyDlrPassportUri: string) => { - const queryPayload = JSON.stringify({ payload: { uri: verifyDlrPassportUri } }); - const queryString = `q=${encodeURIComponent(queryPayload)}`; - - navigate(`/verify?${queryString}`); + const urlComponents = new URL(verifyDlrPassportUri); + navigate(`${urlComponents.pathname}${urlComponents.search}`); }; React.useEffect(() => { diff --git a/packages/services/src/linkResolver.service.ts b/packages/services/src/linkResolver.service.ts index 24b20fd6..2664ceec 100644 --- a/packages/services/src/linkResolver.service.ts +++ b/packages/services/src/linkResolver.service.ts @@ -255,8 +255,8 @@ export const getDlrPassport = async (dlrUrl: string): Promise => { return null; } - // Find DLR passport with MIME type application/json - const dlrPassport = dlrPassports.find((passportItem: any) => passportItem?.type === MimeTypeEnum.applicationJson); + // Find DLR passport with MIME type text/html + const dlrPassport = dlrPassports.find((passportItem: any) => passportItem?.type === MimeTypeEnum.textHtml); if (!dlrPassport) { return null; } From 739fdfb913bf47d171c3274ca1f549730e170f96 Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Wed, 13 Nov 2024 16:01:44 +0700 Subject: [PATCH 8/8] chore: update the error message for the verify page and its unit tests --- .../mock-app/src/__tests__/Verify.test.tsx | 44 ++++++++++++++++++- packages/mock-app/src/pages/Verify.tsx | 25 ++++++----- 2 files changed, 58 insertions(+), 11 deletions(-) diff --git a/packages/mock-app/src/__tests__/Verify.test.tsx b/packages/mock-app/src/__tests__/Verify.test.tsx index dbd13f9c..acd21a28 100644 --- a/packages/mock-app/src/__tests__/Verify.test.tsx +++ b/packages/mock-app/src/__tests__/Verify.test.tsx @@ -424,7 +424,49 @@ describe('Verify', () => { }); await waitFor(() => { - expect(screen.getByText('Hash invalid')).toBeInTheDocument(); + expect(screen.getByText('Failed to compare the hash in the verify URL with the VC hash.')).toBeInTheDocument(); + }); + }); + + it('should show error screen when the key is invalid', async () => { + const mockPayloadInvalidKey = { + payload: { + uri: 'http://localhost:3334/v1/verifiable-credentials/6c70251a-f2e7-48a0-a86c-e1027f0e7143.json', + hash: '595d8d20c586c6f55f8a758f294674fa85069db5c518a0f4cbbd3fd61f46522f', + key: 'invalid-key', + }, + }; + const mockEncryptedCredential = { + cipherText: '+qygK55Jq2S/VmhI8xxHr6JQZbZpM2UbwwPtXgYAh6Opn8Re0y+VStefzXgk3KVRYeaZd+/WZv/Nm3XXdxouGqk2toWHZtAnYAW', + iv: 'HMFLTHEabOowe0pj', + tag: '0B6Js19du2TJ0ADdYe2Ipw==', + type: 'aes-256-gcm' + }; + // URL-encode the payload for use as a query parameter + const encodedPayload = `q=${encodeURIComponent(JSON.stringify(mockPayloadInvalidKey))}`; + (useLocation as any).mockImplementation(() => ({ + search: encodedPayload, + })); + + jest.spyOn(publicAPI, 'get').mockResolvedValueOnce(mockEncryptedCredential); + + (computeHash as any).mockImplementation(() => mockPayloadInvalidKey.payload.hash); + (decryptCredential as any).mockImplementation(() => { throw new Error('Failed to decrypt credential') }); + + (verifyVC as jest.Mock).mockImplementation(() => ({ + verified: true, + })); + + await act(async () => { + render( + + + , + ); + }); + + await waitFor(() => { + expect(screen.getByText('Failed to decrypt credential.')).toBeInTheDocument(); }); }); }); diff --git a/packages/mock-app/src/pages/Verify.tsx b/packages/mock-app/src/pages/Verify.tsx index 9a0bbe95..2a8a6935 100644 --- a/packages/mock-app/src/pages/Verify.tsx +++ b/packages/mock-app/src/pages/Verify.tsx @@ -59,7 +59,7 @@ const Verify = () => { const verifyHash = (credential: VerifiableCredential) => { if (hash) { const computedHash = computeHash(credential); - if (computedHash !== hash) return displayErrorUI(['Hash invalid']); + if (computedHash !== hash) return displayErrorUI(['Failed to compare the hash in the verify URL with the VC hash.']); } return setCredential(credential); @@ -74,15 +74,20 @@ const Verify = () => { 'tag' in encryptedCredential && 'type' in encryptedCredential ) { - const credentialJsonString = decryptCredential({ - cipherText, - key, - iv, - tag, - type, - }); - - credentialObject = JSON.parse(credentialJsonString); + try { + const credentialJsonString = decryptCredential({ + cipherText, + key, + iv, + tag, + type, + }); + + credentialObject = JSON.parse(credentialJsonString); + } catch (error) { + return displayErrorUI(['Failed to decrypt credential.']); + } + } else { credentialObject = _.cloneDeep(encryptedCredential); }