Refacto: folder-based anchoring (#74)
This commit is contained in:
commit
3065225007
1851
package-lock.json
generated
1851
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -52,7 +52,7 @@
|
|||||||
"cron": "^2.3.1",
|
"cron": "^2.3.1",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"jsonwebtoken": "^9.0.0",
|
"jsonwebtoken": "^9.0.0",
|
||||||
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.73",
|
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.77",
|
||||||
"module-alias": "^2.2.2",
|
"module-alias": "^2.2.2",
|
||||||
"multer": "^1.4.5-lts.1",
|
"multer": "^1.4.5-lts.1",
|
||||||
"next": "^13.1.5",
|
"next": "^13.1.5",
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- The values [ANCHORED] on the enum `EDocumentStatus` will be removed. If these variants are still used in the database, this will fail.
|
||||||
|
- You are about to drop the column `blockchain_anchor_uid` on the `documents` table. All the data in the column will be lost.
|
||||||
|
- You are about to drop the `blockchain_anchors` table. If the table is not empty, all the data it contains will be lost.
|
||||||
|
- A unique constraint covering the columns `[folder_anchor_uid]` on the table `office_folders` will be added. If there are existing duplicate values, this will fail.
|
||||||
|
- Added the required column `hash` to the `files` table without a default value. This is not possible if the table is not empty.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- CreateEnum
|
||||||
|
CREATE TYPE "EBlockchainName" AS ENUM ('TEZOS');
|
||||||
|
|
||||||
|
-- CreateEnum
|
||||||
|
CREATE TYPE "EAnchoringStatus" AS ENUM ('QUEUED', 'ATTEMPTING', 'VERIFIED_ON_CHAIN', 'VERIFYING_ON_CHAIN', 'ABANDONED');
|
||||||
|
|
||||||
|
-- AlterEnum
|
||||||
|
BEGIN;
|
||||||
|
CREATE TYPE "EDocumentStatus_new" AS ENUM ('ASKED', 'DEPOSITED', 'VALIDATED', 'REFUSED');
|
||||||
|
ALTER TABLE "documents" ALTER COLUMN "document_status" DROP DEFAULT;
|
||||||
|
ALTER TABLE "document_history" ALTER COLUMN "document_status" DROP DEFAULT;
|
||||||
|
ALTER TABLE "documents" ALTER COLUMN "document_status" TYPE "EDocumentStatus_new" USING ("document_status"::text::"EDocumentStatus_new");
|
||||||
|
ALTER TABLE "document_history" ALTER COLUMN "document_status" TYPE "EDocumentStatus_new" USING ("document_status"::text::"EDocumentStatus_new");
|
||||||
|
ALTER TYPE "EDocumentStatus" RENAME TO "EDocumentStatus_old";
|
||||||
|
ALTER TYPE "EDocumentStatus_new" RENAME TO "EDocumentStatus";
|
||||||
|
DROP TYPE "EDocumentStatus_old";
|
||||||
|
ALTER TABLE "documents" ALTER COLUMN "document_status" SET DEFAULT 'ASKED';
|
||||||
|
ALTER TABLE "document_history" ALTER COLUMN "document_status" SET DEFAULT 'ASKED';
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
-- DropForeignKey
|
||||||
|
ALTER TABLE "documents" DROP CONSTRAINT "documents_blockchain_anchor_uid_fkey";
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "documents" DROP COLUMN "blockchain_anchor_uid";
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "files" ADD COLUMN "hash" VARCHAR(255) NOT NULL;
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "office_folders" ADD COLUMN "folder_anchor_uid" VARCHAR(255);
|
||||||
|
|
||||||
|
-- DropTable
|
||||||
|
DROP TABLE "blockchain_anchors";
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "office_folder_anchors" (
|
||||||
|
"uid" TEXT NOT NULL,
|
||||||
|
"hash_sources" TEXT[],
|
||||||
|
"root_hash" VARCHAR(255) NOT NULL,
|
||||||
|
"blockchain" "EBlockchainName" NOT NULL DEFAULT 'TEZOS',
|
||||||
|
"status" "EAnchoringStatus" NOT NULL DEFAULT 'QUEUED',
|
||||||
|
"anchor_nb_try" INTEGER NOT NULL DEFAULT 0,
|
||||||
|
"anchored_at" TIMESTAMP(3),
|
||||||
|
"tx_id" VARCHAR(255),
|
||||||
|
"tx_link" VARCHAR(255),
|
||||||
|
"tx_hash" VARCHAR(255),
|
||||||
|
"created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updated_at" TIMESTAMP(3),
|
||||||
|
|
||||||
|
CONSTRAINT "office_folder_anchors_pkey" PRIMARY KEY ("uid")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "office_folder_anchors_uid_key" ON "office_folder_anchors"("uid");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "office_folders_folder_anchor_uid_key" ON "office_folders"("folder_anchor_uid");
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "office_folders" ADD CONSTRAINT "office_folders_folder_anchor_uid_fkey" FOREIGN KEY ("folder_anchor_uid") REFERENCES "office_folder_anchors"("uid") ON DELETE SET NULL ON UPDATE CASCADE;
|
@ -133,17 +133,41 @@ model OfficeFolders {
|
|||||||
customers Customers[] @relation("OfficeFolderHasCustomers")
|
customers Customers[] @relation("OfficeFolderHasCustomers")
|
||||||
documents Documents[]
|
documents Documents[]
|
||||||
|
|
||||||
|
folder_anchor OfficeFolderAnchors? @relation(fields: [folder_anchor_uid], references: [uid])
|
||||||
|
folder_anchor_uid String? @unique @db.VarChar(255)
|
||||||
|
|
||||||
@@unique([folder_number, office_uid])
|
@@unique([folder_number, office_uid])
|
||||||
@@map("office_folders")
|
@@map("office_folders")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model OfficeFolderAnchors {
|
||||||
|
uid String @id @unique @default(uuid())
|
||||||
|
|
||||||
|
hash_sources String[]
|
||||||
|
root_hash String @db.VarChar(255)
|
||||||
|
|
||||||
|
blockchain EBlockchainName @default(TEZOS)
|
||||||
|
status EAnchoringStatus @default(QUEUED)
|
||||||
|
anchor_nb_try Int @default(0)
|
||||||
|
|
||||||
|
anchored_at DateTime?
|
||||||
|
tx_id String? @db.VarChar(255)
|
||||||
|
tx_link String? @db.VarChar(255)
|
||||||
|
tx_hash String? @db.VarChar(255)
|
||||||
|
|
||||||
|
folder OfficeFolders?
|
||||||
|
|
||||||
|
created_at DateTime? @default(now())
|
||||||
|
updated_at DateTime? @updatedAt
|
||||||
|
|
||||||
|
@@map("office_folder_anchors")
|
||||||
|
}
|
||||||
|
|
||||||
model Documents {
|
model Documents {
|
||||||
uid String @id @unique @default(uuid())
|
uid String @id @unique @default(uuid())
|
||||||
document_status EDocumentStatus @default(ASKED)
|
document_status EDocumentStatus @default(ASKED)
|
||||||
document_type DocumentTypes @relation(fields: [document_type_uid], references: [uid])
|
document_type DocumentTypes @relation(fields: [document_type_uid], references: [uid])
|
||||||
document_type_uid String @db.VarChar(255)
|
document_type_uid String @db.VarChar(255)
|
||||||
blockchain_anchor BlockchainAnchors? @relation(fields: [blockchain_anchor_uid], references: [uid])
|
|
||||||
blockchain_anchor_uid String? @db.VarChar(255)
|
|
||||||
folder OfficeFolders @relation(fields: [folder_uid], references: [uid])
|
folder OfficeFolders @relation(fields: [folder_uid], references: [uid])
|
||||||
folder_uid String @db.VarChar(255)
|
folder_uid String @db.VarChar(255)
|
||||||
depositor Customers @relation(fields: [depositor_uid], references: [uid], onDelete: Cascade)
|
depositor Customers @relation(fields: [depositor_uid], references: [uid], onDelete: Cascade)
|
||||||
@ -175,6 +199,7 @@ model Files {
|
|||||||
file_path String @unique @db.VarChar(255)
|
file_path String @unique @db.VarChar(255)
|
||||||
file_name String @db.VarChar(255)
|
file_name String @db.VarChar(255)
|
||||||
mimetype String @db.VarChar(255)
|
mimetype String @db.VarChar(255)
|
||||||
|
hash String @db.VarChar(255)
|
||||||
size Int
|
size Int
|
||||||
archived_at DateTime?
|
archived_at DateTime?
|
||||||
key String? @db.VarChar(255)
|
key String? @db.VarChar(255)
|
||||||
@ -184,16 +209,6 @@ model Files {
|
|||||||
@@map("files")
|
@@map("files")
|
||||||
}
|
}
|
||||||
|
|
||||||
model BlockchainAnchors {
|
|
||||||
uid String @id @unique @default(uuid())
|
|
||||||
smartSigJobId String @unique @db.VarChar(255)
|
|
||||||
created_at DateTime? @default(now())
|
|
||||||
updated_at DateTime? @updatedAt
|
|
||||||
documents Documents[]
|
|
||||||
|
|
||||||
@@map("blockchain_anchors")
|
|
||||||
}
|
|
||||||
|
|
||||||
model DocumentTypes {
|
model DocumentTypes {
|
||||||
uid String @id @unique @default(uuid())
|
uid String @id @unique @default(uuid())
|
||||||
name String @db.VarChar(255)
|
name String @db.VarChar(255)
|
||||||
@ -346,7 +361,6 @@ enum EDocumentStatus {
|
|||||||
ASKED
|
ASKED
|
||||||
DEPOSITED
|
DEPOSITED
|
||||||
VALIDATED
|
VALIDATED
|
||||||
ANCHORED
|
|
||||||
REFUSED
|
REFUSED
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,3 +373,15 @@ enum EAppointmentStatus {
|
|||||||
OPEN
|
OPEN
|
||||||
CLOSED
|
CLOSED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum EBlockchainName {
|
||||||
|
TEZOS
|
||||||
|
}
|
||||||
|
|
||||||
|
enum EAnchoringStatus {
|
||||||
|
QUEUED
|
||||||
|
ATTEMPTING
|
||||||
|
VERIFIED_ON_CHAIN
|
||||||
|
VERIFYING_ON_CHAIN
|
||||||
|
ABANDONED
|
||||||
|
}
|
||||||
|
@ -38,6 +38,7 @@ export default class FilesRepository extends BaseRepository {
|
|||||||
file_name: file.file_name,
|
file_name: file.file_name,
|
||||||
file_path: file.file_path,
|
file_path: file.file_path,
|
||||||
mimetype: file.mimetype,
|
mimetype: file.mimetype,
|
||||||
|
hash: file.hash,
|
||||||
size: file.size,
|
size: file.size,
|
||||||
key: key,
|
key: key,
|
||||||
},
|
},
|
||||||
@ -57,6 +58,7 @@ export default class FilesRepository extends BaseRepository {
|
|||||||
file_name: file.file_name,
|
file_name: file.file_name,
|
||||||
file_path: file.file_path,
|
file_path: file.file_path,
|
||||||
mimetype: file.mimetype,
|
mimetype: file.mimetype,
|
||||||
|
hash: file.hash,
|
||||||
size: file.size,
|
size: file.size,
|
||||||
key: key,
|
key: key,
|
||||||
},
|
},
|
||||||
|
@ -15,6 +15,10 @@ export default class CryptoService extends BaseService {
|
|||||||
return crypto.createHash("sha256").update(String(key)).digest("base64").slice(0, 32);
|
return crypto.createHash("sha256").update(String(key)).digest("base64").slice(0, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async getHash(buffer: Buffer): Promise<string> {
|
||||||
|
return crypto.createHash("sha256").update(buffer).digest("hex");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description : encrypt data
|
* @description : encrypt data
|
||||||
* @throws {Error} If data cannot be encrypted
|
* @throws {Error} If data cannot be encrypted
|
||||||
|
@ -71,12 +71,15 @@ export default class FilesService extends BaseService {
|
|||||||
public async create(file: File, fileData: Express.Multer.File) {
|
public async create(file: File, fileData: Express.Multer.File) {
|
||||||
const key = v4();
|
const key = v4();
|
||||||
const encryptedFile = await this.cryptoService.encrypt(fileData.buffer, key);
|
const encryptedFile = await this.cryptoService.encrypt(fileData.buffer, key);
|
||||||
|
const hash = await this.cryptoService.getHash(fileData.buffer);
|
||||||
|
|
||||||
const upload = await this.ipfsService.pinFile(Readable.from(encryptedFile), fileData.originalname);
|
const upload = await this.ipfsService.pinFile(Readable.from(encryptedFile), fileData.originalname);
|
||||||
let fileToCreate: File = file;
|
let fileToCreate: File = file;
|
||||||
fileToCreate.file_name = fileData.originalname;
|
fileToCreate.file_name = fileData.originalname;
|
||||||
fileToCreate.file_path = this.variables.PINATA_GATEWAY.concat(upload.IpfsHash);
|
fileToCreate.file_path = this.variables.PINATA_GATEWAY.concat(upload.IpfsHash);
|
||||||
fileToCreate.mimetype = fileData.mimetype;
|
fileToCreate.mimetype = fileData.mimetype;
|
||||||
fileToCreate.size = fileData.size;
|
fileToCreate.size = fileData.size;
|
||||||
|
fileToCreate.hash = hash;
|
||||||
fileToCreate.archived_at = null;
|
fileToCreate.archived_at = null;
|
||||||
|
|
||||||
return this.filesRepository.create(fileToCreate, key);
|
return this.filesRepository.create(fileToCreate, key);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user