diff --git a/resources/schemas.json b/resources/schemas.json index ea2c2ca1..76645e29 100644 --- a/resources/schemas.json +++ b/resources/schemas.json @@ -864,10 +864,6 @@ "nature": { "type": "string", "description": "The file's nature" - }, - "submitter": { - "type": "string", - "description": "The SS58 address of the file submitter" } } }, @@ -905,10 +901,6 @@ "value": { "type": "string", "description": "The item's value" - }, - "submitter": { - "type": "string", - "description": "The SS58 address of the metadata item submitter" } } }, diff --git a/src/logion/controllers/locrequest.controller.ts b/src/logion/controllers/locrequest.controller.ts index c1f7957c..a0cfa22e 100644 --- a/src/logion/controllers/locrequest.controller.ts +++ b/src/logion/controllers/locrequest.controller.ts @@ -166,13 +166,13 @@ export class LocRequestController extends ApiController { hash: file.hash, nature: file.nature, addedOn: file.addedOn?.toISOString() || undefined, - submitter: locDescription.ownerAddress // TODO Change me + submitter: file.submitter, })), metadata: request.getMetadataItems().map(item => ({ name: item.name, value: item.value, addedOn: item.addedOn?.toISOString() || undefined, - submitter: locDescription.ownerAddress // TODO Change me + submitter: item.submitter, })), links: request.getLinks().map(link => ({ target: link.target, @@ -315,13 +315,13 @@ export class LocRequestController extends ApiController { hash: file.hash, nature: file.nature, addedOn: file.addedOn?.toISOString() || undefined, - submitter: locDescription.ownerAddress // TODO Change me + submitter: file.submitter, })), metadata: request.getMetadataItems(false).map(item => ({ name: item.name, value: item.value, addedOn: item.addedOn?.toISOString() || undefined, - submitter: locDescription.ownerAddress // TODO Change me + submitter: item.submitter, })), links: request.getLinks(false).map(link => ({ target: link.target, @@ -390,8 +390,9 @@ export class LocRequestController extends ApiController { @Async() async addFile(addFileView: AddFileView, requestId: string): Promise { const request = requireDefined(await this.locRequestRepository.findById(requestId)); - this.authenticationService.authenticatedUser(this.request) - .requireNodeOwner(); + const submitter = this.authenticationService.authenticatedUser(this.request) + .require(user => user.isNodeOwner() || user.is(request.requesterAddress), "Only LOC owner or requester can submit a file") + .address const files: fileUpload.FileArray = this.request.files; if(files === undefined || files === null) { @@ -416,7 +417,8 @@ export class LocRequestController extends ApiController { contentType: file.mimetype, hash, oid, - nature: addFileView.nature || "" + nature: addFileView.nature || "", + submitter, }); await this.locRequestRepository.save(request); @@ -438,7 +440,7 @@ export class LocRequestController extends ApiController { async downloadFile(_body: any, requestId: string, hash: string): Promise { const request = requireDefined(await this.locRequestRepository.findById(requestId)); this.authenticationService.authenticatedUser(this.request) - .requireNodeOwner(); + .require(user => user.isNodeOwner() || user.is(request.requesterAddress), "Only LOC owner or requester can download a file") const file = request.getFile(hash); const tempFilePath = "/tmp/download-" + requestId + "-" + hash; @@ -465,7 +467,7 @@ export class LocRequestController extends ApiController { async deleteFile(_body: any, requestId: string, hash: string): Promise { const request = requireDefined(await this.locRequestRepository.findById(requestId)); this.authenticationService.authenticatedUser(this.request) - .requireNodeOwner(); + .require(user => user.isNodeOwner() || user.is(request.requesterAddress), "Only LOC owner or requester can delete a file") const file = request.removeFile(hash); await this.locRequestRepository.save(request); @@ -624,11 +626,12 @@ export class LocRequestController extends ApiController { @SendsResponse() async addMetadata(addMetadataView: AddMetadataView, requestId: string): Promise { const request = requireDefined(await this.locRequestRepository.findById(requestId)); - this.authenticationService.authenticatedUser(this.request) - .requireNodeOwner(); + const submitter = this.authenticationService.authenticatedUser(this.request) + .require(user => user.isNodeOwner() || user.is(request.requesterAddress), "Only LOC owner or requester can submit metadata") + .address const name = requireLength(addMetadataView, "name", 3, 40) const value = requireLength(addMetadataView, "value", 1, 4096) - request.addMetadataItem({ name, value }) + request.addMetadataItem({ name, value, submitter }) await this.locRequestRepository.save(request) this.response.sendStatus(204); } @@ -647,7 +650,7 @@ export class LocRequestController extends ApiController { async deleteMetadata(_body: any, requestId: string, name: string): Promise { const request = requireDefined(await this.locRequestRepository.findById(requestId)); this.authenticationService.authenticatedUser(this.request) - .requireNodeOwner(); + .require(user => user.isNodeOwner() || user.is(request.requesterAddress), "Only LOC owner or requester can delete metadata") const decodedName = decodeURIComponent(name); request.removeMetadataItem(decodedName); diff --git a/src/logion/migration/1641978274519-AddItemSubmitter.ts b/src/logion/migration/1641978274519-AddItemSubmitter.ts new file mode 100644 index 00000000..6b353a22 --- /dev/null +++ b/src/logion/migration/1641978274519-AddItemSubmitter.ts @@ -0,0 +1,27 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class AddItemSubmitter1641978274519 implements MigrationInterface { + name = 'AddItemSubmitter1641978274519' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "public"."loc_request_file" ADD "submitter" character varying(255)`); + await queryRunner.query(` + UPDATE loc_request_file item + SET submitter = (SELECT owner_address FROM loc_request request where item.request_id = request.id) + `); + await queryRunner.query(`ALTER TABLE "public"."loc_request_file" ALTER COLUMN "submitter" SET NOT NULL`); + + await queryRunner.query(`ALTER TABLE "public"."loc_metadata_item" ADD "submitter" character varying(255)`); + await queryRunner.query(` + UPDATE loc_metadata_item item + SET submitter = (SELECT owner_address FROM loc_request request where item.request_id = request.id ) + `); + await queryRunner.query(`ALTER TABLE "public"."loc_metadata_item" ALTER COLUMN "submitter" SET NOT NULL`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "public"."loc_metadata_item" DROP COLUMN "submitter"`); + await queryRunner.query(`ALTER TABLE "public"."loc_request_file" DROP COLUMN "submitter"`); + } + +} diff --git a/src/logion/model/locrequest.model.ts b/src/logion/model/locrequest.model.ts index 54a37449..db7b1b42 100644 --- a/src/logion/model/locrequest.model.ts +++ b/src/logion/model/locrequest.model.ts @@ -43,12 +43,14 @@ export interface FileDescription { readonly contentType: string; readonly nature: string; readonly addedOn?: Moment; + readonly submitter: string; } export interface MetadataItemDescription { readonly name: string; readonly value: string; readonly addedOn?: Moment; + readonly submitter: string; } export interface LinkDescription { @@ -128,6 +130,7 @@ export class LocRequestAggregateRoot { file.contentType = fileDescription.contentType; file.draft = true; file.nature = fileDescription.nature; + file.submitter = fileDescription.submitter file._toAdd = true; this.files!.push(file); } @@ -167,6 +170,7 @@ export class LocRequestAggregateRoot { hash: file!.hash!, oid: file!.oid!, nature: file!.nature!, + submitter: file!.submitter!, addedOn: file!.addedOn !== undefined ? moment(file!.addedOn) : undefined, }; } @@ -215,6 +219,7 @@ export class LocRequestAggregateRoot { item.name = itemDescription.name; item.value = itemDescription.value; item.draft = true; + item.submitter = itemDescription.submitter; item._toAdd = true; this.metadata!.push(item); } @@ -227,6 +232,7 @@ export class LocRequestAggregateRoot { return ({ name: item.name!, value: item.value!, + submitter: item.submitter!, addedOn: item.addedOn ? moment(item.addedOn) : undefined, }) } @@ -509,6 +515,9 @@ export class LocFile extends Child implements HasIndex { @Column({ length: 255, nullable: true }) nature?: string; + @Column({ length: 255 }) + submitter?: string; + @ManyToOne(() => LocRequestAggregateRoot, request => request.files) @JoinColumn({ name: "request_id", referencedColumnName: "id" }) request?: LocRequestAggregateRoot; @@ -540,6 +549,9 @@ export class LocMetadataItem extends Child implements HasIndex { @Column("boolean", { default: false }) draft?: boolean; + @Column({ length: 255 }) + submitter?: string; + @ManyToOne(() => LocRequestAggregateRoot, request => request.metadata) @JoinColumn({ name: "request_id" }) request?: LocRequestAggregateRoot; diff --git a/src/logion/services/authentication.service.ts b/src/logion/services/authentication.service.ts index f28757a2..53f5ecd4 100644 --- a/src/logion/services/authentication.service.ts +++ b/src/logion/services/authentication.service.ts @@ -49,10 +49,11 @@ export class LogionUserCheck implements AuthenticatedUser { && address === this.address; } - require(predicate: (check: LogionUserCheck) => boolean, message?: string): void { + require(predicate: (check: LogionUserCheck) => boolean, message?: string): LogionUserCheck { if(!predicate(this)) { throw unauthorized(message || "Unauthorized"); } + return this; } isOneOf(addresses: (string | undefined | null)[]): boolean { diff --git a/src/logion/services/polkadot.service.ts b/src/logion/services/polkadot.service.ts index 234c9cd4..66c09b0e 100644 --- a/src/logion/services/polkadot.service.ts +++ b/src/logion/services/polkadot.service.ts @@ -62,7 +62,8 @@ export class PolkadotService { }, MetadataItem: { name: "Vec", - value: "Vec" + value: "Vec", + submitter: "AccountId", }, LocType: { _enum: [ @@ -77,6 +78,7 @@ export class PolkadotService { File: { hash: "Hash", nature: "Vec", + submitter: "AccountId", }, LocVoidInfo: { "replacer": "Option" @@ -86,6 +88,7 @@ export class PolkadotService { "V1", "V2MakeLocVoid", "V3RequesterEnum", + "V4ItemSubmitter", ] }, Requester: { diff --git a/test/helpers/testapp.ts b/test/helpers/testapp.ts index 5446f854..98b9f436 100644 --- a/test/helpers/testapp.ts +++ b/test/helpers/testapp.ts @@ -16,6 +16,7 @@ export function setupApp( mockBinder: (container: Container) => void, authSucceed: boolean = true, isNodeOwner: boolean = true, + conditionFulfilled: boolean = true ): Express { const app = express(); @@ -36,7 +37,7 @@ export function setupApp( let container = new Container({ defaultScope: "Singleton" }); container.bind(AuthenticationService) - .toConstantValue(authSucceed ? mockAuthenticationSuccess(isNodeOwner) : mockAuthenticationFailure()); + .toConstantValue(authSucceed ? mockAuthenticationSuccess(isNodeOwner, conditionFulfilled) : mockAuthenticationFailure()); mockBinder(container); @@ -50,13 +51,22 @@ export function setupApp( return app; } -function mockAuthenticationSuccess(isNodeOwner: boolean): AuthenticationService { +function mockAuthenticationSuccess(isNodeOwner: boolean, conditionFulfilled: boolean): AuthenticationService { const authenticatedUser = new Mock(); authenticatedUser.setup(instance => instance.legalOfficer).returns(true); - authenticatedUser.setup(instance => instance.is).returns(() => true); - authenticatedUser.setup(instance => instance.require).returns(() => {}); - authenticatedUser.setup(instance => instance.requireIs).returns(() => {}); + authenticatedUser.setup(instance => instance.is).returns(() => conditionFulfilled); + authenticatedUser.setup(instance => instance.require).returns(() => { + if (!conditionFulfilled) { + throw new UnauthorizedException("") + } + return authenticatedUser.object() + }); + authenticatedUser.setup(instance => instance.requireIs).returns(() => { + if (!conditionFulfilled) { + throw new UnauthorizedException("") + } + }); authenticatedUser.setup(instance => instance.requireLegalOfficer).returns(() => {}); authenticatedUser.setup(instance => instance.requireNodeOwner).returns(() => { if (!isNodeOwner) { diff --git a/test/integration/model/loc_requests.sql b/test/integration/model/loc_requests.sql index 38cc0f1b..86611217 100644 --- a/test/integration/model/loc_requests.sql +++ b/test/integration/model/loc_requests.sql @@ -22,10 +22,10 @@ VALUES (md5(random()::text || clock_timestamp()::text)::uuid, '5FHneW46xGXgs5mUi -- Loc with files, metadata and links INSERT INTO loc_request (id, owner_address, requester_address, description, status, loc_type) VALUES ('2b287596-f9d5-8030-b606-d1da538cb37f', '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY', '5CXLTF2PFBE89tTYsrofGPkSfGTdmW4ciw4vAfgcKhjggRgZ', 'loc-10', 'OPEN', 'Transaction'); -INSERT INTO loc_request_file (request_id, hash, name, oid, content_type, added_on, "index", draft, nature) -VALUES ('2b287596-f9d5-8030-b606-d1da538cb37f', '0x1307990e6ba5ca145eb35e99182a9bec46531bc54ddf656a602c780fa0240dee', 'a file', 123456, 'text/plain', '2021-10-06T11:16:00.000', 0, TRUE, 'some nature'); -INSERT INTO loc_metadata_item (request_id, "index", name, "value_text", added_on, draft) -VALUES ('2b287596-f9d5-8030-b606-d1da538cb37f', 0, 'a name', 'a value', '2021-10-06T11:16:00.000', true); +INSERT INTO loc_request_file (request_id, hash, name, oid, content_type, added_on, "index", draft, nature, submitter) +VALUES ('2b287596-f9d5-8030-b606-d1da538cb37f', '0x1307990e6ba5ca145eb35e99182a9bec46531bc54ddf656a602c780fa0240dee', 'a file', 123456, 'text/plain', '2021-10-06T11:16:00.000', 0, TRUE, 'some nature', '5DDGQertEH5qvKVXUmpT3KNGViCX582Qa2WWb8nGbkmkRHvw'); +INSERT INTO loc_metadata_item (request_id, "index", name, "value_text", added_on, draft, submitter) +VALUES ('2b287596-f9d5-8030-b606-d1da538cb37f', 0, 'a name', 'a value', '2021-10-06T11:16:00.000', true, '5DDGQertEH5qvKVXUmpT3KNGViCX582Qa2WWb8nGbkmkRHvw'); INSERT INTO loc_link (request_id, "index", target, added_on, draft, nature) VALUES ('2b287596-f9d5-8030-b606-d1da538cb37f', 0, 'ec126c6c-64cf-4eb8-bfa6-2a98cd19ad5d', '2021-10-06T11:16:00.000', true, 'link-nature'); -- Open Polkadot Identity locs diff --git a/test/integration/model/locrequest.model.spec.ts b/test/integration/model/locrequest.model.spec.ts index 206bb2f5..edc3662c 100644 --- a/test/integration/model/locrequest.model.spec.ts +++ b/test/integration/model/locrequest.model.spec.ts @@ -11,6 +11,8 @@ import { import { ALICE, BOB } from "../../helpers/addresses"; import { v4 as uuid } from "uuid"; +const SUBMITTER = "5DDGQertEH5qvKVXUmpT3KNGViCX582Qa2WWb8nGbkmkRHvw"; + describe('LocRequestRepository - read accesses', () => { beforeAll(async () => { @@ -169,12 +171,14 @@ function givenOpenLoc(id: string): LocRequestAggregateRoot { oid: 123, contentType: "content/type", nature: "nature1", + submitter: SUBMITTER, }) locRequest.metadata = [] locRequest.addMetadataItem({ name: "itemName", addedOn: moment(), - value: "something valuable" + value: "something valuable", + submitter: SUBMITTER, }) return locRequest; } diff --git a/test/unit/controllers/locrequest.controller.spec.ts b/test/unit/controllers/locrequest.controller.spec.ts index 4ac6c9e0..ca5824ec 100644 --- a/test/unit/controllers/locrequest.controller.spec.ts +++ b/test/unit/controllers/locrequest.controller.spec.ts @@ -60,6 +60,7 @@ const testFile:FileDescription = { contentType: "application/pdf", hash: "0x9383cd5dfeb5870027088289c665c3bae2d339281840473f35311954e984dea9", oid: 123, + submitter: SUBMITTER, addedOn: moment() } @@ -70,7 +71,8 @@ const testLink:LinkDescription = { const testMetadataItem:MetadataItemDescription = { name: "test-data", - value: "test-data-value" + value: "test-data-value", + submitter: SUBMITTER, } const testDataWithUserIdentity = { @@ -309,7 +311,7 @@ describe('LocRequestController', () => { const buffer = Buffer.from(SOME_DATA); await request(app) .post(`/api/loc-request/${ REQUEST_ID }/files`) - .field({ nature: "some nature", submitter: SUBMITTER }) + .field({ nature: "some nature" }) .attach('file', buffer, { filename: FILE_NAME, contentType: 'text/plain', @@ -321,8 +323,8 @@ describe('LocRequestController', () => { }); }) - it('fails to add file to loc when not owner', async () => { - const app = setupApp(LocRequestController, mockModelForAddFile, true, false); + it('fails to add file to loc when neither owner nor requester', async () => { + const app = setupApp(LocRequestController, mockModelForAddFile, true, false, false); const buffer = Buffer.from(SOME_DATA); await request(app) .post(`/api/loc-request/${ REQUEST_ID }/files`) @@ -367,7 +369,7 @@ describe('LocRequestController', () => { expect(file.nature).toBe(testFile.nature) expect(file.hash).toBe(testFile.hash) expect(file.addedOn).toBe(testFile.addedOn?.toISOString()) - expect(file.submitter).toBe(ALICE) // TODO Change me + expect(file.submitter).toBe(SUBMITTER) const link = response.body.links[0] expect(link.nature).toBe(testLink.nature) expect(link.target).toBe(testLink.target) @@ -376,7 +378,7 @@ describe('LocRequestController', () => { expect(metadataItem.name).toBe(testMetadataItem.name) expect(metadataItem.value).toBe(testMetadataItem.value) expect(metadataItem.addedOn).toBe(testMetadataItem.addedOn?.toISOString()) - expect(metadataItem.submitter).toBe(ALICE) // TODO Change me + expect(metadataItem.submitter).toBe(SUBMITTER) }); }); @@ -399,15 +401,15 @@ describe('LocRequestController', () => { const app = setupApp(LocRequestController, (container) => mockModelForAllItems(container, locRequest)) await request(app) .post(`/api/loc-request/${ REQUEST_ID }/metadata`) - .send({ name: SOME_DATA_NAME, value: SOME_DATA_VALUE, submitter: SUBMITTER }) + .send({ name: SOME_DATA_NAME, value: SOME_DATA_VALUE }) .expect(204) locRequest.verify(instance => instance.addMetadataItem( It.Is(item => item.name == SOME_DATA_NAME && item.value == SOME_DATA_VALUE))) }) - it('fails to adds a metadata item when not owner', async () => { + it('fails to adds a metadata item when neither owner nor requester', async () => { const locRequest = mockRequestForMetadata(); - const app = setupApp(LocRequestController, (container) => mockModelForAllItems(container, locRequest), true, false) + const app = setupApp(LocRequestController, (container) => mockModelForAllItems(container, locRequest), true, false, false) await request(app) .post(`/api/loc-request/${ REQUEST_ID }/metadata`) .send({ name: SOME_DATA_NAME, value: SOME_DATA_VALUE }) @@ -790,7 +792,11 @@ function mockRequestForMetadata(): Mock { .returns() request.setup(instance => instance.confirmMetadataItem(SOME_DATA_NAME)) .returns() - request.setup(instance => instance.addMetadataItem({ name: SOME_DATA_NAME, value: SOME_DATA_VALUE})) + request.setup(instance => instance.addMetadataItem({ + name: SOME_DATA_NAME, + value: SOME_DATA_VALUE, + submitter: SUBMITTER + })) .returns() return request; } diff --git a/test/unit/model/locrequest.model.spec.ts b/test/unit/model/locrequest.model.spec.ts index 1e7216d3..b616deb6 100644 --- a/test/unit/model/locrequest.model.spec.ts +++ b/test/unit/model/locrequest.model.spec.ts @@ -16,6 +16,8 @@ import { import { UserIdentity } from "../../../src/logion/model/useridentity"; import { Mock } from "moq.ts"; +const SUBMITTER = "5DDGQertEH5qvKVXUmpT3KNGViCX582Qa2WWb8nGbkmkRHvw"; + describe("LocRequestFactory", () => { it("creates Transaction LOC request", async () => { @@ -229,11 +231,13 @@ describe("LocRequestAggregateRoot (metadata)", () => { const items: MetadataItemDescription[] = [ { name: "same name", - value: "some value" + value: "some value", + submitter: SUBMITTER, }, { name: "same name", - value: "some other value" + value: "some other value", + submitter: SUBMITTER, } ]; expect(() => whenAddingMetadata(items)).toThrowError(); @@ -245,10 +249,12 @@ describe("LocRequestAggregateRoot (metadata)", () => { { name: "name1", value: "value1", + submitter: SUBMITTER, }, { name: "name2", value: "value2", + submitter: SUBMITTER, } ]; whenAddingMetadata(metadata); @@ -260,11 +266,13 @@ describe("LocRequestAggregateRoot (metadata)", () => { const items: MetadataItemDescription[] = [ { name: "name1", - value: "some nice value" + value: "some nice value", + submitter: SUBMITTER, }, { name: "name2", - value: "some other nice value" + value: "some other nice value", + submitter: SUBMITTER, } ]; whenAddingMetadata(items); @@ -273,7 +281,8 @@ describe("LocRequestAggregateRoot (metadata)", () => { const newItems: MetadataItemDescription[] = [ { name: "name1", - value: "some nice value" + value: "some nice value", + submitter: SUBMITTER, } ]; thenExposesMetadata(newItems); @@ -288,7 +297,8 @@ describe("LocRequestAggregateRoot (metadata)", () => { whenAddingMetadata([ { name, - value: "value-1" + value: "value-1", + submitter: SUBMITTER, } ]) whenConfirmingMetadataItem(name) @@ -383,6 +393,7 @@ describe("LocRequestAggregateRoot (files)", () => { contentType: "text/plain", oid: 1234, nature: "nature1", + submitter: SUBMITTER, }, { hash: "hash2", @@ -390,6 +401,7 @@ describe("LocRequestAggregateRoot (files)", () => { contentType: "text/plain", oid: 4567, nature: "nature2", + submitter: SUBMITTER, } ]; whenAddingFiles(files); @@ -409,6 +421,7 @@ describe("LocRequestAggregateRoot (files)", () => { contentType: "text/plain", oid: 1234, nature: "nature1", + submitter: SUBMITTER, }, { hash: "hash1", @@ -416,6 +429,7 @@ describe("LocRequestAggregateRoot (files)", () => { contentType: "text/plain", oid: 4567, nature: "nature2", + submitter: SUBMITTER, } ]; expect(() => whenAddingFiles(files)).toThrowError(); @@ -430,6 +444,7 @@ describe("LocRequestAggregateRoot (files)", () => { contentType: "text/plain", oid: 1234, nature: "nature1", + submitter: SUBMITTER, }, { hash: "hash2", @@ -437,6 +452,7 @@ describe("LocRequestAggregateRoot (files)", () => { contentType: "text/plain", oid: 4567, nature: "nature2", + submitter: SUBMITTER, } ]; whenAddingFiles(files); @@ -450,6 +466,7 @@ describe("LocRequestAggregateRoot (files)", () => { contentType: "text/plain", oid: 4567, nature: "nature2", + submitter: SUBMITTER, } ]; thenExposesFiles(newFiles); @@ -468,6 +485,7 @@ describe("LocRequestAggregateRoot (files)", () => { contentType: "text/plain", oid: 1234, nature: "nature1", + submitter: SUBMITTER, } ]); whenConfirmingFile(hash) @@ -483,6 +501,7 @@ describe("LocRequestAggregateRoot (synchronization)", () => { whenAddingMetadata([{ name: "data-1", value: "value-1", + submitter: SUBMITTER, }]) const addedOn = moment(); whenSettingMetadataItemAddedOn("data-1", addedOn); @@ -491,6 +510,7 @@ describe("LocRequestAggregateRoot (synchronization)", () => { thenExposesMetadataItemByName("data-1", { name: "data-1", value: "value-1", + submitter: SUBMITTER, addedOn: addedOn }) }) @@ -521,6 +541,7 @@ describe("LocRequestAggregateRoot (synchronization)", () => { contentType: "text/plain", oid: 1234, nature: "nature1", + submitter: SUBMITTER, }, { hash: "hash2", @@ -528,6 +549,7 @@ describe("LocRequestAggregateRoot (synchronization)", () => { contentType: "text/plain", oid: 4567, nature: "nature2", + submitter: SUBMITTER, } ]; whenAddingFiles(files); @@ -541,6 +563,7 @@ describe("LocRequestAggregateRoot (synchronization)", () => { contentType: "text/plain", oid: 1234, nature: "nature1", + submitter: SUBMITTER, addedOn: addedOn }) }) @@ -642,6 +665,7 @@ function expectSameFiles(f1: FileDescription, f2: FileDescription) { expect(f1.oid).toEqual(f2.oid); expect(f1.contentType).toEqual(f2.contentType); expect(f1.nature).toEqual(f2.nature); + expect(f1.submitter).toEqual(f2.submitter); if(f1.addedOn === undefined) { expect(f2.addedOn).not.toBeDefined(); } else { @@ -665,6 +689,7 @@ function thenExposesMetadata(expectedMetadata: MetadataItemDescription[]) { request.getMetadataItems().forEach((item, index) => { expect(item.name).toBe(expectedMetadata[index].name); expect(item.value).toBe(expectedMetadata[index].value); + expect(item.submitter).toBe(expectedMetadata[index].submitter); if (item.addedOn === undefined) { expect(expectedMetadata[index].addedOn).not.toBeDefined() } else { @@ -680,6 +705,7 @@ function thenExposesMetadataItemByName(name: string, expectedMetadataItem: Metad function expectSameMetadataItems(item1: MetadataItemDescription, item2: MetadataItemDescription) { expect(item1.name).toEqual(item2.name); expect(item1.value).toEqual(item2.value); + expect(item1.submitter).toEqual(item2.submitter); if (item1.addedOn === undefined) { expect(item2.addedOn).toBeUndefined() } else {