From 6668350a7c8c18c38cf6b2c70b06ac09ca8f16e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20K=C3=B6nig?= <33655937+jkoenig134@users.noreply.github.com> Date: Mon, 28 Oct 2024 15:39:55 +0100 Subject: [PATCH] Multiple open Requests that lead to a Relationship can exist for the same Identity (#309) * fix: do not allow multiple request that would lead to a Relationship * chore: add test * fix: add peer to the query * chore: add filter for decided --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- packages/runtime/src/modules/RequestModule.ts | 23 ++++++++ .../test/modules/RequestModule.test.ts | 58 +++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/packages/runtime/src/modules/RequestModule.ts b/packages/runtime/src/modules/RequestModule.ts index d5dbf3f3e..eabcb4812 100644 --- a/packages/runtime/src/modules/RequestModule.ts +++ b/packages/runtime/src/modules/RequestModule.ts @@ -114,6 +114,29 @@ export class RequestModule extends RuntimeModule { return; } + const otherRequestsThatWouldLeadToARelationship = ( + await services.consumptionServices.incomingRequests.getRequests({ + query: { + "source.type": "RelationshipTemplate", + status: [LocalRequestStatus.Open, LocalRequestStatus.DecisionRequired, LocalRequestStatus.ManualDecisionRequired, LocalRequestStatus.Decided], + peer: template.createdBy + } + }) + ).value; + if (otherRequestsThatWouldLeadToARelationship.length !== 0) { + this.logger.info( + `There is already an open Request for a RelationshipTemplate that would lead to a Relationship with the creator of the RelationshipTemplate '${template.id}'. Skipping creation of a new Request.` + ); + this.runtime.eventBus.publish( + new RelationshipTemplateProcessedEvent(event.eventTargetAddress, { + template, + result: RelationshipTemplateProcessedResult.NonCompletedRequestExists, + requestId: otherRequestsThatWouldLeadToARelationship[0].id + }) + ); + return; + } + const requestCreated = await this.createIncomingRequest(services, body.onNewRelationship, template.id); if (!requestCreated) { diff --git a/packages/runtime/test/modules/RequestModule.test.ts b/packages/runtime/test/modules/RequestModule.test.ts index 375514d27..6d66b8edd 100644 --- a/packages/runtime/test/modules/RequestModule.test.ts +++ b/packages/runtime/test/modules/RequestModule.test.ts @@ -584,3 +584,61 @@ describe("Handling the rejection and the revocation of a Relationship by the Req return sRelationship; } }); + +describe("Handle Multiple RelationshipTemplate loadings", () => { + const runtimeServiceProvider = new RuntimeServiceProvider(); + let sRuntimeServices: TestRuntimeServices; + let rRuntimeServices: TestRuntimeServices; + + beforeAll(async () => { + const runtimeServices = await runtimeServiceProvider.launch(2, { enableRequestModule: true, enableDeciderModule: true }); + + sRuntimeServices = runtimeServices[0]; + rRuntimeServices = runtimeServices[1]; + }, 30000); + + beforeEach(() => { + sRuntimeServices.eventBus.reset(); + rRuntimeServices.eventBus.reset(); + }); + + afterEach(() => { + sRuntimeServices.eventBus.reset(); + rRuntimeServices.eventBus.reset(); + }); + + afterAll(async () => await runtimeServiceProvider.stop()); + + test("no multiple open Requests that lead to a Relationship can exist for the same Identity", async () => { + const relationshipTemplateContent = RelationshipTemplateContent.from({ + onNewRelationship: { "@type": "Request", items: [{ "@type": "TestRequestItem", mustBeAccepted: false }] } + }).toJSON(); + + const firstTemplate = await exchangeTemplate(sRuntimeServices.transport, rRuntimeServices.transport, relationshipTemplateContent); + await rRuntimeServices.eventBus.waitForRunningEventHandlers(); + await expect(rRuntimeServices.eventBus).toHavePublished( + RelationshipTemplateProcessedEvent, + (e) => e.data.result === RelationshipTemplateProcessedResult.ManualRequestDecisionRequired + ); + + const requestForTemplate = (await rRuntimeServices.consumption.incomingRequests.getRequests({ query: { "source.reference": firstTemplate.id } })).value[0]; + + rRuntimeServices.eventBus.reset(); + + const secondTemplate = await exchangeTemplate(sRuntimeServices.transport, rRuntimeServices.transport, relationshipTemplateContent); + await rRuntimeServices.eventBus.waitForRunningEventHandlers(); + + await expect(rRuntimeServices.eventBus).not.toHavePublished( + RelationshipTemplateProcessedEvent, + (e) => e.data.result === RelationshipTemplateProcessedResult.ManualRequestDecisionRequired + ); + + await expect(rRuntimeServices.eventBus).toHavePublished( + RelationshipTemplateProcessedEvent, + (e) => + e.data.result === RelationshipTemplateProcessedResult.NonCompletedRequestExists && + e.data.template.id === secondTemplate.id && + e.data.requestId === requestForTemplate.id + ); + }); +});