diff --git a/src/routes/user/gestionnaires/gestionnaires.controller.spec.ts b/src/routes/user/gestionnaires/gestionnaires.controller.spec.ts new file mode 100644 index 0000000..6dee426 --- /dev/null +++ b/src/routes/user/gestionnaires/gestionnaires.controller.spec.ts @@ -0,0 +1,20 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { GestionnairesController } from './gestionnaires.controller'; +import { GestionnairesService } from './gestionnaires.service'; + +describe('GestionnairesController', () => { + let controller: GestionnairesController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [GestionnairesController], + providers: [GestionnairesService], + }).compile(); + + controller = module.get(GestionnairesController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/src/routes/user/gestionnaires/gestionnaires.controller.ts b/src/routes/user/gestionnaires/gestionnaires.controller.ts new file mode 100644 index 0000000..7a1489f --- /dev/null +++ b/src/routes/user/gestionnaires/gestionnaires.controller.ts @@ -0,0 +1,73 @@ +import { + Controller, + Get, + Post, + Body, + Patch, + Param, + Delete, + UseGuards, +} from '@nestjs/common'; +import { GestionnairesService } from './gestionnaires.service'; +import { RoleType, Users } from 'src/entities/users.entity'; +import { Roles } from 'src/common/decorators/roles.decorator'; +import { UpdateGestionnaireDto } from '../dto/update_gestionnaire.dto'; +import { CreateGestionnaireDto } from '../dto/create_gestionnaire.dto'; +import { RolesGuard } from 'src/common/guards/roles.guard'; +import { ApiBearerAuth, ApiBody, ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger'; +import { AuthGuard } from 'src/common/guards/auth.guard'; + + +@ApiTags('Gestionnaires') +@ApiBearerAuth('access-token') +@UseGuards(AuthGuard, RolesGuard) +@Controller('gestionnaires') +export class GestionnairesController { + constructor(private readonly gestionnairesService: GestionnairesService) { } + + @Roles(RoleType.SUPER_ADMIN) + @ApiResponse({ status: 201, description: 'Le gestionnaire a été créé avec succès.', type: Users }) + @ApiResponse({ status: 409, description: 'Conflit. L\'email est déjà utilisé.' }) + @ApiOperation({ summary: 'Création d\'un gestionnaire' }) + @ApiBody({ type: CreateGestionnaireDto }) + @Post() + create(@Body() dto: CreateGestionnaireDto): Promise { + return this.gestionnairesService.create(dto); + } + + @Roles(RoleType.SUPER_ADMIN, RoleType.GESTIONNAIRE) + @ApiOperation({ summary: 'Liste des gestionnaires' }) + @ApiResponse({ status: 200, description: 'Liste des gestionnaires : ', type: [Users] }) + @Get() + getAll(): Promise { + return this.gestionnairesService.findAll(); + } + + @Roles(RoleType.GESTIONNAIRE, RoleType.SUPER_ADMIN) + @ApiOperation({ summary: 'Récupérer un gestionnaire par ID' }) + @ApiResponse({ status: 400, description: 'ID invalide' }) + @ApiResponse({ status: 403, description: 'Accès refusé' }) + @ApiResponse({ status: 401, description: 'Non authentifié' }) + @ApiParam({ name: 'id', description: 'ID du gestionnaire' }) + @ApiResponse({ status: 200, description: 'Gestionnaire trouvé', type: Users }) + @ApiResponse({ status: 404, description: 'Gestionnaire non trouvé' }) + @Get(':id') + findOne(@Param('id') id: string): Promise { + return this.gestionnairesService.findOne(id); + } + + @Roles(RoleType.SUPER_ADMIN) + @ApiOperation({ summary: 'Mettre à jour un gestionnaire' }) + @ApiResponse({ status: 200, description: 'Le gestionnaire a été mis à jour avec succès.', type: Users }) + @ApiResponse({ status: 404, description: 'Gestionnaire non trouvé' }) + @ApiResponse({ status: 403, description: 'Accès refusé' }) + @ApiResponse({ status: 401, description: 'Non authentifié' }) + @ApiParam({ name: 'id', description: 'ID du gestionnaire' }) + @Patch(':id') + update( + @Param('id') id: string, + @Body() dto: UpdateGestionnaireDto, + ): Promise { + return this.gestionnairesService.update(id, dto); + } +} diff --git a/src/routes/user/gestionnaires/gestionnaires.module.ts b/src/routes/user/gestionnaires/gestionnaires.module.ts new file mode 100644 index 0000000..bfd32f8 --- /dev/null +++ b/src/routes/user/gestionnaires/gestionnaires.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; +import { GestionnairesService } from './gestionnaires.service'; +import { GestionnairesController } from './gestionnaires.controller'; +import { Users } from 'src/entities/users.entity'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +@Module({ + imports: [TypeOrmModule.forFeature([Users])], + controllers: [GestionnairesController], + providers: [GestionnairesService], +}) +export class GestionnairesModule { } diff --git a/src/routes/user/gestionnaires/gestionnaires.service.spec.ts b/src/routes/user/gestionnaires/gestionnaires.service.spec.ts new file mode 100644 index 0000000..5460385 --- /dev/null +++ b/src/routes/user/gestionnaires/gestionnaires.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { GestionnairesService } from './gestionnaires.service'; + +describe('GestionnairesService', () => { + let service: GestionnairesService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [GestionnairesService], + }).compile(); + + service = module.get(GestionnairesService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/src/routes/user/gestionnaires/gestionnaires.service.ts b/src/routes/user/gestionnaires/gestionnaires.service.ts new file mode 100644 index 0000000..4e1406e --- /dev/null +++ b/src/routes/user/gestionnaires/gestionnaires.service.ts @@ -0,0 +1,87 @@ +import { + ConflictException, + Injectable, + NotFoundException, +} from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { RoleType, Users } from 'src/entities/users.entity'; +import { CreateGestionnaireDto } from '../dto/create_gestionnaire.dto'; +import { UpdateGestionnaireDto } from '../dto/update_gestionnaire.dto'; +import * as bcrypt from 'bcrypt'; + +@Injectable() +export class GestionnairesService { + constructor( + @InjectRepository(Users) + private readonly gestionnaireRepository: Repository, + ) { } + + // Création d’un gestionnaire + async create(dto: CreateGestionnaireDto): Promise { + const exist = await this.gestionnaireRepository.findOneBy({ email: dto.email }); + if (exist) throw new ConflictException('Email déjà utilisé'); + + const salt = await bcrypt.genSalt(); + const hashedPassword = await bcrypt.hash(dto.password, salt); + + const entity = this.gestionnaireRepository.create({ + email: dto.email, + password: hashedPassword, + prenom: dto.prenom, + nom: dto.nom, + genre: dto.genre, + statut: dto.statut, + telephone: dto.telephone, + adresse: dto.adresse, + photo_url: dto.photo_url, + consentement_photo: dto.consentement_photo ?? false, + date_consentement_photo: dto.date_consentement_photo + ? new Date(dto.date_consentement_photo) + : undefined, + changement_mdp_obligatoire: dto.changement_mdp_obligatoire ?? false, + role: RoleType.GESTIONNAIRE, + }); + return this.gestionnaireRepository.save(entity); + } + + // Liste des gestionnaires + async findAll(): Promise { + return this.gestionnaireRepository.find({ where: { role: RoleType.GESTIONNAIRE } }); + } + + // Récupérer un gestionnaire par ID + async findOne(id: string): Promise { + const gestionnaire = await this.gestionnaireRepository.findOne({ + where: { id, role: RoleType.GESTIONNAIRE }, + }); + if (!gestionnaire) throw new NotFoundException('Gestionnaire introuvable'); + return gestionnaire; + } + + // Mise à jour d’un gestionnaire + async update(id: string, dto: UpdateGestionnaireDto): Promise { + const gestionnaire = await this.findOne(id); + + if (dto.password) { + const salt = await bcrypt.genSalt(); + gestionnaire.password = await bcrypt.hash(dto.password, salt); + } + + if (dto.date_consentement_photo !== undefined) { + gestionnaire.date_consentement_photo = dto.date_consentement_photo + ? new Date(dto.date_consentement_photo) + : undefined; + } + + const { password, date_consentement_photo, ...rest } = dto; + Object.entries(rest).forEach(([key, value]) => { + if (value !== undefined) { + (gestionnaire as any)[key] = value; + } + }); + + return this.gestionnaireRepository.save(gestionnaire); + } + +}