@@ -19,8 +19,23 @@ import { JobState } from "~/core/jobs/_enums/state.enum";
1919import { inetOrgPersonDto } from './_dto/_parts/inetOrgPerson.dto' ;
2020import { EventEmitter2 } from '@nestjs/event-emitter' ;
2121
22+ /**
23+ * Service abstrait pour la gestion des identités
24+ * Fournit les fonctionnalités de base pour la validation, vérification d'unicité,
25+ * génération d'empreintes et gestion des états des identités
26+ */
2227@Injectable ( )
2328export abstract class AbstractIdentitiesService extends AbstractServiceSchema {
29+ /**
30+ * Constructeur du service abstrait des identités
31+ *
32+ * @param _model - Modèle Mongoose pour les identités
33+ * @param _validation - Service de validation des identités
34+ * @param storage - Service de stockage de fichiers
35+ * @param passwdAdmService - Service d'administration des mots de passe
36+ * @param eventEmitter - Émetteur d'événements
37+ * @param backends - Service de gestion des backends
38+ */
2439 public constructor (
2540 @InjectModel ( Identities . name ) protected _model : Model < Identities > ,
2641 protected readonly _validation : IdentitiesValidationService ,
@@ -35,6 +50,16 @@ export abstract class AbstractIdentitiesService extends AbstractServiceSchema {
3550 } ) ;
3651 }
3752
53+ /**
54+ * Gère les erreurs de validation et détermine l'action appropriée
55+ *
56+ * @param error - L'erreur à traiter (ValidationConfigException, ValidationSchemaException ou autre)
57+ * @param identity - L'identité concernée par l'erreur
58+ * @param logPrefix - Préfixe pour les logs
59+ * @returns L'identité modifiée en cas de ValidationSchemaException
60+ * @throws ValidationConfigException pour les erreurs de configuration
61+ * @throws Error pour les erreurs non gérées
62+ */
3863 protected handleValidationError (
3964 error : Error | HttpException ,
4065 identity : Identities | IdentitiesUpsertDto ,
@@ -59,6 +84,13 @@ export abstract class AbstractIdentitiesService extends AbstractServiceSchema {
5984 }
6085 }
6186
87+ /**
88+ * Transforme récursivement toutes les valeurs null d'un objet en chaînes vides
89+ * Utile pour normaliser les données avant traitement
90+ *
91+ * @param obj - L'objet à transformer (peut être de n'importe quel type)
92+ * @returns L'objet transformé avec les valeurs null remplacées par des chaînes vides
93+ */
6294 public transformNullsToString ( obj ) {
6395 if ( obj === null ) {
6496 return '' ;
@@ -73,7 +105,6 @@ export abstract class AbstractIdentitiesService extends AbstractServiceSchema {
73105 if ( obj [ key ] === null ) {
74106 obj [ key ] = '' ;
75107 } else if ( typeof obj [ key ] === 'object' ) {
76- // console.log('key', key);
77108 obj [ key ] = this . transformNullsToString ( obj [ key ] ) ;
78109 }
79110 }
@@ -82,6 +113,12 @@ export abstract class AbstractIdentitiesService extends AbstractServiceSchema {
82113 return obj ;
83114 }
84115
116+ /**
117+ * Vérifie l'existence d'une photo JPEG dans le stockage
118+ *
119+ * @param data - Les données contenant potentiellement une référence à une photo
120+ * @throws BadRequestException si la photo est référencée mais introuvable dans le stockage
121+ */
85122 protected async checkInetOrgPersonJpegPhoto ( data : any ) {
86123 if ( data ?. inetOrgPerson ?. jpegPhoto ) {
87124 let reqStorage ;
@@ -99,6 +136,14 @@ export abstract class AbstractIdentitiesService extends AbstractServiceSchema {
99136 }
100137 }
101138
139+ /**
140+ * Génère et met à jour l'empreinte digitale d'une identité
141+ * L'empreinte est mise à jour seulement si elle diffère de l'actuelle
142+ *
143+ * @param identity - L'identité pour laquelle générer l'empreinte
144+ * @param fingerprint - Empreinte pré-calculée (optionnelle)
145+ * @returns L'identité mise à jour avec la nouvelle empreinte
146+ */
102147 public async generateFingerprint < T extends AbstractSchema | Document > (
103148 identity : Identities ,
104149 fingerprint ?: string ,
@@ -124,6 +169,13 @@ export abstract class AbstractIdentitiesService extends AbstractServiceSchema {
124169 return updated as unknown as ModifyResult < Query < T , T , any , T > > ;
125170 }
126171
172+ /**
173+ * Sérialise un objet de manière stable et déterministe
174+ * Les clés sont triées pour garantir une sérialisation cohérente
175+ *
176+ * @param obj - L'objet à sérialiser
177+ * @returns La représentation string stable de l'objet
178+ */
127179 private stableStringify ( obj ) {
128180 if ( typeof obj !== "object" || obj === null ) {
129181 return JSON . stringify ( obj ) ;
@@ -138,6 +190,13 @@ export abstract class AbstractIdentitiesService extends AbstractServiceSchema {
138190 ) . join ( ',' ) } }`;
139191 }
140192
193+ /**
194+ * Calcule l'empreinte digitale d'une identité sans la sauvegarder
195+ * Utilise les données inetOrgPerson et additionalFields (sans validations)
196+ *
197+ * @param identity - Les données de l'identité pour calculer l'empreinte
198+ * @returns L'empreinte digitale SHA-256 en hexadécimal
199+ */
141200 public async previewFingerprint ( identity : any ) : Promise < string > {
142201 const inetOrgPerson = inetOrgPersonDto . initForFingerprint ( identity . inetOrgPerson ) ;
143202
@@ -160,6 +219,15 @@ export abstract class AbstractIdentitiesService extends AbstractServiceSchema {
160219 return hash . digest ( 'hex' ) . toString ( ) ;
161220 }
162221
222+ /**
223+ * Active ou désactive une identité en modifiant son statut de données
224+ * Synchronise le changement avec les backends et met à jour l'identité
225+ *
226+ * @param id - L'identifiant de l'identité à modifier
227+ * @param status - Le nouveau statut à appliquer
228+ * @throws HttpException si l'identité n'est pas trouvée ou n'a jamais été synchronisée
229+ * @throws BadRequestException si l'identité est supprimée ou si le backend échoue
230+ */
163231 public async activation ( id : string , status : DataStatusEnum ) {
164232 //recherche de l'identité
165233 let identity : Identities = null ;
@@ -178,9 +246,9 @@ export abstract class AbstractIdentitiesService extends AbstractServiceSchema {
178246 } else {
179247 throw new BadRequestException ( 'Identity is in status deleted' ) ;
180248 }
181- //sauvegarde de l'identité
249+ // sauvegarde de l'identité
182250 if ( statusChanged ) {
183- // le dataStaus à changé on envoye l info aux backend et on enregistre l identité
251+ // le dataStatus à changé on envoye l info aux backend et on enregistre l identité
184252 // Envoi du status au backend
185253 let statusBackend = true
186254 if ( status == DataStatusEnum . INACTIVE || status == DataStatusEnum . PASSWORDNEEDTOBECHANGED ) {
@@ -195,17 +263,57 @@ export abstract class AbstractIdentitiesService extends AbstractServiceSchema {
195263 }
196264 }
197265
198- public async askToChangePassword ( id : string ) {
266+ /**
267+ * Demande le changement de mot de passe pour une identité
268+ * L'identité doit être dans un statut ACTIVE pour que la demande soit acceptée
269+ *
270+ * @param id - L'identifiant de l'identité
271+ * @throws BadRequestException si l'identité n'est pas active
272+ * @throws HttpException si l'identité n'est pas trouvée
273+ */
274+ public async askToChangePassword ( id : string ) : Promise < void > {
275+ // Validation du paramètre d'entrée
276+ if ( ! id || typeof id !== 'string' ) {
277+ throw new BadRequestException ( 'Valid ID is required for password change request' ) ;
278+ }
279+
199280 try {
281+ // Recherche de l'identité
200282 const identity = await this . findById < Identities > ( id ) ;
201- if ( identity . dataStatus === DataStatusEnum . ACTIVE ) {
202- identity . dataStatus = DataStatusEnum . PASSWORDNEEDTOBECHANGED
203- await super . update ( identity . _id , identity ) ;
204- } else {
205- throw new BadRequestException ( 'Identity not in active' ) ;
283+
284+ if ( ! identity ) {
285+ throw new HttpException ( 'Identity not found' , 404 ) ;
286+ }
287+
288+ // Vérification que l'identité est dans un statut actif
289+ if ( identity . dataStatus !== DataStatusEnum . ACTIVE ) {
290+ throw new BadRequestException ( `Identity is not active. Current status: ${ identity . dataStatus } ` ) ;
206291 }
292+
293+ // Mise à jour du statut pour demander le changement de mot de passe
294+ identity . dataStatus = DataStatusEnum . PASSWORDNEEDTOBECHANGED ;
295+
296+ // Sauvegarde de l'identité
297+ await super . update ( identity . _id , identity ) ;
298+
299+ this . logger . log ( `Password change requested for identity ${ id } ` ) ;
300+
207301 } catch ( error ) {
208- throw new HttpException ( 'Id not found' , 400 ) ;
302+ // Gestion spécifique des erreurs déjà connues
303+ if ( error instanceof BadRequestException || error instanceof HttpException ) {
304+ throw error ;
305+ }
306+
307+ // Gestion des erreurs inattendues
308+ this . logger . error ( `Error requesting password change for identity ${ id } : ${ error . message } ` ) ;
309+
310+ // Si l'identité n'est pas trouvée, on retourne une erreur 404
311+ if ( error . message ?. includes ( 'not found' ) || error . name === 'CastError' ) {
312+ throw new HttpException ( 'Identity not found' , 404 ) ;
313+ }
314+
315+ // Pour toute autre erreur, on retourne une erreur 500
316+ throw new HttpException ( 'Failed to request password change' , 500 ) ;
209317 }
210318 }
211319
0 commit comments