Merge branch feature/download-proof-zip into dev (#150)

This commit is contained in:
Arnaud D. Natali 2023-10-19 11:42:44 +02:00 committed by GitHub
commit f08b258b8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 8 deletions

View File

@ -45,6 +45,7 @@
"@mailchimp/mailchimp_transactional": "^1.0.50",
"@pinata/sdk": "^2.1.0",
"@prisma/client": "^4.11.0",
"adm-zip": "^0.5.10",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
"classnames": "^2.3.2",
@ -71,6 +72,7 @@
"uuidv4": "^6.2.13"
},
"devDependencies": {
"@types/adm-zip": "^0.5.3",
"@types/cors": "^2.8.13",
"@types/cron": "^2.0.1",
"@types/express": "^4.17.16",

View File

@ -3,9 +3,10 @@ import { Controller, Get, Post } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController";
import { Service } from "typedi";
import { Document, OfficeFolder } from "le-coffre-resources/dist/Notary";
import { getFolderHashes } from "@Common/optics/notary";
import { getFolderHashes, getFolderFilesUid } from "@Common/optics/notary";
import OfficeFoldersService from "@Services/notary/OfficeFoldersService/OfficeFoldersService";
import OfficeFolderAnchorsRepository from "@Repositories/OfficeFolderAnchorsRepository";
import FilesService from "@Services/common/FilesService/FilesService";
import SecureService from "@Services/common/SecureService/SecureService";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
@ -14,6 +15,7 @@ import OfficeFolderAnchor from "le-coffre-resources/dist/Notary/OfficeFolderAnch
import NotificationBuilder from "@Common/notifications/NotificationBuilder";
import { Prisma } from "@prisma/client";
import OfficeFolderAnchorsService from "@Services/notary/OfficeFolderAnchorsService/OfficeFolderAnchorsService";
import Zip from "adm-zip";
const hydrateOfficeFolderAnchor = (data: any): OfficeFolderAnchor =>
OfficeFolderAnchor.hydrate<OfficeFolderAnchor>(
@ -41,13 +43,14 @@ export default class OfficeFoldersController extends ApiController {
private officeFolderAnchorsRepository: OfficeFolderAnchorsRepository,
private officeFolderAnchorsService: OfficeFolderAnchorsService,
private officeFoldersService: OfficeFoldersService,
private filesService: FilesService,
private notificationBuilder: NotificationBuilder,
) {
super();
}
/**
* @description Download a folder anchoring proof document
* @description Download a folder anchoring proof document along with all accessible files
*/
@Get("/api/v1/notary/anchors/download/:uid", [authHandler, ruleHandler, folderHandler])
protected async download(req: Request, response: Response) {
@ -76,6 +79,7 @@ export default class OfficeFoldersController extends ApiController {
const officeFolder = OfficeFolder.hydrate<OfficeFolder>(officeFolderFound, { strategy: "excludeAll" });
const folderHashes = getFolderHashes(officeFolder);
const folderFilesUid = getFolderFilesUid(officeFolder);
if (folderHashes.length === 0) {
this.httpNotFoundRequest(response, "No file hash to anchor");
@ -83,10 +87,25 @@ export default class OfficeFoldersController extends ApiController {
}
const sortedHashes = [...folderHashes].sort();
const buffer = await this.secureService.download(sortedHashes);
const anchoringProof = await this.secureService.download(sortedHashes);
response.setHeader("Content-Type", "application/pdf");
this.httpSuccess(response, buffer);
const addFileToZip = (zip: Zip) => (uid: string): Promise<void> =>
(async () => {
const data = await this.filesService.download(uid);
if (!data?.buffer) return;
zip.addFile(`${uid}-${data.file.file_name}`, data.buffer);
})()
const uids: string[] = folderFilesUid.filter((uid): uid is string => uid !== undefined);
const zip = new Zip();
zip.addFile(`${uid}-certificat-de-dépôt.pdf`, anchoringProof);
await Promise.allSettled(
uids.map(addFileToZip(zip))
)
response.setHeader("Content-Type", "application/zip");
this.httpSuccess(response, zip.toBuffer());
} catch (error) {
this.httpInternalError(response, error);
return;

View File

@ -10,6 +10,7 @@ import { Document, File, OfficeFolder } from "le-coffre-resources/dist/Notary";
export const folderDocumentsLens = Optics.Lens.fromNullableProp<OfficeFolder>()("documents", []);
export const documentFilesLens = Optics.Lens.fromNullableProp<Document>()("files", []);
export const fileHashLens = Optics.Lens.fromProp<File>()("hash");
export const fileUidLens = Optics.Lens.fromProp<File>()("uid");
/**
* Traversals
@ -17,13 +18,17 @@ export const fileHashLens = Optics.Lens.fromProp<File>()("hash");
export const documentsTraversal = Optics.fromTraversable(Array.Traversable)<Document>();
export const filesTraversal = Optics.fromTraversable(Array.Traversable)<File>();
export const folderHashesTraversal = folderDocumentsLens
export const folderFilesTraversal = folderDocumentsLens
.composeTraversal(documentsTraversal)
.composeLens(documentFilesLens)
.composeTraversal(filesTraversal)
.composeLens(fileHashLens);
.composeTraversal(filesTraversal);
export const folderHashesTraversal = folderFilesTraversal.composeLens(fileHashLens);
export const folderFilesUidTraversal = folderFilesTraversal.composeLens(fileUidLens);
/**
* Getters
*/
export const getFolderFiles = (folder: OfficeFolder) => Traversal.getAll(folder)(folderFilesTraversal);
export const getFolderHashes = (folder: OfficeFolder) => Traversal.getAll(folder)(folderHashesTraversal);
export const getFolderFilesUid = (folder: OfficeFolder) => Traversal.getAll(folder)(folderFilesUidTraversal);