Skip to content

Commit

Permalink
Merge pull request #261 from logion-network/feature/use-hash-vo
Browse files Browse the repository at this point in the history
Use Hash class
  • Loading branch information
gdethier authored Aug 1, 2023
2 parents ae3150c + 1f40000 commit a6f9a28
Show file tree
Hide file tree
Showing 35 changed files with 647 additions and 569 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"typeorm": "node ./node_modules/typeorm/cli.js -d ./dist/db-tools/ormconfig.js"
},
"dependencies": {
"@logion/node-api": "^0.18.0-1",
"@logion/node-api": "^0.18.0-2",
"@logion/node-exiftool": "^2.3.1-3",
"@logion/rest-api-core": "^0.4.3",
"@polkadot/wasm-crypto": "^7.1.1",
Expand Down
8 changes: 4 additions & 4 deletions src/logion/controllers/adapters/locrequestadapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { UserIdentity } from "../../model/useridentity.js";
import { components } from "../components.js";
import { VoteRepository, VoteAggregateRoot } from "../../model/vote.model.js";
import { VerifiedIssuerAggregateRoot, VerifiedIssuerSelectionRepository } from "../../model/verifiedissuerselection.model.js";
import { Fees } from "@logion/node-api";
import { Fees, Hash } from "@logion/node-api";
import { SupportedAccountId } from "../../model/supportedaccountid.model.js";

export type UserPrivateData = {
Expand Down Expand Up @@ -80,7 +80,7 @@ export class LocRequestAdapter {
closedOn: request.closedOn || undefined,
files: request.getFiles(viewer).map(file => ({
name: file.name,
hash: file.hash,
hash: file.hash.toHex(),
nature: file.nature,
submitter: file.submitter,
restrictedDelivery: file.restrictedDelivery,
Expand All @@ -92,7 +92,7 @@ export class LocRequestAdapter {
})),
metadata: request.getMetadataItems(viewer).map(item => ({
name: item.name,
nameHash: item.nameHash,
nameHash: item.nameHash.toHex(),
value: item.value,
submitter: item.submitter,
fees: toFeesView(item.fees),
Expand All @@ -104,7 +104,7 @@ export class LocRequestAdapter {
addedOn: link.addedOn?.toISOString() || undefined,
fees: toFeesView(link.fees),
})),
seal: locDescription.seal?.hash,
seal: locDescription.seal?.hash ? locDescription.seal.hash.toHex() : undefined,
company: locDescription.company,
iDenfy,
voteId: vote?.voteId,
Expand Down
116 changes: 71 additions & 45 deletions src/logion/controllers/collection.controller.ts

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions src/logion/controllers/fileupload.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { UploadedFile, FileArray } from "express-fileupload";
import { badRequest } from "@logion/rest-api-core";
import { sha256File } from "../lib/crypto/hashing.js";
import { Hash } from "@logion/node-api";

export async function getUploadedFile(request: Express.Request, receivedHash: string): Promise<UploadedFile> {
export async function getUploadedFile(request: Express.Request, receivedHash: Hash): Promise<UploadedFile> {
const files: FileArray | undefined = request.files;
if(files === undefined || files === null) {
throw badRequest("No file detected");
Expand All @@ -18,8 +19,8 @@ export async function getUploadedFile(request: Express.Request, receivedHash: st
throw badRequest("File upload failed (truncated)")
}
const localHash = await sha256File(file.tempFilePath);
if(localHash !== receivedHash) {
throw badRequest(`Received hash ${receivedHash} does not match ${localHash}`)
if(!localHash.equalTo(receivedHash)) {
throw badRequest(`Received hash ${ receivedHash.toHex() } does not match ${ localHash.toHex() }`)
}
file.name = Buffer.from(file.name, 'latin1').toString();
return file;
Expand Down
64 changes: 34 additions & 30 deletions src/logion/controllers/locrequest.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ export class LocRequestController extends ApiController {
createdOn: locDescription.createdOn || undefined,
closedOn: request.closedOn || undefined,
files: request.getFiles().map(file => ({
hash: file.hash,
hash: file.hash.toHex(),
nature: file.nature,
addedOn: file.addedOn?.toISOString() || undefined,
submitter: file.submitter,
Expand All @@ -368,7 +368,7 @@ export class LocRequestController extends ApiController {
})),
metadata: request.getMetadataItems().map(item => ({
name: item.name,
nameHash: item.nameHash,
nameHash: item.nameHash.toHex(),
value: item.value,
addedOn: item.addedOn?.toISOString() || undefined,
submitter: item.submitter,
Expand Down Expand Up @@ -508,7 +508,7 @@ export class LocRequestController extends ApiController {
const request = requireDefined(await this.locRequestRepository.findById(requestId));
const contributor = await this.locAuthorizationService.ensureContributor(this.request, request);

const hash = requireDefined(addFileView.hash, () => badRequest("No hash found for upload file"));
const hash = Hash.fromHex(requireDefined(addFileView.hash, () => badRequest("No hash found for upload file")));
if(request.hasFile(hash)) {
throw new Error("File already present");
}
Expand Down Expand Up @@ -553,7 +553,7 @@ export class LocRequestController extends ApiController {
const request = requireDefined(await this.locRequestRepository.findById(requestId));
const { contributor, voter } = await this.ensureContributorOrVoter(request);

const file = request.getFile(hash);
const file = request.getFile(Hash.fromHex(hash));
if (
!accountEquals(contributor, request.getOwner()) &&
!accountEquals(contributor, request.getRequester()) &&
Expand Down Expand Up @@ -588,7 +588,7 @@ export class LocRequestController extends ApiController {
let file: FileDescription | undefined;
await this.locRequestService.update(requestId, async request => {
const contributor = await this.locAuthorizationService.ensureContributor(this.request, request);
file = request.removeFile(contributor, hash);
file = request.removeFile(contributor, Hash.fromHex(hash));
});
if(file) {
await this.fileStorageService.deleteFile(file);
Expand All @@ -615,7 +615,7 @@ export class LocRequestController extends ApiController {
throw badRequest("LOC must be OPEN for requesting item review");
}
await this.locAuthorizationService.ensureContributor(this.request, request);
request.requestFileReview(hash);
request.requestFileReview(Hash.fromHex(hash));
});

const { userIdentity } = await this.locRequestAdapter.findUserPrivateData(request);
Expand All @@ -625,7 +625,7 @@ export class LocRequestController extends ApiController {
}

static reviewFile(spec: OpenAPIV3.Document) {
const operationObject = spec.paths["/api/loc-request/{requestId}/files/{hash}/review"].post!;
const operationObject = spec.paths["/api/loc-request/{requestId}/files/{hashHex}/review"].post!;
operationObject.summary = "Reviews the given file";
operationObject.description = "The authenticated user must be the owner of the LOC.";
operationObject.requestBody = getRequestBody({
Expand All @@ -635,15 +635,16 @@ export class LocRequestController extends ApiController {
operationObject.responses = getDefaultResponsesNoContent();
setPathParameters(operationObject, {
'requestId': "The ID of the LOC",
'hash': "The hash of the file to review"
'hashHex': "The hash of the file to review"
});
}

@HttpPost('/:requestId/files/:hash/review')
@HttpPost('/:requestId/files/:hashHex/review')
@Async()
@SendsResponse()
async reviewFile(view: ReviewItemView, requestId: string, hash: string) {
async reviewFile(view: ReviewItemView, requestId: string, hashHex: string) {
const authenticatedUser = await this.authenticationService.authenticatedUser(this.request);
const hash = Hash.fromHex(hashHex);
const request = await this.locRequestService.update(requestId, async request => {
authenticatedUser.require(user => user.is(request.ownerAddress));
if (view.decision === "ACCEPT") {
Expand All @@ -661,20 +662,21 @@ export class LocRequestController extends ApiController {
}

static confirmFile(spec: OpenAPIV3.Document) {
const operationObject = spec.paths["/api/loc-request/{requestId}/files/{hash}/confirm"].put!;
const operationObject = spec.paths["/api/loc-request/{requestId}/files/{hashHex}/confirm"].put!;
operationObject.summary = "Confirms a file of the LOC";
operationObject.description = "The authenticated user must be the owner of the LOC. Once a file is confirmed, it cannot be deleted anymore.";
operationObject.responses = getDefaultResponsesNoContent();
setPathParameters(operationObject, {
'requestId': "The ID of the LOC",
'hash': "The hash of the file to download"
'hashHex': "The hash of the file to download"
});
}

@HttpPut('/:requestId/files/:hash/confirm')
@HttpPut('/:requestId/files/:hashHex/confirm')
@Async()
@SendsResponse()
async confirmFile(_body: any, requestId: string, hash: string) {
async confirmFile(_body: any, requestId: string, hashHex: string) {
const hash = Hash.fromHex(hashHex);
await this.locRequestService.update(requestId, async request => {
const contributor = await this.locAuthorizationService.ensureContributor(this.request, request);
const file = request.getFile(hash);
Expand Down Expand Up @@ -705,7 +707,7 @@ export class LocRequestController extends ApiController {
const authenticatedUser = await this.authenticationService.authenticatedUser(this.request);
await this.locRequestService.update(requestId, async request => {
authenticatedUser.require(user => user.is(request.ownerAddress));
request.confirmFileAcknowledged(hash)
request.confirmFileAcknowledged(Hash.fromHex(hash));
});
this.response.sendStatus(204);
}
Expand Down Expand Up @@ -877,10 +879,10 @@ export class LocRequestController extends ApiController {

@HttpDelete('/:requestId/metadata/:nameHash')
@Async()
async deleteMetadata(_body: any, requestId: string, nameHash: Hash): Promise<void> {
async deleteMetadata(_body: any, requestId: string, nameHash: string): Promise<void> {
await this.locRequestService.update(requestId, async request => {
const contributor = await this.locAuthorizationService.ensureContributor(this.request, request);
request.removeMetadataItem(contributor, nameHash);
request.removeMetadataItem(contributor, Hash.fromHex(nameHash));
});
}

Expand All @@ -898,19 +900,19 @@ export class LocRequestController extends ApiController {
@HttpPost('/:requestId/metadata/:nameHash/review-request')
@Async()
@SendsResponse()
async requestMetadataReview(_body: any, requestId: string, nameHash: Hash) {
async requestMetadataReview(_body: any, requestId: string, nameHash: string) {
await this.locRequestService.update(requestId, async request => {
if (request.status !== 'OPEN') {
throw badRequest("LOC must be OPEN for requesting item review");
}
await this.locAuthorizationService.ensureContributor(this.request, request);
request.requestMetadataItemReview(nameHash);
request.requestMetadataItemReview(Hash.fromHex(nameHash));
});
this.response.sendStatus(204);
}

static reviewMetadata(spec: OpenAPIV3.Document) {
const operationObject = spec.paths["/api/loc-request/{requestId}/files/{hash}/review"].post!;
const operationObject = spec.paths["/api/loc-request/{requestId}/metadata/{nameHash}/review"].post!;
operationObject.summary = "Reviews the given file";
operationObject.description = "The authenticated user must be the owner of the LOC.";
operationObject.requestBody = getRequestBody({
Expand All @@ -927,15 +929,16 @@ export class LocRequestController extends ApiController {
@HttpPost('/:requestId/metadata/:nameHash/review')
@Async()
@SendsResponse()
async reviewMetadata(view: ReviewItemView, requestId: string, nameHash: Hash) {
async reviewMetadata(view: ReviewItemView, requestId: string, nameHash: string) {
const authenticatedUser = await this.authenticationService.authenticatedUser(this.request);
const hash = Hash.fromHex(nameHash);
await this.locRequestService.update(requestId, async request => {
authenticatedUser.require(user => user.is(request.ownerAddress));
if (view.decision === "ACCEPT") {
request.acceptMetadataItem(nameHash);
request.acceptMetadataItem(hash);
} else {
const reason = requireDefined(view.rejectReason, () => badRequest("Reason is required"));
request.rejectMetadataItem(nameHash, reason);
request.rejectMetadataItem(hash, reason);
}
});
this.response.sendStatus(204);
Expand All @@ -955,12 +958,13 @@ export class LocRequestController extends ApiController {
@HttpPut('/:requestId/metadata/:nameHash/confirm')
@Async()
@SendsResponse()
async confirmMetadata(_body: any, requestId: string, nameHash: Hash) {
async confirmMetadata(_body: any, requestId: string, nameHash: string) {
await this.locRequestService.update(requestId, async request => {
const contributor = await this.locAuthorizationService.ensureContributor(this.request, request);
const item = request.getMetadataItem(nameHash);
const hash = Hash.fromHex(nameHash);
const item = request.getMetadataItem(hash);
if((item.submitter.type !== "Polkadot" && request.isOwner(contributor)) || accountEquals(item.submitter, contributor)) {
request.confirmMetadataItem(nameHash);
request.confirmMetadataItem(hash);
} else {
throw unauthorized("Contributor cannot confirm");
}
Expand All @@ -982,11 +986,11 @@ export class LocRequestController extends ApiController {
@HttpPut('/:requestId/metadata/:nameHash/confirm-acknowledged')
@Async()
@SendsResponse()
async confirmMetadataAcknowledged(_body: any, requestId: string, nameHash: Hash) {
async confirmMetadataAcknowledged(_body: any, requestId: string, nameHash: string) {
const authenticatedUser = await this.authenticationService.authenticatedUser(this.request);
await this.locRequestService.update(requestId, async request => {
authenticatedUser.require(user => user.is(request.ownerAddress));
request.confirmMetadataItemAcknowledged(nameHash)
request.confirmMetadataItemAcknowledged(Hash.fromHex(nameHash));
});
this.response.sendStatus(204);
}
Expand Down Expand Up @@ -1014,8 +1018,8 @@ export class LocRequestController extends ApiController {
let description = `Statement of Facts for LOC ${ new UUID(locId).toDecimalString() }`;
let linkNature = `Original LOC`;
if (loc.locType === 'Collection') {
const itemId = requireDefined(createSofRequestView.itemId,
() => badRequest("Missing itemId"));
const itemId = Hash.fromHex(requireDefined(createSofRequestView.itemId,
() => badRequest("Missing itemId")));
requireDefined(await this.collectionRepository.findBy(locId, itemId),
() => badRequest("Item not found"));
description = `${ description } - ${ itemId }`
Expand Down
3 changes: 2 additions & 1 deletion src/logion/controllers/lofile.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { getUploadedFile } from "./fileupload.js";
import { downloadAndClean } from "../lib/http.js";
import { components } from "./components.js";
import { LoFileService } from "../services/lofile.service.js";
import { Hash } from "@logion/node-api";

type FileUploadData = components["schemas"]["FileUploadData"];

Expand Down Expand Up @@ -70,7 +71,7 @@ export class LoFileController extends ApiController {
const authenticatedUser = await this.authenticationService.authenticatedUserIsLegalOfficerOnNode(this.request);
authenticatedUser.require(user => user.is(legalOfficerAddress));

const file = await getUploadedFile(this.request, requireDefined(body.hash, () => badRequest("No hash found for upload file")));
const file = await getUploadedFile(this.request, Hash.fromHex(requireDefined(body.hash, () => badRequest("No hash found for upload file"))));
const existingLoFile = await this.loFileRepository.findById({ id, legalOfficerAddress } );
if (existingLoFile) {
const oidToRemove = existingLoFile.oid;
Expand Down
Loading

0 comments on commit a6f9a28

Please sign in to comment.