From 49e8f1d89b5a78d2c9b421c9d80e1b18d742a4ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFs=20Mansot?= <26844641+devfull@users.noreply.github.com> Date: Fri, 29 Sep 2023 14:39:19 +0200 Subject: [PATCH 1/3] add `OfficeFolderAnchorsRepository` --- .../OfficeFolderAnchorsRepository.ts | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/common/repositories/OfficeFolderAnchorsRepository.ts diff --git a/src/common/repositories/OfficeFolderAnchorsRepository.ts b/src/common/repositories/OfficeFolderAnchorsRepository.ts new file mode 100644 index 00000000..c0687017 --- /dev/null +++ b/src/common/repositories/OfficeFolderAnchorsRepository.ts @@ -0,0 +1,68 @@ +import Database from "@Common/databases/database"; +import BaseRepository from "@Repositories/BaseRepository"; +import { Service } from "typedi"; +import { OfficeFolderAnchors, Prisma } from "@prisma/client"; +import { OfficeFolderAnchor } from "le-coffre-resources/dist/SuperAdmin"; + +@Service() +export default class OfficeFolderAnchorsRepository extends BaseRepository { + constructor(private database: Database) { + super(); + } + protected get model() { + return this.database.getClient().officeFolderAnchors; + } + protected get instanceDb() { + return this.database.getClient(); + } + + /** + * @description : Create new office folder anchor + */ + public async create(officeFolderAnchor: OfficeFolderAnchor): Promise { + const createArgs: Prisma.OfficeFolderAnchorsCreateArgs = { + data: { + hash_sources: officeFolderAnchor.hash_sources, + root_hash: officeFolderAnchor.root_hash!, + + blockchain: officeFolderAnchor.blockchain as OfficeFolderAnchors["blockchain"], + status: officeFolderAnchor.status as OfficeFolderAnchors["status"], + + anchor_nb_try: officeFolderAnchor.anchor_nb_try, + tx_id: officeFolderAnchor.tx_id, + tx_link: officeFolderAnchor.tx_link, + tx_hash: officeFolderAnchor.tx_hash, + + anchored_at: officeFolderAnchor.anchored_at, + }, + }; + + return this.model.create({ ...createArgs }); + } + + /** + * @description : Update data of an office folder anchor + */ + public async update(officeFolderAnchorUid: string, officeFolderAnchor: OfficeFolderAnchor): Promise { + const updateArgs: Prisma.OfficeFolderAnchorsUpdateArgs = { + where: { + uid: officeFolderAnchorUid, + }, + data: { + blockchain: officeFolderAnchor.blockchain as OfficeFolderAnchors["blockchain"], + status: officeFolderAnchor.status as OfficeFolderAnchors["status"], + + anchor_nb_try: officeFolderAnchor.anchor_nb_try, + tx_id: officeFolderAnchor.tx_id, + tx_link: officeFolderAnchor.tx_link, + tx_hash: officeFolderAnchor.tx_hash, + + anchored_at: officeFolderAnchor.anchored_at, + }, + }; + + return this.model.update({ + ...updateArgs, + }); + } +} From ab4fac8e01ea993faa0e003bd12969e6293dfda1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFs=20Mansot?= <26844641+devfull@users.noreply.github.com> Date: Fri, 29 Sep 2023 15:36:31 +0200 Subject: [PATCH 2/3] link an anchor to folder when requesting a new job --- .../notary/OfficeFolderAnchorsController.ts | 53 +++++++++++++++++-- .../repositories/OfficeFoldersRepository.ts | 2 + 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/app/api/notary/OfficeFolderAnchorsController.ts b/src/app/api/notary/OfficeFolderAnchorsController.ts index 29f9e0ea..bc14dadb 100644 --- a/src/app/api/notary/OfficeFolderAnchorsController.ts +++ b/src/app/api/notary/OfficeFolderAnchorsController.ts @@ -5,15 +5,35 @@ import { Service } from "typedi"; import { OfficeFolder } from "le-coffre-resources/dist/Notary"; import { getFolderHashes } from "@Common/optics/notary"; import OfficeFoldersService from "@Services/notary/OfficeFoldersService/OfficeFoldersService"; +import OfficeFolderAnchorsRepository from "@Repositories/OfficeFolderAnchorsRepository"; import SecureService from "@Services/common/SecureService/SecureService"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import folderHandler from "@App/middlewares/OfficeMembershipHandlers/FolderHandler"; +import OfficeFolderAnchor from "le-coffre-resources/dist/Notary/OfficeFolderAnchor"; +const hydrateOfficeFolderAnchor = (data: any): OfficeFolderAnchor => + OfficeFolderAnchor.hydrate( + { + hash_sources: data.hash_sources, + root_hash: data.root_hash, + + blockchain: data.transactions[0].blockchain, + status: data.transactions[0].status, + + anchor_nb_try: data.transactions[0].anchor_nb_try, + tx_id: data.transactions[0].tx_id.toString(), + tx_link: data.transactions[0].tx_link, + tx_hash: data.transactions[0].tx_hash, + + anchored_at: data.transactions[0].anchoring_timestamp, + }, + { strategy: "excludeAll" }, + ); @Controller() @Service() export default class OfficeFoldersController extends ApiController { - constructor(private secureService: SecureService, private officeFoldersService: OfficeFoldersService) { + constructor(private secureService: SecureService, private officeFolderAnchorsRepository: OfficeFolderAnchorsRepository, private officeFoldersService: OfficeFoldersService) { super(); } @@ -83,16 +103,30 @@ export default class OfficeFoldersController extends ApiController { files: true, }, }, + folder_anchor: true, }; - const officeFolderFound = await this.officeFoldersService.getByUid(uid, query); + const officeFolderFound: any = await this.officeFoldersService.getByUid(uid, query); if (!officeFolderFound) { this.httpNotFoundRequest(response, "Office folder not found"); return; } + const officeFolderAnchorFound = OfficeFolderAnchor.hydrate(officeFolderFound.folder_anchor, { + strategy: "excludeAll", + }); + + if (officeFolderAnchorFound) { + this.httpBadRequest(response, { + error: "Office folder already anchored", + folder_anchor: officeFolderAnchorFound, + }); + return; + } + const officeFolder = OfficeFolder.hydrate(officeFolderFound, { strategy: "excludeAll" }); + const folderHashes = getFolderHashes(officeFolder); if (folderHashes.length === 0) { @@ -101,9 +135,20 @@ export default class OfficeFoldersController extends ApiController { } const sortedHashes = [...folderHashes].sort(); - const anchor = await this.secureService.anchor(sortedHashes); + const data = await this.secureService.anchor(sortedHashes); - this.httpSuccess(response, anchor); + const officeFolderAnchor = hydrateOfficeFolderAnchor(data); + + const newOfficeFolderAnchor = await this.officeFolderAnchorsRepository.create( + officeFolderAnchor + ); + + await this.officeFoldersService.update( + uid, + OfficeFolder.hydrate({ uid: uid, folder_anchor: newOfficeFolderAnchor }, { strategy: "excludeAll" }), + ); + + this.httpSuccess(response, officeFolderAnchor); } catch (error) { this.httpInternalError(response, error); return; diff --git a/src/common/repositories/OfficeFoldersRepository.ts b/src/common/repositories/OfficeFoldersRepository.ts index 8eb5c7c9..5d591906 100644 --- a/src/common/repositories/OfficeFoldersRepository.ts +++ b/src/common/repositories/OfficeFoldersRepository.ts @@ -84,6 +84,7 @@ export default class OfficeFoldersRepository extends BaseRepository { uid: document.uid!, })), }, + folder_anchor_uid: officeFolder.folder_anchor?.uid, }, }; @@ -93,6 +94,7 @@ export default class OfficeFoldersRepository extends BaseRepository { stakeholders: true, customers: true, documents: true, + folder_anchor: true, }, }); } From 279ea66a5022ad2444eead47344ab5898e014ba9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFs=20Mansot?= <26844641+devfull@users.noreply.github.com> Date: Fri, 29 Sep 2023 15:46:43 +0200 Subject: [PATCH 3/3] update anchor when requesting secure status --- .../notary/OfficeFolderAnchorsController.ts | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/app/api/notary/OfficeFolderAnchorsController.ts b/src/app/api/notary/OfficeFolderAnchorsController.ts index bc14dadb..9c4c7fdf 100644 --- a/src/app/api/notary/OfficeFolderAnchorsController.ts +++ b/src/app/api/notary/OfficeFolderAnchorsController.ts @@ -174,9 +174,10 @@ export default class OfficeFoldersController extends ApiController { files: true, }, }, + folder_anchor: true, }; - const officeFolderFound = await this.officeFoldersService.getByUid(uid, query); + const officeFolderFound: any = await this.officeFoldersService.getByUid(uid, query); if (!officeFolderFound) { this.httpNotFoundRequest(response, "Office folder not found"); @@ -192,9 +193,31 @@ export default class OfficeFoldersController extends ApiController { } const sortedHashes = [...folderHashes].sort(); - const anchor = await this.secureService.verify(sortedHashes); + const officeFolderAnchorFound = OfficeFolderAnchor.hydrate(officeFolderFound.folder_anchor, { + strategy: "excludeAll", + }); - this.httpSuccess(response, anchor); + if (!officeFolderAnchorFound || !officeFolderAnchorFound.uid) { + this.httpNotFoundRequest(response, {error: "Not anchored", hash_sources: sortedHashes}); + return; + } + + const data = await this.secureService.verify(sortedHashes); + + if (data.errors || data.transactions.length === 0) { + this.httpNotFoundRequest(response, {error: "Not anchored", hash_sources: sortedHashes}); + return; + } + + const officeFolderAnchor = hydrateOfficeFolderAnchor(data); + + const updatedOfficeFolderAnchor = await this.officeFolderAnchorsRepository.update( + officeFolderAnchorFound.uid, + officeFolderAnchor + ); + + this.httpSuccess(response, updatedOfficeFolderAnchor); + return; } catch (error) { this.httpInternalError(response, error); return;