correction + authguard current id corrected

This commit is contained in:
sdraris 2025-10-01 15:43:36 +02:00
parent 78c155c910
commit 05529d299b
4 changed files with 40 additions and 49 deletions

View File

@ -11,7 +11,7 @@ export class AuthGuard implements CanActivate {
private readonly jwtService: JwtService, private readonly jwtService: JwtService,
private readonly reflector: Reflector, private readonly reflector: Reflector,
private readonly configService: ConfigService, private readonly configService: ConfigService,
) { } ) {}
async canActivate(context: ExecutionContext): Promise<boolean> { async canActivate(context: ExecutionContext): Promise<boolean> {
const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [ const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
@ -24,8 +24,8 @@ export class AuthGuard implements CanActivate {
if (request.path.startsWith('/api-docs')) { if (request.path.startsWith('/api-docs')) {
return true; return true;
} }
const authHeader = request.headers['authorization'] as string | undefined;
const authHeader = request.headers['authorization'] as string | undefined;
if (!authHeader || !authHeader.startsWith('Bearer ')) { if (!authHeader || !authHeader.startsWith('Bearer ')) {
throw new UnauthorizedException('Token manquant ou invalide'); throw new UnauthorizedException('Token manquant ou invalide');
} }
@ -35,7 +35,12 @@ export class AuthGuard implements CanActivate {
const payload = await this.jwtService.verifyAsync(token, { const payload = await this.jwtService.verifyAsync(token, {
secret: this.configService.get<string>('jwt.accessSecret'), secret: this.configService.get<string>('jwt.accessSecret'),
}); });
request.user = payload;
request.user = {
...payload,
id: payload.sub,
};
return true; return true;
} catch (error) { } catch (error) {
throw new UnauthorizedException('Token invalide ou expiré'); throw new UnauthorizedException('Token invalide ou expiré');

View File

@ -1,5 +1,5 @@
import { ApiProperty } from "@nestjs/swagger"; 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"; import { GenreType, StatutEnfantType } from "src/entities/children.entity";
export class CreateEnfantsDto { export class CreateEnfantsDto {
@ -54,10 +54,4 @@ export class CreateEnfantsDto {
@ApiProperty({ default: false }) @ApiProperty({ default: false })
@IsBoolean() @IsBoolean()
is_multiple: boolean; is_multiple: boolean;
@ApiProperty({ example: 'UUID-parent' })
@IsUUID()
@IsNotEmpty()
id_parent: string;
} }

View File

@ -3,56 +3,50 @@ import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagg
import { RolesGuard } from 'src/common/guards/roles.guard'; import { RolesGuard } from 'src/common/guards/roles.guard';
import { EnfantsService } from './enfants.service'; import { EnfantsService } from './enfants.service';
import { Roles } from 'src/common/decorators/roles.decorator'; import { Roles } from 'src/common/decorators/roles.decorator';
import { RoleType } from 'src/entities/users.entity'; import { RoleType, Users } from 'src/entities/users.entity';
import { Children } from 'src/entities/children.entity';
import { CreateEnfantsDto } from './dto/create_enfants.dto'; import { CreateEnfantsDto } from './dto/create_enfants.dto';
import { EnfantResponseDto } from './dto/enfants_response.dto'; import { EnfantResponseDto } from './dto/enfants_response.dto';
import { mapEnfantsToResponseDto, mapEnfantToResponseDto } from './enfants.mapper'; import { mapEnfantsToResponseDto, mapEnfantToResponseDto } from './enfants.mapper';
import { AuthGuard } from 'src/common/guards/auth.guard'; import { AuthGuard } from 'src/common/guards/auth.guard';
import { User } from 'src/common/decorators/user.decorator';
@ApiBearerAuth('access-token') @ApiBearerAuth('access-token')
@ApiTags('Enfants') @ApiTags('Enfants')
@UseGuards(AuthGuard,RolesGuard) @UseGuards(AuthGuard, RolesGuard)
@Controller('enfants') @Controller('enfants')
export class EnfantsController { export class EnfantsController {
constructor(private readonly enfantsService: EnfantsService) { } constructor(private readonly enfantsService: EnfantsService) { }
// Inscrire un enfant
@Post() @Post()
@ApiOperation({ summary: 'Inscrire un enfant' }) @ApiOperation({ summary: 'Inscrire un enfant' })
@ApiResponse({ status: 201, type: EnfantResponseDto, description: 'L\'enfant a été inscrit avec succès.' }) @ApiResponse({ status: 201, type: EnfantResponseDto, description: 'L\'enfant a été inscrit avec succès.' })
@Roles(RoleType.PARENT, RoleType.SUPER_ADMIN, RoleType.GESTIONNAIRE) @Roles(RoleType.PARENT, RoleType.SUPER_ADMIN, RoleType.GESTIONNAIRE)
async create(@Body() dto: CreateEnfantsDto): Promise<EnfantResponseDto> { async create(
const enfant = await this.enfantsService.create(dto); @Body() dto: CreateEnfantsDto,
@User() currentUser: Users, // <-- ton décorateur
// Mapper l'entité enfant vers le DTO de réponse ): Promise<EnfantResponseDto> {
const enfant = await this.enfantsService.create(dto, currentUser);
return mapEnfantToResponseDto(enfant); 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' }) @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.' }) @ApiResponse({ status: 200, type: [EnfantResponseDto], description: 'Liste de tous les enfants avec leurs liens parents.' })
@Get()
@Roles(RoleType.GESTIONNAIRE, RoleType.SUPER_ADMIN) @Roles(RoleType.GESTIONNAIRE, RoleType.SUPER_ADMIN)
async findAll(): Promise<EnfantResponseDto[]> { async findAll(): Promise<EnfantResponseDto[]> {
const enfants = await this.enfantsService.findAll(); const enfants = await this.enfantsService.findAll();
// Mapper les entités enfants vers les DTO de réponse
return mapEnfantsToResponseDto(enfants); return mapEnfantsToResponseDto(enfants);
} }
// Récupérer un enfant par son ID
@Get(':id') @Get(':id')
@ApiOperation({ summary: 'Récupérer un enfant par son 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.' }) @ApiResponse({ status: 200, type: EnfantResponseDto, description: 'Détails de l\'enfant avec ses liens parents.' })
@Roles(RoleType.GESTIONNAIRE, RoleType.SUPER_ADMIN, RoleType.PARENT) @Roles(RoleType.GESTIONNAIRE, RoleType.SUPER_ADMIN, RoleType.PARENT)
async findOne(@Param('id', new ParseUUIDPipe()) id: string): Promise<EnfantResponseDto> { async findOne(@Param('id', new ParseUUIDPipe()) id: string): Promise<EnfantResponseDto> {
const enfant = await this.enfantsService.findOne(id); const enfant = await this.enfantsService.findOne(id);
// Mapper l'entité enfant vers le DTO de réponse
return mapEnfantToResponseDto(enfant); return mapEnfantToResponseDto(enfant);
} }
// Mettre à jour un enfant
@Patch(':id') @Patch(':id')
@ApiOperation({ summary: 'Mettre à jour un enfant' }) @ApiOperation({ summary: 'Mettre à jour un enfant' })
@ApiResponse({ status: 200, type: EnfantResponseDto, description: 'L\'enfant a été mis à jour avec succès.' }) @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<CreateEnfantsDto>, @Body() dto: Partial<CreateEnfantsDto>,
): Promise<EnfantResponseDto> { ): Promise<EnfantResponseDto> {
const enfant = await this.enfantsService.update(id, dto); const enfant = await this.enfantsService.update(id, dto);
// Mapper l'entité enfant vers le DTO de réponse
return mapEnfantToResponseDto(enfant); return mapEnfantToResponseDto(enfant);
} }
// Supprimer un enfant
@Delete(':id') @Delete(':id')
@Roles(RoleType.GESTIONNAIRE, RoleType.SUPER_ADMIN)
@ApiOperation({ summary: 'Supprimer un enfant' }) @ApiOperation({ summary: 'Supprimer un enfant' })
@ApiResponse({ status: 204, description: 'L\'enfant a été supprimé avec succès.' }) @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<void> { async remove(@Param('id', new ParseUUIDPipe()) id: string): Promise<void> {
return this.enfantsService.remove(id); return this.enfantsService.remove(id);
} }

View File

@ -5,6 +5,7 @@ import { Parents } from 'src/entities/parents.entity';
import { ParentsChildren } from 'src/entities/parents_children.entity'; import { ParentsChildren } from 'src/entities/parents_children.entity';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';
import { CreateEnfantsDto } from './dto/create_enfants.dto'; import { CreateEnfantsDto } from './dto/create_enfants.dto';
import { Users } from 'src/entities/users.entity';
@Injectable() @Injectable()
export class EnfantsService { export class EnfantsService {
@ -20,21 +21,17 @@ export class EnfantsService {
) { } ) { }
// Inscruire un enfant // Inscruire un enfant
async create(dto: CreateEnfantsDto): Promise<Children> { async create(dto: CreateEnfantsDto, currentUser: Users): Promise<Children> {
// Récupérer le parent lié à l'utilisateur connecté
// Vérifier que le parent existe
const parent = await this.parentsRepository.findOne({ 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) { 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; 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) { if (dto.status !== StatutEnfantType.A_NAITRE && !dto.photo_url && optionObligatoire) {
throw new BadRequestException(`Pour un enfant actif, une photo est obligatoire`); throw new BadRequestException(`Pour un enfant actif, une photo est obligatoire`);
} }
@ -54,12 +51,13 @@ export class EnfantsService {
}); });
await this.childrenRepository.save(child); 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({ const parentLink = this.parentsChildrenRepository.create({
parentId: parent.user_id, parentId: parent.user_id,
enfantId: child.id, enfantId: child.id,
}); });
await this.parentsChildrenRepository.save(parentLink); await this.parentsChildrenRepository.save(parentLink);
return this.findOne(child.id); return this.findOne(child.id);
} }
@ -93,16 +91,19 @@ export class EnfantsService {
} }
// Mettre à jour un enfant // Mettre à jour un enfant
async update(id: string, dto: Partial<CreateEnfantsDto>): Promise<Children> { // Mettre à jour un enfant
const child = await this.childrenRepository.findOne({ where: { id } }); async update(id: string, dto: Partial<CreateEnfantsDto>): Promise<Children> {
if (!child) { const child = await this.childrenRepository.findOne({ where: { id } });
throw new NotFoundException(`Id d'enfant : ${id} introuvable`); 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);
} }
// On na plus besoin de gérer id_parent ici
await this.childrenRepository.update(id, dto);
return this.findOne(id);
}
// Supprimer un enfant // Supprimer un enfant
async remove(id: string): Promise<void> { async remove(id: string): Promise<void> {
await this.childrenRepository.delete(id); await this.childrenRepository.delete(id);