From fd8ad47cf74b809d8185231c705ec8caf611df7b Mon Sep 17 00:00:00 2001 From: Mathis Date: Mon, 30 Sep 2024 08:46:45 +0200 Subject: [PATCH] Standardize code formatting for consistency Update all NestJS imports to use double quotes instead of single quotes across multiple files. Adjusted indentation in various files to ensure uniform code style. These changes improve code readability and maintainability. --- .../src/app/admin/admin.controller.spec.ts | 30 +- .../backend/src/app/admin/admin.controller.ts | 8 +- apps/backend/src/app/admin/admin.module.ts | 10 +- .../src/app/admin/admin.service.spec.ts | 26 +- apps/backend/src/app/admin/admin.service.ts | 2 +- apps/backend/src/app/app.module.ts | 68 ++-- apps/backend/src/app/auth/auth.controller.ts | 109 +++---- apps/backend/src/app/auth/auth.dto.ts | 58 ++-- apps/backend/src/app/auth/auth.guard.ts | 126 ++++---- apps/backend/src/app/auth/auth.module.ts | 14 +- apps/backend/src/app/auth/auth.service.ts | 241 +++++++------- .../app/authors/authors.controller.spec.ts | 30 +- .../src/app/authors/authors.controller.ts | 71 +++-- .../backend/src/app/authors/authors.module.ts | 10 +- .../src/app/authors/authors.service.spec.ts | 26 +- .../src/app/authors/authors.service.ts | 2 +- .../src/app/credentials/credentials.module.ts | 6 +- .../app/credentials/credentials.service.ts | 88 +++--- apps/backend/src/app/db/schema.ts | 26 +- .../src/app/files/files.controller.spec.ts | 30 +- .../backend/src/app/files/files.controller.ts | 8 +- apps/backend/src/app/files/files.module.ts | 10 +- .../src/app/files/files.service.spec.ts | 26 +- apps/backend/src/app/files/files.service.ts | 2 +- apps/backend/src/app/global.dto.ts | 0 .../src/app/groups/groups.controller.spec.ts | 30 +- .../src/app/groups/groups.controller.ts | 75 ++--- apps/backend/src/app/groups/groups.module.ts | 10 +- .../src/app/groups/groups.service.spec.ts | 26 +- apps/backend/src/app/groups/groups.service.ts | 2 +- apps/backend/src/app/groups/groups.types.ts | 8 +- .../app/machines/machines.controller.spec.ts | 30 +- .../src/app/machines/machines.controller.ts | 65 ++-- .../src/app/machines/machines.module.ts | 10 +- .../src/app/machines/machines.service.spec.ts | 26 +- .../src/app/machines/machines.service.ts | 2 +- .../backend/src/app/storage/storage.module.ts | 2 +- .../src/app/storage/storage.service.ts | 125 +++++--- apps/backend/src/app/storage/storage.types.ts | 23 +- apps/frontend/src/components/ui/use-toast.ts | 293 +++++++++--------- apps/frontend/src/lib/utils.ts | 6 +- 41 files changed, 898 insertions(+), 862 deletions(-) create mode 100644 apps/backend/src/app/global.dto.ts diff --git a/apps/backend/src/app/admin/admin.controller.spec.ts b/apps/backend/src/app/admin/admin.controller.spec.ts index 714d356..550ea86 100644 --- a/apps/backend/src/app/admin/admin.controller.spec.ts +++ b/apps/backend/src/app/admin/admin.controller.spec.ts @@ -1,20 +1,20 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AdminController } from './admin.controller'; -import { AdminService } from './admin.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { AdminController } from "./admin.controller"; +import { AdminService } from "./admin.service"; -describe('AdminController', () => { - let controller: AdminController; +describe("AdminController", () => { + let controller: AdminController; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [AdminController], - providers: [AdminService], - }).compile(); + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [AdminController], + providers: [AdminService], + }).compile(); - controller = module.get(AdminController); - }); + controller = module.get(AdminController); + }); - it('should be defined', () => { - expect(controller).toBeDefined(); - }); + it("should be defined", () => { + expect(controller).toBeDefined(); + }); }); diff --git a/apps/backend/src/app/admin/admin.controller.ts b/apps/backend/src/app/admin/admin.controller.ts index 70a9d11..faf55d0 100644 --- a/apps/backend/src/app/admin/admin.controller.ts +++ b/apps/backend/src/app/admin/admin.controller.ts @@ -1,7 +1,7 @@ -import { Controller } from '@nestjs/common'; -import { AdminService } from './admin.service'; +import { Controller } from "@nestjs/common"; +import { AdminService } from "./admin.service"; -@Controller('admin') +@Controller("admin") export class AdminController { - constructor(private readonly adminService: AdminService) {} + constructor(private readonly adminService: AdminService) {} } diff --git a/apps/backend/src/app/admin/admin.module.ts b/apps/backend/src/app/admin/admin.module.ts index 2926ee8..6d1a040 100644 --- a/apps/backend/src/app/admin/admin.module.ts +++ b/apps/backend/src/app/admin/admin.module.ts @@ -1,9 +1,9 @@ -import { Module } from '@nestjs/common'; -import { AdminService } from './admin.service'; -import { AdminController } from './admin.controller'; +import { Module } from "@nestjs/common"; +import { AdminController } from "./admin.controller"; +import { AdminService } from "./admin.service"; @Module({ - controllers: [AdminController], - providers: [AdminService], + controllers: [AdminController], + providers: [AdminService], }) export class AdminModule {} diff --git a/apps/backend/src/app/admin/admin.service.spec.ts b/apps/backend/src/app/admin/admin.service.spec.ts index 5e5e153..3d0ea1d 100644 --- a/apps/backend/src/app/admin/admin.service.spec.ts +++ b/apps/backend/src/app/admin/admin.service.spec.ts @@ -1,18 +1,18 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AdminService } from './admin.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { AdminService } from "./admin.service"; -describe('AdminService', () => { - let service: AdminService; +describe("AdminService", () => { + let service: AdminService; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [AdminService], - }).compile(); + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [AdminService], + }).compile(); - service = module.get(AdminService); - }); + service = module.get(AdminService); + }); - it('should be defined', () => { - expect(service).toBeDefined(); - }); + it("should be defined", () => { + expect(service).toBeDefined(); + }); }); diff --git a/apps/backend/src/app/admin/admin.service.ts b/apps/backend/src/app/admin/admin.service.ts index 796f9fd..c63a8cd 100644 --- a/apps/backend/src/app/admin/admin.service.ts +++ b/apps/backend/src/app/admin/admin.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable } from "@nestjs/common"; @Injectable() export class AdminService {} diff --git a/apps/backend/src/app/app.module.ts b/apps/backend/src/app/app.module.ts index 055aaac..73f434a 100644 --- a/apps/backend/src/app/app.module.ts +++ b/apps/backend/src/app/app.module.ts @@ -1,39 +1,39 @@ -import { Module } from '@nestjs/common'; +import { Module } from "@nestjs/common"; -import { AppController } from './app.controller'; -import { AppService } from './app.service'; -import { DbModule } from './db/db.module'; -import { ThrottlerModule } from '@nestjs/throttler'; -import { ConfigModule } from '@nestjs/config'; -import { AuthModule } from './auth/auth.module'; -import { CredentialsModule } from './credentials/credentials.module'; -import { FilesModule } from './files/files.module'; -import { AdminModule } from './admin/admin.module'; -import { GroupsModule } from './groups/groups.module'; -import { MachinesModule } from './machines/machines.module'; -import { AuthorsModule } from 'apps/backend/src/app/authors/authors.module'; +import { ConfigModule } from "@nestjs/config"; +import { ThrottlerModule } from "@nestjs/throttler"; +import { AuthorsModule } from "apps/backend/src/app/authors/authors.module"; +import { AdminModule } from "./admin/admin.module"; +import { AppController } from "./app.controller"; +import { AppService } from "./app.service"; +import { AuthModule } from "./auth/auth.module"; +import { CredentialsModule } from "./credentials/credentials.module"; +import { DbModule } from "./db/db.module"; +import { FilesModule } from "./files/files.module"; +import { GroupsModule } from "./groups/groups.module"; +import { MachinesModule } from "./machines/machines.module"; @Module({ - imports: [ - ThrottlerModule.forRoot([ - { - ttl: 60000, - limit: 10, - }, - ]), - ConfigModule.forRoot({ - isGlobal: true, - }), - DbModule, - AuthModule, - CredentialsModule, - FilesModule, - AdminModule, - GroupsModule, - MachinesModule, - AuthorsModule, - ], - controllers: [AppController], - providers: [AppService], + imports: [ + ThrottlerModule.forRoot([ + { + ttl: 60000, + limit: 10, + }, + ]), + ConfigModule.forRoot({ + isGlobal: true, + }), + DbModule, + AuthModule, + CredentialsModule, + FilesModule, + AdminModule, + GroupsModule, + MachinesModule, + AuthorsModule, + ], + controllers: [AppController], + providers: [AppService], }) export class AppModule {} diff --git a/apps/backend/src/app/auth/auth.controller.ts b/apps/backend/src/app/auth/auth.controller.ts index 9ee7454..1de69e6 100644 --- a/apps/backend/src/app/auth/auth.controller.ts +++ b/apps/backend/src/app/auth/auth.controller.ts @@ -1,66 +1,67 @@ import { - Body, - Controller, - Delete, - Get, - HttpCode, - HttpStatus, Patch, - Post, - UnauthorizedException, - UseGuards + Body, + Controller, + Delete, + Get, + HttpCode, + HttpStatus, + Patch, + Post, + UnauthorizedException, + UseGuards, } from "@nestjs/common"; +import { SignInDto, SignUpDto } from "apps/backend/src/app/auth/auth.dto"; +import { AuthService } from "apps/backend/src/app/auth/auth.service"; import { UserGuard } from "./auth.guard"; -import { AuthService } from 'apps/backend/src/app/auth/auth.service'; -import { SignInDto, SignUpDto } from 'apps/backend/src/app/auth/auth.dto'; @Controller("auth") export class AuthController { - constructor(private readonly authService: AuthService) { } + constructor(private readonly authService: AuthService) {} - //TODO Initial account validation for admin privileges - //POST signup - @HttpCode(HttpStatus.CREATED) - @Post("signup") - async signUp(@Body() dto: SignUpDto) { - console.log(dto); - return this.authService.doRegister(dto); - } + //TODO Initial account validation for admin privileges + //POST signup + @HttpCode(HttpStatus.CREATED) + @Post("signup") + async signUp(@Body() dto: SignUpDto) { + console.log(dto); + return this.authService.doRegister(dto); + } - //POST signin - @HttpCode(HttpStatus.OK) - @Post("signin") - async signIn(@Body() dto: SignInDto) { - console.log(dto); - return this.authService.doLogin(dto); - } - //GET me -- Get current user data via jwt - @HttpCode(HttpStatus.OK) - @Get("me") - @UseGuards(UserGuard) - async getMe(@Body() body: object) { - // @ts-ignore - const targetId = body.sourceUserId - const userData = await this.authService.fetchUserById(targetId) - if (!userData) { - throw new UnauthorizedException(); - } - return userData; - } - //DELETE me - @HttpCode(HttpStatus.FOUND) - @Delete("me") - @UseGuards(UserGuard) - async deleteMe(@Body() body: object) { - // @ts-ignore - const targetId = body.sourceUserId - try { - await this.authService.deleteUser(targetId) - } catch (err) { - throw new UnauthorizedException(); - } - } + //POST signin + @HttpCode(HttpStatus.OK) + @Post("signin") + async signIn(@Body() dto: SignInDto) { + console.log(dto); + return this.authService.doLogin(dto); + } + //GET me -- Get current user data via jwt + @HttpCode(HttpStatus.OK) + @Get("me") + @UseGuards(UserGuard) + async getMe(@Body() body: object) { + // @ts-ignore + const targetId = body.sourceUserId; + const userData = await this.authService.fetchUserById(targetId); + if (!userData) { + throw new UnauthorizedException(); + } + return userData; + } + //DELETE me + @HttpCode(HttpStatus.FOUND) + @Delete("me") + @UseGuards(UserGuard) + async deleteMe(@Body() body: object) { + // @ts-ignore + const targetId = body.sourceUserId; + try { + await this.authService.deleteUser(targetId); + } catch (err) { + throw new UnauthorizedException(); + } + } - /* + /* //PATCH me @HttpCode(HttpStatus.OK) @Patch("me") diff --git a/apps/backend/src/app/auth/auth.dto.ts b/apps/backend/src/app/auth/auth.dto.ts index 6119775..9dd6daa 100644 --- a/apps/backend/src/app/auth/auth.dto.ts +++ b/apps/backend/src/app/auth/auth.dto.ts @@ -1,14 +1,14 @@ import { - IsEmail, - IsNotEmpty, - IsString, - IsStrongPassword, - MaxLength, - MinLength, + IsEmail, + IsNotEmpty, + IsString, + IsStrongPassword, + MaxLength, + MinLength, } from "class-validator"; export class SignUpDto { - /* + /* @MinLength(1) @MaxLength(24) @IsNotEmpty() @@ -22,33 +22,33 @@ export class SignUpDto { lastName: string; **/ - @MaxLength(32) - @IsEmail() - @IsNotEmpty() - email: string; + @MaxLength(32) + @IsEmail() + @IsNotEmpty() + email: string; - @IsString() - @IsNotEmpty() - @IsStrongPassword({ - minLength: 6, - minSymbols: 1, - }) - password: string; + @IsString() + @IsNotEmpty() + @IsStrongPassword({ + minLength: 6, + minSymbols: 1, + }) + password: string; } export class SignInDto { - @MaxLength(32) - @IsEmail() - @IsNotEmpty() - email: string; + @MaxLength(32) + @IsEmail() + @IsNotEmpty() + email: string; - @IsString() - @IsNotEmpty() - @IsStrongPassword({ - minLength: 6, - minSymbols: 1, - }) - password: string; + @IsString() + @IsNotEmpty() + @IsStrongPassword({ + minLength: 6, + minSymbols: 1, + }) + password: string; } /* diff --git a/apps/backend/src/app/auth/auth.guard.ts b/apps/backend/src/app/auth/auth.guard.ts index 53418eb..2cffdb3 100644 --- a/apps/backend/src/app/auth/auth.guard.ts +++ b/apps/backend/src/app/auth/auth.guard.ts @@ -1,87 +1,89 @@ -import { Injectable, CanActivate, ExecutionContext, UnauthorizedException, Inject } from "@nestjs/common"; -import type { Request } from "express"; -import { eq } from "drizzle-orm"; +import { + CanActivate, + ExecutionContext, + Inject, + Injectable, + UnauthorizedException, +} from "@nestjs/common"; import { Reflector } from "@nestjs/core"; -import { DbService } from 'apps/backend/src/app/db/db.service'; -import { UsersTable } from 'apps/backend/src/app/db/schema'; -import { CredentialsService } from 'apps/backend/src/app/credentials/credentials.service'; +import { CredentialsService } from "apps/backend/src/app/credentials/credentials.service"; +import { DbService } from "apps/backend/src/app/db/db.service"; +import { UsersTable } from "apps/backend/src/app/db/schema"; +import { eq } from "drizzle-orm"; +import type { Request } from "express"; @Injectable() export class UserGuard implements CanActivate { + constructor( + @Inject(CredentialsService) + private readonly credentialService: CredentialsService, + @Inject(DbService) private readonly databaseService: DbService, + ) {} - constructor( - @Inject(CredentialsService) private readonly credentialService: CredentialsService, - @Inject(DbService) private readonly databaseService: DbService, - ) { - } + async canActivate(context: ExecutionContext): Promise { + const request: Request = context.switchToHttp().getRequest(); + const authHeader = request.headers.authorization; - async canActivate( - context: ExecutionContext - ): Promise { - const request: Request = context.switchToHttp().getRequest(); - const authHeader = request.headers.authorization; + if (!authHeader) + throw new UnauthorizedException("No authorization header found."); - if (!authHeader) - throw new UnauthorizedException("No authorization header found."); + const token = authHeader.split(" ")[1]; + const vToken = await this.credentialService.verifyAuthToken(token); - const token = authHeader.split(" ")[1]; - const vToken = await this.credentialService.verifyAuthToken(token); + const user = await this.databaseService + .use() + .select() + .from(UsersTable) + .where(eq(UsersTable.uuid, vToken.payload.sub)); - const user = await this.databaseService.use() - .select() - .from(UsersTable) - .where(eq(UsersTable.uuid, vToken.payload.sub)); - - if (user.length !== 1) - throw new UnauthorizedException("No such user found."); - /* + if (user.length !== 1) + throw new UnauthorizedException("No such user found."); + /* if (user[0].emailCode) throw new UnauthorizedException("Email not verified."); */ - // Inject user ID into request body - request.body.sourceUserId = vToken.payload.sub; + // Inject user ID into request body + request.body.sourceUserId = vToken.payload.sub; - return true; - } + return true; + } } @Injectable() export class AdminGuard implements CanActivate { + constructor( + @Inject(CredentialsService) + private readonly credentialService: CredentialsService, + @Inject(DbService) private readonly databaseService: DbService, + ) {} + async canActivate(context: ExecutionContext): Promise { + const request: Request = context.switchToHttp().getRequest(); - constructor( - @Inject(CredentialsService) private readonly credentialService: CredentialsService, - @Inject(DbService) private readonly databaseService: DbService, - ) {} - async canActivate( - context: ExecutionContext - ): Promise { - const request: Request = context.switchToHttp().getRequest(); + const authHeader = request.headers.authorization; + if (!authHeader) { + throw new UnauthorizedException("No authorization header found."); + } + const token = authHeader.split(" ")[1]; + const vToken = await this.credentialService.verifyAuthToken(token); - const authHeader = request.headers.authorization; - if (!authHeader) { - throw new UnauthorizedException("No authorization header found."); + const user = await this.databaseService + .use() + .select() + .from(UsersTable) + .where(eq(UsersTable.uuid, vToken.payload.sub)); - } - const token = authHeader.split(" ")[1]; - const vToken = await this.credentialService.verifyAuthToken(token); + if (user.length !== 1) + throw new UnauthorizedException("No such user found."); - const user = await this.databaseService.use() - .select() - .from(UsersTable) - .where(eq(UsersTable.uuid, vToken.payload.sub)); + if (!user[0].isAdmin) { + throw new UnauthorizedException("Administrator only.."); + } - if (user.length !== 1) - throw new UnauthorizedException("No such user found."); + // Inject user ID into request body + request.body.sourceUserId = vToken.payload.sub; - if (!user[0].isAdmin) { - throw new UnauthorizedException("Administrator only.."); - } - - // Inject user ID into request body - request.body.sourceUserId = vToken.payload.sub; - - return true; - } -} \ No newline at end of file + return true; + } +} diff --git a/apps/backend/src/app/auth/auth.module.ts b/apps/backend/src/app/auth/auth.module.ts index b76747e..8139a75 100644 --- a/apps/backend/src/app/auth/auth.module.ts +++ b/apps/backend/src/app/auth/auth.module.ts @@ -1,14 +1,14 @@ import { Module } from "@nestjs/common"; +import { AdminGuard, UserGuard } from "apps/backend/src/app/auth/auth.guard"; +import { CredentialsModule } from "apps/backend/src/app/credentials/credentials.module"; +import { CredentialsService } from "apps/backend/src/app/credentials/credentials.service"; +import { DbModule } from "apps/backend/src/app/db/db.module"; import { AuthController } from "./auth.controller"; import { AuthService } from "./auth.service"; -import { DbModule } from 'apps/backend/src/app/db/db.module'; -import { CredentialsModule } from 'apps/backend/src/app/credentials/credentials.module'; -import { CredentialsService } from 'apps/backend/src/app/credentials/credentials.service'; -import { AdminGuard, UserGuard } from 'apps/backend/src/app/auth/auth.guard'; @Module({ - imports: [DbModule, CredentialsModule], - providers: [AuthService, CredentialsService, AdminGuard, UserGuard], - controllers: [AuthController], + imports: [DbModule, CredentialsModule], + providers: [AuthService, CredentialsService, AdminGuard, UserGuard], + controllers: [AuthController], }) export class AuthModule {} diff --git a/apps/backend/src/app/auth/auth.service.ts b/apps/backend/src/app/auth/auth.service.ts index 969661f..b307e37 100644 --- a/apps/backend/src/app/auth/auth.service.ts +++ b/apps/backend/src/app/auth/auth.service.ts @@ -1,113 +1,113 @@ import { - Injectable, - OnModuleInit, - UnauthorizedException, + Injectable, + OnModuleInit, + UnauthorizedException, } from "@nestjs/common"; +import { SignInDto, SignUpDto } from "apps/backend/src/app/auth/auth.dto"; +import { CredentialsService } from "apps/backend/src/app/credentials/credentials.service"; +import { DbService } from "apps/backend/src/app/db/db.service"; +import { UsersTable } from "apps/backend/src/app/db/schema"; import { eq } from "drizzle-orm"; -import { DbService } from 'apps/backend/src/app/db/db.service'; -import { CredentialsService } from 'apps/backend/src/app/credentials/credentials.service'; -import { UsersTable } from 'apps/backend/src/app/db/schema'; -import { SignInDto, SignUpDto } from 'apps/backend/src/app/auth/auth.dto'; @Injectable() export class AuthService implements OnModuleInit { - constructor( - private db: DbService, - private credentials: CredentialsService, - ) {} + constructor( + private db: DbService, + private credentials: CredentialsService, + ) {} - //TODO Initial account validation for admin privileges - async doRegister(data: SignUpDto) { - console.log(data); - const existingUser = await this.db - .use() - .select() - .from(UsersTable) - .where(eq(UsersTable.email, data.email)) - .prepare("userByEmail") - .execute(); - if (existingUser.length !== 0) - throw new UnauthorizedException("Already exist"); - const query = await this.db - .use() - .insert(UsersTable) - .values({ - //firstName: data.firstName, - //lastName: data.lastName, - email: data.email, - hash: await this.credentials.hash(data.password), - }) - .returning() - .prepare("insertUser") - .execute() - .catch((err) => { - console.error(err); - throw new UnauthorizedException( - "Error occurred while inserting user", - err, - ); - }); - return { - message: "User created, check your email for validation.", - token: await this.credentials.signAuthToken({ sub: query[0].uuid }), - }; - } + //TODO Initial account validation for admin privileges + async doRegister(data: SignUpDto) { + console.log(data); + const existingUser = await this.db + .use() + .select() + .from(UsersTable) + .where(eq(UsersTable.email, data.email)) + .prepare("userByEmail") + .execute(); + if (existingUser.length !== 0) + throw new UnauthorizedException("Already exist"); + const query = await this.db + .use() + .insert(UsersTable) + .values({ + //firstName: data.firstName, + //lastName: data.lastName, + email: data.email, + hash: await this.credentials.hash(data.password), + }) + .returning() + .prepare("insertUser") + .execute() + .catch((err) => { + console.error(err); + throw new UnauthorizedException( + "Error occurred while inserting user", + err, + ); + }); + return { + message: "User created, check your email for validation.", + token: await this.credentials.signAuthToken({ sub: query[0].uuid }), + }; + } - async doLogin(data: SignInDto) { - const user = await this.db - .use() - .select() - .from(UsersTable) - .where(eq(UsersTable.email, data.email)) - .prepare("userByEmail") - .execute(); - if (user.length !== 1) - throw new UnauthorizedException("Invalid credentials"); - const passwordMatch = await this.credentials.check( - data.password, - user[0].hash, - ); - if (!passwordMatch) throw new UnauthorizedException("Invalid credentials"); - const token = await this.credentials.signAuthToken({ sub: user[0].uuid }); - return { - message: "Login successful", - token: token, - }; - } + async doLogin(data: SignInDto) { + const user = await this.db + .use() + .select() + .from(UsersTable) + .where(eq(UsersTable.email, data.email)) + .prepare("userByEmail") + .execute(); + if (user.length !== 1) + throw new UnauthorizedException("Invalid credentials"); + const passwordMatch = await this.credentials.check( + data.password, + user[0].hash, + ); + if (!passwordMatch) throw new UnauthorizedException("Invalid credentials"); + const token = await this.credentials.signAuthToken({ sub: user[0].uuid }); + return { + message: "Login successful", + token: token, + }; + } - async fetchUserById(userId: string) { - const user = await this.db - .use() - .select() - .from(UsersTable) - .where(eq(UsersTable.uuid, userId)) - .prepare("userById") - .execute(); - if (user.length !== 1) { - throw new UnauthorizedException("User not found"); - } - delete user[0].hash; - //delete user[0].emailCode; - return user[0]; - } + async fetchUserById(userId: string) { + const user = await this.db + .use() + .select() + .from(UsersTable) + .where(eq(UsersTable.uuid, userId)) + .prepare("userById") + .execute(); + if (user.length !== 1) { + throw new UnauthorizedException("User not found"); + } + delete user[0].hash; + //delete user[0].emailCode; + return user[0]; + } - async fetchUsers() { - //TODO Pagination - const usersInDb = await this.db.use().select().from(UsersTable); - const result = { - total: usersInDb.length, - users: usersInDb.map((user) => { - delete user.hash; - return { - ...user, - }; - }), - }; - console.log(result); - return result; - } + async fetchUsers() { + //TODO Pagination + const usersInDb = await this.db.use().select().from(UsersTable); + const result = { + total: usersInDb.length, + users: usersInDb.map((user) => { + delete user.hash; + return { + ...user, + }; + }), + }; + console.log(result); + return result; + } - /* + /* async updateUser(targetId: string, userData: IUserUpdateData) { const validationResult = UserUpdateSchema.safeParse(userData); if (!validationResult.success) { @@ -133,27 +133,26 @@ export class AuthService implements OnModuleInit { } */ - async deleteUser(targetId: string) { - await this.db - .use() - .delete(UsersTable) - .where(eq(UsersTable.uuid, targetId)) - .prepare("deleteUserById") - .execute() - .catch((err) => { - console.error(err); - throw new UnauthorizedException( - "Error occurred while deleting user", - err, - ); - }); - return true; - } + async deleteUser(targetId: string) { + await this.db + .use() + .delete(UsersTable) + .where(eq(UsersTable.uuid, targetId)) + .prepare("deleteUserById") + .execute() + .catch((err) => { + console.error(err); + throw new UnauthorizedException( + "Error occurred while deleting user", + err, + ); + }); + return true; + } - async onModuleInit() { - setTimeout(() => { - this.fetchUsers(); - }, 2000); - } + async onModuleInit() { + setTimeout(() => { + this.fetchUsers(); + }, 2000); + } } - diff --git a/apps/backend/src/app/authors/authors.controller.spec.ts b/apps/backend/src/app/authors/authors.controller.spec.ts index fd4a443..cbc7e2e 100644 --- a/apps/backend/src/app/authors/authors.controller.spec.ts +++ b/apps/backend/src/app/authors/authors.controller.spec.ts @@ -1,20 +1,20 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AuthorsController } from 'apps/backend/src/app/authors/authors.controller'; -import { AuthorsService } from 'apps/backend/src/app/authors/authors.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { AuthorsController } from "apps/backend/src/app/authors/authors.controller"; +import { AuthorsService } from "apps/backend/src/app/authors/authors.service"; -describe('AuthorsController', () => { - let controller: AuthorsController; +describe("AuthorsController", () => { + let controller: AuthorsController; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [AuthorsController], - providers: [AuthorsService], - }).compile(); + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [AuthorsController], + providers: [AuthorsService], + }).compile(); - controller = module.get(AuthorsController); - }); + controller = module.get(AuthorsController); + }); - it('should be defined', () => { - expect(controller).toBeDefined(); - }); + it("should be defined", () => { + expect(controller).toBeDefined(); + }); }); diff --git a/apps/backend/src/app/authors/authors.controller.ts b/apps/backend/src/app/authors/authors.controller.ts index cf222a9..ec80ac9 100644 --- a/apps/backend/src/app/authors/authors.controller.ts +++ b/apps/backend/src/app/authors/authors.controller.ts @@ -1,41 +1,44 @@ -import { Controller, DefaultValuePipe, Delete, Get, Param, ParseIntPipe, Post, Query } from '@nestjs/common'; -import { AuthorsService } from 'apps/backend/src/app/authors/authors.service'; +import { + Controller, + DefaultValuePipe, + Delete, + Get, + Param, + ParseIntPipe, + Post, + Query, +} from "@nestjs/common"; +import { AuthorsService } from "apps/backend/src/app/authors/authors.service"; -@Controller('authors') +@Controller("authors") export class AuthorsController { - constructor(private readonly authorService: AuthorsService) {} + constructor(private readonly authorService: AuthorsService) {} - @Get() - async findMany( - @Query("limit", new DefaultValuePipe(20), ParseIntPipe) limit: number, - @Query("offset", new DefaultValuePipe(0), ParseIntPipe) offset: number, - @Query("search", new DefaultValuePipe("")) search: string - ) { - const query = {limit, offset, search} + @Get() + async findMany( + @Query("limit", new DefaultValuePipe(20), ParseIntPipe) limit: number, + @Query("offset", new DefaultValuePipe(0), ParseIntPipe) offset: number, + @Query("search", new DefaultValuePipe("")) search: string, + ) { + const query = { limit, offset, search }; + } - } + //POST a new group + @Post("new") + async newAuthor() {} - //POST a new group - @Post("new") - async newAuthor() { + //DELETE a group + @Delete(":authorId") + async deleteAuthor(@Param("authorId") authorId: string) {} - } - - //DELETE a group - @Delete(":authorId") - async deleteAuthor(@Param('authorId') authorId: string) { - - } - - //GET files associated to authors with limit and offset - @Get(":authorId") - async getForAuthor( - @Query("limit", new DefaultValuePipe(20), ParseIntPipe) limit: number, - @Query("offset", new DefaultValuePipe(0), ParseIntPipe) offset: number, - @Query("search", new DefaultValuePipe("")) search: string, - @Param('authorId') authorId: string - ) { - const query = {limit, offset, search} - - } + //GET files associated to authors with limit and offset + @Get(":authorId") + async getForAuthor( + @Query("limit", new DefaultValuePipe(20), ParseIntPipe) limit: number, + @Query("offset", new DefaultValuePipe(0), ParseIntPipe) offset: number, + @Query("search", new DefaultValuePipe("")) search: string, + @Param("authorId") authorId: string, + ) { + const query = { limit, offset, search }; + } } diff --git a/apps/backend/src/app/authors/authors.module.ts b/apps/backend/src/app/authors/authors.module.ts index f09496e..9482e37 100644 --- a/apps/backend/src/app/authors/authors.module.ts +++ b/apps/backend/src/app/authors/authors.module.ts @@ -1,9 +1,9 @@ -import { Module } from '@nestjs/common'; -import { AuthorsService } from 'apps/backend/src/app/authors/authors.service'; -import { AuthorsController } from 'apps/backend/src/app/authors/authors.controller'; +import { Module } from "@nestjs/common"; +import { AuthorsController } from "apps/backend/src/app/authors/authors.controller"; +import { AuthorsService } from "apps/backend/src/app/authors/authors.service"; @Module({ - controllers: [AuthorsController], - providers: [AuthorsService], + controllers: [AuthorsController], + providers: [AuthorsService], }) export class AuthorsModule {} diff --git a/apps/backend/src/app/authors/authors.service.spec.ts b/apps/backend/src/app/authors/authors.service.spec.ts index 1a19df0..3ee590f 100644 --- a/apps/backend/src/app/authors/authors.service.spec.ts +++ b/apps/backend/src/app/authors/authors.service.spec.ts @@ -1,18 +1,18 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AuthorsService } from 'apps/backend/src/app/authors/authors.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { AuthorsService } from "apps/backend/src/app/authors/authors.service"; -describe('AuthorsService', () => { - let service: AuthorsService; +describe("AuthorsService", () => { + let service: AuthorsService; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [AuthorsService], - }).compile(); + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [AuthorsService], + }).compile(); - service = module.get(AuthorsService); - }); + service = module.get(AuthorsService); + }); - it('should be defined', () => { - expect(service).toBeDefined(); - }); + it("should be defined", () => { + expect(service).toBeDefined(); + }); }); diff --git a/apps/backend/src/app/authors/authors.service.ts b/apps/backend/src/app/authors/authors.service.ts index 4fd5760..dd04e4e 100644 --- a/apps/backend/src/app/authors/authors.service.ts +++ b/apps/backend/src/app/authors/authors.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable } from "@nestjs/common"; @Injectable() export class AuthorsService {} diff --git a/apps/backend/src/app/credentials/credentials.module.ts b/apps/backend/src/app/credentials/credentials.module.ts index 37c4990..589578a 100644 --- a/apps/backend/src/app/credentials/credentials.module.ts +++ b/apps/backend/src/app/credentials/credentials.module.ts @@ -3,8 +3,8 @@ import { ConfigModule } from "@nestjs/config"; import { CredentialsService } from "./credentials.service"; @Module({ - imports: [ConfigModule], - providers: [CredentialsService], - exports: [CredentialsService], + imports: [ConfigModule], + providers: [CredentialsService], + exports: [CredentialsService], }) export class CredentialsModule {} diff --git a/apps/backend/src/app/credentials/credentials.service.ts b/apps/backend/src/app/credentials/credentials.service.ts index 4c679e0..39081dc 100644 --- a/apps/backend/src/app/credentials/credentials.service.ts +++ b/apps/backend/src/app/credentials/credentials.service.ts @@ -6,52 +6,52 @@ import { JWTPayload, generateSecret } from "jose"; @Injectable() export class CredentialsService { - constructor(private readonly configService: ConfigService) {} + constructor(private readonly configService: ConfigService) {} - async hash(plaintextPassword: string) { - console.log(plaintextPassword); - if (plaintextPassword.length < 6) - throw new BadRequestException("Password is not strong enough !"); - return argon.hash(plaintextPassword, { - secret: Buffer.from(this.configService.get("APP_HASH_SECRET")), - }); - } + async hash(plaintextPassword: string) { + console.log(plaintextPassword); + if (plaintextPassword.length < 6) + throw new BadRequestException("Password is not strong enough !"); + return argon.hash(plaintextPassword, { + secret: Buffer.from(this.configService.get("APP_HASH_SECRET")), + }); + } - async check(plaintextPassword: string, hashedPassword: string) { - return argon.verify(hashedPassword, plaintextPassword, { - secret: Buffer.from(this.configService.get("APP_HASH_SECRET")), - }); - } + async check(plaintextPassword: string, hashedPassword: string) { + return argon.verify(hashedPassword, plaintextPassword, { + secret: Buffer.from(this.configService.get("APP_HASH_SECRET")), + }); + } - async verifyAuthToken(token: string) { - try { - const result = await jose.jwtVerify( - token, - Uint8Array.from(this.configService.get("APP_TOKEN_SECRET")), - { - audience: "auth:user", - issuer: "FabLab", - }, - ); - console.log(result); - return result; - } catch (error) { - console.log(error) - throw new BadRequestException("Invalid token"); - } - } + async verifyAuthToken(token: string) { + try { + const result = await jose.jwtVerify( + token, + Uint8Array.from(this.configService.get("APP_TOKEN_SECRET")), + { + audience: "auth:user", + issuer: "FabLab", + }, + ); + console.log(result); + return result; + } catch (error) { + console.log(error); + throw new BadRequestException("Invalid token"); + } + } - async signAuthToken(payload: JWTPayload) { - console.log(this.configService.get("APP_TOKEN_SECRET")); - const token = new jose.SignJWT(payload) - .setProtectedHeader({ alg: "HS512", enc: "A128CBC-HS512" }) - .setIssuedAt() - .setExpirationTime("5 day") - .setIssuer("FabLab") - .setAudience("auth:user"); - console.log(token); - return await token.sign( - Uint8Array.from(this.configService.get("APP_TOKEN_SECRET")), - ); - } + async signAuthToken(payload: JWTPayload) { + console.log(this.configService.get("APP_TOKEN_SECRET")); + const token = new jose.SignJWT(payload) + .setProtectedHeader({ alg: "HS512", enc: "A128CBC-HS512" }) + .setIssuedAt() + .setExpirationTime("5 day") + .setIssuer("FabLab") + .setAudience("auth:user"); + console.log(token); + return await token.sign( + Uint8Array.from(this.configService.get("APP_TOKEN_SECRET")), + ); + } } diff --git a/apps/backend/src/app/db/schema.ts b/apps/backend/src/app/db/schema.ts index 8f838cd..33d6f50 100644 --- a/apps/backend/src/app/db/schema.ts +++ b/apps/backend/src/app/db/schema.ts @@ -61,9 +61,11 @@ export const FilesTable = pgTable("files", { }) .notNull(), - checksum: p.varchar("checksum", { - length: 64 - }).notNull(), + checksum: p + .varchar("checksum", { + length: 64, + }) + .notNull(), uploader: p .varchar("uploader", { @@ -71,9 +73,7 @@ export const FilesTable = pgTable("files", { }) .notNull(), - groupId: p - .uuid("group_id") - .references(()=> FilesGroupTable.uuid), + groupId: p.uuid("group_id").references(() => FilesGroupTable.uuid), fileSize: p.integer("file_size").notNull(), @@ -101,15 +101,15 @@ export const FilesTable = pgTable("files", { export const FilesGroupTable = pgTable("f_groups", { // Unique identifier on a technical aspect. - uuid: p.uuid("uuid").unique().primaryKey().defaultRandom().notNull(), + uuid: p.uuid("uuid").unique().primaryKey().defaultRandom().notNull(), - groupName: p - .varchar("group_name", { - length: 64, - }) + groupName: p + .varchar("group_name", { + length: 64, + }) .unique() - .notNull(), -}) + .notNull(), +}); //TODO Files types export const FilesTypesTable = pgTable("f_types", { diff --git a/apps/backend/src/app/files/files.controller.spec.ts b/apps/backend/src/app/files/files.controller.spec.ts index b352a39..97aaa47 100644 --- a/apps/backend/src/app/files/files.controller.spec.ts +++ b/apps/backend/src/app/files/files.controller.spec.ts @@ -1,20 +1,20 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { FilesController } from './files.controller'; -import { FilesService } from './files.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { FilesController } from "./files.controller"; +import { FilesService } from "./files.service"; -describe('FilesController', () => { - let controller: FilesController; +describe("FilesController", () => { + let controller: FilesController; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [FilesController], - providers: [FilesService], - }).compile(); + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [FilesController], + providers: [FilesService], + }).compile(); - controller = module.get(FilesController); - }); + controller = module.get(FilesController); + }); - it('should be defined', () => { - expect(controller).toBeDefined(); - }); + it("should be defined", () => { + expect(controller).toBeDefined(); + }); }); diff --git a/apps/backend/src/app/files/files.controller.ts b/apps/backend/src/app/files/files.controller.ts index 79a5fe4..3f89e02 100644 --- a/apps/backend/src/app/files/files.controller.ts +++ b/apps/backend/src/app/files/files.controller.ts @@ -1,7 +1,7 @@ -import { Controller } from '@nestjs/common'; -import { FilesService } from './files.service'; +import { Controller } from "@nestjs/common"; +import { FilesService } from "./files.service"; -@Controller('files') +@Controller("files") export class FilesController { - constructor(private readonly filesService: FilesService) {} + constructor(private readonly filesService: FilesService) {} } diff --git a/apps/backend/src/app/files/files.module.ts b/apps/backend/src/app/files/files.module.ts index 9b10b69..3689d40 100644 --- a/apps/backend/src/app/files/files.module.ts +++ b/apps/backend/src/app/files/files.module.ts @@ -1,9 +1,9 @@ -import { Module } from '@nestjs/common'; -import { FilesService } from './files.service'; -import { FilesController } from './files.controller'; +import { Module } from "@nestjs/common"; +import { FilesController } from "./files.controller"; +import { FilesService } from "./files.service"; @Module({ - controllers: [FilesController], - providers: [FilesService], + controllers: [FilesController], + providers: [FilesService], }) export class FilesModule {} diff --git a/apps/backend/src/app/files/files.service.spec.ts b/apps/backend/src/app/files/files.service.spec.ts index c653b32..38817b2 100644 --- a/apps/backend/src/app/files/files.service.spec.ts +++ b/apps/backend/src/app/files/files.service.spec.ts @@ -1,18 +1,18 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { FilesService } from './files.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { FilesService } from "./files.service"; -describe('FilesService', () => { - let service: FilesService; +describe("FilesService", () => { + let service: FilesService; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [FilesService], - }).compile(); + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [FilesService], + }).compile(); - service = module.get(FilesService); - }); + service = module.get(FilesService); + }); - it('should be defined', () => { - expect(service).toBeDefined(); - }); + it("should be defined", () => { + expect(service).toBeDefined(); + }); }); diff --git a/apps/backend/src/app/files/files.service.ts b/apps/backend/src/app/files/files.service.ts index ab8a4e6..8075ec8 100644 --- a/apps/backend/src/app/files/files.service.ts +++ b/apps/backend/src/app/files/files.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable } from "@nestjs/common"; @Injectable() export class FilesService {} diff --git a/apps/backend/src/app/global.dto.ts b/apps/backend/src/app/global.dto.ts new file mode 100644 index 0000000..e69de29 diff --git a/apps/backend/src/app/groups/groups.controller.spec.ts b/apps/backend/src/app/groups/groups.controller.spec.ts index 66ef3d4..cbb4687 100644 --- a/apps/backend/src/app/groups/groups.controller.spec.ts +++ b/apps/backend/src/app/groups/groups.controller.spec.ts @@ -1,20 +1,20 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { GroupsController } from './groups.controller'; -import { GroupsService } from './groups.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { GroupsController } from "./groups.controller"; +import { GroupsService } from "./groups.service"; -describe('GroupsController', () => { - let controller: GroupsController; +describe("GroupsController", () => { + let controller: GroupsController; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [GroupsController], - providers: [GroupsService], - }).compile(); + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [GroupsController], + providers: [GroupsService], + }).compile(); - controller = module.get(GroupsController); - }); + controller = module.get(GroupsController); + }); - it('should be defined', () => { - expect(controller).toBeDefined(); - }); + it("should be defined", () => { + expect(controller).toBeDefined(); + }); }); diff --git a/apps/backend/src/app/groups/groups.controller.ts b/apps/backend/src/app/groups/groups.controller.ts index 85569e5..1036324 100644 --- a/apps/backend/src/app/groups/groups.controller.ts +++ b/apps/backend/src/app/groups/groups.controller.ts @@ -1,43 +1,46 @@ -import { Controller, DefaultValuePipe, Delete, Get, Param, ParseIntPipe, Post, Query } from '@nestjs/common'; -import { GroupsService } from './groups.service'; -import { ISearchQuery } from 'apps/backend/src/app/groups/groups.types'; +import { + Controller, + DefaultValuePipe, + Delete, + Get, + Param, + ParseIntPipe, + Post, + Query, +} from "@nestjs/common"; +import { ISearchQuery } from "apps/backend/src/app/groups/groups.types"; +import { GroupsService } from "./groups.service"; -@Controller('groups') +@Controller("groups") export class GroupsController { - constructor(private readonly groupsService: GroupsService) {} + constructor(private readonly groupsService: GroupsService) {} - //GET all groups with limit and offset + optional search - @Get() - async findMany( - @Query("limit", new DefaultValuePipe(20), ParseIntPipe) limit: number, - @Query("offset", new DefaultValuePipe(0), ParseIntPipe) offset: number, - @Query("search", new DefaultValuePipe("")) search: string - ) { - const query = {limit, offset, search} + //GET all groups with limit and offset + optional search + @Get() + async findMany( + @Query("limit", new DefaultValuePipe(20), ParseIntPipe) limit: number, + @Query("offset", new DefaultValuePipe(0), ParseIntPipe) offset: number, + @Query("search", new DefaultValuePipe("")) search: string, + ) { + const query = { limit, offset, search }; + } - } + //POST a new group + @Post("new") + async newGroup() {} - //POST a new group - @Post("new") - async newGroup() { + //DELETE a group + @Delete(":groupId") + async deleteGroup(@Param("groupId") groupId: string) {} - } - - //DELETE a group - @Delete(":groupId") - async deleteGroup(@Param('groupId') groupId: string) { - - } - - //GET files associated to group with limit and offset - @Get(":groupId") - async getForGroup( - @Query("limit", new DefaultValuePipe(20), ParseIntPipe) limit: number, - @Query("offset", new DefaultValuePipe(0), ParseIntPipe) offset: number, - @Query("search", new DefaultValuePipe("")) search: string, - @Param('groupId') groupId: string - ) { - const query = {limit, offset, search} - - } + //GET files associated to group with limit and offset + @Get(":groupId") + async getForGroup( + @Query("limit", new DefaultValuePipe(20), ParseIntPipe) limit: number, + @Query("offset", new DefaultValuePipe(0), ParseIntPipe) offset: number, + @Query("search", new DefaultValuePipe("")) search: string, + @Param("groupId") groupId: string, + ) { + const query = { limit, offset, search }; + } } diff --git a/apps/backend/src/app/groups/groups.module.ts b/apps/backend/src/app/groups/groups.module.ts index 83d027d..718f09d 100644 --- a/apps/backend/src/app/groups/groups.module.ts +++ b/apps/backend/src/app/groups/groups.module.ts @@ -1,9 +1,9 @@ -import { Module } from '@nestjs/common'; -import { GroupsService } from './groups.service'; -import { GroupsController } from './groups.controller'; +import { Module } from "@nestjs/common"; +import { GroupsController } from "./groups.controller"; +import { GroupsService } from "./groups.service"; @Module({ - controllers: [GroupsController], - providers: [GroupsService], + controllers: [GroupsController], + providers: [GroupsService], }) export class GroupsModule {} diff --git a/apps/backend/src/app/groups/groups.service.spec.ts b/apps/backend/src/app/groups/groups.service.spec.ts index 77bd2c6..dd1b8ed 100644 --- a/apps/backend/src/app/groups/groups.service.spec.ts +++ b/apps/backend/src/app/groups/groups.service.spec.ts @@ -1,18 +1,18 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { GroupsService } from './groups.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { GroupsService } from "./groups.service"; -describe('GroupsService', () => { - let service: GroupsService; +describe("GroupsService", () => { + let service: GroupsService; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [GroupsService], - }).compile(); + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [GroupsService], + }).compile(); - service = module.get(GroupsService); - }); + service = module.get(GroupsService); + }); - it('should be defined', () => { - expect(service).toBeDefined(); - }); + it("should be defined", () => { + expect(service).toBeDefined(); + }); }); diff --git a/apps/backend/src/app/groups/groups.service.ts b/apps/backend/src/app/groups/groups.service.ts index efa0581..29d53cc 100644 --- a/apps/backend/src/app/groups/groups.service.ts +++ b/apps/backend/src/app/groups/groups.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable } from "@nestjs/common"; @Injectable() export class GroupsService {} diff --git a/apps/backend/src/app/groups/groups.types.ts b/apps/backend/src/app/groups/groups.types.ts index 5fcc2ee..d17430d 100644 --- a/apps/backend/src/app/groups/groups.types.ts +++ b/apps/backend/src/app/groups/groups.types.ts @@ -1,5 +1,5 @@ export interface ISearchQuery { - limit: number; - offset: number; - search?: string; -} \ No newline at end of file + limit: number; + offset: number; + search?: string; +} diff --git a/apps/backend/src/app/machines/machines.controller.spec.ts b/apps/backend/src/app/machines/machines.controller.spec.ts index fc9d727..d1f35b1 100644 --- a/apps/backend/src/app/machines/machines.controller.spec.ts +++ b/apps/backend/src/app/machines/machines.controller.spec.ts @@ -1,20 +1,20 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { MachinesController } from 'apps/backend/src/app/machines/machines.controller'; -import { MachinesService } from 'apps/backend/src/app/machines/machines.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { MachinesController } from "apps/backend/src/app/machines/machines.controller"; +import { MachinesService } from "apps/backend/src/app/machines/machines.service"; -describe('MachineController', () => { - let controller: MachinesController; +describe("MachineController", () => { + let controller: MachinesController; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [MachinesController], - providers: [MachinesService], - }).compile(); + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [MachinesController], + providers: [MachinesService], + }).compile(); - controller = module.get(MachinesController); - }); + controller = module.get(MachinesController); + }); - it('should be defined', () => { - expect(controller).toBeDefined(); - }); + it("should be defined", () => { + expect(controller).toBeDefined(); + }); }); diff --git a/apps/backend/src/app/machines/machines.controller.ts b/apps/backend/src/app/machines/machines.controller.ts index c5808e4..6bd6496 100644 --- a/apps/backend/src/app/machines/machines.controller.ts +++ b/apps/backend/src/app/machines/machines.controller.ts @@ -1,38 +1,41 @@ -import { Controller, DefaultValuePipe, Delete, Get, Param, ParseIntPipe, Post, Query } from '@nestjs/common'; -import { MachinesService } from 'apps/backend/src/app/machines/machines.service'; +import { + Controller, + DefaultValuePipe, + Delete, + Get, + Param, + ParseIntPipe, + Post, + Query, +} from "@nestjs/common"; +import { MachinesService } from "apps/backend/src/app/machines/machines.service"; -@Controller('machines') +@Controller("machines") export class MachinesController { - constructor(private readonly machineService: MachinesService) {} + constructor(private readonly machineService: MachinesService) {} - @Get() - async findMany( - @Query("limit", new DefaultValuePipe(20), ParseIntPipe) limit: number, - @Query("offset", new DefaultValuePipe(0), ParseIntPipe) offset: number, - @Query("search", new DefaultValuePipe("")) search: string - ) { - const query = {limit, offset, search} + @Get() + async findMany( + @Query("limit", new DefaultValuePipe(20), ParseIntPipe) limit: number, + @Query("offset", new DefaultValuePipe(0), ParseIntPipe) offset: number, + @Query("search", new DefaultValuePipe("")) search: string, + ) { + const query = { limit, offset, search }; + } - } + @Post("new") + async newMachine() {} - @Post("new") - async newMachine() { + @Delete(":machineId") + async deleteGroup(@Param("machineId") machineId: string) {} - } - - @Delete(":machineId") - async deleteGroup(@Param('machineId') machineId: string) { - - } - - @Get(":groupId") - async getForGroup( - @Query("limit", new DefaultValuePipe(20), ParseIntPipe) limit: number, - @Query("offset", new DefaultValuePipe(0), ParseIntPipe) offset: number, - @Query("search", new DefaultValuePipe("")) search: string, - @Param('machineId') machineId: string - ) { - const query = {limit, offset, search} - - } + @Get(":groupId") + async getForGroup( + @Query("limit", new DefaultValuePipe(20), ParseIntPipe) limit: number, + @Query("offset", new DefaultValuePipe(0), ParseIntPipe) offset: number, + @Query("search", new DefaultValuePipe("")) search: string, + @Param("machineId") machineId: string, + ) { + const query = { limit, offset, search }; + } } diff --git a/apps/backend/src/app/machines/machines.module.ts b/apps/backend/src/app/machines/machines.module.ts index 6b84b65..4c79ab7 100644 --- a/apps/backend/src/app/machines/machines.module.ts +++ b/apps/backend/src/app/machines/machines.module.ts @@ -1,9 +1,9 @@ -import { Module } from '@nestjs/common'; -import { MachinesService } from 'apps/backend/src/app/machines/machines.service'; -import { MachinesController } from 'apps/backend/src/app/machines/machines.controller'; +import { Module } from "@nestjs/common"; +import { MachinesController } from "apps/backend/src/app/machines/machines.controller"; +import { MachinesService } from "apps/backend/src/app/machines/machines.service"; @Module({ - controllers: [MachinesController], - providers: [MachinesService], + controllers: [MachinesController], + providers: [MachinesService], }) export class MachinesModule {} diff --git a/apps/backend/src/app/machines/machines.service.spec.ts b/apps/backend/src/app/machines/machines.service.spec.ts index 53a657a..5e5df43 100644 --- a/apps/backend/src/app/machines/machines.service.spec.ts +++ b/apps/backend/src/app/machines/machines.service.spec.ts @@ -1,18 +1,18 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { MachinesService } from 'apps/backend/src/app/machines/machines.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { MachinesService } from "apps/backend/src/app/machines/machines.service"; -describe('MachinesService', () => { - let service: MachinesService; +describe("MachinesService", () => { + let service: MachinesService; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [MachinesService], - }).compile(); + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [MachinesService], + }).compile(); - service = module.get(MachinesService); - }); + service = module.get(MachinesService); + }); - it('should be defined', () => { - expect(service).toBeDefined(); - }); + it("should be defined", () => { + expect(service).toBeDefined(); + }); }); diff --git a/apps/backend/src/app/machines/machines.service.ts b/apps/backend/src/app/machines/machines.service.ts index 165c8ba..93d52c6 100644 --- a/apps/backend/src/app/machines/machines.service.ts +++ b/apps/backend/src/app/machines/machines.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable } from "@nestjs/common"; @Injectable() export class MachinesService {} diff --git a/apps/backend/src/app/storage/storage.module.ts b/apps/backend/src/app/storage/storage.module.ts index 128f770..a42b9a9 100644 --- a/apps/backend/src/app/storage/storage.module.ts +++ b/apps/backend/src/app/storage/storage.module.ts @@ -1,6 +1,6 @@ import { Module } from "@nestjs/common"; +import { DbModule } from "apps/backend/src/app/db/db.module"; import { StorageService } from "apps/backend/src/app/storage/storage.service"; -import { DbModule } from 'apps/backend/src/app/db/db.module'; @Module({ imports: [DbModule], diff --git a/apps/backend/src/app/storage/storage.service.ts b/apps/backend/src/app/storage/storage.service.ts index 9613ad3..50ae43e 100644 --- a/apps/backend/src/app/storage/storage.service.ts +++ b/apps/backend/src/app/storage/storage.service.ts @@ -8,11 +8,14 @@ import { InternalServerErrorException, NotFoundException, } from "@nestjs/common"; +import { DbService } from "apps/backend/src/app/db/db.service"; +import { + FilesTypeForMachine, + FilesTypesTable, +} from "apps/backend/src/app/db/schema"; +import { IFileInformation } from "apps/backend/src/app/storage/storage.types"; +import { eq } from "drizzle-orm"; import FileType from "file-type"; -import { DbService } from 'apps/backend/src/app/db/db.service'; -import { IFileInformation } from 'apps/backend/src/app/storage/storage.types'; -import { FilesTypeForMachine, FilesTypesTable } from 'apps/backend/src/app/db/schema'; -import { eq } from 'drizzle-orm'; @Injectable() export class StorageService { @@ -20,7 +23,6 @@ export class StorageService { private maxFileSize = 256; // MiB unit constructor(private readonly dbService: DbService) {} - /** * Save a file to the specified directory. * @@ -44,8 +46,10 @@ export class StorageService { * @param {Buffer} file - The file to check. * @return {Promise} - A Promise that resolves to true if the conditions are met, false otherwise. */ - private async checkConditions(machineIds: Array,file: Buffer): Promise { - + private async checkConditions( + machineIds: Array, + file: Buffer, + ): Promise { /** * Checks if the current MIME type is allowed based on the given set of allowed MIME types. * @param {Set} allowedMime - The set of allowed MIME types. @@ -60,53 +64,55 @@ export class StorageService { const fileType = await FileType.fileTypeFromBuffer(file); // Array of MIMEs with possible duplicate field - const _mimes: Array = [] + const _mimes: Array = []; // Fetching MIMEs for the associated machines for (const machineId of machineIds) { - console.debug(`Fetching mimeTypes for machine : ${machineId}`) + console.debug(`Fetching mimeTypes for machine : ${machineId}`); // Get MIMEs associated to a machine - const allowedMimeId = this.dbService.use() + const allowedMimeId = this.dbService + .use() .select() .from(FilesTypeForMachine) - .where(eq(FilesTypeForMachine.machineId, machineId)).as("allowedMimeId"); - const _allowedMime = await this.dbService.use() + .where(eq(FilesTypeForMachine.machineId, machineId)) + .as("allowedMimeId"); + const _allowedMime = await this.dbService + .use() .select({ slug: FilesTypesTable.mime, - name: FilesTypesTable.typeName + name: FilesTypesTable.typeName, }) .from(FilesTypesTable) - .leftJoin(allowedMimeId, eq(FilesTypesTable.id, allowedMimeId.fileTypeId)) - console.debug(`Total : ${_allowedMime.length}`) + .leftJoin( + allowedMimeId, + eq(FilesTypesTable.id, allowedMimeId.fileTypeId), + ); + console.debug(`Total : ${_allowedMime.length}`); // Append each MIME of a machine for (const allowedMimeElement of _allowedMime) { - _mimes.push(allowedMimeElement.slug) + _mimes.push(allowedMimeElement.slug); } } //Store the MIMEs without duplicate - const mimeSet = new Set(_mimes) - console.debug(`Indexed ${mimeSet.size} unique mimeTypes`) + const mimeSet = new Set(_mimes); + console.debug(`Indexed ${mimeSet.size} unique mimeTypes`); //check file size is less than 2mb const fileSize = file.byteLength; if (fileSize > this.maxFileSize * (1024 * 1024)) { - throw new BadRequestException( - "File size to high.", - { - cause: "File size", - description: `File size exceeds the limit. Maximum file size allowed is ${this.maxFileSize}MiB.` - } - ); + throw new BadRequestException("File size to high.", { + cause: "File size", + description: `File size exceeds the limit. Maximum file size allowed is ${this.maxFileSize}MiB.`, + }); } - if (!checkMime(mimeSet, fileType.mime)) throw new BadRequestException( - { - cause: "MIME type", - description: `Invalid MIME type. Allowed MIME types are: ${[...mimeSet].join(", ")}.` - } - ) + if (!checkMime(mimeSet, fileType.mime)) + throw new BadRequestException({ + cause: "MIME type", + description: `Invalid MIME type. Allowed MIME types are: ${[...mimeSet].join(", ")}.`, + }); - return true + return true; } /** @@ -133,12 +139,16 @@ export class StorageService { public async getChecksum(file: Buffer): Promise { return new Promise((resolve) => { try { - const checksum = crypto.createHash("sha256").update(file).digest("hex").toLowerCase(); - resolve(checksum) + const checksum = crypto + .createHash("sha256") + .update(file) + .digest("hex") + .toLowerCase(); + resolve(checksum); } catch (err) { - throw new InternalServerErrorException(err) + throw new InternalServerErrorException(err); } - }) + }); } /** @@ -149,9 +159,13 @@ export class StorageService { * @param {boolean} [isDocumentation] - Optional flag to indicate if the file is a documentation file. * @returns {Promise} - A Promise that resolves to the generated file information. */ - public async generateInformation(file: Buffer, fileDisplayName: string, isDocumentation?: boolean): Promise { + public async generateInformation( + file: Buffer, + fileDisplayName: string, + isDocumentation?: boolean, + ): Promise { const fileType = await FileType.fileTypeFromBuffer(file); - const checksum = await this.getChecksum(file) + const checksum = await this.getChecksum(file); const fileName = `${isDocumentation ? "doc" : "file"}-${checksum}.${fileType.ext.toLowerCase()}`; return { fileName: fileName, @@ -159,24 +173,39 @@ export class StorageService { fileSize: file.byteLength, fileChecksum: checksum, fileType: fileType, - isDocumentation: isDocumentation || false - } + isDocumentation: isDocumentation || false, + }; } - public async new(fileDisplayName: string, file: Buffer, isDocumentation?: boolean) { + public async new( + fileDisplayName: string, + file: Buffer, + isDocumentation?: boolean, + ) { try { - const info = await this.generateInformation(file, fileDisplayName, isDocumentation); - 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`) - const condition = await this.checkConditions([/* TODO import autorized file format */], file) + const info = await this.generateInformation( + file, + fileDisplayName, + isDocumentation, + ); + 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`, + ); + const condition = await this.checkConditions( + [ + /* TODO import autorized file format */ + ], + file, + ); if (!condition) { - console.warn(`File "${info.fileDisplayName}" did not pass the files requirement.\n${info.fileChecksum}`) + console.warn( + `File "${info.fileDisplayName}" did not pass the files requirement.\n${info.fileChecksum}`, + ); } //TODO Append in DB and save to storage - - } catch (err) { - throw new BadRequestException(err) + throw new BadRequestException(err); } } } diff --git a/apps/backend/src/app/storage/storage.types.ts b/apps/backend/src/app/storage/storage.types.ts index 071572b..888a151 100644 --- a/apps/backend/src/app/storage/storage.types.ts +++ b/apps/backend/src/app/storage/storage.types.ts @@ -1,17 +1,16 @@ -import FileType from 'file-type'; - +import FileType from "file-type"; export interface IFileInformation { - fileDisplayName: string; - fileName: string; - fileChecksum: string; - isDocumentation: boolean; - fileType: FileType.FileTypeResult; - fileSize: number; + fileDisplayName: string; + fileName: string; + fileChecksum: string; + isDocumentation: boolean; + fileType: FileType.FileTypeResult; + fileSize: number; } export interface IFileWithInformation { - buffer: Buffer; - info: IFileInformation; - additionalData?: AdditionalData -} \ No newline at end of file + buffer: Buffer; + info: IFileInformation; + additionalData?: AdditionalData; +} diff --git a/apps/frontend/src/components/ui/use-toast.ts b/apps/frontend/src/components/ui/use-toast.ts index 524a3fd..71b8d28 100644 --- a/apps/frontend/src/components/ui/use-toast.ts +++ b/apps/frontend/src/components/ui/use-toast.ts @@ -1,195 +1,192 @@ -"use client" +"use client"; // Inspired by react-hot-toast library -import * as React from "react" +import * as React from "react"; -import type { - ToastActionElement, - ToastProps, -} from "./toast" +import type { ToastActionElement, ToastProps } from "./toast"; -const TOAST_LIMIT = 1 -const TOAST_REMOVE_DELAY = 1000000 +const TOAST_LIMIT = 1; +const TOAST_REMOVE_DELAY = 1000000; type ToasterToast = ToastProps & { - id: string - title?: React.ReactNode - description?: React.ReactNode - action?: ToastActionElement -} + id: string; + title?: React.ReactNode; + description?: React.ReactNode; + action?: ToastActionElement; +}; const actionTypes = { - ADD_TOAST: "ADD_TOAST", - UPDATE_TOAST: "UPDATE_TOAST", - DISMISS_TOAST: "DISMISS_TOAST", - REMOVE_TOAST: "REMOVE_TOAST", -} as const + ADD_TOAST: "ADD_TOAST", + UPDATE_TOAST: "UPDATE_TOAST", + DISMISS_TOAST: "DISMISS_TOAST", + REMOVE_TOAST: "REMOVE_TOAST", +} as const; -let count = 0 +let count = 0; function genId() { - count = (count + 1) % Number.MAX_SAFE_INTEGER - return count.toString() + count = (count + 1) % Number.MAX_SAFE_INTEGER; + return count.toString(); } -type ActionType = typeof actionTypes +type ActionType = typeof actionTypes; type Action = - | { - type: ActionType["ADD_TOAST"] - toast: ToasterToast - } - | { - type: ActionType["UPDATE_TOAST"] - toast: Partial - } - | { - type: ActionType["DISMISS_TOAST"] - toastId?: ToasterToast["id"] - } - | { - type: ActionType["REMOVE_TOAST"] - toastId?: ToasterToast["id"] - } + | { + type: ActionType["ADD_TOAST"]; + toast: ToasterToast; + } + | { + type: ActionType["UPDATE_TOAST"]; + toast: Partial; + } + | { + type: ActionType["DISMISS_TOAST"]; + toastId?: ToasterToast["id"]; + } + | { + type: ActionType["REMOVE_TOAST"]; + toastId?: ToasterToast["id"]; + }; interface State { - toasts: ToasterToast[] + toasts: ToasterToast[]; } -const toastTimeouts = new Map>() +const toastTimeouts = new Map>(); const addToRemoveQueue = (toastId: string) => { - if (toastTimeouts.has(toastId)) { - return - } + if (toastTimeouts.has(toastId)) { + return; + } - const timeout = setTimeout(() => { - toastTimeouts.delete(toastId) - dispatch({ - type: "REMOVE_TOAST", - toastId: toastId, - }) - }, TOAST_REMOVE_DELAY) + const timeout = setTimeout(() => { + toastTimeouts.delete(toastId); + dispatch({ + type: "REMOVE_TOAST", + toastId: toastId, + }); + }, TOAST_REMOVE_DELAY); - toastTimeouts.set(toastId, timeout) -} + toastTimeouts.set(toastId, timeout); +}; export const reducer = (state: State, action: Action): State => { - switch (action.type) { - case "ADD_TOAST": - return { - ...state, - toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT), - } + switch (action.type) { + case "ADD_TOAST": + return { + ...state, + toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT), + }; - case "UPDATE_TOAST": - return { - ...state, - toasts: state.toasts.map((t) => - t.id === action.toast.id ? { ...t, ...action.toast } : t - ), - } + case "UPDATE_TOAST": + return { + ...state, + toasts: state.toasts.map((t) => + t.id === action.toast.id ? { ...t, ...action.toast } : t, + ), + }; - case "DISMISS_TOAST": { - const { toastId } = action + case "DISMISS_TOAST": { + const { toastId } = action; - // ! Side effects ! - This could be extracted into a dismissToast() action, - // but I'll keep it here for simplicity - if (toastId) { - addToRemoveQueue(toastId) - } else { - for (const toast1 of state.toasts) { - addToRemoveQueue(toast1.id) - } - } + // ! Side effects ! - This could be extracted into a dismissToast() action, + // but I'll keep it here for simplicity + if (toastId) { + addToRemoveQueue(toastId); + } else { + for (const toast1 of state.toasts) { + addToRemoveQueue(toast1.id); + } + } - return { - ...state, - toasts: state.toasts.map((t) => - t.id === toastId || toastId === undefined - ? { - ...t, - open: false, - } - : t - ), - } - } - case "REMOVE_TOAST": - if (action.toastId === undefined) { - return { - ...state, - toasts: [], - } - } - return { - ...state, - toasts: state.toasts.filter((t) => t.id !== action.toastId), - } - } -} + return { + ...state, + toasts: state.toasts.map((t) => + t.id === toastId || toastId === undefined + ? { + ...t, + open: false, + } + : t, + ), + }; + } + case "REMOVE_TOAST": + if (action.toastId === undefined) { + return { + ...state, + toasts: [], + }; + } + return { + ...state, + toasts: state.toasts.filter((t) => t.id !== action.toastId), + }; + } +}; -const listeners: Array<(state: State) => void> = [] +const listeners: Array<(state: State) => void> = []; -let memoryState: State = { toasts: [] } +let memoryState: State = { toasts: [] }; function dispatch(action: Action) { - memoryState = reducer(memoryState, action) - for (const listener of listeners) { - listener(memoryState) - } + memoryState = reducer(memoryState, action); + for (const listener of listeners) { + listener(memoryState); + } } -type Toast = Omit +type Toast = Omit; function toast({ ...props }: Toast) { - const id = genId() + const id = genId(); - const update = (props: ToasterToast) => - dispatch({ - type: "UPDATE_TOAST", - toast: { ...props, id }, - }) - const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id }) + const update = (props: ToasterToast) => + dispatch({ + type: "UPDATE_TOAST", + toast: { ...props, id }, + }); + const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id }); - dispatch({ - type: "ADD_TOAST", - toast: { - ...props, - id, - open: true, - onOpenChange: (open) => { - if (!open) dismiss() - }, - }, - }) + dispatch({ + type: "ADD_TOAST", + toast: { + ...props, + id, + open: true, + onOpenChange: (open) => { + if (!open) dismiss(); + }, + }, + }); - return { - id: id, - dismiss, - update, - } + return { + id: id, + dismiss, + update, + }; } function useToast() { - const [state, setState] = React.useState(memoryState) + const [state, setState] = React.useState(memoryState); - // biome-ignore lint/correctness/useExhaustiveDependencies: - React.useEffect(() => { - listeners.push(setState) - return () => { - const index = listeners.indexOf(setState) - if (index > -1) { - listeners.splice(index, 1) - } - } - }, [state]) + // biome-ignore lint/correctness/useExhaustiveDependencies: + React.useEffect(() => { + listeners.push(setState); + return () => { + const index = listeners.indexOf(setState); + if (index > -1) { + listeners.splice(index, 1); + } + }; + }, [state]); - return { - ...state, - toast, - dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }), - } + return { + ...state, + toast, + dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }), + }; } -export { useToast, toast } +export { useToast, toast }; diff --git a/apps/frontend/src/lib/utils.ts b/apps/frontend/src/lib/utils.ts index d084cca..ac680b3 100644 --- a/apps/frontend/src/lib/utils.ts +++ b/apps/frontend/src/lib/utils.ts @@ -1,6 +1,6 @@ -import { type ClassValue, clsx } from "clsx" -import { twMerge } from "tailwind-merge" +import { type ClassValue, clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)) + return twMerge(clsx(inputs)); }