Compare commits

..

No commits in common. "711877bf60bcaf6890c99eaec93fae5a46553028" and "30026df2d04cf47017dec78230ef6313a5b694f9" have entirely different histories.

9 changed files with 92 additions and 105 deletions

View File

@ -153,8 +153,6 @@ export const MachinesTable = pgTable("machines", {
//TODO Many to Many table betwen File en Machine //TODO Many to Many table betwen File en Machine
export const FilesForMachinesTable = pgTable("files_for_machines", { export const FilesForMachinesTable = pgTable("files_for_machines", {
id: p.uuid('id').primaryKey().notNull().defaultRandom(),
fileId: p fileId: p
.uuid("file_id") .uuid("file_id")
.notNull() .notNull()

View File

@ -34,8 +34,6 @@ export class FilesController {
}); });
req.on("end", async () => { req.on("end", async () => {
try {
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;
@ -43,43 +41,36 @@ export class FilesController {
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(_fileName, _groupId, _uploadedBy, _machineId, _isDocumentation, _isRestricted, _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 || !_groupId || !_machineId) { if (!_fileName || !_groupId || !_machineId) {
throw new BadRequestException("Header(s) manquant(s)"); throw new BadRequestException("Header(s) manquant(s)");
} }
const machineId = Array(_machineId); const machineId = Array(..._machineId);
const Params = new Map() const Params = new Map()
.set("fileName", _fileName.toString()) .set("fileName", _fileName.toString())
.set("groupId", Array(JSON.parse(_groupId.toString()))) .set("groupId", _groupId.toString())
.set("uploadedBy", _uploadedBy.toString()) .set("uploadedBy", _uploadedBy.toString())
.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(Params);
//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. //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.
if (_isAdmin) { if (_isAdmin) {
Params.set("isDocumentation", Boolean(_isDocumentation)); Params.set("isDocumentation", Boolean(_isDocumentation));
Params.set("isRestricted", Boolean(_isRestricted)); Params.set("isRestricted", Boolean(_isRestricted));
} }
return await this.filesService.save(fileBuffer, Params); await this.filesService.save(fileBuffer, Params);
} catch (err) {
// @ts-ignore
return res.status(err.status || HttpStatus.INTERNAL_SERVER_ERROR).send(err) return { message: "Fichier sauvegardé avec succès" };
}
}); });
req.on("error", (err) => { req.on("error", (err) => {
// @ts-ignore throw new BadRequestException(err.message);
return res.status(err.status || HttpStatus.INTERNAL_SERVER_ERROR).send(err)
}); });
return;
} }
@Get("find") @Get("find")

View File

@ -1,9 +1,9 @@
import { Module } from "@nestjs/common"; import { Module } from "@nestjs/common";
import { CredentialsModule } from "../credentials/credentials.module";
import { DbModule } from "../db/db.module"; import { DbModule } from "../db/db.module";
import { StorageModule } from "../storage/storage.module"; import { StorageModule } from "../storage/storage.module";
import { FilesController } from "./files.controller"; import { FilesController } from "./files.controller";
import { FilesService } from "./files.service"; import { FilesService } from "./files.service";
import { CredentialsModule } from '../credentials/credentials.module';
@Module({ @Module({
imports: [StorageModule, DbModule, CredentialsModule], imports: [StorageModule, DbModule, CredentialsModule],

View File

@ -9,9 +9,9 @@ import {
FilesForMachinesTable, FilesForMachinesTable,
FilesGroupTable, FilesGroupTable,
FilesTable, FilesTable,
FilesTypeForMachine, FilesTypesTable, FilesTypeForMachine,
MachinesTable MachinesTable,
} from 'apps/backend/src/app/db/schema'; } from "apps/backend/src/app/db/schema";
import { StorageService } from "apps/backend/src/app/storage/storage.service"; import { StorageService } from "apps/backend/src/app/storage/storage.service";
import { data } from "autoprefixer"; import { data } from "autoprefixer";
import { eq, ilike } from "drizzle-orm"; import { eq, ilike } from "drizzle-orm";
@ -49,7 +49,6 @@ export class FilesService {
"Multiples entries found in the database.\nInformation from the first row will be used.", "Multiples entries found in the database.\nInformation from the first row will be used.",
); );
const file = foundFiles[0]; const file = foundFiles[0];
console.log(file);
const fileBuffer = await this.storage.read( const fileBuffer = await this.storage.read(
file.checksum, file.checksum,
@ -63,7 +62,7 @@ export class FilesService {
); );
const fileNameWithoutSpaces = file.fileName.replace(/\s/g, "_"); const fileNameWithoutSpaces = file.fileName.replace(/\s/g, "_");
return new StreamableFile(fileBuffer, { return new StreamableFile(fileBuffer, {
disposition: `attachment; filename="${fileNameWithoutSpaces}.${fileInformation.fileType.extension.toLowerCase()}"`, disposition: `attachment; filename="${fileNameWithoutSpaces}.${fileInformation.fileType[0].extension.toLowerCase()}"`,
}); });
} }
@ -81,14 +80,12 @@ export class FilesService {
//TODO save a file //TODO save a file
public async save(file: Buffer, data: Map<string, unknown>) { public async save(file: Buffer, data: Map<string, unknown>) {
try { const _machineIds = Array.from(data.get("machineId") as string[]);
const _machineIds = data.get("machineId").toString().split(",");
const machinesIds = new Set<string>(); const machinesIds = new Set<string>();
for (const machineId of _machineIds) {
console.log( console.log(
`Checking if machine with ID ${machineId} exist in the database...`, `Checking if machine with ID ${_machineIds} exist in the database...`,
); );
for (const machineId of _machineIds) {
const machineExists = await this.database const machineExists = await this.database
.use() .use()
.select({ .select({
@ -120,34 +117,27 @@ export class FilesService {
throw new NotFoundException(`Group with ID "${_group}" not found`); throw new NotFoundException(`Group with ID "${_group}" not found`);
} }
try {
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, _machineIds,
Boolean(data.get("isDocumentation")), Boolean(data.get("isDocumentation")),
); );
console.log(saveResult);
const mimeId = await this.database.use()
.select()
.from(FilesTypesTable)
.where(eq(FilesTypesTable.mime, saveResult.fileType.mime))
const inserted = await this.database const inserted = await this.database
.use() .use()
.insert(FilesTable) .insert(FilesTable)
.values({ .values({
fileName: data.get("fileName") as string, fileName: data.get("fileName") as string,
checksum: saveResult.fileChecksum, checksum: saveResult.fileChecksum,
extension: saveResult.fileType.extension, extension: saveResult.fileType[0].extension,
fileSize: saveResult.fileSize, fileSize: saveResult.fileSize,
fileType: mimeId[0].id, fileType: saveResult.fileType.mime,
isRestricted: Boolean(data.get("isRestricted")), isRestricted: Boolean(data.get("isRestricted")),
isDocumentation: Boolean(data.get("isDocumentation")), isDocumentation: Boolean(data.get("isDocumentation")),
uploadedBy: data.get("uploadedBy") as string, uploadedBy: data.get("uploadedBy") as string,
}) })
.returning(); .returning();
console.log(inserted);
for (const machineId of machinesIds) { for (const machineId of machinesIds) {
//TODO insert a link betwen fileId and MachineIds[] //TODO insert a link betwen fileId and MachineIds[]
@ -159,10 +149,20 @@ export class FilesService {
machineId: machineId, machineId: machineId,
}); });
} }
} catch (e) {
return inserted[0]; throw new InternalServerErrorException(
} catch (err) { "It seems that the insertion in the database failed.",
throw err; {
cause:
process.env.NODE_ENV === "production"
? "Internal server error"
: {
message: e.message,
stack: e.stack,
},
description: `Nom de fichier : "${data.get("fileName")}" `,
},
);
} }
} }
} }

View File

@ -1,7 +1,7 @@
import { Module } from "@nestjs/common"; import { Module } from "@nestjs/common";
import { DbModule } from "apps/backend/src/app/db/db.module";
import { MachinesController } from "apps/backend/src/app/machines/machines.controller"; import { MachinesController } from "apps/backend/src/app/machines/machines.controller";
import { MachinesService } from "apps/backend/src/app/machines/machines.service"; import { MachinesService } from "apps/backend/src/app/machines/machines.service";
import { DbModule } from 'apps/backend/src/app/db/db.module';
@Module({ @Module({
imports: [DbModule], imports: [DbModule],

View File

@ -5,6 +5,6 @@ import { StorageService } from "../storage/storage.service";
@Module({ @Module({
imports: [DbModule], imports: [DbModule],
providers: [StorageService], providers: [StorageService],
exports: [StorageService], exports: [StorageService]
}) })
export class StorageModule {} export class StorageModule {}

View File

@ -16,7 +16,7 @@ import {
} from "apps/backend/src/app/db/schema"; } from "apps/backend/src/app/db/schema";
import { IFileInformation } from "apps/backend/src/app/storage/storage.types"; import { IFileInformation } from "apps/backend/src/app/storage/storage.types";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { filetypeinfo } from "magic-bytes.js"; import { filetypeinfo } from 'magic-bytes.js';
@Injectable() @Injectable()
export class StorageService { export class StorageService {
@ -34,7 +34,7 @@ export class StorageService {
*/ */
private async saveFile(fileName: string, file: Buffer): Promise<void> { private async saveFile(fileName: string, file: Buffer): Promise<void> {
try { try {
await writeFile(join(process.cwd(), "assets/", fileName), file, "utf8"); await writeFile(join(process.cwd(), "files/", fileName), file, "utf8");
} catch (err) { } catch (err) {
console.error(err); console.error(err);
throw new InternalServerErrorException("File save failed !"); throw new InternalServerErrorException("File save failed !");
@ -123,7 +123,7 @@ export class StorageService {
*/ */
private async getFile(fileName: string): Promise<Buffer> { private async getFile(fileName: string): Promise<Buffer> {
try { try {
return await readFile(join(process.cwd(), "assets/", fileName)); return await readFile(join(process.cwd(), "files/", fileName));
} catch (err) { } catch (err) {
throw new NotFoundException("File not found"); throw new NotFoundException("File not found");
} }
@ -245,11 +245,9 @@ export class StorageService {
await this.saveFile(info.fileName, file); await this.saveFile(info.fileName, file);
// All good we return data about the file to append it to the db. // All good we return data about the file to append it to the db.
console.log(`File "${info.fileName}" saved successfully.`);
return info; return info;
} catch (err) { } catch (err) {
console.error(err); throw new BadRequestException(err);
throw err;
} }
} }
} }

View File

@ -1,5 +1,5 @@
import { StreamableFile } from "@nestjs/common"; import { StreamableFile } from "@nestjs/common";
import { GuessedFile } from "magic-bytes.js/dist/model/tree"; import { GuessedFile } from 'magic-bytes.js/dist/model/tree';
export interface IFileInformation { export interface IFileInformation {
fileDisplayName: string; fileDisplayName: string;

View File