Compare commits
4 Commits
04a37d19b7
...
1fc9185afc
Author | SHA1 | Date | |
---|---|---|---|
1fc9185afc | |||
8686f0c27b | |||
79b2dec9e9 | |||
3e6b2dc2bc |
@ -73,7 +73,10 @@ export const FilesTable = pgTable("files", {
|
|||||||
})
|
})
|
||||||
.notNull(),
|
.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(),
|
fileSize: p.integer("file_size").notNull(),
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ import {
|
|||||||
BadRequestException,
|
BadRequestException,
|
||||||
Controller,
|
Controller,
|
||||||
DefaultValuePipe,
|
DefaultValuePipe,
|
||||||
|
Delete,
|
||||||
Get,
|
Get,
|
||||||
HttpCode,
|
HttpCode,
|
||||||
HttpStatus,
|
HttpStatus,
|
||||||
@ -17,7 +18,7 @@ import {
|
|||||||
StreamableFile,
|
StreamableFile,
|
||||||
UseGuards,
|
UseGuards,
|
||||||
} from "@nestjs/common";
|
} from "@nestjs/common";
|
||||||
import { InsertAdminState } from "../auth/auth.guard";
|
import { AdminGuard, InsertAdminState } from "../auth/auth.guard";
|
||||||
import { FilesService } from "./files.service";
|
import { FilesService } from "./files.service";
|
||||||
|
|
||||||
@Controller("files")
|
@Controller("files")
|
||||||
@ -121,4 +122,11 @@ export class FilesController {
|
|||||||
async getFile(@Param("fileId") fileId: string) {
|
async getFile(@Param("fileId") fileId: string) {
|
||||||
return await this.filesService.get(fileId);
|
return await this.filesService.get(fileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UseGuards(AdminGuard)
|
||||||
|
@HttpCode(HttpStatus.OK)
|
||||||
|
@Delete(":fileId")
|
||||||
|
async deleteFile(@Param("fileId") fileId: string) {
|
||||||
|
return await this.filesService.deleteFile(fileId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,54 @@ export class FilesService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<void>} 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
|
||||||
|
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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches for files in the database using the specified search field, limit, and offset.
|
* Searches for files in the database using the specified search field, limit, and offset.
|
||||||
*
|
*
|
||||||
@ -172,13 +220,14 @@ export class FilesService {
|
|||||||
})
|
})
|
||||||
.returning();
|
.returning();
|
||||||
if (groupExists[0].uuid) {
|
if (groupExists[0].uuid) {
|
||||||
await this.database.use()
|
await this.database
|
||||||
|
.use()
|
||||||
.update(FilesTable)
|
.update(FilesTable)
|
||||||
// @ts-ignore TODO FIX
|
// @ts-ignore TODO FIX
|
||||||
.set({groupId: groupExists[0].uuid})
|
.set({ groupId: groupExists[0].uuid })
|
||||||
.where(eq(FilesTable.uuid, inserted[0].uuid))
|
.where(eq(FilesTable.uuid, inserted[0].uuid))
|
||||||
.prepare("addGroupToFile")
|
.prepare("addGroupToFile")
|
||||||
.execute()
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(inserted);
|
console.log(inserted);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import * as console from "node:console";
|
import * as console from "node:console";
|
||||||
import * as crypto from "node:crypto";
|
import * as crypto from "node:crypto";
|
||||||
import { readFile, writeFile } from "node:fs/promises";
|
import { readFile, rm, writeFile } from "node:fs/promises";
|
||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
import {
|
import {
|
||||||
BadRequestException,
|
BadRequestException,
|
||||||
@ -59,11 +59,16 @@ export class StorageService {
|
|||||||
* @param {string} currentMime - The MIME type to check for presence in all sets.
|
* @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.
|
* @return {boolean} Returns true if the MIME type is found in all sets, otherwise false.
|
||||||
*/
|
*/
|
||||||
function checkMime(mimesForMachines: Map<string, Set<string>>, currentMime: string): boolean {
|
function checkMime(
|
||||||
|
mimesForMachines: Map<string, Set<string>>,
|
||||||
|
currentMime: string,
|
||||||
|
): boolean {
|
||||||
let notFoundCount = 0;
|
let notFoundCount = 0;
|
||||||
for (const mimesForMachine of mimesForMachines) {
|
for (const mimesForMachine of mimesForMachines) {
|
||||||
const [key, set] = mimesForMachine
|
const [key, set] = mimesForMachine;
|
||||||
if (!set.has(currentMime)) {notFoundCount++}
|
if (!set.has(currentMime)) {
|
||||||
|
notFoundCount++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return notFoundCount === 0;
|
return notFoundCount === 0;
|
||||||
}
|
}
|
||||||
@ -73,7 +78,10 @@ export class StorageService {
|
|||||||
// Array of MIMEs with possible duplicate field
|
// Array of MIMEs with possible duplicate field
|
||||||
const _mimes: Array<string> = [];
|
const _mimes: Array<string> = [];
|
||||||
|
|
||||||
const machinesMap: Map<string, Set<string>> = new Map<string, Set<string>>()
|
const machinesMap: Map<string, Set<string>> = new Map<
|
||||||
|
string,
|
||||||
|
Set<string>
|
||||||
|
>();
|
||||||
// Fetching MIMEs for the associated machines
|
// Fetching MIMEs for the associated machines
|
||||||
for (const machineId of machineIds) {
|
for (const machineId of machineIds) {
|
||||||
console.debug(`Fetching mimeTypes for machine : ${machineId}`);
|
console.debug(`Fetching mimeTypes for machine : ${machineId}`);
|
||||||
@ -97,12 +105,12 @@ export class StorageService {
|
|||||||
);
|
);
|
||||||
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)
|
tempSet.add(allowedMimeElement.slug);
|
||||||
}
|
}
|
||||||
machinesMap.set(machineId, tempSet)
|
machinesMap.set(machineId, tempSet);
|
||||||
tempSet.clear()
|
tempSet.clear();
|
||||||
}
|
}
|
||||||
//Store the MIMEs without duplicate
|
//Store the MIMEs without duplicate
|
||||||
const mimeSet = new Set(_mimes);
|
const mimeSet = new Set(_mimes);
|
||||||
@ -263,4 +271,29 @@ export class StorageService {
|
|||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a file from the storage.
|
||||||
|
*
|
||||||
|
* @param {string} checksum - The checksum of the file to delete.
|
||||||
|
* @param {string} extension - The extension of the file to delete.
|
||||||
|
* @param {boolean} isDocumentation - A flag indicating whether the file is a documentation file.
|
||||||
|
* @return {Promise<void>} A promise that resolves when the file is successfully deleted.
|
||||||
|
* @throws {NotFoundException} Throws an exception if the file cannot be found.
|
||||||
|
*/
|
||||||
|
public async delete(
|
||||||
|
checksum: string,
|
||||||
|
extension: string,
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user