diff --git a/apps/backend/src/app/db/schema.ts b/apps/backend/src/app/db/schema.ts index 50cace2..48e2009 100644 --- a/apps/backend/src/app/db/schema.ts +++ b/apps/backend/src/app/db/schema.ts @@ -73,7 +73,10 @@ export const FilesTable = pgTable("files", { }) .notNull(), - groupId: p.uuid("group_id").default(null).references(() => FilesGroupTable.uuid), + groupId: p + .uuid("group_id") + .default(null) + .references(() => FilesGroupTable.uuid), fileSize: p.integer("file_size").notNull(), diff --git a/apps/backend/src/app/files/files.controller.ts b/apps/backend/src/app/files/files.controller.ts index 62ad2f9..82f48f3 100644 --- a/apps/backend/src/app/files/files.controller.ts +++ b/apps/backend/src/app/files/files.controller.ts @@ -2,7 +2,8 @@ import { IncomingMessage } from "node:http"; import { BadRequestException, Controller, - DefaultValuePipe, Delete, + DefaultValuePipe, + Delete, Get, HttpCode, HttpStatus, @@ -15,9 +16,9 @@ import { Res, Response, StreamableFile, - UseGuards -} from '@nestjs/common'; -import { AdminGuard, InsertAdminState } from '../auth/auth.guard'; + UseGuards, +} from "@nestjs/common"; +import { AdminGuard, InsertAdminState } from "../auth/auth.guard"; import { FilesService } from "./files.service"; @Controller("files") @@ -125,7 +126,7 @@ export class FilesController { @UseGuards(AdminGuard) @HttpCode(HttpStatus.OK) @Delete(":fileId") - async deleteFile(@Param("fileId") fileId: string) { - return await this.filesService.deleteFile(fileId); - } + async deleteFile(@Param("fileId") fileId: string) { + return await this.filesService.deleteFile(fileId); + } } diff --git a/apps/backend/src/app/files/files.service.ts b/apps/backend/src/app/files/files.service.ts index a0ee54f..08bcbac 100644 --- a/apps/backend/src/app/files/files.service.ts +++ b/apps/backend/src/app/files/files.service.ts @@ -67,12 +67,52 @@ export class FilesService { }); } - //TODO DELETE FILE + /** + * Deletes a file from the storage and/or the database based on the provided file ID. + * + * @param {string} fileId - The unique identifier of the file to delete. + * @return {Promise} A promise that resolves when the deletion process is complete. + * @throws {NotFoundException} If the file is not found in the database. + */ public async deleteFile(fileId: string) { //get checksum for fileId - //check if multiple entry for checksum + const currentFileInDb = await this.database + .use() + .select() + .from(FilesTable) + .where(eq(FilesTable.uuid, fileId)) + .prepare("findFileById") + .execute(); + if (currentFileInDb.length === 0) + throw new NotFoundException("File not found in database"); + + //check if multiple entry for checksum + const sameFileInStorage = await this.database + .use() + .select() + .from(FilesTable) + .where(eq(FilesTable.checksum, currentFileInDb[0].checksum)); + if (sameFileInStorage.length > 1) { //if that the case then only remove the entry in database relative to fileId. + await this.database + .use() + .delete(FilesTable) + .where(eq(FilesTable.uuid, fileId)) + .execute(); + } + if (sameFileInStorage.length === 1) { //if there is one only entry then remove the file from the storage and the database. + await this.database + .use() + .delete(FilesTable) + .where(eq(FilesTable.uuid, fileId)) + .execute(); + await this.storage.delete( + currentFileInDb[0].checksum, + currentFileInDb[0].extension, + currentFileInDb[0].isDocumentation, + ); + } } /** @@ -180,13 +220,14 @@ export class FilesService { }) .returning(); if (groupExists[0].uuid) { - await this.database.use() + await this.database + .use() .update(FilesTable) // @ts-ignore TODO FIX - .set({groupId: groupExists[0].uuid}) + .set({ groupId: groupExists[0].uuid }) .where(eq(FilesTable.uuid, inserted[0].uuid)) .prepare("addGroupToFile") - .execute() + .execute(); } console.log(inserted); diff --git a/apps/backend/src/app/storage/storage.service.ts b/apps/backend/src/app/storage/storage.service.ts index f6bd2f4..66f3f2d 100644 --- a/apps/backend/src/app/storage/storage.service.ts +++ b/apps/backend/src/app/storage/storage.service.ts @@ -1,6 +1,6 @@ import * as console from "node:console"; import * as crypto from "node:crypto"; -import { readFile, writeFile, rm } from "node:fs/promises"; +import { readFile, rm, writeFile } from "node:fs/promises"; import { join } from "node:path"; import { BadRequestException, @@ -59,11 +59,16 @@ export class StorageService { * @param {string} currentMime - The MIME type to check for presence in all sets. * @return {boolean} Returns true if the MIME type is found in all sets, otherwise false. */ - function checkMime(mimesForMachines: Map>, currentMime: string): boolean { + function checkMime( + mimesForMachines: Map>, + currentMime: string, + ): boolean { let notFoundCount = 0; for (const mimesForMachine of mimesForMachines) { - const [key, set] = mimesForMachine - if (!set.has(currentMime)) {notFoundCount++} + const [key, set] = mimesForMachine; + if (!set.has(currentMime)) { + notFoundCount++; + } } return notFoundCount === 0; } @@ -73,7 +78,10 @@ export class StorageService { // Array of MIMEs with possible duplicate field const _mimes: Array = []; - const machinesMap: Map> = new Map>() + const machinesMap: Map> = new Map< + string, + Set + >(); // Fetching MIMEs for the associated machines for (const machineId of machineIds) { console.debug(`Fetching mimeTypes for machine : ${machineId}`); @@ -97,12 +105,12 @@ export class StorageService { ); console.debug(`Total : ${_allowedMime.length}`); // Append each MIME of a machine - const tempSet = new Set() + const tempSet = new Set(); for (const allowedMimeElement of _allowedMime) { - tempSet.add(allowedMimeElement.slug) + tempSet.add(allowedMimeElement.slug); } - machinesMap.set(machineId, tempSet) - tempSet.clear() + machinesMap.set(machineId, tempSet); + tempSet.clear(); } //Store the MIMEs without duplicate const mimeSet = new Set(_mimes); @@ -279,13 +287,13 @@ export class StorageService { isDocumentation: boolean, ) { try { - const fileName = `${isDocumentation ? "doc" : "file"}-${checksum}.${extension.toLowerCase()}`; - console.log(`Deleting file "${fileName}" from storage...`); - await rm(join(process.cwd(), "assets/", fileName)); - console.log(`File "${fileName}" deleted successfully.`); - } catch (err) { - console.log("File not found."); - throw new NotFoundException(err); - } + const fileName = `${isDocumentation ? "doc" : "file"}-${checksum}.${extension.toLowerCase()}`; + console.log(`Deleting file "${fileName}" from storage...`); + await rm(join(process.cwd(), "assets/", fileName)); + console.log(`File "${fileName}" deleted successfully.`); + } catch (err) { + console.log("File not found."); + throw new NotFoundException(err); + } } }