Compare commits

..

No commits in common. "4547a22f5cad127181e173a9e196411d77589d34" and "2f0c2f8b7ceb3bb4f5dc28acfb5526d912707f93" have entirely different histories.

13 changed files with 37 additions and 103 deletions

View File

@ -1,10 +1,8 @@
import { Controller, Get } from "@nestjs/common"; import { Controller, Get } from "@nestjs/common";
import { AppService } from "./app.service"; import { AppService } from "./app.service";
import { ApiTags } from '@nestjs/swagger';
@Controller() @Controller()
@ApiTags("useless")
export class AppController { export class AppController {
constructor(private readonly appService: AppService) {} constructor(private readonly appService: AppService) {}

View File

@ -13,9 +13,7 @@ import {
import { SignInDto, SignUpDto } from "apps/backend/src/app/auth/auth.dto"; import { SignInDto, SignUpDto } from "apps/backend/src/app/auth/auth.dto";
import { AuthService } from "apps/backend/src/app/auth/auth.service"; import { AuthService } from "apps/backend/src/app/auth/auth.service";
import { UserGuard } from "./auth.guard"; import { UserGuard } from "./auth.guard";
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
@ApiTags('User authentification')
@Controller("auth") @Controller("auth")
export class AuthController { export class AuthController {
constructor(private readonly authService: AuthService) {} constructor(private readonly authService: AuthService) {}
@ -35,7 +33,6 @@ export class AuthController {
return this.authService.doLogin(dto); return this.authService.doLogin(dto);
} }
//GET me -- Get current user data via jwt //GET me -- Get current user data via jwt
@ApiBearerAuth()
@HttpCode(HttpStatus.OK) @HttpCode(HttpStatus.OK)
@Get("me") @Get("me")
@UseGuards(UserGuard) @UseGuards(UserGuard)
@ -49,7 +46,6 @@ export class AuthController {
return userData; return userData;
} }
//DELETE me //DELETE me
@ApiBearerAuth()
@HttpCode(HttpStatus.FOUND) @HttpCode(HttpStatus.FOUND)
@Delete("me") @Delete("me")
@UseGuards(UserGuard) @UseGuards(UserGuard)

View File

@ -6,7 +6,6 @@ import {
MaxLength, MaxLength,
MinLength, MinLength,
} from "class-validator"; } from "class-validator";
import { ApiProperty } from '@nestjs/swagger';
export class SignUpDto { export class SignUpDto {
/* /*
@ -23,17 +22,11 @@ export class SignUpDto {
lastName: string; lastName: string;
**/ **/
@ApiProperty({
example: 'jean@paul.fr',
})
@MaxLength(32) @MaxLength(32)
@IsEmail() @IsEmail()
@IsNotEmpty() @IsNotEmpty()
email: string; email: string;
@ApiProperty({
example: 'zSEs-6ze$',
})
@IsString() @IsString()
@IsNotEmpty() @IsNotEmpty()
@IsStrongPassword({ @IsStrongPassword({
@ -43,16 +36,12 @@ export class SignUpDto {
} }
export class SignInDto { export class SignInDto {
@MaxLength(32)@ApiProperty({ @MaxLength(32)
example: 'jean@paul.fr',
})
@IsEmail() @IsEmail()
@IsNotEmpty() @IsNotEmpty()
email: string; email: string;
@IsString()@ApiProperty({ @IsString()
example: 'zSEs-6ze$',
})
@IsNotEmpty() @IsNotEmpty()
@IsStrongPassword({ @IsStrongPassword({
minLength: 6, minLength: 6,

View File

@ -11,9 +11,7 @@ import {
} from "@nestjs/common"; } from "@nestjs/common";
import { AdminGuard } from "apps/backend/src/app/auth/auth.guard"; import { AdminGuard } from "apps/backend/src/app/auth/auth.guard";
import { AuthorsService } from "apps/backend/src/app/authors/authors.service"; import { AuthorsService } from "apps/backend/src/app/authors/authors.service";
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
@ApiTags('File authors')
@Controller("authors") @Controller("authors")
export class AuthorsController { export class AuthorsController {
constructor(private readonly authorService: AuthorsService) {} constructor(private readonly authorService: AuthorsService) {}
@ -27,8 +25,8 @@ export class AuthorsController {
return await this.authorService.find(limit, offset, search); return await this.authorService.find(limit, offset, search);
} }
//TODO Refactor //TODO DTO
@ApiBearerAuth()
@UseGuards(AdminGuard) @UseGuards(AdminGuard)
@Delete(":autor") @Delete(":autor")
async deleteAuthor(@Param("author") author: string) { async deleteAuthor(@Param("author") author: string) {

View File

@ -103,7 +103,7 @@ export const FilesTable = pgTable("files", {
}) })
.notNull(), .notNull(),
}); });
export type IFileTable = typeof FilesTable.$inferSelect; export type IFileTable = typeof FilesTable.$inferSelect
export const FilesGroupTable = pgTable("f_groups", { export const FilesGroupTable = pgTable("f_groups", {
uuid: p.uuid("uuid").unique().primaryKey().defaultRandom().notNull(), uuid: p.uuid("uuid").unique().primaryKey().defaultRandom().notNull(),
@ -115,7 +115,8 @@ export const FilesGroupTable = pgTable("f_groups", {
.unique() .unique()
.notNull(), .notNull(),
}); });
export type IFileGroupTable = typeof FilesGroupTable.$inferSelect; export type IFileGroupTable = typeof FilesGroupTable.$inferSelect
//TODO Files types //TODO Files types
export const FilesTypesTable = pgTable("f_types", { export const FilesTypesTable = pgTable("f_types", {
@ -136,7 +137,7 @@ export const FilesTypesTable = pgTable("f_types", {
.unique() .unique()
.notNull(), .notNull(),
}); });
export type IFilesTypesTable = typeof FilesTypesTable.$inferSelect; export type IFilesTypesTable = typeof FilesTypesTable.$inferSelect
export const MachinesTable = pgTable("machines", { export const MachinesTable = pgTable("machines", {
id: p.uuid("id").unique().primaryKey().defaultRandom().notNull(), id: p.uuid("id").unique().primaryKey().defaultRandom().notNull(),
@ -155,7 +156,7 @@ export const MachinesTable = pgTable("machines", {
//supported files format //supported files format
}); });
export type IMachinesTable = typeof MachinesTable.$inferSelect; export type IMachinesTable = typeof MachinesTable.$inferSelect
//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", {
@ -171,7 +172,7 @@ export const FilesForMachinesTable = pgTable("files_for_machines", {
.notNull() .notNull()
.references(() => MachinesTable.id), .references(() => MachinesTable.id),
}); });
export type IFilesForMachinesTable = typeof FilesForMachinesTable.$inferSelect; export type IFilesForMachinesTable = typeof FilesForMachinesTable.$inferSelect
export const FilesTypeForMachine = pgTable("f_type_for_machines", { export const FilesTypeForMachine = pgTable("f_type_for_machines", {
id: p.uuid("id").unique().primaryKey().defaultRandom().notNull(), id: p.uuid("id").unique().primaryKey().defaultRandom().notNull(),
@ -185,11 +186,11 @@ export const FilesTypeForMachine = pgTable("f_type_for_machines", {
.notNull() .notNull()
.references(() => FilesTypesTable.id), .references(() => FilesTypesTable.id),
}); });
export type IFilesTypeForMachine = typeof FilesTypeForMachine.$inferSelect; export type IFilesTypeForMachine = typeof FilesTypeForMachine.$inferSelect
export interface IWithCount<T> { export interface IWithCount<T> {
count: number; count: number;
limit: number; limit: number;
currentOffset: number; currentOffset: number;
data: T[]; data: T
} }

View File

@ -23,9 +23,7 @@ import {
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";
import { FilesService } from "./files.service"; import { FilesService } from "./files.service";
import { ApiBearerAuth, ApiSecurity, ApiTags } from '@nestjs/swagger';
@ApiTags('Files')
@Controller("files") @Controller("files")
export class FilesController { export class FilesController {
constructor(private readonly filesService: FilesService) {} constructor(private readonly filesService: FilesService) {}
@ -131,7 +129,6 @@ export class FilesController {
return await this.filesService.getAllFilesTypes(); return await this.filesService.getAllFilesTypes();
} }
@ApiBearerAuth()
@HttpCode(HttpStatus.CREATED) @HttpCode(HttpStatus.CREATED)
@UseGuards(AdminGuard) @UseGuards(AdminGuard)
@Post("types/new") @Post("types/new")
@ -139,7 +136,6 @@ export class FilesController {
return await this.filesService.createFileType(body.name, body.mime); return await this.filesService.createFileType(body.name, body.mime);
} }
@ApiBearerAuth()
@HttpCode(HttpStatus.ACCEPTED) @HttpCode(HttpStatus.ACCEPTED)
@UseGuards(AdminGuard) @UseGuards(AdminGuard)
@Delete("types/:typeId") @Delete("types/:typeId")
@ -153,7 +149,6 @@ export class FilesController {
return await this.filesService.get(fileId); return await this.filesService.get(fileId);
} }
@ApiBearerAuth()
@HttpCode(HttpStatus.OK) @HttpCode(HttpStatus.OK)
@UseGuards(AdminGuard) @UseGuards(AdminGuard)
@Delete(":fileId") @Delete(":fileId")

View File

@ -1,26 +1,27 @@
import { DefaultValuePipe } from "@nestjs/common"; import { DefaultValuePipe } from "@nestjs/common";
import { IsUUID, MaxLength, MinLength } from "class-validator"; import { IsUUID, MaxLength, MinLength } from "class-validator";
import { ApiBearerAuth, ApiProperty } from '@nestjs/swagger';
export class CreateFilesDto {
@MaxLength(128)
@MinLength(4)
fileName: string;
@MaxLength(64)
@MinLength(2)
uploadedBy: string;
isDocumentation?: boolean;
isRestricted?: boolean;
@IsUUID()
groupId: string;
}
export class CreateFileTypeDto { export class CreateFileTypeDto {
@ApiProperty({
description: "Admin uniquement, nom d'affichage.",
examples: [
".scad",
"jpg"
]
})
@MaxLength(128) @MaxLength(128)
@MinLength(3) @MinLength(3)
name: string; name: string;
@ApiProperty({
description: "Admin uniquement, Multipurpose Internet Mail Extensions (MIME)",
examples: [
"application/x-openscad",
"image/jpeg"
]
})
@MaxLength(64) @MaxLength(64)
@MinLength(4) @MinLength(4)
mime: string; mime: string;

View File

@ -12,12 +12,10 @@ import {
FilesTable, FilesTable,
FilesTypeForMachine, FilesTypeForMachine,
FilesTypesTable, FilesTypesTable,
IFileTable,
IWithCount,
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 { count, eq, ilike } from "drizzle-orm"; import { eq, ilike } from "drizzle-orm";
@Injectable() @Injectable()
export class FilesService { export class FilesService {
@ -126,27 +124,17 @@ export class FilesService {
} }
/** /**
* Searches for files in the database based on the provided search field, limit, and offset. * Searches for files in the database using the specified search field, limit, and offset.
* *
* @param {number} limit - The maximum number of results to return. * @param {number} limit - The maximum number of results to return.
* @param {number} offset - The offset for the results. * @param {number} offset - The number of results to skip before starting to return results.
* @param {string} searchField - The value to search for within the file names. * @param {string} searchField - The field used to search for matching file names.
* @return {Promise<IWithCount<IFileTable>>} A promise that resolves to an object containing the count of files that match the search criteria, the provided limit, the current offset, and the matching data. *
* @return {Promise<object>} A promise that resolves to the search results.
*/ */
public async search( public async search(limit: number, offset: number, searchField: string) {
limit: number,
offset: number,
searchField: string,
): Promise<IWithCount<IFileTable>> {
try { try {
const countResult = await this.database return await this.database
.use()
.select({ count: count() })
.from(FilesTable)
.where(ilike(FilesTable.fileName, String(`%${searchField}%`)))
.prepare("searchFilesCount")
.execute();
const dataResult = await this.database
.use() .use()
.select() .select()
.from(FilesTable) .from(FilesTable)
@ -155,12 +143,6 @@ export class FilesService {
.offset(offset) .offset(offset)
.prepare("searchFiles") .prepare("searchFiles")
.execute(); .execute();
return {
count: countResult[0].count,
limit: limit,
currentOffset: offset,
data: dataResult,
};
} catch (error) { } catch (error) {
throw new InternalServerErrorException(error); throw new InternalServerErrorException(error);
} }

View File

@ -14,9 +14,7 @@ import { AdminGuard } from "apps/backend/src/app/auth/auth.guard";
import { CreateGroupDto } from "apps/backend/src/app/groups/groups.dto"; import { CreateGroupDto } from "apps/backend/src/app/groups/groups.dto";
import { ISearchQuery } from "apps/backend/src/app/groups/groups.types"; import { ISearchQuery } from "apps/backend/src/app/groups/groups.types";
import { GroupsService } from "./groups.service"; import { GroupsService } from "./groups.service";
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
@ApiTags('File groups')
@Controller("groups") @Controller("groups")
export class GroupsController { export class GroupsController {
constructor(private readonly groupsService: GroupsService) {} constructor(private readonly groupsService: GroupsService) {}
@ -35,7 +33,6 @@ export class GroupsController {
return await this.groupsService.newGroup(body.groupName); return await this.groupsService.newGroup(body.groupName);
} }
@ApiBearerAuth()
@UseGuards(AdminGuard) @UseGuards(AdminGuard)
@Delete(":groupId") @Delete(":groupId")
async deleteGroup(@Param("groupId") groupId: string) { async deleteGroup(@Param("groupId") groupId: string) {

View File

@ -1,11 +1,6 @@
import { IsString, MaxLength, MinLength } from "class-validator"; import { IsString, MaxLength, MinLength } from "class-validator";
import { ApiProperty } from '@nestjs/swagger';
export class CreateGroupDto { export class CreateGroupDto {
@ApiProperty({
description: "Nom unique.",
example: "Numérique en communs"
})
@IsString() @IsString()
@MinLength(4) @MinLength(4)
@MaxLength(64) @MaxLength(64)

View File

@ -19,9 +19,7 @@ import {
TypeDto, TypeDto,
} from "apps/backend/src/app/machines/machines.dto"; } from "apps/backend/src/app/machines/machines.dto";
import { MachinesService } from "apps/backend/src/app/machines/machines.service"; import { MachinesService } from "apps/backend/src/app/machines/machines.service";
import { ApiTags } from '@nestjs/swagger';
@ApiTags('Machines')
@Controller("machines") @Controller("machines")
export class MachinesController { export class MachinesController {
constructor(private readonly machineService: MachinesService) {} constructor(private readonly machineService: MachinesService) {}

View File

@ -1,27 +1,16 @@
import { IsUUID, MaxLength, MinLength } from "class-validator"; import { IsUUID, MaxLength, MinLength } from "class-validator";
import { ApiProperty } from '@nestjs/swagger';
export class CreateMachineDto { export class CreateMachineDto {
@ApiProperty({
example: "Découpeuse laser portable"
})
@MaxLength(128) @MaxLength(128)
@MinLength(4) @MinLength(4)
machineName: string; machineName: string;
@ApiProperty({
example: "Découpe au laser"
})
@MaxLength(64) @MaxLength(64)
@MinLength(2) @MinLength(2)
machineType: string; machineType: string;
} }
export class TypeDto { export class TypeDto {
@ApiProperty({
description: "Un identifiant unique présent en base de donnée qui représente un MIME",
example: "dfd0fbb1-2bf3-4dbe-b86d-89b1bff5106c"
})
@IsUUID() @IsUUID()
fileTypeId: string; fileTypeId: string;
} }

View File

@ -10,11 +10,6 @@ async function bootstrap() {
.setTitle("Fab Explorer") .setTitle("Fab Explorer")
.setDescription("Définition de l'api du FabLab Explorer") .setDescription("Définition de l'api du FabLab Explorer")
.setVersion("1.0") .setVersion("1.0")
.addBearerAuth({
type: 'http',
scheme: 'bearer',
in: 'header',
})
.build(); .build();
const app = await NestFactory.create(AppModule); const app = await NestFactory.create(AppModule);