import FilesRepository from "@Repositories/FilesRepository"; import BaseService from "@Services/BaseService"; import { Service } from "typedi"; import { File } from "le-coffre-resources/dist/SuperAdmin"; import CryptoService from "../CryptoService/CryptoService"; import IpfsService from "../IpfsService/IpfsService"; import { BackendVariables } from "@Common/config/variables/Variables"; import { Readable } from "stream"; import { v4 } from "uuid"; import { Files, Prisma } from "@prisma/client"; @Service() export default class FilesService extends BaseService { constructor( private filesRepository: FilesRepository, private ipfsService: IpfsService, private variables: BackendVariables, private cryptoService: CryptoService, ) { super(); } /** * @description : Get all files * @throws {Error} If files cannot be ge */ public async get(query: Prisma.FilesFindManyArgs) { return this.filesRepository.findMany(query); } /** * @description : Get a file by uid * @throws {Error} If project cannot be created */ public async getByUid(uid: string, query?: Prisma.FilesInclude) { return this.filesRepository.findOneByUid(uid, query); } /** * @description : Get a file by uid with office * @throws {Error} If project cannot be created */ public async getByUidWithOffice(uid: string) { return this.filesRepository.findOneByUidWithOffice(uid); } /** * @description : Get a file by uid with document * @throws {Error} If project cannot be created */ public async getByUidWithDocument(uid: string) { return this.filesRepository.findOneByUidWithDocument(uid); } /** * @description : view a file * @throws {Error} If file cannot be deleted */ public async download(uid: string) { const file = await this.filesRepository.findOneByUid(uid); if (!file?.key) return null; const fileResult = await fetch(file.file_path); const fileArrayBuffer = await fileResult.arrayBuffer(); return { file: file, buffer: await this.cryptoService.decrypt(Buffer.from(fileArrayBuffer), file.key) }; } /** * @description : Create a new file * @throws {Error} If file cannot be created */ public async create(file: File, fileData: Express.Multer.File) { const key = v4(); const encryptedFile = await this.cryptoService.encrypt(fileData.buffer, key); const upload = await this.ipfsService.pinFile(Readable.from(encryptedFile), fileData.originalname); let fileToCreate: File = file; fileToCreate.file_name = fileData.originalname; fileToCreate.file_path = this.variables.PINATA_GATEWAY.concat(upload.IpfsHash); fileToCreate.mimetype = fileData.mimetype; fileToCreate.size = fileData.size; fileToCreate.archived_at = null; return this.filesRepository.create(fileToCreate, key); } /** * @description : Modify a new file * @throws {Error} If file cannot be modified */ public async update(uid: string, file: File): Promise { const key = v4(); return this.filesRepository.update(uid, file, key); } /** * @description : Delete a file key and archive * @throws {Error} If file key cannot be deleted or archived */ public async deleteKeyAndArchive(uid: string): Promise { try { const fileToUnpin = await this.filesRepository.findOneByUid(uid); if (!fileToUnpin) throw new Error("file not found"); const fileHash = fileToUnpin.file_path.substring(this.variables.PINATA_GATEWAY.length); await this.ipfsService.unpinFile(fileHash); } catch (error) { console.error(error); } return this.filesRepository.deleteKeyAndArchive(uid); } }