From 547ab0b23051dbadb40c51cf9340cb38e1d2ac26 Mon Sep 17 00:00:00 2001 From: Vins Date: Wed, 5 Jun 2024 09:39:11 +0200 Subject: [PATCH 1/9] Customer notes feature finished --- Dockerfile | 2 +- package.json | 2 +- src/app/api/customer/NotesController.ts | 202 ++++++++++++++++++ .../api/customer/OfficeFoldersController.ts | 2 +- src/app/api/notary/OfficeFoldersController.ts | 7 +- src/app/index.ts | 2 + .../migration.sql | 20 ++ src/common/databases/schema.prisma | 14 ++ src/common/repositories/NotesRepository.ts | 74 +++++++ .../customer/NotesService/NotesService.ts | 48 +++++ 10 files changed, 367 insertions(+), 6 deletions(-) create mode 100644 src/app/api/customer/NotesController.ts create mode 100644 src/common/databases/migrations/20240603201549_folder_customer_notes/migration.sql create mode 100644 src/common/repositories/NotesRepository.ts create mode 100644 src/services/customer/NotesService/NotesService.ts diff --git a/Dockerfile b/Dockerfile index d33dbefb..e98bde33 100644 --- a/Dockerfile +++ b/Dockerfile @@ -36,5 +36,5 @@ COPY --from=deps --chown=lecoffreuser leCoffre/src/common/databases ./src/common RUN apk update && apk add chromium USER lecoffreuser -CMD ["npm", "run", "start"] +CMD ["npm", "run", "api:start"] EXPOSE 3001 \ No newline at end of file diff --git a/package.json b/package.json index 688f4c6c..ba8a4fdc 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "file-type-checker": "^1.0.8", "fp-ts": "^2.16.1", "jsonwebtoken": "^9.0.0", - "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.139", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.151", "module-alias": "^2.2.2", "monocle-ts": "^2.3.13", "multer": "^1.4.5-lts.1", diff --git a/src/app/api/customer/NotesController.ts b/src/app/api/customer/NotesController.ts new file mode 100644 index 00000000..11d59973 --- /dev/null +++ b/src/app/api/customer/NotesController.ts @@ -0,0 +1,202 @@ +import { Response, Request } from "express"; +import { Controller, Get, Post, Put } from "@ControllerPattern/index"; +import ApiController from "@Common/system/controller-pattern/ApiController"; +import { Service } from "typedi"; +import { Prisma } from "@prisma/client"; +import authHandler from "@App/middlewares/AuthHandler"; +import Note from "le-coffre-resources/dist/Customer/Note"; +import NotesService from "@Services/customer/NotesService/NotesService"; + +@Controller() +@Service() +export default class NotesController extends ApiController { + constructor(private notesService: NotesService) { + super(); + } + + /** + * @description Get all Notes + * @returns Note[] list of Notes + */ + @Get("/api/v1/customer/notes", [authHandler]) + protected async get(req: Request, response: Response) { + try { + //get query + let query: Prisma.NotesFindManyArgs = {}; + if (req.query["q"]) { + query = JSON.parse(req.query["q"] as string); + if (query.where?.uid) { + this.httpBadRequest(response, "You can't filter by uid"); + return; + } + } + + //call service to get prisma entity + const noteEntities = await this.notesService.get(query); + + //Hydrate ressource with prisma entity + const notes = Note.hydrateArray(noteEntities, { strategy: "excludeAll" }); + + //success + this.httpSuccess(response, notes); + } catch (error) { + this.httpBadRequest(response, error); + return; + } + } + + /** + * @description Get a specific customer note + */ + @Get("/api/v1/customer/notes/customer/:customer-uid/folders/:folder-uid/", [authHandler]) + protected async getCustomerNoteByFolderUid(req: Request, response: Response) { + try { + const customerUid = req.params["customer-uid"]; + const folderUid = req.params["folder-uid"]; + if (!customerUid || !folderUid) { + this.httpBadRequest(response, "No uid provided"); + return; + } + + //get query + const query: Prisma.NotesFindManyArgs = { + where: { + customer: { + uid: customerUid + }, + folder: { + uid: folderUid + } + } + }; + + //call service to get prisma entity + const noteEntities = await this.notesService.get(query); + + if(noteEntities.length === 0) { + this.httpNotFoundRequest(response, "No notes found"); + return; + } + + //Hydrate ressource with prisma entity + const notes = Note.hydrateArray(noteEntities, { strategy: "excludeAll" }); + + //success + this.httpSuccess(response, notes); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } + + /** + * @description Get a specific note by uid + */ + @Get("/api/v1/customer/notes/:uid", [authHandler]) + protected async getOneByUid(req: Request, response: Response) { + try { + const uid = req.params["uid"]; + if (!uid) { + this.httpBadRequest(response, "No uid provided"); + return; + } + + //get query + let query; + if (req.query["q"]) { + query = JSON.parse(req.query["q"] as string); + } + + const noteEntity = await this.notesService.getByUid(uid, query); + + if (!noteEntity) { + this.httpNotFoundRequest(response, "note not found"); + return; + } + + //Hydrate ressource with prisma entity + const note = Note.hydrate(noteEntity); + + //success + this.httpSuccess(response, note); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } + + /** + * @description Create a new note + */ + @Post("/api/v1/customer/notes", [authHandler]) + protected async post(req: Request, response: Response) { + try { + //init OfficeFolder resource with request body values + const noteRessource = Note.hydrate(req.body); + // noteRessource.validateOrReject?.({ groups: ["createFolder"], forbidUnknownValues: false }); + + //call service to get prisma entity + try { + const noteEntity = await this.notesService.create(noteRessource); + //Hydrate ressource with prisma entity + const note = Note.hydrate(noteEntity, { + strategy: "excludeAll", + }); + //success + this.httpCreated(response, note); + } catch (error) { + this.httpValidationError(response, error); + return; + } + } catch (error) { + this.httpInternalError(response, error); + return; + } + } + + /** + * @description Modify a specific note by uid + */ + @Put("/api/v1/customer/notes/:uid", [authHandler]) + protected async put(req: Request, response: Response) { + try { + const uid = req.params["uid"]; + if (!uid) { + this.httpBadRequest(response, "No uid provided"); + return; + } + + const noteFound = await this.notesService.getByUid(uid); + + if (!noteFound) { + this.httpNotFoundRequest(response, "office folder not found"); + return; + } + + //init OfficeFolder resource with request body values + const noteEntity = Note.hydrate(req.body); + + //validate folder + //await validateOrReject(noteEntity, { groups: ["updateFolder"], forbidUnknownValues: false }); + + //call service to get prisma entity + try { + const noteEntityUpdated = await this.notesService.update(uid, noteEntity); + + //Hydrate ressource with prisma entity + const note = Note.hydrate(noteEntityUpdated, { + strategy: "excludeAll", + }); + + //success + this.httpSuccess(response, note); + } catch (error) { + this.httpValidationError(response, error); + return; + } + } catch (error) { + this.httpInternalError(response, error); + return; + } + } +} diff --git a/src/app/api/customer/OfficeFoldersController.ts b/src/app/api/customer/OfficeFoldersController.ts index a90a5876..f8bea23d 100644 --- a/src/app/api/customer/OfficeFoldersController.ts +++ b/src/app/api/customer/OfficeFoldersController.ts @@ -95,7 +95,7 @@ export default class OfficeFoldersController extends ApiController { } //Hydrate ressource with prisma entity - const officeFolder = OfficeFolderNotary.hydrate(officeFolderEntity, { strategy: "excludeAll" }); + const officeFolder = OfficeFolderNotary.hydrate(officeFolderEntity); if(officeFolder.customers) { officeFolder.customers = officeFolder.customers!.filter((customer) => customer.contact?.email === email); diff --git a/src/app/api/notary/OfficeFoldersController.ts b/src/app/api/notary/OfficeFoldersController.ts index 45941476..2d8f7792 100644 --- a/src/app/api/notary/OfficeFoldersController.ts +++ b/src/app/api/notary/OfficeFoldersController.ts @@ -261,9 +261,9 @@ export default class OfficeFoldersController extends ApiController { let query; if (req.query["q"]) { query = JSON.parse(req.query["q"] as string); - } + } - const officeFolderEntity = await this.officeFoldersService.getByUid(uid, query); + const officeFolderEntity = await this.officeFoldersService.getByUid(uid, query); if (!officeFolderEntity) { this.httpNotFoundRequest(response, "folder not found"); @@ -271,7 +271,8 @@ export default class OfficeFoldersController extends ApiController { } //Hydrate ressource with prisma entity - const officeFolder = OfficeFolder.hydrate(officeFolderEntity, { strategy: "excludeAll" }); + const officeFolder = OfficeFolder.hydrate(officeFolderEntity); + //success this.httpSuccess(response, officeFolder); diff --git a/src/app/index.ts b/src/app/index.ts index 1590b6f1..c5767457 100644 --- a/src/app/index.ts +++ b/src/app/index.ts @@ -53,6 +53,7 @@ import SubscriptionsController from "./api/admin/SubscriptionsController"; import StripeController from "./api/admin/StripeController"; import StripeWebhooks from "@Common/webhooks/stripeWebhooks"; import RulesGroupsController from "./api/admin/RulesGroupsController"; +import NotesController from "./api/customer/NotesController"; /** * @description This allow to declare all controllers used in the application @@ -114,5 +115,6 @@ export default { Container.get(StripeController); Container.get(StripeWebhooks); Container.get(RulesGroupsController); + Container.get(NotesController); }, }; diff --git a/src/common/databases/migrations/20240603201549_folder_customer_notes/migration.sql b/src/common/databases/migrations/20240603201549_folder_customer_notes/migration.sql new file mode 100644 index 00000000..848a2ab9 --- /dev/null +++ b/src/common/databases/migrations/20240603201549_folder_customer_notes/migration.sql @@ -0,0 +1,20 @@ +-- CreateTable +CREATE TABLE "notes" ( + "uid" TEXT NOT NULL, + "content" VARCHAR(1000) NOT NULL, + "created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3), + "customer_uid" VARCHAR(255) NOT NULL, + "folder_uid" VARCHAR(255) NOT NULL, + + CONSTRAINT "notes_pkey" PRIMARY KEY ("uid") +); + +-- CreateIndex +CREATE UNIQUE INDEX "notes_uid_key" ON "notes"("uid"); + +-- AddForeignKey +ALTER TABLE "notes" ADD CONSTRAINT "notes_customer_uid_fkey" FOREIGN KEY ("customer_uid") REFERENCES "customers"("uid") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "notes" ADD CONSTRAINT "notes_folder_uid_fkey" FOREIGN KEY ("folder_uid") REFERENCES "office_folders"("uid") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/src/common/databases/schema.prisma b/src/common/databases/schema.prisma index e42133a9..259c59f1 100644 --- a/src/common/databases/schema.prisma +++ b/src/common/databases/schema.prisma @@ -128,6 +128,7 @@ model Customers { totpCodes TotpCodes[] office Offices @relation(fields: [office_uid], references: [uid], onDelete: Cascade) office_uid String @db.VarChar(255) + notes Notes[] @@map("customers") } @@ -172,6 +173,7 @@ model OfficeFolders { folder_anchor OfficeFolderAnchors? @relation(fields: [folder_anchor_uid], references: [uid]) folder_anchor_uid String? @unique @db.VarChar(255) + notes Notes[] @@unique([folder_number, office_uid]) @@map("office_folders") @@ -417,6 +419,18 @@ model Seats { @@map("seats") } +model Notes { + uid String @id @unique @default(uuid()) + content String @db.VarChar(1000) + created_at DateTime? @default(now()) + updated_at DateTime? @updatedAt + customer Customers @relation(fields: [customer_uid], references: [uid], onDelete: Cascade) + customer_uid String @db.VarChar(255) + folder OfficeFolders @relation(fields: [folder_uid], references: [uid], onDelete: Cascade) + folder_uid String @db.VarChar(255) + @@map("notes") +} + enum ESubscriptionStatus { ACTIVE INACTIVE diff --git a/src/common/repositories/NotesRepository.ts b/src/common/repositories/NotesRepository.ts new file mode 100644 index 00000000..8300ab96 --- /dev/null +++ b/src/common/repositories/NotesRepository.ts @@ -0,0 +1,74 @@ +import Database from "@Common/databases/database"; +import BaseRepository from "@Repositories/BaseRepository"; +import { Service } from "typedi"; +import { Notes, Prisma } from "@prisma/client"; +import Note from "le-coffre-resources/dist/Customer/Note"; + +@Service() +export default class NotesRepository extends BaseRepository { + constructor(private database: Database) { + super(); + } + protected get model() { + return this.database.getClient().notes; + } + protected get instanceDb() { + return this.database.getClient(); + } + + /** + * @description : Find many notes + */ + public async findMany(query: Prisma.NotesFindManyArgs) { + return this.model.findMany(query); + } + + /** + * @description : Find one note + */ + public async findOneByUid(uid: string, query?: Prisma.NotesInclude) { + return this.model.findUnique({ + where: { uid }, + include: query, + }); + } + + /** + * @description : Create new note + */ + public async create(note: Note): Promise { + const createArgs: Prisma.NotesCreateArgs = { + data: { + content: note.content || "", + customer: { + connect: { + uid: note.customer!.uid, + }, + }, + folder: { + connect: { + uid: note.folder!.uid, + }, + }, + }, + }; + + return this.model.create(createArgs); + } + + /** + * @description : Update data of an office folder + */ + public async update(noteUid: string, note: Note): Promise { + const updateArgs: Prisma.NotesUpdateArgs = { + where: { + uid: noteUid, + }, + data: { + content: note.content || "", + }, + }; + + return this.model.update(updateArgs); + } +} diff --git a/src/services/customer/NotesService/NotesService.ts b/src/services/customer/NotesService/NotesService.ts new file mode 100644 index 00000000..81b120be --- /dev/null +++ b/src/services/customer/NotesService/NotesService.ts @@ -0,0 +1,48 @@ +import BaseService from "@Services/BaseService"; +import { Service } from "typedi"; +import { Notes, Prisma } from "@prisma/client"; +import NotesRepository from "@Repositories/NotesRepository"; +import Note from "le-coffre-resources/dist/Customer/Note"; + +@Service() +export default class NotesService extends BaseService { + constructor( + private notesRepository: NotesRepository, + ) { + super(); + } + + /** + * @description : Get all notes + * @throws {Error} If notes cannot be get + */ + public async get(query: Prisma.NotesFindManyArgs) { + return this.notesRepository.findMany(query); + } + + /** + * @description : Get a note by uid + * @throws {Error} If note cannot be get + */ + public async getByUid(uid: string, query?: Prisma.NotesInclude) { + return this.notesRepository.findOneByUid(uid, query); + } + + /** + * @description : Create a new note + * @throws {Error} If note cannot be created + */ + public async create(noteEntity: Note): Promise { + return this.notesRepository.create(noteEntity); + } + + /** + * @description : Modify a note + * @throws {Error} If note cannot be modified + */ + public async update(noteUid: string, noteEntity: Note): Promise { + return this.notesRepository.update(noteUid, noteEntity); + } + + +} From 98a16942616d256a72e11113df2bc51fa3c0f49f Mon Sep 17 00:00:00 2001 From: Vins Date: Wed, 12 Jun 2024 14:52:51 +0200 Subject: [PATCH 2/9] Changed anchor proof file --- .../notary/OfficeFolderAnchorsController.ts | 2 +- .../AnchoringProofService.ts | 160 ++++++++++++------ .../common/SecureService/SecureService.ts | 5 +- 3 files changed, 113 insertions(+), 54 deletions(-) diff --git a/src/app/api/notary/OfficeFolderAnchorsController.ts b/src/app/api/notary/OfficeFolderAnchorsController.ts index cb16501b..f43c28d8 100644 --- a/src/app/api/notary/OfficeFolderAnchorsController.ts +++ b/src/app/api/notary/OfficeFolderAnchorsController.ts @@ -87,7 +87,7 @@ export default class OfficeFoldersController extends ApiController { } const sortedHashes = [...folderHashes].sort(); - const anchoringProof = await this.secureService.download(sortedHashes); + const anchoringProof = await this.secureService.download(sortedHashes, officeFolder.name); const addFileToZip = (zip: Zip) => (uid: string): Promise => (async () => { diff --git a/src/services/common/AnchoringProofService/AnchoringProofService.ts b/src/services/common/AnchoringProofService/AnchoringProofService.ts index 8d43a5b0..db055ef3 100644 --- a/src/services/common/AnchoringProofService/AnchoringProofService.ts +++ b/src/services/common/AnchoringProofService/AnchoringProofService.ts @@ -6,6 +6,7 @@ export interface AnchoringProofData { rootHash: string; anchoringTime: string; txLink: string; + office_name: string; } @Service() @@ -14,57 +15,111 @@ export default class AnchoringProofService extends BaseService { super(); } - private static svgTemplateDocument: string = ` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ANCHORING_TIME]] - Certificat de dépôt international - Hash : - [[ROOT_HASH]] - - Déposant(s) - Auteur : - Not.IT - Partenaire technique : - Smart-Chain - - Explorateur blockchain - [[TX_LINK]] - - + // private static svgTemplateDocument: string = ` + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // [[ANCHORING_TIME]] + // Certificat de dépôt international + // Hash : + // [[ROOT_HASH]] + // + // Déposant(s) + // Auteur : + // Not.IT + // Partenaire technique : + // Smart-Chain + // + // Explorateur blockchain + // [[TX_LINK]] + // + // + // `; + + private static svgTemplateDocumentBis: string = ` + + + + + + + Certificat de dépôt international + [[ANCHORING_TIME]] + Nom de l'office + [[OFFICE_NAME]] + + Déposant(s) + LEcoffre.io + + Hash + [[ROOT_HASH]] + + Explorateur blockchain + [[TX_LINK]] + + + À quoi ça sert ? + Un certificat d'ancrage sur la blockchain permet d'établir de manière irréfutable l'enregistrement de données spécifiques à une date et une heure déterminées. Il constitue une preuve immuable et juridiquement opposable de l'existence et de l'intégrité des informations à un moment donné. En cas de litige, ce certificat peut être utilisé pour démontrer de manière incontestable que les données n'ont pas été altérées depuis leur enregistrement, offrant ainsi une preuve solide devant les tribunaux. + + Qu'est-ce qu'un explorateur blockchain ? + Un explorateur blockchain est un outil numérique permettant d'accéder et de consulter les transactions et les données enregistrées sur la blockchain. Il assure une transparence totale, permettant à toute partie prenante de vérifier les opérations et les enregistrements effectués sur la chaîne de blocs. + + Qu'est-ce qu'un hash ? + Un hash est une empreinte cryptographique unique générée par un algorithme à partir de données spécifiques. Il agit comme une signature numérique permettant de vérifier l'intégrité des données : toute modification, même infime, des données d'origine entraîne la production d'un hash distinct, garantissant ainsi l'authenticité et l'intégrité des informations. + + + + + + + + + + + + + + + + + + + + + + `; /** @@ -81,7 +136,7 @@ export default class AnchoringProofService extends BaseService { var htmlContent = ` - ${AnchoringProofService.svgTemplateDocument} + ${AnchoringProofService.svgTemplateDocumentBis} `; @@ -89,6 +144,7 @@ export default class AnchoringProofService extends BaseService { htmlContent = htmlContent .replace("[[ROOT_HASH]]", data.rootHash) .replace("[[ANCHORING_TIME]]", data.anchoringTime) + .replace("[[OFFICE_NAME]]", data.office_name) .replace(/\[\[TX_LINK\]\]/g, data.txLink); await page.setContent(htmlContent); diff --git a/src/services/common/SecureService/SecureService.ts b/src/services/common/SecureService/SecureService.ts index 37dd961b..b69d1d90 100644 --- a/src/services/common/SecureService/SecureService.ts +++ b/src/services/common/SecureService/SecureService.ts @@ -63,7 +63,7 @@ export default class SecureService extends BaseService { * @description : Download the anchoring proof document * @throws {Error} If transaction is not verified on chain */ - public async download(hash_sources: string[]) { + public async download(hash_sources: string[], office_name: string) { const anchor = await this.verify(hash_sources); if (anchor.transactions.length === 0) { @@ -71,6 +71,8 @@ export default class SecureService extends BaseService { } const transaction = anchor.transactions[0]; + console.log(transaction); + if (transaction.status !== EAnchoringStatus.VERIFIED_ON_CHAIN) { throw new Error(`Transaction not verified on chain: ${transaction.status}`); @@ -83,6 +85,7 @@ export default class SecureService extends BaseService { timeZone: "Europe/Paris", timeZoneName: "short", }), + office_name: office_name, }); } } From e3913f8d5c9c84534faf272f713194422d0294f4 Mon Sep 17 00:00:00 2001 From: Vins Date: Wed, 12 Jun 2024 15:05:27 +0200 Subject: [PATCH 3/9] Testing modification --- .../AnchoringProofService.ts | 51 ++++++++++++------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/src/services/common/AnchoringProofService/AnchoringProofService.ts b/src/services/common/AnchoringProofService/AnchoringProofService.ts index db055ef3..2602db84 100644 --- a/src/services/common/AnchoringProofService/AnchoringProofService.ts +++ b/src/services/common/AnchoringProofService/AnchoringProofService.ts @@ -73,6 +73,38 @@ export default class AnchoringProofService extends BaseService { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Certificat de dépôt international @@ -100,25 +132,6 @@ export default class AnchoringProofService extends BaseService { Un hash est une empreinte cryptographique unique générée par un algorithme à partir de données spécifiques. Il agit comme une signature numérique permettant de vérifier l'intégrité des données : toute modification, même infime, des données d'origine entraîne la production d'un hash distinct, garantissant ainsi l'authenticité et l'intégrité des informations. - - - - - - - - - - - - - - - - - - - `; From 5d49e534167219f87c26f4ac1cc6d524235ec037 Mon Sep 17 00:00:00 2001 From: Vins Date: Wed, 12 Jun 2024 15:13:34 +0200 Subject: [PATCH 4/9] Fixed office name --- src/app/api/notary/OfficeFolderAnchorsController.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/api/notary/OfficeFolderAnchorsController.ts b/src/app/api/notary/OfficeFolderAnchorsController.ts index f43c28d8..459f19f4 100644 --- a/src/app/api/notary/OfficeFolderAnchorsController.ts +++ b/src/app/api/notary/OfficeFolderAnchorsController.ts @@ -87,7 +87,7 @@ export default class OfficeFoldersController extends ApiController { } const sortedHashes = [...folderHashes].sort(); - const anchoringProof = await this.secureService.download(sortedHashes, officeFolder.name); + const anchoringProof = await this.secureService.download(sortedHashes, officeFolder.office!.name); const addFileToZip = (zip: Zip) => (uid: string): Promise => (async () => { From b607a3e7851f2e200ae2291bd70b5a12ffc3db6c Mon Sep 17 00:00:00 2001 From: Vins Date: Wed, 12 Jun 2024 15:22:55 +0200 Subject: [PATCH 5/9] retest baseTemplate --- .../AnchoringProofService.ts | 185 ++++++++++++------ 1 file changed, 120 insertions(+), 65 deletions(-) diff --git a/src/services/common/AnchoringProofService/AnchoringProofService.ts b/src/services/common/AnchoringProofService/AnchoringProofService.ts index 2602db84..07dca505 100644 --- a/src/services/common/AnchoringProofService/AnchoringProofService.ts +++ b/src/services/common/AnchoringProofService/AnchoringProofService.ts @@ -68,71 +68,126 @@ export default class AnchoringProofService extends BaseService { // // `; - private static svgTemplateDocumentBis: string = ` + // private static svgTemplateDocumentBis: string = ` + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // Certificat de dépôt international + // [[ANCHORING_TIME]] + // Nom de l'office + // [[OFFICE_NAME]] + // + // Déposant(s) + // LEcoffre.io + // + // Hash + // [[ROOT_HASH]] + // + // Explorateur blockchain + // [[TX_LINK]] + // + // + // À quoi ça sert ? + // Un certificat d'ancrage sur la blockchain permet d'établir de manière irréfutable l'enregistrement de données spécifiques à une date et une heure déterminées. Il constitue une preuve immuable et juridiquement opposable de l'existence et de l'intégrité des informations à un moment donné. En cas de litige, ce certificat peut être utilisé pour démontrer de manière incontestable que les données n'ont pas été altérées depuis leur enregistrement, offrant ainsi une preuve solide devant les tribunaux. + // + // Qu'est-ce qu'un explorateur blockchain ? + // Un explorateur blockchain est un outil numérique permettant d'accéder et de consulter les transactions et les données enregistrées sur la blockchain. Il assure une transparence totale, permettant à toute partie prenante de vérifier les opérations et les enregistrements effectués sur la chaîne de blocs. + // + // Qu'est-ce qu'un hash ? + // Un hash est une empreinte cryptographique unique générée par un algorithme à partir de données spécifiques. Il agit comme une signature numérique permettant de vérifier l'intégrité des données : toute modification, même infime, des données d'origine entraîne la production d'un hash distinct, garantissant ainsi l'authenticité et l'intégrité des informations. + // + // + // + // `; + + private static baseTemplate : string = ` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Certificat de dépôt international - [[ANCHORING_TIME]] - Nom de l'office - [[OFFICE_NAME]] - - Déposant(s) - LEcoffre.io - - Hash - [[ROOT_HASH]] - - Explorateur blockchain - [[TX_LINK]] - - - À quoi ça sert ? - Un certificat d'ancrage sur la blockchain permet d'établir de manière irréfutable l'enregistrement de données spécifiques à une date et une heure déterminées. Il constitue une preuve immuable et juridiquement opposable de l'existence et de l'intégrité des informations à un moment donné. En cas de litige, ce certificat peut être utilisé pour démontrer de manière incontestable que les données n'ont pas été altérées depuis leur enregistrement, offrant ainsi une preuve solide devant les tribunaux. - - Qu'est-ce qu'un explorateur blockchain ? - Un explorateur blockchain est un outil numérique permettant d'accéder et de consulter les transactions et les données enregistrées sur la blockchain. Il assure une transparence totale, permettant à toute partie prenante de vérifier les opérations et les enregistrements effectués sur la chaîne de blocs. - - Qu'est-ce qu'un hash ? - Un hash est une empreinte cryptographique unique générée par un algorithme à partir de données spécifiques. Il agit comme une signature numérique permettant de vérifier l'intégrité des données : toute modification, même infime, des données d'origine entraîne la production d'un hash distinct, garantissant ainsi l'authenticité et l'intégrité des informations. - - - + + + + + +Certificat de dépôt international +01-01-2023 12:30:15 CET +Nom du client +Doe John + +Déposant(s) +LEcoffre.io + +Hash +b834ce9229ee2c2283c837685772a473 + +Explorateur blockchain +https://tzstats.com/opYWLHH96gbV8HPajRqmoRx3UBVbr6iXz43kuHqm8ey4LLPWqeC + + +À quoi ça sert ? +Un certificat d'ancrage sur la blockchain permet d'établir de manière irréfutable l'enregistrement de données spécifiques à une date et une heure déterminées. Il constitue une preuve immuable et juridiquement opposable de l'existence et de l'intégrité des informations à un moment donné. En cas de litige, ce certificat peut être utilisé pour démontrer de manière incontestable que les données n'ont pas été altérées depuis leur enregistrement, offrant ainsi une preuve solide devant les tribunaux. + +Qu'est-ce qu'un explorateur blockchain ? +Un explorateur blockchain est un outil numérique permettant d'accéder et de consulter les transactions et les données enregistrées sur la blockchain. Il assure une transparence totale, permettant à toute partie prenante de vérifier les opérations et les enregistrements effectués sur la chaîne de blocs. + +Qu'est-ce qu'un hash ? +Un hash est une empreinte cryptographique unique générée par un algorithme à partir de données spécifiques. Il agit comme une signature numérique permettant de vérifier l'intégrité des données : toute modification, même infime, des données d'origine entraîne la production d'un hash distinct, garantissant ainsi l'authenticité et l'intégrité des informations. + + + + + + + + + + + + + + + + + + + + + + + `; /** @@ -149,7 +204,7 @@ export default class AnchoringProofService extends BaseService { var htmlContent = ` - ${AnchoringProofService.svgTemplateDocumentBis} + ${AnchoringProofService.baseTemplate} `; From e5beaa587d75a6811363d26314ec8ab149cfa6ea Mon Sep 17 00:00:00 2001 From: Vins Date: Wed, 12 Jun 2024 15:39:49 +0200 Subject: [PATCH 6/9] Fixed include office --- src/app/api/notary/OfficeFolderAnchorsController.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/api/notary/OfficeFolderAnchorsController.ts b/src/app/api/notary/OfficeFolderAnchorsController.ts index 459f19f4..96bba906 100644 --- a/src/app/api/notary/OfficeFolderAnchorsController.ts +++ b/src/app/api/notary/OfficeFolderAnchorsController.ts @@ -68,6 +68,7 @@ export default class OfficeFoldersController extends ApiController { files: true, }, }, + office: true, }; const officeFolderFound = await this.officeFoldersService.getByUid(uid, query); From af9387e73b4488188513ef94e9f333bb979be402 Mon Sep 17 00:00:00 2001 From: Vins Date: Wed, 12 Jun 2024 16:20:39 +0200 Subject: [PATCH 7/9] final version of anchoring proof --- .../AnchoringProofService.ts | 131 ++++-------------- 1 file changed, 28 insertions(+), 103 deletions(-) diff --git a/src/services/common/AnchoringProofService/AnchoringProofService.ts b/src/services/common/AnchoringProofService/AnchoringProofService.ts index 07dca505..8e823076 100644 --- a/src/services/common/AnchoringProofService/AnchoringProofService.ts +++ b/src/services/common/AnchoringProofService/AnchoringProofService.ts @@ -68,93 +68,37 @@ export default class AnchoringProofService extends BaseService { // // `; - // private static svgTemplateDocumentBis: string = ` - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // Certificat de dépôt international - // [[ANCHORING_TIME]] - // Nom de l'office - // [[OFFICE_NAME]] - // - // Déposant(s) - // LEcoffre.io - // - // Hash - // [[ROOT_HASH]] - // - // Explorateur blockchain - // [[TX_LINK]] - // - // - // À quoi ça sert ? - // Un certificat d'ancrage sur la blockchain permet d'établir de manière irréfutable l'enregistrement de données spécifiques à une date et une heure déterminées. Il constitue une preuve immuable et juridiquement opposable de l'existence et de l'intégrité des informations à un moment donné. En cas de litige, ce certificat peut être utilisé pour démontrer de manière incontestable que les données n'ont pas été altérées depuis leur enregistrement, offrant ainsi une preuve solide devant les tribunaux. - // - // Qu'est-ce qu'un explorateur blockchain ? - // Un explorateur blockchain est un outil numérique permettant d'accéder et de consulter les transactions et les données enregistrées sur la blockchain. Il assure une transparence totale, permettant à toute partie prenante de vérifier les opérations et les enregistrements effectués sur la chaîne de blocs. - // - // Qu'est-ce qu'un hash ? - // Un hash est une empreinte cryptographique unique générée par un algorithme à partir de données spécifiques. Il agit comme une signature numérique permettant de vérifier l'intégrité des données : toute modification, même infime, des données d'origine entraîne la production d'un hash distinct, garantissant ainsi l'authenticité et l'intégrité des informations. - // - // - // - // `; - - private static baseTemplate : string = ` - + private static svgTemplateDocumentBis: string = ` + - -Certificat de dépôt international -01-01-2023 12:30:15 CET -Nom du client -Doe John - -Déposant(s) -LEcoffre.io - -Hash -b834ce9229ee2c2283c837685772a473 - -Explorateur blockchain -https://tzstats.com/opYWLHH96gbV8HPajRqmoRx3UBVbr6iXz43kuHqm8ey4LLPWqeC + + + + + + + + + + + + +Certificat de dépôt international +[[ANCHORING_TIME]] +Nom de l'office +[[OFFICE_NAME]] + +Déposant(s) +LEcoffre.io + +Hash +[[ROOT_HASH]] + +Explorateur blockchain +[[TX_LINK]] À quoi ça sert ? @@ -167,25 +111,6 @@ export default class AnchoringProofService extends BaseService { Un hash est une empreinte cryptographique unique générée par un algorithme à partir de données spécifiques. Il agit comme une signature numérique permettant de vérifier l'intégrité des données : toute modification, même infime, des données d'origine entraîne la production d'un hash distinct, garantissant ainsi l'authenticité et l'intégrité des informations. - - - - - - - - - - - - - - - - - - - `; @@ -204,7 +129,7 @@ export default class AnchoringProofService extends BaseService { var htmlContent = ` - ${AnchoringProofService.baseTemplate} + ${AnchoringProofService.svgTemplateDocumentBis} `; From 833b42d62cc5efae0748c19cc5d6b2e2bdbe8a26 Mon Sep 17 00:00:00 2001 From: Vins Date: Wed, 12 Jun 2024 16:34:55 +0200 Subject: [PATCH 8/9] New anchor proof done --- .../AnchoringProofService.ts | 133 ++++-------------- 1 file changed, 29 insertions(+), 104 deletions(-) diff --git a/src/services/common/AnchoringProofService/AnchoringProofService.ts b/src/services/common/AnchoringProofService/AnchoringProofService.ts index 07dca505..61b7ec94 100644 --- a/src/services/common/AnchoringProofService/AnchoringProofService.ts +++ b/src/services/common/AnchoringProofService/AnchoringProofService.ts @@ -68,93 +68,37 @@ export default class AnchoringProofService extends BaseService { // // `; - // private static svgTemplateDocumentBis: string = ` - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // Certificat de dépôt international - // [[ANCHORING_TIME]] - // Nom de l'office - // [[OFFICE_NAME]] - // - // Déposant(s) - // LEcoffre.io - // - // Hash - // [[ROOT_HASH]] - // - // Explorateur blockchain - // [[TX_LINK]] - // - // - // À quoi ça sert ? - // Un certificat d'ancrage sur la blockchain permet d'établir de manière irréfutable l'enregistrement de données spécifiques à une date et une heure déterminées. Il constitue une preuve immuable et juridiquement opposable de l'existence et de l'intégrité des informations à un moment donné. En cas de litige, ce certificat peut être utilisé pour démontrer de manière incontestable que les données n'ont pas été altérées depuis leur enregistrement, offrant ainsi une preuve solide devant les tribunaux. - // - // Qu'est-ce qu'un explorateur blockchain ? - // Un explorateur blockchain est un outil numérique permettant d'accéder et de consulter les transactions et les données enregistrées sur la blockchain. Il assure une transparence totale, permettant à toute partie prenante de vérifier les opérations et les enregistrements effectués sur la chaîne de blocs. - // - // Qu'est-ce qu'un hash ? - // Un hash est une empreinte cryptographique unique générée par un algorithme à partir de données spécifiques. Il agit comme une signature numérique permettant de vérifier l'intégrité des données : toute modification, même infime, des données d'origine entraîne la production d'un hash distinct, garantissant ainsi l'authenticité et l'intégrité des informations. - // - // - // - // `; - - private static baseTemplate : string = ` - + private static svgTemplateDocumentBis: string = ` + - -Certificat de dépôt international -01-01-2023 12:30:15 CET -Nom du client -Doe John - -Déposant(s) -LEcoffre.io - -Hash -b834ce9229ee2c2283c837685772a473 - -Explorateur blockchain -https://tzstats.com/opYWLHH96gbV8HPajRqmoRx3UBVbr6iXz43kuHqm8ey4LLPWqeC + + + + + + + + + + + + +Certificat de dépôt international +[[ANCHORING_TIME]] +Nom de l'office +[[OFFICE_NAME]] + +Déposant(s) +LEcoffre.io + +Hash +[[ROOT_HASH]] + +Explorateur blockchain +[[TX_LINK]] À quoi ça sert ? @@ -167,25 +111,6 @@ export default class AnchoringProofService extends BaseService { Un hash est une empreinte cryptographique unique générée par un algorithme à partir de données spécifiques. Il agit comme une signature numérique permettant de vérifier l'intégrité des données : toute modification, même infime, des données d'origine entraîne la production d'un hash distinct, garantissant ainsi l'authenticité et l'intégrité des informations. - - - - - - - - - - - - - - - - - - - `; @@ -204,7 +129,7 @@ export default class AnchoringProofService extends BaseService { var htmlContent = ` - ${AnchoringProofService.baseTemplate} + ${AnchoringProofService.svgTemplateDocumentBis} `; @@ -250,4 +175,4 @@ export default class AnchoringProofService extends BaseService { return buffer; } -} +} \ No newline at end of file From 19bb3eb1e88e8a927b7fa76aede09ba021e5eeea Mon Sep 17 00:00:00 2001 From: Vins Date: Wed, 12 Jun 2024 17:52:15 +0200 Subject: [PATCH 9/9] Updated anchoring proof --- .../AnchoringProofService.ts | 45 ++++++++++--------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/src/services/common/AnchoringProofService/AnchoringProofService.ts b/src/services/common/AnchoringProofService/AnchoringProofService.ts index 61b7ec94..4487f75c 100644 --- a/src/services/common/AnchoringProofService/AnchoringProofService.ts +++ b/src/services/common/AnchoringProofService/AnchoringProofService.ts @@ -77,7 +77,7 @@ export default class AnchoringProofService extends BaseService { - + @@ -88,31 +88,32 @@ export default class AnchoringProofService extends BaseService { Certificat de dépôt international [[ANCHORING_TIME]] -Nom de l'office -[[OFFICE_NAME]] - -Déposant(s) -LEcoffre.io - -Hash -[[ROOT_HASH]] - -Explorateur blockchain -[[TX_LINK]] - - -À quoi ça sert ? -Un certificat d'ancrage sur la blockchain permet d'établir de manière irréfutable l'enregistrement de données spécifiques à une date et une heure déterminées. Il constitue une preuve immuable et juridiquement opposable de l'existence et de l'intégrité des informations à un moment donné. En cas de litige, ce certificat peut être utilisé pour démontrer de manière incontestable que les données n'ont pas été altérées depuis leur enregistrement, offrant ainsi une preuve solide devant les tribunaux. - -Qu'est-ce qu'un explorateur blockchain ? -Un explorateur blockchain est un outil numérique permettant d'accéder et de consulter les transactions et les données enregistrées sur la blockchain. Il assure une transparence totale, permettant à toute partie prenante de vérifier les opérations et les enregistrements effectués sur la chaîne de blocs. - -Qu'est-ce qu'un hash ? -Un hash est une empreinte cryptographique unique générée par un algorithme à partir de données spécifiques. Il agit comme une signature numérique permettant de vérifier l'intégrité des données : toute modification, même infime, des données d'origine entraîne la production d'un hash distinct, garantissant ainsi l'authenticité et l'intégrité des informations. +Nom de l'office +[[OFFICE_NAME]] + +Déposant(s) +LEcoffre.io + +Hash +[[ROOT_HASH]] + +Explorateur blockchain +[[TX_LINK]] + + +À quoi ça sert ? +Un certificat d'ancrage sur la blockchain permet d'établir de manière irréfutable l'enregistrement de données spécifiques à une date et une heure déterminées. Il constitue une preuve immuable et juridiquement opposable de l'existence et de l'intégrité des informations. En cas de litige, ce certificat peut démontrer de manière incontestable que les données n'ont pas été altérées depuis leur enregistrement. + +Qu'est-ce qu'un explorateur blockchain ? +Un explorateur blockchain est un outil numérique permettant d'accéder et de consulter les transactions et les données enregistrées sur la blockchain. Il assure une transparence totale, permettant à toute partie prenante de vérifier les opérations et les enregistrements effectués sur la chaîne de blocs. + +Qu'est-ce qu'un hash ? +Un hash est une empreinte cryptographique unique générée par un algorithme à partir de données spécifiques. Il agit comme une signature numérique permettant de vérifier l'intégrité des données : toute modification, même infime, des données d'origine entraîne la production d'un hash distinct, garantissant ainsi l'authenticité et l'intégrité des informations. + `; /**