Refactor and log changes in storage and file services
Convert array of machine IDs to sets for uniqueness in methods. Add console logs for debugging and update error handling to improve clarity. Refactor the files controller for better readability.
This commit is contained in:
parent
ff649ebdbf
commit
6f9d25a58b
@ -1,24 +1,24 @@
|
|||||||
import { IncomingMessage } from "node:http";
|
import { IncomingMessage } from "node:http";
|
||||||
import {
|
import {
|
||||||
BadRequestException,
|
BadRequestException,
|
||||||
Body,
|
Body,
|
||||||
Controller,
|
Controller,
|
||||||
DefaultValuePipe,
|
DefaultValuePipe,
|
||||||
Delete,
|
Delete,
|
||||||
Get,
|
Get,
|
||||||
HttpCode,
|
HttpCode,
|
||||||
HttpStatus,
|
HttpStatus,
|
||||||
Param,
|
Param,
|
||||||
ParseIntPipe,
|
ParseIntPipe,
|
||||||
ParseUUIDPipe,
|
ParseUUIDPipe,
|
||||||
Post,
|
Post,
|
||||||
Query,
|
Query,
|
||||||
Req,
|
Req,
|
||||||
Request,
|
Request,
|
||||||
Res,
|
Res,
|
||||||
Response,
|
Response,
|
||||||
StreamableFile,
|
StreamableFile,
|
||||||
UseGuards,
|
UseGuards,
|
||||||
} from "@nestjs/common";
|
} from "@nestjs/common";
|
||||||
import { CreateFileTypeDto } from "apps/backend/src/app/files/files.dto";
|
import { CreateFileTypeDto } from "apps/backend/src/app/files/files.dto";
|
||||||
import { AdminGuard, InsertAdminState } from "../auth/auth.guard";
|
import { AdminGuard, InsertAdminState } from "../auth/auth.guard";
|
||||||
@ -26,132 +26,133 @@ import { FilesService } from "./files.service";
|
|||||||
|
|
||||||
@Controller("files")
|
@Controller("files")
|
||||||
export class FilesController {
|
export class FilesController {
|
||||||
constructor(private readonly filesService: FilesService) { }
|
constructor(private readonly filesService: FilesService) {}
|
||||||
|
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
@UseGuards(InsertAdminState)
|
@UseGuards(InsertAdminState)
|
||||||
@Post("new")
|
@Post("new")
|
||||||
async saveFile(@Req() req: IncomingMessage, @Res() res: Response) {
|
async saveFile(@Req() req: IncomingMessage, @Res() res: Response) {
|
||||||
let fileBuffer: Buffer = Buffer.from([]);
|
let fileBuffer: Buffer = Buffer.from([]);
|
||||||
req.on("data", (chunk: Buffer) => {
|
req.on("data", (chunk: Buffer) => {
|
||||||
fileBuffer = Buffer.concat([fileBuffer, chunk]);
|
fileBuffer = Buffer.concat([fileBuffer, chunk]);
|
||||||
});
|
});
|
||||||
|
|
||||||
req.on("end", async () => {
|
req.on("end", async () => {
|
||||||
try {
|
try {
|
||||||
console.log(fileBuffer);
|
console.log(fileBuffer);
|
||||||
const _fileName = req.headers["file_name"] as string;
|
const _fileName = req.headers["file_name"] as string;
|
||||||
const _groupId = req.headers["group_id"] as string;
|
const _groupId = req.headers["group_id"] as string;
|
||||||
const _uploadedBy = req.headers["uploaded_by"] as string;
|
const _uploadedBy = req.headers["uploaded_by"] as string;
|
||||||
const _machineId = req.headers["machine_id"];
|
const _machineId = req.headers["machine_id"];
|
||||||
const _isDocumentation = req.headers["is_documentation"] as string;
|
const _isDocumentation = req.headers["is_documentation"] as string;
|
||||||
const _isRestricted = req.headers["is_restricted"] as string;
|
const _isRestricted = req.headers["is_restricted"] as string;
|
||||||
const _isAdmin = Boolean(req.headers["is_admin"] as string | boolean);
|
const _isAdmin = Boolean(req.headers["is_admin"] as string | boolean);
|
||||||
console.log(
|
console.log(
|
||||||
_fileName,
|
_fileName,
|
||||||
_groupId,
|
_groupId,
|
||||||
_uploadedBy,
|
_uploadedBy,
|
||||||
_machineId,
|
_machineId,
|
||||||
_isDocumentation,
|
_isDocumentation,
|
||||||
_isRestricted,
|
_isRestricted,
|
||||||
_isAdmin,
|
_isAdmin,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Vérifier que les en-têtes nécessaires sont présents
|
// Vérifier que les en-têtes nécessaires sont présents
|
||||||
if (!_fileName || !_machineId) {
|
if (!_fileName || !_machineId || !_uploadedBy) {
|
||||||
throw new BadRequestException("Header(s) manquant(s)");
|
throw new BadRequestException("Header(s) manquant(s)");
|
||||||
}
|
}
|
||||||
console.log("Header found !");
|
console.log("Header found !");
|
||||||
const machineId = Array(_machineId);
|
const machineId = Array(_machineId);
|
||||||
|
|
||||||
const Params = new Map()
|
const Params = new Map()
|
||||||
.set("fileName", _fileName.toString())
|
.set("groupId", null)
|
||||||
.set("groupId", _groupId.toString() || null)
|
.set("fileName", _fileName.toString())
|
||||||
.set("uploadedBy", _uploadedBy.toString())
|
.set("uploadedBy", String(_uploadedBy))
|
||||||
.set("machineId", Array(JSON.parse(machineId.toString())))
|
.set("machineId", Array(machineId))
|
||||||
.set("isDocumentation", false)
|
.set("isDocumentation", false)
|
||||||
.set("isRestricted", false);
|
.set("isRestricted", false);
|
||||||
|
|
||||||
console.log("Current params :\n", Params);
|
if (_groupId) Params.set("groupId", String(_groupId));
|
||||||
|
|
||||||
//TODO Integrate a verification if the source is an admin, if that the case then it can define isDocumentation and isRestricted else throw in case of presence of those parameters.
|
console.log("Current params :\n", Params);
|
||||||
if (_isAdmin) {
|
|
||||||
Params.set("isDocumentation", Boolean(_isDocumentation));
|
|
||||||
Params.set("isRestricted", Boolean(_isRestricted));
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("Executing save procedure...");
|
//TODO Integrate a verification if the source is an admin, if that the case then it can define isDocumentation and isRestricted else throw in case of presence of those parameters.
|
||||||
return (
|
if (_isAdmin) {
|
||||||
res
|
Params.set("isDocumentation", Boolean(_isDocumentation));
|
||||||
// @ts-ignore
|
Params.set("isRestricted", Boolean(_isRestricted));
|
||||||
.status(HttpStatus.CREATED)
|
}
|
||||||
.send(await this.filesService.save(fileBuffer, Params))
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return (
|
|
||||||
res
|
|
||||||
// @ts-ignore
|
|
||||||
.status(err.status || HttpStatus.INTERNAL_SERVER_ERROR)
|
|
||||||
.send(err)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
req.on("error", (err) => {
|
console.log("Executing save procedure...");
|
||||||
return (
|
return (
|
||||||
res
|
res
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
.status(err.status || HttpStatus.INTERNAL_SERVER_ERROR)
|
.status(HttpStatus.CREATED)
|
||||||
.send(err)
|
.send(await this.filesService.save(fileBuffer, Params))
|
||||||
);
|
);
|
||||||
});
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
return (
|
||||||
|
res
|
||||||
|
// @ts-ignore
|
||||||
|
.status(err.status || HttpStatus.INTERNAL_SERVER_ERROR)
|
||||||
|
.send(err)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return;
|
req.on("error", (err) => {
|
||||||
}
|
return (
|
||||||
|
res
|
||||||
|
// @ts-ignore
|
||||||
|
.status(err.status || HttpStatus.INTERNAL_SERVER_ERROR)
|
||||||
|
.send(err)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
@HttpCode(HttpStatus.FOUND)
|
return;
|
||||||
@Get("find")
|
}
|
||||||
async findMany(
|
|
||||||
@Query("limit", new DefaultValuePipe(20), ParseIntPipe) limit: number,
|
|
||||||
@Query("offset", new DefaultValuePipe(0), ParseIntPipe) offset: number,
|
|
||||||
@Query("search", new DefaultValuePipe("")) search: string,
|
|
||||||
) {
|
|
||||||
return this.filesService.search(limit, offset, search);
|
|
||||||
}
|
|
||||||
|
|
||||||
@HttpCode(HttpStatus.FOUND)
|
@HttpCode(HttpStatus.FOUND)
|
||||||
@Get("types")
|
@Get("find")
|
||||||
async getTypes() {
|
async findMany(
|
||||||
console.log("Performing request")
|
@Query("limit", new DefaultValuePipe(20), ParseIntPipe) limit: number,
|
||||||
return await this.filesService.getAllFilesTypes();
|
@Query("offset", new DefaultValuePipe(0), ParseIntPipe) offset: number,
|
||||||
}
|
@Query("search", new DefaultValuePipe("")) search: string,
|
||||||
|
) {
|
||||||
|
return this.filesService.search(limit, offset, search);
|
||||||
|
}
|
||||||
|
|
||||||
@HttpCode(HttpStatus.CREATED)
|
@HttpCode(HttpStatus.FOUND)
|
||||||
@UseGuards(AdminGuard)
|
@Get("types")
|
||||||
@Post("types/new")
|
async getTypes() {
|
||||||
async newType(@Body() body: CreateFileTypeDto) {
|
console.log("Performing request");
|
||||||
return await this.filesService.createFileType(body.name, body.mime);
|
return await this.filesService.getAllFilesTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
@HttpCode(HttpStatus.ACCEPTED)
|
@HttpCode(HttpStatus.CREATED)
|
||||||
@UseGuards(AdminGuard)
|
@UseGuards(AdminGuard)
|
||||||
@Delete("types/:typeId")
|
@Post("types/new")
|
||||||
async delType(@Param(":typeId", ParseUUIDPipe) typeId: string) {
|
async newType(@Body() body: CreateFileTypeDto) {
|
||||||
return await this.filesService.removeFileType(typeId)
|
return await this.filesService.createFileType(body.name, body.mime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@HttpCode(HttpStatus.FOUND)
|
@HttpCode(HttpStatus.ACCEPTED)
|
||||||
@Get(":fileId")
|
@UseGuards(AdminGuard)
|
||||||
async getFile(@Param("fileId") fileId: string) {
|
@Delete("types/:typeId")
|
||||||
return await this.filesService.get(fileId);
|
async delType(@Param(":typeId", ParseUUIDPipe) typeId: string) {
|
||||||
}
|
return await this.filesService.removeFileType(typeId);
|
||||||
|
}
|
||||||
|
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.FOUND)
|
||||||
@UseGuards(AdminGuard)
|
@Get(":fileId")
|
||||||
@Delete(":fileId")
|
async getFile(@Param("fileId") fileId: string) {
|
||||||
async deleteFile(@Param("fileId", ParseUUIDPipe) fileId: string) {
|
return await this.filesService.get(fileId);
|
||||||
return await this.filesService.deleteFile(fileId);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
@HttpCode(HttpStatus.OK)
|
||||||
|
@UseGuards(AdminGuard)
|
||||||
|
@Delete(":fileId")
|
||||||
|
async deleteFile(@Param("fileId", ParseUUIDPipe) fileId: string) {
|
||||||
|
return await this.filesService.deleteFile(fileId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -195,7 +195,7 @@ export class FilesService {
|
|||||||
.where(eq(FilesGroupTable.uuid, _group))
|
.where(eq(FilesGroupTable.uuid, _group))
|
||||||
.prepare("checkGroupExists")
|
.prepare("checkGroupExists")
|
||||||
.execute();
|
.execute();
|
||||||
|
if (!_group) console.log("No group to link with the file.");
|
||||||
if (_group && groupExists.length === 0) {
|
if (_group && groupExists.length === 0) {
|
||||||
throw new NotFoundException(`Group with ID "${_group}" not found`);
|
throw new NotFoundException(`Group with ID "${_group}" not found`);
|
||||||
}
|
}
|
||||||
@ -203,7 +203,7 @@ export class FilesService {
|
|||||||
const saveResult = await this.storage.new(
|
const saveResult = await this.storage.new(
|
||||||
data.get("fileName") as string,
|
data.get("fileName") as string,
|
||||||
file,
|
file,
|
||||||
_machineIds,
|
machinesIds,
|
||||||
Boolean(data.get("isDocumentation")),
|
Boolean(data.get("isDocumentation")),
|
||||||
);
|
);
|
||||||
console.log(saveResult);
|
console.log(saveResult);
|
||||||
@ -212,7 +212,7 @@ export class FilesService {
|
|||||||
.select()
|
.select()
|
||||||
.from(FilesTypesTable)
|
.from(FilesTypesTable)
|
||||||
.where(eq(FilesTypesTable.mime, saveResult.fileType.mime));
|
.where(eq(FilesTypesTable.mime, saveResult.fileType.mime));
|
||||||
|
console.log(mimeId);
|
||||||
const inserted = await this.database
|
const inserted = await this.database
|
||||||
.use()
|
.use()
|
||||||
.insert(FilesTable)
|
.insert(FilesTable)
|
||||||
@ -227,7 +227,9 @@ export class FilesService {
|
|||||||
uploadedBy: data.get("uploadedBy") as string,
|
uploadedBy: data.get("uploadedBy") as string,
|
||||||
})
|
})
|
||||||
.returning();
|
.returning();
|
||||||
if (groupExists[0].uuid) {
|
console.log(inserted);
|
||||||
|
if (_group) {
|
||||||
|
console.log("Adding group ip to file..");
|
||||||
await this.database
|
await this.database
|
||||||
.use()
|
.use()
|
||||||
.update(FilesTable)
|
.update(FilesTable)
|
||||||
@ -238,7 +240,7 @@ export class FilesService {
|
|||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(inserted);
|
console.log("File insertion done");
|
||||||
|
|
||||||
for (const machineId of machinesIds) {
|
for (const machineId of machinesIds) {
|
||||||
console.log(
|
console.log(
|
||||||
@ -299,7 +301,7 @@ export class FilesService {
|
|||||||
.from(FilesTypesTable)
|
.from(FilesTypesTable)
|
||||||
.prepare("getAllFilesTypes")
|
.prepare("getAllFilesTypes")
|
||||||
.execute();
|
.execute();
|
||||||
console.log(result)
|
console.log(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import * as console from "node:console";
|
|
||||||
import * as crypto from "node:crypto";
|
import * as crypto from "node:crypto";
|
||||||
import { readFile, rm, writeFile } from "node:fs/promises";
|
import { readFile, rm, writeFile } from "node:fs/promises";
|
||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
@ -43,13 +42,15 @@ export class StorageService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the current MIME type and file size meet the specified conditions.
|
* Checks the conditions for the provided file and machine IDs.
|
||||||
* @param {Array<string>} machineIds - The IDs of the associated machines.
|
*
|
||||||
* @param {Buffer} file - The file to check.
|
* @param {Set<string>} machinesIds - A set containing machine identifiers.
|
||||||
* @return {Promise<boolean>} - A Promise that resolves to true if the conditions are met, false otherwise.
|
* @param {Buffer} file - The file buffer that needs to be checked.
|
||||||
|
* @return {Promise<boolean>} Returns a promise that resolves to true if the conditions are met, otherwise it throws an exception.
|
||||||
|
* @throws {BadRequestException} If the file size exceeds the allowed maximum size or the file MIME type is not allowed.
|
||||||
*/
|
*/
|
||||||
private async checkConditions(
|
private async checkConditions(
|
||||||
machineIds: Array<string>,
|
machinesIds: Set<string>,
|
||||||
file: Buffer,
|
file: Buffer,
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
/**
|
/**
|
||||||
@ -65,6 +66,7 @@ export class StorageService {
|
|||||||
): boolean {
|
): boolean {
|
||||||
let notFoundCount = 0;
|
let notFoundCount = 0;
|
||||||
for (const mimesForMachine of mimesForMachines) {
|
for (const mimesForMachine of mimesForMachines) {
|
||||||
|
console.log(mimesForMachine);
|
||||||
const [key, set] = mimesForMachine;
|
const [key, set] = mimesForMachine;
|
||||||
if (!set.has(currentMime)) {
|
if (!set.has(currentMime)) {
|
||||||
notFoundCount++;
|
notFoundCount++;
|
||||||
@ -82,10 +84,12 @@ export class StorageService {
|
|||||||
string,
|
string,
|
||||||
Set<string>
|
Set<string>
|
||||||
>();
|
>();
|
||||||
|
const mimeSet = new Set(_mimes);
|
||||||
// Fetching MIMEs for the associated machines
|
// Fetching MIMEs for the associated machines
|
||||||
for (const machineId of machineIds) {
|
for (const machineId of machinesIds) {
|
||||||
console.debug(`Fetching mimeTypes for machine : ${machineId}`);
|
console.debug(`Fetching mimeTypes for machine : ${machineId}`);
|
||||||
// Get MIMEs associated to a machine
|
// Get MIMEs associated to a machine
|
||||||
|
/*
|
||||||
const allowedMimeId = this.dbService
|
const allowedMimeId = this.dbService
|
||||||
.use()
|
.use()
|
||||||
.select()
|
.select()
|
||||||
@ -102,18 +106,31 @@ export class StorageService {
|
|||||||
.leftJoin(
|
.leftJoin(
|
||||||
allowedMimeId,
|
allowedMimeId,
|
||||||
eq(FilesTypesTable.id, allowedMimeId.fileTypeId),
|
eq(FilesTypesTable.id, allowedMimeId.fileTypeId),
|
||||||
|
);*/
|
||||||
|
|
||||||
|
const _allowedMime = await this.dbService
|
||||||
|
.use()
|
||||||
|
.select()
|
||||||
|
.from(FilesTypeForMachine)
|
||||||
|
.where(eq(FilesTypeForMachine.machineId, machineId))
|
||||||
|
.leftJoin(
|
||||||
|
FilesTypesTable,
|
||||||
|
eq(FilesTypesTable.id, FilesTypeForMachine.fileTypeId),
|
||||||
);
|
);
|
||||||
|
console.log(_allowedMime);
|
||||||
console.debug(`Total : ${_allowedMime.length}`);
|
console.debug(`Total : ${_allowedMime.length}`);
|
||||||
// Append each MIME of a machine
|
// Append each MIME of a machine
|
||||||
const tempSet = new Set<string>();
|
const tempSet = new Set<string>();
|
||||||
for (const allowedMimeElement of _allowedMime) {
|
for (const allowedMimeElement of _allowedMime) {
|
||||||
tempSet.add(allowedMimeElement.slug);
|
console.debug(
|
||||||
|
`Adding ${allowedMimeElement.f_types.mime} for verification..`,
|
||||||
|
);
|
||||||
|
tempSet.add(allowedMimeElement.f_types.mime);
|
||||||
|
mimeSet.add(allowedMimeElement.f_types.mime);
|
||||||
}
|
}
|
||||||
machinesMap.set(machineId, tempSet);
|
machinesMap.set(machineId, tempSet);
|
||||||
tempSet.clear();
|
|
||||||
}
|
}
|
||||||
//Store the MIMEs without duplicate
|
//Store the MIMEs without duplicate
|
||||||
const mimeSet = new Set(_mimes);
|
|
||||||
console.debug(`Indexed ${mimeSet.size} unique mimeTypes`);
|
console.debug(`Indexed ${mimeSet.size} unique mimeTypes`);
|
||||||
|
|
||||||
//check file size is less than 2mb
|
//check file size is less than 2mb
|
||||||
@ -236,7 +253,7 @@ export class StorageService {
|
|||||||
public async new(
|
public async new(
|
||||||
fileDisplayName: string,
|
fileDisplayName: string,
|
||||||
file: Buffer,
|
file: Buffer,
|
||||||
machinesId: Array<string>,
|
machinesId: Set<string>,
|
||||||
isDocumentation?: boolean,
|
isDocumentation?: boolean,
|
||||||
): Promise<IFileInformation> {
|
): Promise<IFileInformation> {
|
||||||
try {
|
try {
|
||||||
@ -246,7 +263,7 @@ export class StorageService {
|
|||||||
isDocumentation,
|
isDocumentation,
|
||||||
);
|
);
|
||||||
console.log(
|
console.log(
|
||||||
`Trying to append a new file : "${info.fileDisplayName}"...\n > Checksum SHA-256 : ${info.fileChecksum}\n > Size : ${info.fileSize / (1024 * 1024)}Mio\n > File format : ${info.fileType.mime}\n`,
|
`Trying to append a new file : "${info.fileDisplayName}"...\n > Checksum SHA-256 : ${info.fileChecksum}\n > Size : ${(info.fileSize / (1024 * 1024)).toFixed(6)} Mio\n > File format : ${info.fileType.mime}\n`,
|
||||||
);
|
);
|
||||||
const condition = await this.checkConditions(machinesId, file);
|
const condition = await this.checkConditions(machinesId, file);
|
||||||
if (!condition) {
|
if (!condition) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user