diff --git a/apps/shared/src/events/__tests__/connectionEvents.spec.ts b/apps/shared/src/events/__tests__/connectionEvents.spec.ts index 42ea6e6b7b46ed3c38bc46c279d5841ff444d2f2..70f97f016b6db6c607667ac17ff57f860702386c 100644 --- a/apps/shared/src/events/__tests__/connectionEvents.spec.ts +++ b/apps/shared/src/events/__tests__/connectionEvents.spec.ts @@ -5,6 +5,7 @@ import { } from '@aries-framework/core'; import { + EventDidcommConnectionsBlock, EventDidcommConnectionsCreateWithSelf, EventDidcommConnectionsGetAll, EventDidcommConnectionsGetById, @@ -49,4 +50,21 @@ describe('Connection Events', () => { state: DidExchangeState.Completed, }); }); + + it('should create a new connections block event', () => { + const event = new EventDidcommConnectionsBlock( + new ConnectionRecord({ + role: DidExchangeRole.Requester, + state: DidExchangeState.Completed, + }), + ); + + expect(typeof event.id).toStrictEqual('string'); + expect(event.type).toStrictEqual('EventDidcommConnectionsBlock'); + expect(event.timestamp).toBeInstanceOf(Date); + expect(event.instance).toMatchObject({ + role: DidExchangeRole.Requester, + state: DidExchangeState.Completed, + }); + }); }); diff --git a/apps/shared/src/events/connectionEvents.ts b/apps/shared/src/events/connectionEvents.ts index 1831f5cd2249438ed2498eabfaa8e19e7a9b349b..22177f11d50f62c43265e5f978330e6e92c16d3f 100644 --- a/apps/shared/src/events/connectionEvents.ts +++ b/apps/shared/src/events/connectionEvents.ts @@ -55,9 +55,7 @@ export class EventDidcommConnectionsCreateWithSelf extends BaseEvent<ConnectionR public static token = 'didcomm.connections.createWithSelf'; public get instance() { - return JsonTransformer.fromJSON(this.data, ConnectionRecord, { - validate: true, - }); + return JsonTransformer.fromJSON(this.data, ConnectionRecord); } public static fromEvent(e: EventDidcommConnectionsCreateWithSelf) { @@ -69,3 +67,17 @@ export class EventDidcommConnectionsCreateWithSelf extends BaseEvent<ConnectionR ); } } + +export class EventDidcommConnectionsBlock extends BaseEvent<ConnectionRecord | null> { + public static token = 'didcomm.connections.block'; + + public get instance() { + return this.data + ? JsonTransformer.fromJSON(this.data, ConnectionRecord) + : null; + } + + public static fromEvent(e: EventDidcommConnectionsBlock) { + return new EventDidcommConnectionsBlock(e.data, e.id, e.type, e.timestamp); + } +} diff --git a/apps/ssi-abstraction/src/agent/agent.service.ts b/apps/ssi-abstraction/src/agent/agent.service.ts index 0d68b5e3c1ea246439dcf3977901188f465cd45a..10bcad88fa13ee5fd2ecadf0af64baac1a9ba33f 100644 --- a/apps/ssi-abstraction/src/agent/agent.service.ts +++ b/apps/ssi-abstraction/src/agent/agent.service.ts @@ -203,6 +203,11 @@ export class AgentService implements OnApplicationShutdown { public async onApplicationShutdown() { if (!this.agent.isInitialized) return; - await this.agent.shutdown(); + // If we cannot shutdown the wallet on application shutdown, no error will occur + // This is done because the Askar shutdown procedure is a bit buggy + try { + await this.agent.shutdown(); + // eslint-disable-next-line no-empty + } catch {} } } diff --git a/apps/ssi-abstraction/src/agent/connections/connections.controller.ts b/apps/ssi-abstraction/src/agent/connections/connections.controller.ts index 322f3376da65439c0ee86d74047c76f28db96ac8..0eb6bc7c9c5bccf4763067b8c66e76ffc66283c5 100644 --- a/apps/ssi-abstraction/src/agent/connections/connections.controller.ts +++ b/apps/ssi-abstraction/src/agent/connections/connections.controller.ts @@ -4,6 +4,7 @@ import { EventDidcommConnectionsGetById, EventDidcommConnectionsGetAll, EventDidcommConnectionsCreateWithSelf, + EventDidcommConnectionsBlock, } from '@ocm/shared'; import { ConnectionsService } from './connections.service.js'; @@ -36,4 +37,15 @@ export class ConnectionsController { await this.connectionsService.createConnectionWithSelf(), ); } + + @MessagePattern(EventDidcommConnectionsBlock.token) + public async blockConnection({ + idOrDid, + }: { + idOrDid: string; + }): Promise<EventDidcommConnectionsBlock> { + return new EventDidcommConnectionsBlock( + await this.connectionsService.blockByIdOrDid(idOrDid), + ); + } } diff --git a/apps/ssi-abstraction/src/agent/connections/connections.service.ts b/apps/ssi-abstraction/src/agent/connections/connections.service.ts index 4c6901cd52a6efb5d07993104564adfc4e6657ac..ba72b2c157f28af5007e74e92860c96c1188a157 100644 --- a/apps/ssi-abstraction/src/agent/connections/connections.service.ts +++ b/apps/ssi-abstraction/src/agent/connections/connections.service.ts @@ -9,6 +9,7 @@ import { ConnectionRepository, DidExchangeState, } from '@aries-framework/core'; +import { isDid } from '@aries-framework/core/build/utils/did.js'; import { Injectable } from '@nestjs/common'; import { MetadataTokens } from '../../common/constants.js'; @@ -30,6 +31,37 @@ export class ConnectionsService { return await this.agent.connections.findById(id); } + public async blockByIdOrDid( + idOrDid: string, + ): Promise<ConnectionRecord | null> { + if (isDid(idOrDid)) { + const records = await this.agent.connections.findAllByQuery({ + theirDid: idOrDid, + }); + + if (records.length === 0) { + return null; + } + + if (records.length > 1) { + throw new Error( + 'Found multiple records with the same DID. This should not be possible', + ); + } + + await this.agent.connections.deleteById(records[0].id); + + return records[0]; + } + + const record = await this.agent.connections.findById(idOrDid); + if (!record) return null; + + await this.agent.connections.deleteById(record.id); + + return record; + } + public async createConnectionWithSelf(): Promise<ConnectionRecord> { const outOfBandRecord = await this.agent.oob.createInvitation(); const invitation = outOfBandRecord.outOfBandInvitation; diff --git a/apps/ssi-abstraction/test/connections.e2e-spec.ts b/apps/ssi-abstraction/test/connections.e2e-spec.ts index 8fa8364d9dd5ec34e366cccdfe3c1e43f541bfff..3f52769ae31e430e6621f072a774fa26dadfe612 100644 --- a/apps/ssi-abstraction/test/connections.e2e-spec.ts +++ b/apps/ssi-abstraction/test/connections.e2e-spec.ts @@ -8,6 +8,7 @@ import { EventDidcommConnectionsGetById, EventDidcommConnectionsGetAll, EventDidcommConnectionsCreateWithSelf, + EventDidcommConnectionsBlock, } from '@ocm/shared'; import { firstValueFrom } from 'rxjs'; @@ -83,4 +84,16 @@ describe('Connections', () => { ); expect(metadata).toMatchObject({ trusted: true }); }); + + it(EventDidcommConnectionsBlock.token, async () => { + const response$: Observable<EventDidcommConnectionsBlock> = client.send( + EventDidcommConnectionsBlock.token, + { idOrDid: 'some-id' }, + ); + + const response = await firstValueFrom(response$); + const eventInstance = EventDidcommConnectionsBlock.fromEvent(response); + + expect(eventInstance.instance).toBeNull(); + }); });