Skip to content

Commit

Permalink
feat(oob): allow to append attachments to invitations (#926)
Browse files Browse the repository at this point in the history
Signed-off-by: Ariel Gentile <[email protected]>
  • Loading branch information
genaris authored Jul 4, 2022
1 parent 95f90a5 commit 4800700
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Attachment } from './Attachment'
export function AttachmentDecorated<T extends BaseMessageConstructor>(Base: T) {
class AttachmentDecoratorExtension extends Base {
/**
* The ~attach decorator is required for appending attachments to a preview
* The ~attach decorator is required for appending attachments to a message
*/
@Expose({ name: '~attach' })
@Type(() => Attachment)
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export { InjectionSymbols } from './constants'
export type { Wallet } from './wallet/Wallet'
export type { TransportSession } from './agent/TransportService'
export { TransportService } from './agent/TransportService'
export { Attachment } from './decorators/attachment/Attachment'

import { parseInvitationUrl } from './utils/parseInvitation'
import { uuid } from './utils/uuid'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { validateOrReject } from 'class-validator'
import { parseUrl } from 'query-string'

import { Attachment } from '../../../decorators/attachment/Attachment'
import { ClassValidationError } from '../../../error/ClassValidationError'
import { JsonEncoder } from '../../../utils/JsonEncoder'
import { JsonTransformer } from '../../../utils/JsonTransformer'
Expand Down Expand Up @@ -71,6 +72,16 @@ describe('ConnectionInvitationMessage', () => {
serviceEndpoint: 'https://example.com',
label: 'test',
imageUrl: 'test-image-path',
appendedAttachments: [
new Attachment({
id: 'test-attachment',
data: {
json: {
value: 'test',
},
},
}),
],
})

const invitationUrl = invitation.toUrl({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { Attachment } from '../../../decorators/attachment/Attachment'

import { Transform } from 'class-transformer'
import { ArrayNotEmpty, IsArray, IsOptional, IsString, IsUrl, ValidateIf } from 'class-validator'
import { parseUrl } from 'query-string'
Expand All @@ -12,6 +14,7 @@ export interface BaseInvitationOptions {
id?: string
label: string
imageUrl?: string
appendedAttachments?: Attachment[]
}

export interface InlineInvitationOptions {
Expand Down Expand Up @@ -41,6 +44,7 @@ export class ConnectionInvitationMessage extends AgentMessage {
this.id = options.id || this.generateId()
this.label = options.label
this.imageUrl = options.imageUrl
this.appendedAttachments = options.appendedAttachments

if (isDidInvitation(options)) {
this.did = options.did
Expand Down
5 changes: 5 additions & 0 deletions packages/core/src/modules/oob/OutOfBandModule.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { AgentMessage } from '../../agent/AgentMessage'
import type { AgentMessageReceivedEvent } from '../../agent/Events'
import type { Attachment } from '../../decorators/attachment/Attachment'
import type { Logger } from '../../logger'
import type { ConnectionRecord, Routing, ConnectionInvitationMessage } from '../../modules/connections'
import type { DependencyManager } from '../../plugins'
Expand Down Expand Up @@ -54,6 +55,7 @@ export interface CreateOutOfBandInvitationConfig {
multiUseInvitation?: boolean
autoAcceptConnection?: boolean
routing?: Routing
appendedAttachments?: Attachment[]
}

export interface CreateLegacyInvitationConfig {
Expand Down Expand Up @@ -134,6 +136,8 @@ export class OutOfBandModule {
const messages = config.messages && config.messages.length > 0 ? config.messages : undefined
const label = config.label ?? this.agentConfig.label
const imageUrl = config.imageUrl ?? this.agentConfig.connectionImageUrl
const appendedAttachments =
config.appendedAttachments && config.appendedAttachments.length > 0 ? config.appendedAttachments : undefined

if (!handshake && !messages) {
throw new AriesFrameworkError(
Expand Down Expand Up @@ -182,6 +186,7 @@ export class OutOfBandModule {
accept: didCommProfiles,
services,
handshakeProtocols,
appendedAttachments,
}
const outOfBandInvitation = new OutOfBandInvitation(options)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { ClassValidationError } from '../../../error/ClassValidationError'

import { Attachment } from '../../../decorators/attachment/Attachment'
import { JsonEncoder } from '../../../utils/JsonEncoder'
import { JsonTransformer } from '../../../utils/JsonTransformer'
import { OutOfBandInvitation } from '../messages/OutOfBandInvitation'
Expand Down Expand Up @@ -86,6 +87,70 @@ describe('OutOfBandInvitation', () => {
expect(invitation).toBeInstanceOf(OutOfBandInvitation)
})

test('create an instance of `OutOfBandInvitation` from JSON object with appended attachments', () => {
const json = {
'@type': 'https://didcomm.org/out-of-band/1.1/invitation',
'@id': '69212a3a-d068-4f9d-a2dd-4741bca89af3',
label: 'Faber College',
goal_code: 'issue-vc',
goal: 'To issue a Faber College Graduate credential',
handshake_protocols: ['https://didcomm.org/didexchange/1.0', 'https://didcomm.org/connections/1.0'],
services: ['did:sov:LjgpST2rjsoxYegQDRm7EL'],
'~attach': [
{
'@id': 'view-1',
'mime-type': 'image/png',
filename: 'IMG1092348.png',
lastmod_time: '2018-12-24 18:24:07Z',
description: 'view from doorway, facing east, with lights off',
data: {
base64: 'dmlldyBmcm9tIGRvb3J3YXksIGZhY2luZyBlYXN0LCB3aXRoIGxpZ2h0cyBvZmY=',
},
},
{
'@id': 'view-2',
'mime-type': 'image/png',
filename: 'IMG1092349.png',
lastmod_time: '2018-12-24 18:25:49Z',
description: 'view with lamp in the background',
data: {
base64: 'dmlldyB3aXRoIGxhbXAgaW4gdGhlIGJhY2tncm91bmQ=',
},
},
],
}

const invitation = OutOfBandInvitation.fromJson(json)
expect(invitation).toBeDefined()
expect(invitation).toBeInstanceOf(OutOfBandInvitation)
expect(invitation.appendedAttachments).toBeDefined()
expect(invitation.appendedAttachments?.length).toEqual(2)
expect(invitation.getAppendedAttachmentById('view-1')).toEqual(
new Attachment({
id: 'view-1',
mimeType: 'image/png',
filename: 'IMG1092348.png',
lastmodTime: new Date('2018-12-24 18:24:07Z'),
description: 'view from doorway, facing east, with lights off',
data: {
base64: 'dmlldyBmcm9tIGRvb3J3YXksIGZhY2luZyBlYXN0LCB3aXRoIGxpZ2h0cyBvZmY=',
},
})
)
expect(invitation.getAppendedAttachmentById('view-2')).toEqual(
new Attachment({
id: 'view-2',
mimeType: 'image/png',
filename: 'IMG1092349.png',
lastmodTime: new Date('2018-12-24 18:25:49Z'),
description: 'view with lamp in the background',
data: {
base64: 'dmlldyB3aXRoIGxhbXAgaW4gdGhlIGJhY2tncm91bmQ=',
},
})
)
})

test('throw validation error when services attribute is empty', () => {
const json = {
'@type': 'https://didcomm.org/out-of-band/1.1/invitation',
Expand Down
48 changes: 47 additions & 1 deletion packages/core/src/modules/oob/__tests__/helpers.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Attachment } from '../../../decorators/attachment/Attachment'
import { JsonTransformer } from '../../../utils'
import { ConnectionInvitationMessage } from '../../connections'
import { DidCommV1Service } from '../../dids'
Expand All @@ -13,10 +14,23 @@ describe('convertToNewInvitation', () => {
recipientKeys: ['8HH5gYEeNc3z7PYXmd54d4x6qAfCNrqQqEB3nS7Zfu7K'],
serviceEndpoint: 'https://my-agent.com',
routingKeys: ['6fioC1zcDPyPEL19pXRS2E4iJ46zH7xP6uSgAaPdwDrx'],
appendedAttachments: [
new Attachment({
id: 'attachment-1',
mimeType: 'text/plain',
description: 'attachment description',
filename: 'test.jpg',
data: {
json: {
text: 'sample',
value: 1,
},
},
}),
],
})

const oobInvitation = convertToNewInvitation(connectionInvitation)

expect(oobInvitation).toMatchObject({
id: 'd88ff8fd-6c43-4683-969e-11a87a572cf2',
imageUrl: 'https://my-image.com',
Expand All @@ -29,6 +43,15 @@ describe('convertToNewInvitation', () => {
serviceEndpoint: 'https://my-agent.com',
},
],
appendedAttachments: [
{
id: 'attachment-1',
description: 'attachment description',
filename: 'test.jpg',
mimeType: 'text/plain',
data: { json: { text: 'sample', value: 1 } },
},
],
})
})

Expand All @@ -38,6 +61,20 @@ describe('convertToNewInvitation', () => {
imageUrl: 'https://my-image.com',
label: 'a-label',
did: 'did:sov:a-did',
appendedAttachments: [
new Attachment({
id: 'attachment-1',
mimeType: 'text/plain',
description: 'attachment description',
filename: 'test.jpg',
data: {
json: {
text: 'sample',
value: 1,
},
},
}),
],
})

const oobInvitation = convertToNewInvitation(connectionInvitation)
Expand All @@ -47,6 +84,15 @@ describe('convertToNewInvitation', () => {
imageUrl: 'https://my-image.com',
label: 'a-label',
services: ['did:sov:a-did'],
appendedAttachments: [
{
id: 'attachment-1',
description: 'attachment description',
filename: 'test.jpg',
mimeType: 'text/plain',
data: { json: { text: 'sample', value: 1 } },
},
],
})
})

Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/modules/oob/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export function convertToNewInvitation(oldInvitation: ConnectionInvitationMessag
id: oldInvitation.id,
label: oldInvitation.label,
imageUrl: oldInvitation.imageUrl,
appendedAttachments: oldInvitation.appendedAttachments,
accept: ['didcomm/aip1', 'didcomm/aip2;env=rfc19'],
services: [service],
handshakeProtocols: [HandshakeProtocol.Connections],
Expand All @@ -45,6 +46,7 @@ export function convertToOldInvitation(newInvitation: OutOfBandInvitation) {
label: newInvitation.label,
did: service,
imageUrl: newInvitation.imageUrl,
appendedAttachments: newInvitation.appendedAttachments,
}
} else {
options = {
Expand All @@ -54,6 +56,7 @@ export function convertToOldInvitation(newInvitation: OutOfBandInvitation) {
routingKeys: service.routingKeys?.map(didKeyToVerkey),
serviceEndpoint: service.serviceEndpoint,
imageUrl: newInvitation.imageUrl,
appendedAttachments: newInvitation.appendedAttachments,
}
}

Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/modules/oob/messages/OutOfBandInvitation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export interface OutOfBandInvitationOptions {
handshakeProtocols?: HandshakeProtocol[]
services: Array<OutOfBandDidCommService | string>
imageUrl?: string
appendedAttachments?: Attachment[]
}

export class OutOfBandInvitation extends AgentMessage {
Expand All @@ -41,6 +42,7 @@ export class OutOfBandInvitation extends AgentMessage {
this.handshakeProtocols = options.handshakeProtocols
this.services = options.services
this.imageUrl = options.imageUrl
this.appendedAttachments = options.appendedAttachments
}
}

Expand Down

0 comments on commit 4800700

Please sign in to comment.