Skip to content

Commit

Permalink
Merge pull request #251 from logion-network/feature/fix-confirm
Browse files Browse the repository at this point in the history
Some confirmations aknownledge as well
  • Loading branch information
gdethier authored Jun 1, 2023
2 parents ed4650c + d4e3d4e commit 3e0877d
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 26 deletions.
19 changes: 15 additions & 4 deletions src/logion/controllers/locrequest.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
requireLength,
AuthenticationService,
forbidden,
unauthorized,
} from "@logion/rest-api-core";
import { UUID } from "@logion/node-api";

Expand Down Expand Up @@ -636,8 +637,13 @@ export class LocRequestController extends ApiController {
@SendsResponse()
async confirmFile(_body: any, requestId: string, hash: string) {
await this.locRequestService.update(requestId, async request => {
await this.locAuthorizationService.ensureContributor(this.request, request);
request.confirmFile(hash);
const contributor = await this.locAuthorizationService.ensureContributor(this.request, request);
const file = request.getFile(hash);
if((file.submitter.type !== "Polkadot" && request.isOwner(contributor)) || accountEquals(file.submitter, contributor)) {
request.confirmFile(hash);
} else {
throw unauthorized("Contributor cannot confirm");
}
});
this.response.sendStatus(204);
}
Expand Down Expand Up @@ -859,8 +865,13 @@ export class LocRequestController extends ApiController {
async confirmMetadata(_body: any, requestId: string, name: string) {
const decodedName = decodeURIComponent(name);
await this.locRequestService.update(requestId, async request => {
await this.locAuthorizationService.ensureContributor(this.request, request);
request.confirmMetadataItem(decodedName);
const contributor = await this.locAuthorizationService.ensureContributor(this.request, request);
const item = request.getMetadataItem(decodedName);
if((item.submitter.type !== "Polkadot" && request.isOwner(contributor)) || accountEquals(item.submitter, contributor)) {
request.confirmMetadataItem(decodedName);
} else {
throw unauthorized("Contributor cannot confirm");
}
});
this.response.sendStatus(204);
}
Expand Down
39 changes: 22 additions & 17 deletions src/logion/model/locrequest.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,12 @@ export class EmbeddableLifecycle {
this.reviewedOn = moment().toDate();
}

confirm() {
if (this.status !== "REVIEW_ACCEPTED" && this.status !== "PUBLISHED") {
confirm(isAcknowledged: boolean) {
const acknowledgedOrPublished = isAcknowledged ? "ACKNOWLEDGED" : "PUBLISHED";
if (this.status !== "REVIEW_ACCEPTED" && this.status !== acknowledgedOrPublished) {
throw badRequest(`Cannot confirm item with status ${ this.status }`);
}
this.status = "PUBLISHED";
this.status = acknowledgedOrPublished;
}

confirmAcknowledged(acknowledgedOn?: Moment) {
Expand Down Expand Up @@ -356,28 +357,32 @@ export class LocRequestAggregateRoot {
}

requestFileReview(hash: string) {
this.mutateFile(hash, item => item.requestReview());
this.mutateFile(hash, item => item.lifecycle!.requestReview());
}

acceptFile(hash: string) {
this.mutateFile(hash, item => item.accept());
this.mutateFile(hash, item => item.lifecycle!.accept());
}

rejectFile(hash: string, reason: string) {
this.mutateFile(hash, item => item.reject(reason));
this.mutateFile(hash, item => item.lifecycle!.reject(reason));
}

confirmFile(hash: string) {
this.mutateFile(hash, item => item.confirm());
this.mutateFile(hash, item => item.lifecycle!.confirm(item.submitter?.type !== "Polkadot" || this.isOwner(item.submitter.toSupportedAccountId())));
}

isOwner(account?: SupportedAccountId) {
return accountEquals(account, { address: this.ownerAddress, type: "Polkadot" });
}

confirmFileAcknowledged(hash: string, acknowledgedOn?: Moment) {
this.mutateFile(hash, item => item.confirmAcknowledged(acknowledgedOn));
this.mutateFile(hash, item => item.lifecycle!.confirmAcknowledged(acknowledgedOn));
}

private mutateFile(hash: string, mutator: (item: EmbeddableLifecycle) => void) {
private mutateFile(hash: string, mutator: (item: LocFile) => void) {
const file = this.getFileOrThrow(hash);
mutator(file.lifecycle!);
mutator(file);
file._toUpdate = true;
}

Expand Down Expand Up @@ -537,31 +542,31 @@ export class LocRequestAggregateRoot {
}

requestMetadataItemReview(name: string) {
this.mutateMetadataItem(name, item => item.requestReview());
this.mutateMetadataItem(name, item => item.lifecycle!.requestReview());
}

acceptMetadataItem(name: string) {
this.mutateMetadataItem(name, item => item.accept());
this.mutateMetadataItem(name, item => item.lifecycle!.accept());
}

rejectMetadataItem(name: string, reason: string) {
this.mutateMetadataItem(name, item => item.reject(reason));
this.mutateMetadataItem(name, item => item.lifecycle!.reject(reason));
}

confirmMetadataItem(name: string) {
this.mutateMetadataItem(name, item => item.confirm());
this.mutateMetadataItem(name, item => item.lifecycle!.confirm(item.submitter?.type !== "Polkadot" || this.isOwner(item.submitter.toSupportedAccountId())));
}

confirmMetadataItemAcknowledged(name: string, acknowledgedOn?: Moment) {
this.mutateMetadataItem(name, item => item.confirmAcknowledged(acknowledgedOn));
this.mutateMetadataItem(name, item => item.lifecycle!.confirmAcknowledged(acknowledgedOn));
}

private mutateMetadataItem(name: string, mutator: (item: EmbeddableLifecycle) => void) {
private mutateMetadataItem(name: string, mutator: (item: LocMetadataItem) => void) {
const metadataItem = requireDefined(
this.metadataItem(name),
() => badRequest(`Metadata Item not found: ${ name }`)
);
mutator(metadataItem.lifecycle!);
mutator(metadataItem);
metadataItem._toUpdate = true;
}

Expand Down
17 changes: 12 additions & 5 deletions test/unit/controllers/locrequest.controller.items.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { writeFile } from 'fs/promises';
import { LocRequestController } from "../../../src/logion/controllers/locrequest.controller.js";
import { Container } from "inversify";
import request from "supertest";
import { BOB, ALICE_ACCOUNT } from "../../helpers/addresses.js";
import { BOB, ALICE_ACCOUNT, ALICE } from "../../helpers/addresses.js";
import { Mock, It } from "moq.ts";
import {
LocRequestAggregateRoot,
Expand Down Expand Up @@ -185,13 +185,11 @@ describe('LocRequestController - Items -', () => {
});

it('confirms a metadata item', async () => {
const locRequest = mockRequestForMetadata();
const app = setupApp(LocRequestController, (container) => mockModelForAnyItem(container, locRequest, 'NOT_ISSUER'))
const app = setupApp(LocRequestController, (container) => mockModelForConfirmMetadata(container))
const dataName = encodeURIComponent(SOME_DATA_NAME)
await request(app)
.put(`/api/loc-request/${ REQUEST_ID }/metadata/${ dataName }/confirm`)
.expect(204)
locRequest.verify(instance => instance.confirmMetadataItem(SOME_DATA_NAME))
.expect(204);
});

it('adds a link', async () => {
Expand Down Expand Up @@ -381,6 +379,7 @@ async function testDeleteFileSuccess(app: Express, locRequest: Mock<LocRequestAg
function mockModelForConfirmFile(container: Container) {
const { request, repository } = buildMocksForUpdate(container);
setupRequest(request, REQUEST_ID, "Transaction", "OPEN", testData);
request.setup(instance => instance.getFile(SOME_DATA_HASH)).returns({ submitter: { type: "Polkadot", address: ALICE } } as FileDescription);
request.setup(instance => instance.confirmFile(SOME_DATA_HASH)).returns();
mockPolkadotIdentityLoc(repository, false);
}
Expand Down Expand Up @@ -463,3 +462,11 @@ function mockModelForAddLink(container: Container, request: Mock<LocRequestAggre

mockPolkadotIdentityLoc(repository, false);
}

function mockModelForConfirmMetadata(container: Container) {
const { request, repository } = buildMocksForUpdate(container);
setupRequest(request, REQUEST_ID, "Transaction", "OPEN", testData);
request.setup(instance => instance.getMetadataItem(SOME_DATA_NAME)).returns({ submitter: { type: "Polkadot", address: ALICE } } as MetadataItemDescription);
request.setup(instance => instance.confirmMetadataItem(SOME_DATA_NAME)).returns();
mockPolkadotIdentityLoc(repository, false);
}

0 comments on commit 3e0877d

Please sign in to comment.