From b0f05ee0bb18787af55ace5556cfb377f1917c21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9rard=20Dethier?= Date: Tue, 4 Jan 2022 15:55:47 +0100 Subject: [PATCH] feat: fix LOC request relations. logion-network/logion-internal#299 --- .../controllers/locrequest.controller.ts | 6 +- src/logion/model/locrequest.model.ts | 28 ++++--- test/integration/model/loc_requests.sql | 2 +- .../model/locrequest.model.spec.ts | 5 ++ .../controllers/locrequest.controller.spec.ts | 6 +- test/unit/model/locrequest.model.spec.ts | 73 +++++++++++-------- 6 files changed, 75 insertions(+), 45 deletions(-) diff --git a/src/logion/controllers/locrequest.controller.ts b/src/logion/controllers/locrequest.controller.ts index d6b73bbe..92ee6527 100644 --- a/src/logion/controllers/locrequest.controller.ts +++ b/src/logion/controllers/locrequest.controller.ts @@ -115,17 +115,17 @@ export class LocRequestController extends ApiController { } let request: LocRequestAggregateRoot; if (authenticatedUser.isNodeOwner()) { - request = this.locRequestFactory.newOpenLoc({ + request = await this.locRequestFactory.newOpenLoc({ id: uuid(), description, }); } else { - request = this.locRequestFactory.newLocRequest({ + request = await this.locRequestFactory.newLocRequest({ id: uuid(), description }); } - await this.checkIdentityLoc(request.requesterIdentityLoc) + await this.checkIdentityLoc(request.requesterIdentityLocId) await this.locRequestRepository.save(request); const userIdentity = await this.findUserIdentity(request); return this.toView(request, userIdentity); diff --git a/src/logion/model/locrequest.model.ts b/src/logion/model/locrequest.model.ts index 7889672e..54a37449 100644 --- a/src/logion/model/locrequest.model.ts +++ b/src/logion/model/locrequest.model.ts @@ -104,7 +104,7 @@ export class LocRequestAggregateRoot { } : undefined; return { requesterAddress: this.requesterAddress, - requesterIdentityLoc: this.requesterIdentityLoc, + requesterIdentityLoc: this.requesterIdentityLocId, ownerAddress: this.ownerAddress!, description: this.description!, createdOn: this.createdOn!, @@ -416,9 +416,12 @@ export class LocRequestAggregateRoot { @Column({ length: 255, name: "requester_address", nullable: true }) requesterAddress?: string; - @ManyToOne(() => LocRequestAggregateRoot) - @JoinColumn({ name: "requester_identity_loc", referencedColumnName: "id" }) - requesterIdentityLoc?: string; + @ManyToOne(() => LocRequestAggregateRoot, { nullable: true }) + @JoinColumn({ name: "requester_identity_loc" }) + _requesterIdentityLoc?: LocRequestAggregateRoot; + + @Column({ name: "requester_identity_loc", nullable: true }) + requesterIdentityLocId?: string; @Column({ length: 255, name: "owner_address" }) ownerAddress?: string; @@ -689,13 +692,17 @@ export interface NewLocRequestParameters { @injectable() export class LocRequestFactory { - public newOpenLoc(params: NewLocRequestParameters): LocRequestAggregateRoot { - const request = this.newLocRequest(params); + constructor( + private repository: LocRequestRepository + ) {} + + async newOpenLoc(params: NewLocRequestParameters): Promise { + const request = await this.newLocRequest(params); request.accept(moment()) - return request + return request; } - public newLocRequest(params: NewLocRequestParameters): LocRequestAggregateRoot { + async newLocRequest(params: NewLocRequestParameters): Promise { const { description } = params; this.ensureCorrectRequester(description) this.ensureUserIdentityPresent(description) @@ -703,7 +710,10 @@ export class LocRequestFactory { request.id = params.id; request.status = "REQUESTED"; request.requesterAddress = description.requesterAddress; - request.requesterIdentityLoc = description.requesterIdentityLoc; + if(description.requesterIdentityLoc) { + request._requesterIdentityLoc = await this.repository.findById(description.requesterIdentityLoc); + request.requesterIdentityLocId = description.requesterIdentityLoc; + } request.ownerAddress = description.ownerAddress; request.description = description.description; request.locType = description.locType; diff --git a/test/integration/model/loc_requests.sql b/test/integration/model/loc_requests.sql index 86872de5..38cc0f1b 100644 --- a/test/integration/model/loc_requests.sql +++ b/test/integration/model/loc_requests.sql @@ -44,7 +44,7 @@ INSERT INTO loc_request (id, owner_address, description, status, loc_type) VALUES ('518536e4-71e6-4c4f-82db-b16cbfb495ed', '5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty', 'loc-16', 'OPEN', 'Identity'); -- Open Transaction locs linked to Logion Identity INSERT INTO loc_request (id, requester_identity_loc, owner_address, description, status, loc_type) -VALUES (md5(random()::text || clock_timestamp()::text)::uuid, 'f5085ab0-e2ad-45f4-8b52-424f74cb9387', '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY', 'loc-17', 'OPEN', 'Transaction'); +VALUES ('f93bc0d2-f443-49ff-a9de-a6331167b267', 'f5085ab0-e2ad-45f4-8b52-424f74cb9387', '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY', 'loc-17', 'OPEN', 'Transaction'); INSERT INTO loc_request (id, requester_identity_loc, owner_address, description, status, loc_type) VALUES (md5(random()::text || clock_timestamp()::text)::uuid, '7eb5b359-088b-4051-9507-fb66cf7d03aa', '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY', 'loc-18', 'OPEN', 'Transaction'); INSERT INTO loc_request (id, requester_identity_loc, owner_address, description, status, loc_type) diff --git a/test/integration/model/locrequest.model.spec.ts b/test/integration/model/locrequest.model.spec.ts index b026d9ee..206bb2f5 100644 --- a/test/integration/model/locrequest.model.spec.ts +++ b/test/integration/model/locrequest.model.spec.ts @@ -101,6 +101,10 @@ describe('LocRequestRepository - read accesses', () => { expect(request!.links![0].draft).toBe(true); }) + it("populates requesterIdentityLoc", async () => { + const request = await repository.findById(LOGION_TRANSACTION_LOC_ID); + expect(request?.requesterIdentityLocId).toBeDefined(); + }) }) describe('LocRequestRepository.save()', () => { @@ -202,3 +206,4 @@ function checkDescription(requests: LocRequestAggregateRoot[], expectedLocType: } const LOC_WITH_FILES = "2b287596-f9d5-8030-b606-d1da538cb37f"; +const LOGION_TRANSACTION_LOC_ID = "f93bc0d2-f443-49ff-a9de-a6331167b267"; diff --git a/test/unit/controllers/locrequest.controller.spec.ts b/test/unit/controllers/locrequest.controller.spec.ts index 3c977150..bf828c9f 100644 --- a/test/unit/controllers/locrequest.controller.spec.ts +++ b/test/unit/controllers/locrequest.controller.spec.ts @@ -507,14 +507,14 @@ function mockModelForCreation(container: Container, hasProtection: boolean = fal params.description.ownerAddress == ALICE && params.description.description == testData.description ))) - .returns(request.object()) + .returns(Promise.resolve(request.object())) const openLoc = mockRequest("OPEN", hasProtection ? testData : testDataWithUserIdentity) factory.setup(instance => instance.newOpenLoc(It.Is(params => params.description.requesterAddress == testData.requesterAddress && params.description.ownerAddress == ALICE && params.description.description == testData.description ))) - .returns(openLoc.object()) + .returns(Promise.resolve(openLoc.object())) container.bind(LocRequestFactory).toConstantValue(factory.object()); container.bind(ProtectionRequestRepository).toConstantValue(mockProtectionRepository(hasProtection)); @@ -538,7 +538,7 @@ function mockModelForCreationWithIdentityLoc(container: Container): void { params.description.requesterIdentityLoc === IDENTITY_LOC_ID && params.description.ownerAddress == ALICE ))) - .returns(request.object()) + .returns(Promise.resolve(request.object())) container.bind(LocRequestFactory).toConstantValue(factory.object()); const protectionRepository = new Mock(); diff --git a/test/unit/model/locrequest.model.spec.ts b/test/unit/model/locrequest.model.spec.ts index faeb5c8f..1e7216d3 100644 --- a/test/unit/model/locrequest.model.spec.ts +++ b/test/unit/model/locrequest.model.spec.ts @@ -10,81 +10,87 @@ import { MetadataItemDescription, LinkDescription, VoidInfo, - LocType + LocType, + LocRequestRepository } from "../../../src/logion/model/locrequest.model"; import { UserIdentity } from "../../../src/logion/model/useridentity"; +import { Mock } from "moq.ts"; describe("LocRequestFactory", () => { - it("creates Transaction LOC request", () => { + it("creates Transaction LOC request", async () => { givenRequestId(uuid()); const description = createDescription('Transaction', "5Ew3MyB15VprZrjQVkpQFj8okmc9xLDSEdNhqMMS5cXsqxoW"); givenLocDescription(description); - whenCreatingLocRequest(); + await whenCreatingLocRequest(); thenRequestCreatedWithDescription(description); }); - it("creates an open Transaction LOC with requester address", () => { + it("creates an open Transaction LOC with requester address", async () => { givenRequestId(uuid()); const description = createDescription('Transaction', "5Ew3MyB15VprZrjQVkpQFj8okmc9xLDSEdNhqMMS5cXsqxoW"); givenLocDescription(description); - whenCreatingOpenLoc(); + await whenCreatingOpenLoc(); thenOpenLocCreatedWithDescription(description) }); - it("creates an open Transaction LOC with requester id loc", () => { + it("creates an open Transaction LOC with requester id loc", async () => { givenRequestId(uuid()); - const description = createDescription('Transaction', undefined, uuid().toString()); + const requesterIdentityLocId = uuid().toString(); + const description = createDescription('Transaction', undefined, requesterIdentityLocId); + const requesterIdentityLoc = new Mock(); + requesterIdentityLoc.setup(instance => instance.id).returns(requesterIdentityLocId); + repository.setup(instance => instance.findById(requesterIdentityLocId)).returns(Promise.resolve(requesterIdentityLoc.object())); givenLocDescription(description); - whenCreatingOpenLoc(); + await whenCreatingOpenLoc(); thenOpenLocCreatedWithDescription(description) }); - it("fails to create an open Transaction LOC with 2 requesters", () => { + it("fails to create an open Transaction LOC with 2 requesters", async () => { givenRequestId(uuid()); const description = createDescription('Transaction', "5Ew3MyB15VprZrjQVkpQFj8okmc9xLDSEdNhqMMS5cXsqxoW", uuid().toString()); givenLocDescription(description); - expect(() => whenCreatingOpenLoc()).toThrowError(); + await expectAsyncToThrow(whenCreatingOpenLoc); }); - it("fails to create an open Transaction LOC with no requester", () => { + it("fails to create an open Transaction LOC with no requester", async () => { givenRequestId(uuid()); const description = createDescription('Transaction'); givenLocDescription(description); - expect(() => whenCreatingOpenLoc()).toThrowError(); + await expectAsyncToThrow(whenCreatingOpenLoc); }); - it("creates Identity LOC request", () => { + it("creates Identity LOC request", async () => { givenRequestId(uuid()); const description = createDescription('Identity', "5Ew3MyB15VprZrjQVkpQFj8okmc9xLDSEdNhqMMS5cXsqxoW"); givenLocDescription(description); - whenCreatingLocRequest(); + await whenCreatingLocRequest(); thenRequestCreatedWithDescription(description); }); - it("creates an open Identity LOC with requester address", () => { + it("creates an open Identity LOC with requester address", async () => { givenRequestId(uuid()); const description = createDescription('Identity', "5Ew3MyB15VprZrjQVkpQFj8okmc9xLDSEdNhqMMS5cXsqxoW"); givenLocDescription(description); - whenCreatingOpenLoc(); + await whenCreatingOpenLoc(); thenOpenLocCreatedWithDescription(description) }); - it("fails to create an open Identity LOC with requester id loc", () => { + it("fails to create an open Identity LOC with requester id loc", async () => { givenRequestId(uuid()); const description = createDescription('Identity', undefined, uuid().toString()); givenLocDescription(description); - expect(() => whenCreatingOpenLoc()).toThrowError() + await expectAsyncToThrow(whenCreatingOpenLoc); }); - it("fails to create an open Identity LOC with 2 requesters", () => { + it("fails to create an open Identity LOC with 2 requesters", async () => { givenRequestId(uuid()); const description = createDescription('Identity', "5Ew3MyB15VprZrjQVkpQFj8okmc9xLDSEdNhqMMS5cXsqxoW", uuid().toString()); givenLocDescription(description); - expect(() => whenCreatingOpenLoc()).toThrowError(); + await expectAsyncToThrow(whenCreatingOpenLoc); }); - it("creates an open Identity LOC with no requester", () => { + it("creates an open Identity LOC with no requester", async () => { givenRequestId(uuid()); const userIdentity = { firstName: "Scott", @@ -94,14 +100,14 @@ describe("LocRequestFactory", () => { }; const description = createDescription('Identity', undefined, undefined, userIdentity); givenLocDescription(description); - whenCreatingOpenLoc(); + await whenCreatingOpenLoc(); }); - it("fails to create an open Identity LOC with no requester when identity is missing", () => { + it("fails to create an open Identity LOC with no requester when identity is missing", async () => { givenRequestId(uuid()); const description = createDescription('Identity'); givenLocDescription(description); - expect(() => whenCreatingOpenLoc()).toThrowError(); + await expectAsyncToThrow(whenCreatingOpenLoc); }); function createDescription(locType: LocType, requesterAddress?: string, requesterIdentityLoc?: string, userIdentity?: UserIdentity): LocRequestDescription { @@ -586,21 +592,23 @@ function givenLocDescription(value: LocRequestDescription) { let locDescription: LocRequestDescription; -function whenCreatingLocRequest() { - createdLocRequest = factory.newLocRequest({ +async function whenCreatingLocRequest() { + const factory = new LocRequestFactory(repository.object()); + createdLocRequest = await factory.newLocRequest({ id: requestId, description: locDescription }); } -function whenCreatingOpenLoc() { - createdLocRequest = factory.newOpenLoc({ +async function whenCreatingOpenLoc() { + const factory = new LocRequestFactory(repository.object()); + createdLocRequest = await factory.newOpenLoc({ id: requestId, description: locDescription }); } -const factory = new LocRequestFactory(); +const repository = new Mock(); let createdLocRequest: LocRequestAggregateRoot; @@ -841,3 +849,10 @@ function whenVoiding(reason: string, voidingDate: Moment) { request.preVoid(reason); request.voidLoc(voidingDate); } + +async function expectAsyncToThrow(func: () => Promise) { + try { + await func(); + expect(true).toBe(false); + } catch(_) {} +}