diff --git a/src/logion/model/locrequest.model.ts b/src/logion/model/locrequest.model.ts index 3446e16..adb2bf5 100644 --- a/src/logion/model/locrequest.model.ts +++ b/src/logion/model/locrequest.model.ts @@ -942,7 +942,10 @@ export class LocRequestAggregateRoot { } private canRemove(address: SupportedAccountId, item: Submitted): boolean { - return this.isOwner(address) || accountEquals(address, item.submitter); + return this.isOwner(address) || ( + accountEquals(address, item.submitter) + && (item.lifecycle?.status === "DRAFT" || item.lifecycle?.status === "REVIEW_REJECTED") + ); } requestMetadataItemReview(nameHash: Hash) { @@ -1625,6 +1628,7 @@ export class LocMetadataItem extends Child implements HasIndex, Submitted { interface Submitted { submitter?: EmbeddableSupportedAccountId; + lifecycle?: EmbeddableLifecycle; } @Entity("loc_link") diff --git a/test/unit/model/locrequest.model.spec.ts b/test/unit/model/locrequest.model.spec.ts index 521bb60..52b7dbb 100644 --- a/test/unit/model/locrequest.model.spec.ts +++ b/test/unit/model/locrequest.model.spec.ts @@ -877,8 +877,32 @@ describe("LocRequestAggregateRoot (metadata)", () => { request.cancelPreAcknowledgeMetadataItem(nameHash, OWNER_ACCOUNT); expect(request.getMetadataOrThrow(nameHash).lifecycle?.status).toBe("PUBLISHED"); }); + + it("requester cannot remove accepted metadata", () => { + const nameHash = givenRequestWithAcceptedMetadata(); + expect(() => request.removeMetadataItem(SUBMITTER, nameHash)).toThrowError("Item removal not allowed"); + }); + + it("owner can still remove accepted metadata", () => { + const nameHash = givenRequestWithAcceptedMetadata(); + expect(() => request.removeMetadataItem(ALICE_ACCOUNT, nameHash)).not.toThrow(); + }); }) +function givenRequestWithAcceptedMetadata() { + givenRequestWithStatus("OPEN"); + const name = "Name"; + request.addMetadataItem({ + name, + submitter: SUBMITTER, + value: "Value", + }, "MANUAL_BY_USER"); + const nameHash = Hash.of(name); + request.requestMetadataItemReview(nameHash); + request.acceptMetadataItem(nameHash); + return nameHash; +} + describe("LocRequestAggregateRoot (links)", () => { it("does not accept several links with same target", () => { @@ -1114,8 +1138,31 @@ describe("LocRequestAggregateRoot (links)", () => { request.cancelPreAcknowledgeLink(target, OWNER_ACCOUNT); expect(request.getLinkOrThrow(target).lifecycle?.status).toBe("PUBLISHED"); }); + + it("requester cannot remove accepted link", () => { + const target = givenRequestWithAcceptedLink(); + expect(() => request.removeLink(SUBMITTER, target)).toThrowError("Item removal not allowed"); + }); + + it("owner can still remove accepted link", () => { + const target = givenRequestWithAcceptedLink(); + expect(() => request.removeLink(ALICE_ACCOUNT, target)).not.toThrow(); + }); }) +function givenRequestWithAcceptedLink() { + givenRequestWithStatus("OPEN"); + const target = new UUID().toString(); + request.addLink({ + target, + submitter: SUBMITTER, + nature: "Nature", + }, "MANUAL_BY_USER"); + request.requestLinkReview(target); + request.acceptLink(target); + return target; +} + describe("LocRequestAggregateRoot (files)", () => { it("adds and exposes files", () => { @@ -1578,8 +1625,34 @@ describe("LocRequestAggregateRoot (files)", () => { request.cancelPreAcknowledgeFile(hash, VERIFIED_ISSUER); expect(request.getFileOrThrow(hash).lifecycle?.status).toBe("PUBLISHED"); }); + + it("requester cannot remove accepted file", () => { + const hash = givenRequestWithAcceptedFile(); + expect(() => request.removeFile(SUBMITTER, hash)).toThrowError("Item removal not allowed"); + }); + + it("owner can still remove accepted file", () => { + const hash = givenRequestWithAcceptedFile(); + expect(() => request.removeFile(ALICE_ACCOUNT, hash)).not.toThrow(); + }); }); +function givenRequestWithAcceptedFile() { + givenRequestWithStatus("OPEN"); + const hash = Hash.of("content"); + request.addFile({ + hash, + name: "test.txt", + restrictedDelivery: false, + size: 7, + submitter: SUBMITTER, + nature: "Nature", + }, "MANUAL_BY_USER"); + request.requestFileReview(hash); + request.acceptFile(hash); + return hash; +} + const hash1 = Hash.of("hash1"); const hash2 = Hash.of("hash2");