Skip to content

Commit 4d7d3c1

Browse files
feat: generic attachment handler (openwallet-foundation#578)
Signed-off-by: morrieinmaas <[email protected]> Co-authored-by: annelein <[email protected]>
1 parent cf69a54 commit 4d7d3c1

11 files changed

+65
-54
lines changed

Diff for: packages/core/src/decorators/attachment/Attachment.test.ts

+33-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { JsonTransformer } from '../..'
1+
import { JsonEncoder } from '../../utils/JsonEncoder'
2+
import { JsonTransformer } from '../../utils/JsonTransformer'
23

3-
import { Attachment } from './Attachment'
4+
import { Attachment, AttachmentData } from './Attachment'
45

56
const mockJson = {
67
'@id': 'ceffce22-6471-43e4-8945-b604091981c9',
@@ -17,6 +18,18 @@ const mockJson = {
1718
},
1819
}
1920

21+
const mockJsonBase64 = {
22+
'@id': 'ceffce22-6471-43e4-8945-b604091981c9',
23+
description: 'A small picture of a cat',
24+
filename: 'cat.png',
25+
'mime-type': 'text/plain',
26+
lastmod_time: new Date(),
27+
byte_count: 9200,
28+
data: {
29+
base64: JsonEncoder.toBase64(mockJson.data.json),
30+
},
31+
}
32+
2033
const id = 'ceffce22-6471-43e4-8945-b604091981c9'
2134
const description = 'A small picture of a cat'
2235
const filename = 'cat.png'
@@ -29,6 +42,7 @@ const data = {
2942
},
3043
sha256: '00d7b2068a0b237f14a7979bbfc01ad62f60792e459467bfc4a7d3b9a6dbbe3e',
3144
}
45+
const dataInstance = new AttachmentData(data)
3246

3347
describe('Decorators | Attachment', () => {
3448
it('should correctly transform Json to Attachment class', () => {
@@ -39,7 +53,7 @@ describe('Decorators | Attachment', () => {
3953
expect(decorator.filename).toBe(mockJson.filename)
4054
expect(decorator.lastmodTime).toEqual(mockJson.lastmod_time)
4155
expect(decorator.byteCount).toEqual(mockJson.byte_count)
42-
expect(decorator.data).toEqual(mockJson.data)
56+
expect(decorator.data).toMatchObject(mockJson.data)
4357
})
4458

4559
it('should correctly transform Attachment class to Json', () => {
@@ -50,7 +64,7 @@ describe('Decorators | Attachment', () => {
5064
mimeType,
5165
lastmodTime,
5266
byteCount,
53-
data,
67+
data: dataInstance,
5468
})
5569

5670
const json = JsonTransformer.toJSON(decorator)
@@ -64,6 +78,20 @@ describe('Decorators | Attachment', () => {
6478
data,
6579
}
6680

67-
expect(json).toEqual(transformed)
81+
expect(json).toMatchObject(transformed)
82+
})
83+
84+
it('should return the data correctly if only JSON exists', () => {
85+
const decorator = JsonTransformer.fromJSON(mockJson, Attachment)
86+
87+
const gotData = decorator.data.getDataAsJson()
88+
expect(decorator.data.json).toEqual(gotData)
89+
})
90+
91+
it('should return the data correctly if only Base64 exists', () => {
92+
const decorator = JsonTransformer.fromJSON(mockJsonBase64, Attachment)
93+
94+
const gotData = decorator.data.getDataAsJson()
95+
expect(mockJson.data.json).toEqual(gotData)
6896
})
6997
})

Diff for: packages/core/src/decorators/attachment/Attachment.ts

+15
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import {
1111
ValidateNested,
1212
} from 'class-validator'
1313

14+
import { AriesFrameworkError } from '../../error'
15+
import { JsonEncoder } from '../../utils/JsonEncoder'
1416
import { uuid } from '../../utils/uuid'
1517

1618
export interface AttachmentOptions {
@@ -45,6 +47,19 @@ export class AttachmentData {
4547
}
4648
}
4749

50+
/*
51+
* Helper function returning JSON representation of attachment data (if present). Tries to obtain the data from .base64 or .json, throws an error otherwise
52+
*/
53+
public getDataAsJson<T>(): T {
54+
if (typeof this.base64 === 'string') {
55+
return JsonEncoder.fromBase64(this.base64) as T
56+
} else if (this.json) {
57+
return this.json as T
58+
} else {
59+
throw new AriesFrameworkError('No attachment data found in `json` or `base64` data fields.')
60+
}
61+
}
62+
4863
/**
4964
* Base64-encoded data, when representing arbitrary content inline instead of via links. Optional.
5065
*/

Diff for: packages/core/src/modules/credentials/CredentialResponseCoordinator.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ export class CredentialResponseCoordinator {
133133
const indyCredential = credentialRecord.credentialMessage.indyCredential
134134

135135
if (!indyCredential) {
136-
this.agentConfig.logger.error(`Missing required base64 encoded attachment data for credential`)
136+
this.agentConfig.logger.error(`Missing required base64 or json encoded attachment data for credential`)
137137
return false
138138
}
139139

Diff for: packages/core/src/modules/credentials/__tests__/CredentialService.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,7 @@ describe('CredentialService', () => {
587587
})
588588
)
589589
).rejects.toThrowError(
590-
`Missing required base64 encoded attachment data for credential request with thread id ${threadId}`
590+
`Missing required base64 or json encoded attachment data for credential request with thread id ${threadId}`
591591
)
592592
})
593593

Diff for: packages/core/src/modules/credentials/messages/IssueCredentialMessage.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { Equals, IsArray, IsInstance, IsOptional, IsString, ValidateNested } fro
55

66
import { AgentMessage } from '../../../agent/AgentMessage'
77
import { Attachment } from '../../../decorators/attachment/Attachment'
8-
import { JsonEncoder } from '../../../utils/JsonEncoder'
98

109
export const INDY_CREDENTIAL_ATTACHMENT_ID = 'libindy-cred-0'
1110

@@ -48,13 +47,8 @@ export class IssueCredentialMessage extends AgentMessage {
4847
public get indyCredential(): Cred | null {
4948
const attachment = this.credentialAttachments.find((attachment) => attachment.id === INDY_CREDENTIAL_ATTACHMENT_ID)
5049

51-
// Return null if attachment is not found
52-
if (!attachment?.data?.base64) {
53-
return null
54-
}
55-
5650
// Extract credential from attachment
57-
const credentialJson = JsonEncoder.fromBase64(attachment.data.base64)
51+
const credentialJson = attachment?.data?.getDataAsJson<Cred>() ?? null
5852

5953
return credentialJson
6054
}

Diff for: packages/core/src/modules/credentials/messages/OfferCredentialMessage.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { Equals, IsArray, IsInstance, IsOptional, IsString, ValidateNested } fro
55

66
import { AgentMessage } from '../../../agent/AgentMessage'
77
import { Attachment } from '../../../decorators/attachment/Attachment'
8-
import { JsonEncoder } from '../../../utils/JsonEncoder'
98

109
import { CredentialPreview } from './CredentialPreview'
1110

@@ -63,13 +62,8 @@ export class OfferCredentialMessage extends AgentMessage {
6362
public get indyCredentialOffer(): CredOffer | null {
6463
const attachment = this.offerAttachments.find((attachment) => attachment.id === INDY_CREDENTIAL_OFFER_ATTACHMENT_ID)
6564

66-
// Return null if attachment is not found
67-
if (!attachment?.data?.base64) {
68-
return null
69-
}
70-
7165
// Extract credential offer from attachment
72-
const credentialOfferJson = JsonEncoder.fromBase64(attachment.data.base64)
66+
const credentialOfferJson = attachment?.data?.getDataAsJson<CredOffer>() ?? null
7367

7468
return credentialOfferJson
7569
}

Diff for: packages/core/src/modules/credentials/messages/RequestCredentialMessage.ts

+1-8
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { Equals, IsArray, IsInstance, IsOptional, IsString, ValidateNested } fro
55

66
import { AgentMessage } from '../../../agent/AgentMessage'
77
import { Attachment } from '../../../decorators/attachment/Attachment'
8-
import { JsonEncoder } from '../../../utils/JsonEncoder'
98

109
export const INDY_CREDENTIAL_REQUEST_ATTACHMENT_ID = 'libindy-cred-request-0'
1110

@@ -49,14 +48,8 @@ export class RequestCredentialMessage extends AgentMessage {
4948
const attachment = this.requestAttachments.find(
5049
(attachment) => attachment.id === INDY_CREDENTIAL_REQUEST_ATTACHMENT_ID
5150
)
52-
53-
// Return null if attachment is not found
54-
if (!attachment?.data?.base64) {
55-
return null
56-
}
57-
5851
// Extract proof request from attachment
59-
const credentialReqJson = JsonEncoder.fromBase64(attachment.data.base64)
52+
const credentialReqJson = attachment?.data?.getDataAsJson<CredReq>() ?? null
6053

6154
return credentialReqJson
6255
}

Diff for: packages/core/src/modules/credentials/services/CredentialService.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ export class CredentialService {
357357
const indyCredentialOffer = credentialOfferMessage.indyCredentialOffer
358358
if (!indyCredentialOffer) {
359359
throw new CredentialProblemReportError(
360-
`Missing required base64 encoded attachment data for credential offer with thread id ${credentialOfferMessage.threadId}`,
360+
`Missing required base64 or json encoded attachment data for credential offer with thread id ${credentialOfferMessage.threadId}`,
361361
{ problemCode: CredentialProblemReportReason.IssuanceAbandoned }
362362
)
363363
}
@@ -433,7 +433,7 @@ export class CredentialService {
433433

434434
if (!credentialOffer) {
435435
throw new CredentialProblemReportError(
436-
`Missing required base64 encoded attachment data for credential offer with thread id ${credentialRecord.threadId}`,
436+
`Missing required base64 or json encoded attachment data for credential offer with thread id ${credentialRecord.threadId}`,
437437
{ problemCode: CredentialProblemReportReason.IssuanceAbandoned }
438438
)
439439
}
@@ -494,7 +494,7 @@ export class CredentialService {
494494

495495
if (!indyCredentialRequest) {
496496
throw new CredentialProblemReportError(
497-
`Missing required base64 encoded attachment data for credential request with thread id ${credentialRequestMessage.threadId}`,
497+
`Missing required base64 or json encoded attachment data for credential request with thread id ${credentialRequestMessage.threadId}`,
498498
{ problemCode: CredentialProblemReportReason.IssuanceAbandoned }
499499
)
500500
}
@@ -554,7 +554,7 @@ export class CredentialService {
554554
const indyCredentialOffer = offerMessage?.indyCredentialOffer
555555
if (!indyCredentialOffer) {
556556
throw new CredentialProblemReportError(
557-
`Missing required base64 encoded attachment data for credential offer with thread id ${credentialRecord.threadId}`,
557+
`Missing required base64 or json encoded attachment data for credential offer with thread id ${credentialRecord.threadId}`,
558558
{ problemCode: CredentialProblemReportReason.IssuanceAbandoned }
559559
)
560560
}
@@ -563,7 +563,7 @@ export class CredentialService {
563563
const indyCredentialRequest = requestMessage?.indyCredentialRequest
564564
if (!indyCredentialRequest) {
565565
throw new CredentialProblemReportError(
566-
`Missing required base64 encoded attachment data for credential request with thread id ${credentialRecord.threadId}`,
566+
`Missing required base64 or json encoded attachment data for credential request with thread id ${credentialRecord.threadId}`,
567567
{ problemCode: CredentialProblemReportReason.IssuanceAbandoned }
568568
)
569569
}
@@ -641,7 +641,7 @@ export class CredentialService {
641641
const indyCredential = issueCredentialMessage.indyCredential
642642
if (!indyCredential) {
643643
throw new CredentialProblemReportError(
644-
`Missing required base64 encoded attachment data for credential with thread id ${issueCredentialMessage.threadId}`,
644+
`Missing required base64 or json encoded attachment data for credential with thread id ${issueCredentialMessage.threadId}`,
645645
{ problemCode: CredentialProblemReportReason.IssuanceAbandoned }
646646
)
647647
}

Diff for: packages/core/src/modules/proofs/messages/PresentationMessage.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { Equals, IsArray, IsString, ValidateNested, IsOptional, IsInstance } fro
55

66
import { AgentMessage } from '../../../agent/AgentMessage'
77
import { Attachment } from '../../../decorators/attachment/Attachment'
8-
import { JsonEncoder } from '../../../utils/JsonEncoder'
98

109
export const INDY_PROOF_ATTACHMENT_ID = 'libindy-presentation-0'
1110

@@ -60,12 +59,7 @@ export class PresentationMessage extends AgentMessage {
6059
public get indyProof(): IndyProof | null {
6160
const attachment = this.presentationAttachments.find((attachment) => attachment.id === INDY_PROOF_ATTACHMENT_ID)
6261

63-
// Return null if attachment is not found
64-
if (!attachment?.data?.base64) {
65-
return null
66-
}
67-
68-
const proofJson = JsonEncoder.fromBase64(attachment.data.base64)
62+
const proofJson = attachment?.data?.getDataAsJson<IndyProof>() ?? null
6963

7064
return proofJson
7165
}

Diff for: packages/core/src/modules/proofs/messages/RequestPresentationMessage.ts

+1-8
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { Equals, IsArray, IsString, ValidateNested, IsOptional, IsInstance } fro
33

44
import { AgentMessage } from '../../../agent/AgentMessage'
55
import { Attachment } from '../../../decorators/attachment/Attachment'
6-
import { JsonEncoder } from '../../../utils/JsonEncoder'
76
import { JsonTransformer } from '../../../utils/JsonTransformer'
87
import { ProofRequest } from '../models'
98

@@ -58,14 +57,8 @@ export class RequestPresentationMessage extends AgentMessage {
5857
const attachment = this.requestPresentationAttachments.find(
5958
(attachment) => attachment.id === INDY_PROOF_REQUEST_ATTACHMENT_ID
6059
)
61-
62-
// Return null if attachment is not found
63-
if (!attachment?.data?.base64) {
64-
return null
65-
}
66-
6760
// Extract proof request from attachment
68-
const proofRequestJson = JsonEncoder.fromBase64(attachment.data.base64)
61+
const proofRequestJson = attachment?.data?.getDataAsJson<ProofRequest>() ?? null
6962
const proofRequest = JsonTransformer.fromJSON(proofRequestJson, ProofRequest)
7063

7164
return proofRequest

Diff for: packages/core/src/modules/proofs/services/ProofService.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ export class ProofService {
354354
// Assert attachment
355355
if (!proofRequest) {
356356
throw new PresentationProblemReportError(
357-
`Missing required base64 encoded attachment data for presentation request with thread id ${proofRequestMessage.threadId}`,
357+
`Missing required base64 or json encoded attachment data for presentation request with thread id ${proofRequestMessage.threadId}`,
358358
{ problemCode: PresentationProblemReportReason.abandoned }
359359
)
360360
}
@@ -423,7 +423,7 @@ export class ProofService {
423423
const indyProofRequest = proofRecord.requestMessage?.indyProofRequest
424424
if (!indyProofRequest) {
425425
throw new PresentationProblemReportError(
426-
`Missing required base64 encoded attachment data for presentation with thread id ${proofRecord.threadId}`,
426+
`Missing required base64 or json encoded attachment data for presentation with thread id ${proofRecord.threadId}`,
427427
{ problemCode: PresentationProblemReportReason.abandoned }
428428
)
429429
}
@@ -490,14 +490,14 @@ export class ProofService {
490490

491491
if (!indyProofJson) {
492492
throw new PresentationProblemReportError(
493-
`Missing required base64 encoded attachment data for presentation with thread id ${presentationMessage.threadId}`,
493+
`Missing required base64 or json encoded attachment data for presentation with thread id ${presentationMessage.threadId}`,
494494
{ problemCode: PresentationProblemReportReason.abandoned }
495495
)
496496
}
497497

498498
if (!indyProofRequest) {
499499
throw new PresentationProblemReportError(
500-
`Missing required base64 encoded attachment data for presentation request with thread id ${presentationMessage.threadId}`,
500+
`Missing required base64 or json encoded attachment data for presentation request with thread id ${presentationMessage.threadId}`,
501501
{ problemCode: PresentationProblemReportReason.abandoned }
502502
)
503503
}

0 commit comments

Comments
 (0)