import { ConflictException, Injectable, UnauthorizedException, } from '@nestjs/common'; import { UserService } from '../user/user.service'; import { JwtService } from '@nestjs/jwt'; import * as bcrypt from 'bcrypt'; import { RegisterDto } from './dto/register.dto'; import { ConfigService } from '@nestjs/config'; import { RoleType, StatutUtilisateurType, Users } from 'src/entities/users.entity'; import { LoginDto } from './dto/login.dto'; import { DeepPartial } from 'typeorm'; @Injectable() export class AuthService { constructor( private readonly usersService: UserService, private readonly jwtService: JwtService, private readonly configService: ConfigService, ) { } /** * Génère un access_token et un refresh_token */ async generateTokens(userId: string, email: string, role: RoleType) { const accessSecret = this.configService.get('jwt.accessSecret'); const accessExpiresIn = this.configService.get('jwt.accessExpiresIn'); const refreshSecret = this.configService.get('jwt.refreshSecret'); const refreshExpiresIn = this.configService.get('jwt.refreshExpiresIn'); const [accessToken, refreshToken] = await Promise.all([ this.jwtService.signAsync({ sub: userId, email, role }, { secret: accessSecret, expiresIn: accessExpiresIn }), this.jwtService.signAsync({ sub: userId }, { secret: refreshSecret, expiresIn: refreshExpiresIn }), ]); return { access_token: accessToken, refresh_token: refreshToken, }; } /** * Connexion utilisateur */ async login(dto: LoginDto) { try { const user = await this.usersService.findByEmailOrNull(dto.email); if (!user) { throw new UnauthorizedException('Email invalide'); } console.log("Tentative login:", dto.email, JSON.stringify(dto.password)); console.log("Utilisateur trouvé:", user.email, user.password); const isMatch = await bcrypt.compare(dto.password, user.password); console.log("Résultat bcrypt.compare:", isMatch); if (!isMatch) { throw new UnauthorizedException('Mot de passe invalide'); } // if (user.password !== dto.password) { // throw new UnauthorizedException('Mot de passe invalide'); // } return this.generateTokens(user.id, user.email, user.role); } catch (error) { console.error('Erreur de connexion :', error); throw new UnauthorizedException('Identifiants invalides'); } } /** * Rafraîchir les tokens */ async refreshTokens(refreshToken: string) { try { const payload = await this.jwtService.verifyAsync(refreshToken, { secret: this.configService.get('jwt.refreshSecret'), }); 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) { const exists = await this.usersService.findByEmailOrNull(registerDto.email); if (exists) { throw new ConflictException('Email déjà utilisé'); } const allowedRoles = new Set([RoleType.PARENT, RoleType.ASSISTANTE_MATERNELLE]); if (!allowedRoles.has(registerDto.role)) { registerDto.role = RoleType.PARENT; } registerDto.statut = StatutUtilisateurType.EN_ATTENTE; if (!registerDto.consentement_photo) { registerDto.date_consentement_photo = null; } else if (registerDto.date_consentement_photo) { const date = new Date(registerDto.date_consentement_photo); if (isNaN(date.getTime())) { registerDto.date_consentement_photo = null; } } const user = await this.usersService.createUser(registerDto); const tokens = await this.generateTokens(user.id, user.email, user.role); return { ...tokens, user: { id: user.id, email: user.email, role: user.role, prenom: user.prenom, nom: user.nom, statut: user.statut, }, }; } async logout(userId: string) { // Pour une implémentation simple, on ne fait rien ici. } }