feat(#111): Reprise après refus – backend
- GET /auth/reprise-dossier?token= : dossier pour préremplir (token seul) - PATCH /auth/reprise-resoumettre : token + champs modifiables → en_attente, token invalidé - POST /auth/reprise-identify : numero_dossier + email → type + token - UserService: findByTokenReprise, resoumettreReprise, findByNumeroDossierAndEmailForReprise Made-with: Cursor
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { BadRequestException, ForbiddenException, Injectable, Logger, NotFoundException } from "@nestjs/common";
|
||||
import { InjectRepository } from "@nestjs/typeorm";
|
||||
import { RoleType, StatutUtilisateurType, Users } from "src/entities/users.entity";
|
||||
import { In, Repository } from "typeorm";
|
||||
import { In, MoreThan, Repository } from "typeorm";
|
||||
import { CreateUserDto } from "./dto/create_user.dto";
|
||||
import { CreateAdminDto } from "./dto/create_admin.dto";
|
||||
import { UpdateUserDto } from "./dto/update_user.dto";
|
||||
@@ -392,6 +392,52 @@ export class UserService {
|
||||
return savedUser;
|
||||
}
|
||||
|
||||
/** Trouve un user par token reprise valide (non expiré). Ticket #111 */
|
||||
async findByTokenReprise(token: string): Promise<Users | null> {
|
||||
return this.usersRepository.findOne({
|
||||
where: {
|
||||
token_reprise: token,
|
||||
statut: StatutUtilisateurType.REFUSE,
|
||||
token_reprise_expire_le: MoreThan(new Date()),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/** Resoumission reprise : met à jour les champs autorisés, passe en en_attente, invalide le token. Ticket #111 */
|
||||
async resoumettreReprise(
|
||||
token: string,
|
||||
dto: { prenom?: string; nom?: string; telephone?: string; adresse?: string; ville?: string; code_postal?: string; photo_url?: string },
|
||||
): Promise<Users> {
|
||||
const user = await this.findByTokenReprise(token);
|
||||
if (!user) {
|
||||
throw new NotFoundException('Token reprise invalide ou expiré.');
|
||||
}
|
||||
if (dto.prenom !== undefined) user.prenom = dto.prenom;
|
||||
if (dto.nom !== undefined) user.nom = dto.nom;
|
||||
if (dto.telephone !== undefined) user.telephone = dto.telephone;
|
||||
if (dto.adresse !== undefined) user.adresse = dto.adresse;
|
||||
if (dto.ville !== undefined) user.ville = dto.ville;
|
||||
if (dto.code_postal !== undefined) user.code_postal = dto.code_postal;
|
||||
if (dto.photo_url !== undefined) user.photo_url = dto.photo_url;
|
||||
user.statut = StatutUtilisateurType.EN_ATTENTE;
|
||||
user.token_reprise = undefined;
|
||||
user.token_reprise_expire_le = undefined;
|
||||
return this.usersRepository.save(user);
|
||||
}
|
||||
|
||||
/** Pour modale reprise : numero_dossier + email → user en REFUSE avec token valide. Ticket #111 */
|
||||
async findByNumeroDossierAndEmailForReprise(numero_dossier: string, email: string): Promise<Users | null> {
|
||||
const user = await this.usersRepository.findOne({
|
||||
where: {
|
||||
email: email.trim().toLowerCase(),
|
||||
numero_dossier: numero_dossier.trim(),
|
||||
statut: StatutUtilisateurType.REFUSE,
|
||||
token_reprise_expire_le: MoreThan(new Date()),
|
||||
},
|
||||
});
|
||||
return user ?? null;
|
||||
}
|
||||
|
||||
async remove(id: string, currentUser: Users): Promise<void> {
|
||||
if (currentUser.role !== RoleType.SUPER_ADMIN) {
|
||||
throw new ForbiddenException('Accès réservé aux super admins');
|
||||
|
||||
Reference in New Issue
Block a user