diff --git a/src/common/guards/auth.guard.ts b/src/common/guards/auth.guard.ts index a4d1314..ecf0361 100644 --- a/src/common/guards/auth.guard.ts +++ b/src/common/guards/auth.guard.ts @@ -11,7 +11,7 @@ export class AuthGuard implements CanActivate { private readonly jwtService: JwtService, private readonly reflector: Reflector, private readonly configService: ConfigService, - ) { } + ) {} async canActivate(context: ExecutionContext): Promise { const isPublic = this.reflector.getAllAndOverride(IS_PUBLIC_KEY, [ @@ -24,8 +24,8 @@ export class AuthGuard implements CanActivate { if (request.path.startsWith('/api-docs')) { return true; } - const authHeader = request.headers['authorization'] as string | undefined; + const authHeader = request.headers['authorization'] as string | undefined; if (!authHeader || !authHeader.startsWith('Bearer ')) { throw new UnauthorizedException('Token manquant ou invalide'); } @@ -35,7 +35,12 @@ export class AuthGuard implements CanActivate { const payload = await this.jwtService.verifyAsync(token, { secret: this.configService.get('jwt.accessSecret'), }); - request.user = payload; + + request.user = { + ...payload, + id: payload.sub, + }; + return true; } catch (error) { throw new UnauthorizedException('Token invalide ou expiré'); diff --git a/src/routes/enfants/dto/create_enfants.dto.ts b/src/routes/enfants/dto/create_enfants.dto.ts index d6cbd8f..2281e0e 100644 --- a/src/routes/enfants/dto/create_enfants.dto.ts +++ b/src/routes/enfants/dto/create_enfants.dto.ts @@ -1,5 +1,5 @@ import { ApiProperty } from "@nestjs/swagger"; -import { IsBoolean, IsDateString, IsEnum, IsNotEmpty, IsOptional, IsString, IsUUID, MaxLength, ValidateIf } from "class-validator"; +import { IsBoolean, IsDateString, IsEnum, IsNotEmpty, IsOptional, IsString, MaxLength, ValidateIf } from "class-validator"; import { GenreType, StatutEnfantType } from "src/entities/children.entity"; export class CreateEnfantsDto { @@ -54,10 +54,4 @@ export class CreateEnfantsDto { @ApiProperty({ default: false }) @IsBoolean() is_multiple: boolean; - - @ApiProperty({ example: 'UUID-parent' }) - @IsUUID() - @IsNotEmpty() - id_parent: string; - } diff --git a/src/routes/enfants/enfants.controller.ts b/src/routes/enfants/enfants.controller.ts index 437633e..29e916e 100644 --- a/src/routes/enfants/enfants.controller.ts +++ b/src/routes/enfants/enfants.controller.ts @@ -3,56 +3,50 @@ import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagg import { RolesGuard } from 'src/common/guards/roles.guard'; import { EnfantsService } from './enfants.service'; import { Roles } from 'src/common/decorators/roles.decorator'; -import { RoleType } from 'src/entities/users.entity'; -import { Children } from 'src/entities/children.entity'; +import { RoleType, Users } from 'src/entities/users.entity'; import { CreateEnfantsDto } from './dto/create_enfants.dto'; import { EnfantResponseDto } from './dto/enfants_response.dto'; import { mapEnfantsToResponseDto, mapEnfantToResponseDto } from './enfants.mapper'; import { AuthGuard } from 'src/common/guards/auth.guard'; +import { User } from 'src/common/decorators/user.decorator'; @ApiBearerAuth('access-token') @ApiTags('Enfants') -@UseGuards(AuthGuard,RolesGuard) +@UseGuards(AuthGuard, RolesGuard) @Controller('enfants') export class EnfantsController { constructor(private readonly enfantsService: EnfantsService) { } - // Inscrire un enfant + @Post() @ApiOperation({ summary: 'Inscrire un enfant' }) @ApiResponse({ status: 201, type: EnfantResponseDto, description: 'L\'enfant a été inscrit avec succès.' }) @Roles(RoleType.PARENT, RoleType.SUPER_ADMIN, RoleType.GESTIONNAIRE) - async create(@Body() dto: CreateEnfantsDto): Promise { - const enfant = await this.enfantsService.create(dto); - - // Mapper l'entité enfant vers le DTO de réponse + async create( + @Body() dto: CreateEnfantsDto, + @User() currentUser: Users, // <-- ton décorateur + ): Promise { + const enfant = await this.enfantsService.create(dto, currentUser); return mapEnfantToResponseDto(enfant); } - - // Récupérer tous les enfants avec leurs liens parents + + @Get() @ApiOperation({ summary: 'Récupérer tous les enfants avec leurs liens parents' }) @ApiResponse({ status: 200, type: [EnfantResponseDto], description: 'Liste de tous les enfants avec leurs liens parents.' }) - @Get() @Roles(RoleType.GESTIONNAIRE, RoleType.SUPER_ADMIN) async findAll(): Promise { const enfants = await this.enfantsService.findAll(); - - // Mapper les entités enfants vers les DTO de réponse return mapEnfantsToResponseDto(enfants); } - // Récupérer un enfant par son ID @Get(':id') @ApiOperation({ summary: 'Récupérer un enfant par son ID' }) @ApiResponse({ status: 200, type: EnfantResponseDto, description: 'Détails de l\'enfant avec ses liens parents.' }) @Roles(RoleType.GESTIONNAIRE, RoleType.SUPER_ADMIN, RoleType.PARENT) async findOne(@Param('id', new ParseUUIDPipe()) id: string): Promise { const enfant = await this.enfantsService.findOne(id); - - // Mapper l'entité enfant vers le DTO de réponse return mapEnfantToResponseDto(enfant); } - // Mettre à jour un enfant @Patch(':id') @ApiOperation({ summary: 'Mettre à jour un enfant' }) @ApiResponse({ status: 200, type: EnfantResponseDto, description: 'L\'enfant a été mis à jour avec succès.' }) @@ -62,16 +56,13 @@ export class EnfantsController { @Body() dto: Partial, ): Promise { const enfant = await this.enfantsService.update(id, dto); - - // Mapper l'entité enfant vers le DTO de réponse return mapEnfantToResponseDto(enfant); } - // Supprimer un enfant @Delete(':id') - @Roles(RoleType.GESTIONNAIRE, RoleType.SUPER_ADMIN) @ApiOperation({ summary: 'Supprimer un enfant' }) @ApiResponse({ status: 204, description: 'L\'enfant a été supprimé avec succès.' }) + @Roles(RoleType.GESTIONNAIRE, RoleType.SUPER_ADMIN) async remove(@Param('id', new ParseUUIDPipe()) id: string): Promise { return this.enfantsService.remove(id); } diff --git a/src/routes/enfants/enfants.service.ts b/src/routes/enfants/enfants.service.ts index fa0bd4c..926ab29 100644 --- a/src/routes/enfants/enfants.service.ts +++ b/src/routes/enfants/enfants.service.ts @@ -5,6 +5,7 @@ import { Parents } from 'src/entities/parents.entity'; import { ParentsChildren } from 'src/entities/parents_children.entity'; import { Repository } from 'typeorm'; import { CreateEnfantsDto } from './dto/create_enfants.dto'; +import { Users } from 'src/entities/users.entity'; @Injectable() export class EnfantsService { @@ -20,21 +21,17 @@ export class EnfantsService { ) { } // Inscruire un enfant - async create(dto: CreateEnfantsDto): Promise { - - // Vérifier que le parent existe + async create(dto: CreateEnfantsDto, currentUser: Users): Promise { + // Récupérer le parent lié à l'utilisateur connecté const parent = await this.parentsRepository.findOne({ - where: { user_id: dto.id_parent }, + where: { user_id: currentUser.id }, }); - // Si le parent n'existe pas, lever une exception if (!parent) { - throw new NotFoundException(`Id de parent : ${dto.id_parent} introuvable`); + throw new NotFoundException(`Parent introuvable pour l'utilisateur connecté`); } - // Evolution future : rendre l'option photo obligatoire ou non configurable + // Vérifier la règle métier sur la photo const optionObligatoire = false; - // Si l'enfant est pas a naitre, vérifier qu'une photo est fournie - // Puis si l'option est obligatoire if (dto.status !== StatutEnfantType.A_NAITRE && !dto.photo_url && optionObligatoire) { throw new BadRequestException(`Pour un enfant actif, une photo est obligatoire`); } @@ -54,12 +51,13 @@ export class EnfantsService { }); await this.childrenRepository.save(child); - // Créer le lien entre le parent et l'enfant + // Créer le lien automatiquement avec le parent connecté const parentLink = this.parentsChildrenRepository.create({ parentId: parent.user_id, enfantId: child.id, }); await this.parentsChildrenRepository.save(parentLink); + return this.findOne(child.id); } @@ -93,16 +91,19 @@ export class EnfantsService { } // Mettre à jour un enfant - async update(id: string, dto: Partial): Promise { - const child = await this.childrenRepository.findOne({ where: { id } }); - if (!child) { - throw new NotFoundException(`Id d'enfant : ${id} introuvable`); - } - const { id_parent, ...childData } = dto; - await this.childrenRepository.update(id, childData); - return this.findOne(id); + // Mettre à jour un enfant +async update(id: string, dto: Partial): Promise { + const child = await this.childrenRepository.findOne({ where: { id } }); + if (!child) { + throw new NotFoundException(`Id d'enfant : ${id} introuvable`); } + // On n’a plus besoin de gérer id_parent ici + await this.childrenRepository.update(id, dto); + return this.findOne(id); +} + + // Supprimer un enfant async remove(id: string): Promise { await this.childrenRepository.delete(id);