Selaa lähdekoodia

(feat) peut créer des users et des compagnies

Brin AMONKONAN 1 vuosi sitten
vanhempi
sitoutus
1336bdd324

+ 1 - 0
node_app/src/domain/entities/company.entity.ts

@@ -6,6 +6,7 @@ export class Company {
   name: string;
   address: string;
   manager: any;
+  managerId: number;
   vehicules: Vehicule[];
   drivers: Driver[];
 

+ 1 - 1
node_app/src/infrastructure/database/repositories/company.repository.ts

@@ -21,7 +21,7 @@ export class CompanyRepository implements IBaseRepository<Company> {
         name: data.name,
         address: data.address,
         manager: {
-          connect: { id: data.manager.id },
+          connect: { id: data.managerId },
         },
         vehicules: {
           connect:

+ 1 - 0
node_app/src/infrastructure/services/auth.service.ts

@@ -37,6 +37,7 @@ export class AuthService implements IAuthService {
       try {
         // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
         const decoded = this.jwtService.verify(token);
+        console.log('LE JWT ==========>', decoded);
         resolve(decoded as string);
       } catch (error) {
         reject(error instanceof Error ? error : new Error(String(error)));

+ 12 - 1
node_app/src/main.ts

@@ -24,7 +24,18 @@ async function bootstrap() {
     .setDescription('The Transport API description')
     .setVersion('1.0')
     .addTag('Transport')
-    .addServer('/api') // Ajout explicite du préfixe API comme serveur
+    .addServer('/api')
+    .addBearerAuth(
+      {
+        type: 'http',
+        scheme: 'bearer',
+        bearerFormat: 'JWT',
+        name: 'JWT',
+        description: 'Entrez votre token JWT',
+        in: 'header',
+      },
+      'access-token',
+    )
     .build();
 
   const document = SwaggerModule.createDocument(app, config, {

+ 23 - 2
node_app/src/presentation/controllers/auth.controller.ts

@@ -8,15 +8,35 @@ import {
   HttpCode,
   HttpStatus,
 } from '@nestjs/common';
-import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
+import {
+  ApiOperation,
+  ApiResponse,
+  ApiTags,
+  ApiProperty,
+} from '@nestjs/swagger';
 import { IAuthService } from '../../application/interfaces/i-auth.service';
 import { Inject } from '@nestjs/common';
 import { AuthGuard } from '../guards/auth.guard';
 import { UserResponseDto } from '../../application/dto/responses/user-response.dto';
 import { User } from 'src/domain/entities/user.entity';
+import { IsEmail, IsNotEmpty, IsString } from 'class-validator';
+import { Public } from '../decorators/public.decorator';
 
-class LoginDto {
+export class LoginDto {
+  @ApiProperty({
+    example: 'utilisateur@exemple.com',
+    description: "Adresse email de l'utilisateur",
+  })
+  @IsEmail({}, { message: 'Veuillez fournir une adresse email valide' })
+  @IsNotEmpty({ message: "L'email est requis" })
   email: string;
+
+  @ApiProperty({
+    example: 'motdepasse123',
+    description: "Mot de passe de l'utilisateur",
+  })
+  @IsString({ message: 'Le mot de passe doit être une chaîne de caractères' })
+  @IsNotEmpty({ message: 'Le mot de passe est requis' })
   password: string;
 }
 
@@ -29,6 +49,7 @@ export class AuthController {
   ) {}
 
   @Post('login')
+  @Public() // Cette route est publique
   @HttpCode(HttpStatus.OK)
   @ApiOperation({ description: 'Connexion utilisateur' })
   @ApiResponse({ status: 200, description: 'Connexion réussie' })

+ 18 - 3
node_app/src/presentation/controllers/company.controller.ts

@@ -1,3 +1,4 @@
+/* eslint-disable no-useless-catch */
 import {
   Controller,
   Get,
@@ -7,17 +8,26 @@ import {
   Put,
   Delete,
 } from '@nestjs/common';
-import { ApiResponse, ApiTags, ApiOperation, ApiParam } from '@nestjs/swagger';
+import {
+  ApiResponse,
+  ApiTags,
+  ApiOperation,
+  ApiParam,
+  ApiSecurity,
+} from '@nestjs/swagger';
 import { CreateCompanyDto } from '../../application/dto/create-company.dto';
 import { UpdateCompanyDto } from '../../application/dto/update-company.dto';
 import { FindAllCompaniesUseCase } from '../../application/use-cases/company/find-all-companies.use-case';
 import { CompanyResponseDto } from 'src/application/dto/responses/company-response.dto';
+import { CreateCompanyUseCase } from '../../application/use-cases/company/create-company.use-case';
 
 @ApiTags('companies')
 @Controller('companies')
+@ApiSecurity('access-token')
 export class CompanyController {
   constructor(
     private readonly findAllCompaniesUseCase: FindAllCompaniesUseCase,
+    private readonly createCompanyUseCase: CreateCompanyUseCase,
   ) {}
 
   @Post()
@@ -25,10 +35,15 @@ export class CompanyController {
   @ApiResponse({
     status: 201,
     description: "L'entreprise a été créée avec succès",
-    type: CreateCompanyDto,
+    type: CompanyResponseDto,
   })
   async create(@Body() createCompanyDto: CreateCompanyDto) {
-    // Implementation
+    try {
+      const result = await this.createCompanyUseCase.execute(createCompanyDto);
+      return result;
+    } catch (error) {
+      throw error; // L'exception sera gérée par les filtres d'exception globaux
+    }
   }
 
   @Get()

+ 8 - 1
node_app/src/presentation/controllers/driver.controller.ts

@@ -7,12 +7,19 @@ import {
   Put,
   Delete,
 } from '@nestjs/common';
-import { ApiTags, ApiResponse, ApiOperation, ApiParam } from '@nestjs/swagger';
+import {
+  ApiTags,
+  ApiResponse,
+  ApiOperation,
+  ApiParam,
+  ApiSecurity,
+} from '@nestjs/swagger';
 import { CreateDriverDto } from '../../application/dto/create-driver.dto';
 import { DriverResponseDto } from '../../application/dto/responses/driver-response.dto';
 
 @ApiTags('drivers')
 @Controller('drivers')
+@ApiSecurity('access-token')
 export class DriverController {
   constructor() {}
 

+ 42 - 33
node_app/src/presentation/controllers/place.controller.ts

@@ -1,33 +1,42 @@
-import { Controller, Get, Post, Body, Param, Put, Delete } from '@nestjs/common';
-import { ApiTags } from '@nestjs/swagger';
-
-@ApiTags('places')
-@Controller('places')
-export class PlaceController {
-  constructor() {}
-
-  @Post()
-  async create(@Body() createPlaceDto: any) {
-    // TODO: Implement create place use case
-  }
-
-  @Get()
-  async findAll() {
-    // TODO: Implement get all places use case
-  }
-
-  @Get(':id')
-  async findOne(@Param('id') id: string) {
-    // TODO: Implement get place by id use case
-  }
-
-  @Put(':id')
-  async update(@Param('id') id: string, @Body() updatePlaceDto: any) {
-    // TODO: Implement update place use case
-  }
-
-  @Delete(':id')
-  async remove(@Param('id') id: string) {
-    // TODO: Implement delete place use case
-  }
-}
+import {
+  Controller,
+  Get,
+  Post,
+  Body,
+  Param,
+  Put,
+  Delete,
+} from '@nestjs/common';
+import { ApiSecurity, ApiTags } from '@nestjs/swagger';
+
+@ApiTags('places')
+@Controller('places')
+@ApiSecurity('access-token')
+export class PlaceController {
+  constructor() {}
+
+  @Post()
+  async create(@Body() createPlaceDto: any) {
+    // TODO: Implement create place use case
+  }
+
+  @Get()
+  async findAll() {
+    // TODO: Implement get all places use case
+  }
+
+  @Get(':id')
+  async findOne(@Param('id') id: string) {
+    // TODO: Implement get place by id use case
+  }
+
+  @Put(':id')
+  async update(@Param('id') id: string, @Body() updatePlaceDto: any) {
+    // TODO: Implement update place use case
+  }
+
+  @Delete(':id')
+  async remove(@Param('id') id: string) {
+    // TODO: Implement delete place use case
+  }
+}

+ 42 - 33
node_app/src/presentation/controllers/reservation.controller.ts

@@ -1,33 +1,42 @@
-import { Controller, Get, Post, Body, Param, Put, Delete } from '@nestjs/common';
-import { ApiTags } from '@nestjs/swagger';
-
-@ApiTags('reservations')
-@Controller('reservations')
-export class ReservationController {
-  constructor() {}
-
-  @Post()
-  async create(@Body() createReservationDto: any) {
-    // TODO: Implement create reservation use case
-  }
-
-  @Get()
-  async findAll() {
-    // TODO: Implement get all reservations use case
-  }
-
-  @Get(':id')
-  async findOne(@Param('id') id: string) {
-    // TODO: Implement get reservation by id use case
-  }
-
-  @Put(':id')
-  async update(@Param('id') id: string, @Body() updateReservationDto: any) {
-    // TODO: Implement update reservation use case
-  }
-
-  @Delete(':id')
-  async remove(@Param('id') id: string) {
-    // TODO: Implement delete reservation use case
-  }
-}
+import {
+  Controller,
+  Get,
+  Post,
+  Body,
+  Param,
+  Put,
+  Delete,
+} from '@nestjs/common';
+import { ApiSecurity, ApiTags } from '@nestjs/swagger';
+
+@ApiTags('reservations')
+@Controller('reservations')
+@ApiSecurity('access-token')
+export class ReservationController {
+  constructor() {}
+
+  @Post()
+  async create(@Body() createReservationDto: any) {
+    // TODO: Implement create reservation use case
+  }
+
+  @Get()
+  async findAll() {
+    // TODO: Implement get all reservations use case
+  }
+
+  @Get(':id')
+  async findOne(@Param('id') id: string) {
+    // TODO: Implement get reservation by id use case
+  }
+
+  @Put(':id')
+  async update(@Param('id') id: string, @Body() updateReservationDto: any) {
+    // TODO: Implement update reservation use case
+  }
+
+  @Delete(':id')
+  async remove(@Param('id') id: string) {
+    // TODO: Implement delete reservation use case
+  }
+}

+ 42 - 33
node_app/src/presentation/controllers/trajet.controller.ts

@@ -1,33 +1,42 @@
-import { Controller, Get, Post, Body, Param, Put, Delete } from '@nestjs/common';
-import { ApiTags } from '@nestjs/swagger';
-
-@ApiTags('trajets')
-@Controller('trajets')
-export class TrajetController {
-  constructor() {}
-
-  @Post()
-  async create(@Body() createTrajetDto: any) {
-    // TODO: Implement create trajet use case
-  }
-
-  @Get()
-  async findAll() {
-    // TODO: Implement get all trajets use case
-  }
-
-  @Get(':id')
-  async findOne(@Param('id') id: string) {
-    // TODO: Implement get trajet by id use case
-  }
-
-  @Put(':id')
-  async update(@Param('id') id: string, @Body() updateTrajetDto: any) {
-    // TODO: Implement update trajet use case
-  }
-
-  @Delete(':id')
-  async remove(@Param('id') id: string) {
-    // TODO: Implement delete trajet use case
-  }
-}
+import {
+  Controller,
+  Get,
+  Post,
+  Body,
+  Param,
+  Put,
+  Delete,
+} from '@nestjs/common';
+import { ApiSecurity, ApiTags } from '@nestjs/swagger';
+
+@ApiTags('trajets')
+@Controller('trajets')
+@ApiSecurity('access-token') // Indique que les routes nécessitent un token Bearer pour l'authentification
+export class TrajetController {
+  constructor() {}
+
+  @Post()
+  async create(@Body() createTrajetDto: any) {
+    // TODO: Implement create trajet use case
+  }
+
+  @Get()
+  async findAll() {
+    // TODO: Implement get all trajets use case
+  }
+
+  @Get(':id')
+  async findOne(@Param('id') id: string) {
+    // TODO: Implement get trajet by id use case
+  }
+
+  @Put(':id')
+  async update(@Param('id') id: string, @Body() updateTrajetDto: any) {
+    // TODO: Implement update trajet use case
+  }
+
+  @Delete(':id')
+  async remove(@Param('id') id: string) {
+    // TODO: Implement delete trajet use case
+  }
+}

+ 19 - 1
node_app/src/presentation/controllers/user.controller.ts

@@ -11,7 +11,12 @@ import {
 } from '@nestjs/common';
 import { CreateUserUseCase } from '../../application/use-cases/create-user.use-case';
 import { CreateUserDto } from '../../application/dto/create-user.dto';
-import { ApiOperation, ApiResponse, ApiParam } from '@nestjs/swagger';
+import {
+  ApiOperation,
+  ApiResponse,
+  ApiParam,
+  ApiSecurity,
+} from '@nestjs/swagger';
 import { UseInterceptors } from '@nestjs/common';
 import { BodyParserInterceptor } from '../../interceptors/body-parser.interceptor';
 import { FindUserByIdUseCase } from '../../application/use-cases/find-user-by-id.use-case';
@@ -19,9 +24,11 @@ import { UpdateUserUseCase } from '../../application/use-cases/update-user.use-c
 import { UpdateUserDto } from '../../application/dto/update-user.dto';
 import { DeleteUserUseCase } from '../../application/use-cases/delete-user.use-case';
 import { FindAllUsersUseCase } from '../../application/use-cases/find-all-users.use-case';
+import { Public } from '../decorators/public.decorator';
 
 @Controller('users')
 @UseInterceptors(BodyParserInterceptor)
+@ApiSecurity('access-token') // Indique que les routes nécessitent un token Bearer pour l'authentification
 export class UserController {
   constructor(
     private readonly createUserUseCase: CreateUserUseCase,
@@ -32,6 +39,7 @@ export class UserController {
   ) {}
 
   @Post()
+  @Public() // Cette route est publique pour permettre l'inscription des utilisateurs
   @ApiOperation({ description: 'Creater un utilisateur' })
   @ApiResponse({ status: 200 })
   async create(@Body() createUserDto: CreateUserDto) {
@@ -47,21 +55,25 @@ export class UserController {
   }
 
   @Get(':id')
+  // Route protégée - nécessite une authentification
   @ApiOperation({ description: 'Récupérer un utilisateur par son ID' })
   @ApiResponse({ status: 200, description: 'Utilisateur trouvé' })
   @ApiResponse({ status: 404, description: 'Utilisateur non trouvé' })
+  @ApiResponse({ status: 401, description: 'Non autorisé' })
   @ApiParam({ name: 'id', description: "ID de l'utilisateur", type: 'number' })
   async findOne(@Param('id', ParseIntPipe) id: number) {
     return this.findUserByIdUseCase.execute(id);
   }
 
   @Put(':id')
+  // Route protégée - nécessite une authentification
   @ApiOperation({ description: 'Mettre à jour un utilisateur par son ID' })
   @ApiResponse({
     status: 200,
     description: 'Utilisateur mis à jour avec succès',
   })
   @ApiResponse({ status: 404, description: 'Utilisateur non trouvé' })
+  @ApiResponse({ status: 401, description: 'Non autorisé' })
   @ApiParam({ name: 'id', description: "ID de l'utilisateur", type: 'number' })
   async update(
     @Param('id', ParseIntPipe) id: number,
@@ -71,6 +83,7 @@ export class UserController {
   }
 
   @Patch(':id')
+  // Route protégée - nécessite une authentification
   @ApiOperation({
     description: 'Mettre à jour partiellement un utilisateur par son ID',
   })
@@ -79,6 +92,7 @@ export class UserController {
     description: 'Utilisateur partiellement mis à jour avec succès',
   })
   @ApiResponse({ status: 404, description: 'Utilisateur non trouvé' })
+  @ApiResponse({ status: 401, description: 'Non autorisé' })
   @ApiParam({ name: 'id', description: "ID de l'utilisateur", type: 'number' })
   async partialUpdate(
     @Param('id', ParseIntPipe) id: number,
@@ -88,9 +102,11 @@ export class UserController {
   }
 
   @Delete(':id')
+  // Route protégée - nécessite une authentification
   @ApiOperation({ description: 'Supprimer un utilisateur par son ID' })
   @ApiResponse({ status: 200, description: 'Utilisateur supprimé avec succès' })
   @ApiResponse({ status: 404, description: 'Utilisateur non trouvé' })
+  @ApiResponse({ status: 401, description: 'Non autorisé' })
   @ApiParam({ name: 'id', description: "ID de l'utilisateur", type: 'number' })
   async remove(@Param('id', ParseIntPipe) id: number) {
     await this.deleteUserUseCase.execute(id);
@@ -98,8 +114,10 @@ export class UserController {
   }
 
   @Get()
+  // Route protégée - nécessite une authentification
   @ApiOperation({ description: 'Récupérer tous les utilisateurs' })
   @ApiResponse({ status: 200, description: 'Liste des utilisateurs' })
+  @ApiResponse({ status: 401, description: 'Non autorisé' })
   async findAll() {
     return this.findAllUsersUseCase.execute();
   }

+ 8 - 1
node_app/src/presentation/controllers/vehicle.controller.ts

@@ -7,12 +7,19 @@ import {
   Put,
   Delete,
 } from '@nestjs/common';
-import { ApiTags, ApiResponse, ApiOperation, ApiParam } from '@nestjs/swagger';
+import {
+  ApiTags,
+  ApiResponse,
+  ApiOperation,
+  ApiParam,
+  ApiSecurity,
+} from '@nestjs/swagger';
 import { CreateVehiculeDto } from '../../application/dto/create-vehicule.dto';
 import { VehiculeResponseDto } from '../../application/dto/responses/vehicule-response.dto';
 
 @ApiTags('Vehicules')
 @Controller('Vehicules')
+@ApiSecurity('access-token')
 export class VehiculeController {
   constructor() {}
 

+ 4 - 0
node_app/src/presentation/decorators/public.decorator.ts

@@ -0,0 +1,4 @@
+import { SetMetadata } from '@nestjs/common';
+
+export const IS_PUBLIC_KEY = 'isPublic';
+export const Public = () => SetMetadata(IS_PUBLIC_KEY, true);

+ 24 - 7
node_app/src/presentation/guards/auth.guard.ts

@@ -6,31 +6,48 @@ import {
   ExecutionContext,
   Inject,
 } from '@nestjs/common';
-import { Observable } from 'rxjs';
+import { Reflector } from '@nestjs/core';
 import { IAuthService } from '../../application/interfaces/i-auth.service';
+import { IS_PUBLIC_KEY } from '../decorators/public.decorator';
 
 @Injectable()
 export class AuthGuard implements CanActivate {
   constructor(
     @Inject('IAuthService')
     private readonly authService: IAuthService,
+    private reflector: Reflector,
   ) {}
 
-  canActivate(
-    context: ExecutionContext,
-  ): boolean | Promise<boolean> | Observable<boolean> {
+  async canActivate(context: ExecutionContext): Promise<boolean> {
+    // Vérifier si la route est marquée comme publique
     const request = context.switchToHttp().getRequest();
-    const token = request.headers.authorization?.split(' ')[1];
+    const authHeader = request.headers['authorization'];
+
+    const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
+      context.getHandler(),
+      context.getClass(),
+    ]);
+
+    if (isPublic) {
+      return true;
+    }
+
+    if (!authHeader || !authHeader.startsWith('Bearer ')) {
+      return false;
+    }
+
+    const token = authHeader?.split(' ')[1];
 
     if (!token) {
+      console.log('No token provided');
       return false;
     }
 
     try {
-      const payload = this.authService.verifyToken(token);
+      const payload = await this.authService.verifyToken(token);
       request.user = payload;
       return true;
-    } catch {
+    } catch (error) {
       return false;
     }
   }