From 7b79b63101e8fb2c6253b6c61bbeed2decdfa2dd Mon Sep 17 00:00:00 2001 From: sdraris Date: Wed, 3 Sep 2025 11:44:37 +0200 Subject: [PATCH] auth correction --- src/routes/auth/auth.controller.ts | 8 +- src/routes/auth/auth.service.ts | 122 +++++++++++++++++++++++++---- 2 files changed, 110 insertions(+), 20 deletions(-) diff --git a/src/routes/auth/auth.controller.ts b/src/routes/auth/auth.controller.ts index a2a7d25..ed3e5bf 100644 --- a/src/routes/auth/auth.controller.ts +++ b/src/routes/auth/auth.controller.ts @@ -1,8 +1,8 @@ import { Body, Controller, Post } from '@nestjs/common'; import { LoginDto } from '../user/dto/login.dto'; import { AuthService } from './auth.service'; -import { CreateUserDto } from '../user/dto/create_user.dto'; import { Public } from 'src/common/decorators/public.decorator'; +import { RegisterDto } from '../user/dto/register.dto'; @Controller('auth') export class AuthController { @@ -15,8 +15,8 @@ export class AuthController { } @Public() - @Post('bootstrap-super-admin') - async bootstrapSuperAdmin(@Body() dto: CreateUserDto) { - return this.authService.bootstrapSuperAdmin(dto); + @Post('register') + async register(@Body() dto: RegisterDto) { + return this.authService.register(dto); } } diff --git a/src/routes/auth/auth.service.ts b/src/routes/auth/auth.service.ts index 4408f72..8d932ac 100644 --- a/src/routes/auth/auth.service.ts +++ b/src/routes/auth/auth.service.ts @@ -1,33 +1,123 @@ -import { Injectable, UnauthorizedException } from '@nestjs/common'; +import { + ConflictException, + Injectable, + UnauthorizedException, +} from '@nestjs/common'; import { UserService } from '../user/user.service'; import { JwtService } from '@nestjs/jwt'; -import { RoleType } from 'src/entities/users.entity'; import * as bcrypt from 'bcrypt'; +import { RegisterDto } from '../user/dto/register.dto'; +import { ConfigService } from '@nestjs/config'; +import { RoleType, StatutUtilisateurType } from 'src/entities/users.entity'; +import { LoginDto } from '../user/dto/login.dto'; @Injectable() export class AuthService { constructor( - private readonly userService: UserService, + private readonly usersService: UserService, private readonly jwtService: JwtService, + private readonly configService: ConfigService, ) { } - async bootstrapSuperAdmin(dto: any) { - const user = await this.userService.create({ - ...dto, - role: RoleType.SUPER_ADMIN, - }, undefined); - return { message: 'Super admin cree avec succes !', user }; + /** + * Génère un access_token et un refresh_token + */ + async generateTokens(userId: string, email: string, role: RoleType) { + const [accessToken, refreshToken] = await Promise.all([ + this.jwtService.signAsync( + { sub: userId, email, role }, + { + secret: this.configService.get('jwt.secret'), + expiresIn: this.configService.get('jwt.access_token_expires'), + }, + ), + this.jwtService.signAsync( + { sub: userId }, + { + secret: this.configService.get('jwt.refresh_token_secret'), + expiresIn: this.configService.get( + 'jwt.refresh_token_expires', + ), + }, + ), + ]); + + return { + access_token: accessToken, + refresh_token: refreshToken, + }; } - async login({ email, password }: { email: string, password: string }) { - const user = await this.userService.findByEmail(email) - if (!user) throw new UnauthorizedException('Identifiants invalides !'); + /** + * Connexion utilisateur + */ + async login(dto : LoginDto) { + const user = await this.usersService.findByEmail(dto.email); + + // Vérification du mot de passe + const isMatch = await bcrypt.compare(dto.password, user.password_hash); + if (!isMatch) { + throw new UnauthorizedException('Identifiants invalides'); + } + + return this.generateTokens(user.id, user.email, user.role); + } + + /** + * Rafraîchir les tokens + */ + async refreshTokens(refreshToken: string) { + try { + const payload = await this.jwtService.verifyAsync(refreshToken, { + secret: this.configService.get('jwt.refresh_token_secret'), + }); + + const user = await this.usersService.findOne(payload.sub); + if (!user) { + throw new UnauthorizedException('Utilisateur introuvable'); + } + + return this.generateTokens(user.id, user.email, user.role); + } catch { + throw new UnauthorizedException('Refresh token invalide'); + } + } + + /** + * Inscription utilisateur lambda (parent ou assistante maternelle) + */ + async register(registerDto: RegisterDto) { + // Vérifier si l'email existe déjà + const exists = await this.usersService.findByEmail(registerDto.email).catch(() => null); + if (exists) { + throw new ConflictException('Email déjà utilisé'); + } + + // Filtrer les rôles autorisés + const allowedRoles = new Set([RoleType.PARENT, RoleType.ASSISTANTE_MATERNELLE]); + if (!allowedRoles.has(registerDto.role)) { + registerDto.role = RoleType.PARENT; + } + + // Statut par défaut + registerDto.status = StatutUtilisateurType.EN_ATTENTE; + + // Création de l'utilisateur (UserService gère le hash) + const user = await this.usersService.create(registerDto); + + // Génération des tokens + const tokens = await this.generateTokens(user.id, user.email, user.role); - const isMatch = await bcrypt.compare(password, user.password_hash); - if (!isMatch) throw new UnauthorizedException('Identifiants invalides !'); - const payload = { id: user.id, email: user.email, role: user.role }; return { - access_token: this.jwtService.sign(payload), + ...tokens, + user: { + id: user.id, + email: user.email, + role: user.role, + first_name: user.first_name, + last_name: user.last_name, + status: user.status, + }, }; } }