@@ -188,6 +188,92 @@ export class PostgresUserService implements IServicelocator {
188
188
}
189
189
}
190
190
191
+ async learnerforgotPassword ( request : any , body : any , response : Response < any , Record < string , any > > ) {
192
+ const apiId = APIID . USER_FORGOT_PASSWORD ;
193
+ const tenantId = request . headers . tenantid ;
194
+ const decoded : any = jwt_decode ( request . headers . authorization ) ;
195
+
196
+ try {
197
+ // Check if User Exists
198
+ const userDetail = await this . usersRepository . findOne ( {
199
+ where : { username : body . userName }
200
+ } ) ;
201
+ if ( ! userDetail ) {
202
+ return APIResponse . error (
203
+ response ,
204
+ apiId ,
205
+ API_RESPONSES . USERNAME_NOT_FOUND ,
206
+ 'User not found.' ,
207
+ HttpStatus . NOT_FOUND
208
+ ) ;
209
+ }
210
+
211
+ // Validate Learner-Tenant & Admin-Tenant Mapping in a single function
212
+ await this . validateUserandTenantMapping ( userDetail . userId , tenantId ) ;
213
+ await this . validateUserandTenantMapping ( decoded . sub , tenantId ) ;
214
+
215
+ // Get Keycloak Admin Token
216
+ const keycloakResponse = await getKeycloakAdminToken ( ) ;
217
+ const keyClocktoken = keycloakResponse . data . access_token ;
218
+
219
+ // Check Role and Access
220
+ const role = await this . getUserRoles ( decoded . sub , tenantId ) ;
221
+ if ( role . code === 'cohort_admin' ) {
222
+ const cohortIds = await this . getCohortIdsForTenant ( decoded . sub , tenantId ) ;
223
+ const learnercohorts = await this . cohortMemberRepository . find ( {
224
+ where : { userId : userDetail . userId , cohortId : In ( cohortIds ) }
225
+ } ) ;
226
+ if ( learnercohorts . length === 0 ) {
227
+ return APIResponse . error (
228
+ response ,
229
+ apiId ,
230
+ 'You don\'t have access to update the password of this learner' ,
231
+ 'Unauthorized access attempt.' ,
232
+ HttpStatus . UNAUTHORIZED
233
+ ) ;
234
+ }
235
+ }
236
+
237
+ // Validate new password
238
+ if ( ! body . newPassword || body . newPassword . length < 8 ) {
239
+ return APIResponse . error (
240
+ response ,
241
+ apiId ,
242
+ 'New password does not meet security requirements.' ,
243
+ 'Password too short.' ,
244
+ HttpStatus . BAD_REQUEST
245
+ ) ;
246
+ }
247
+
248
+ // Reset Keycloak Password
249
+ await this . resetKeycloakPassword (
250
+ request ,
251
+ userDetail ,
252
+ keyClocktoken ,
253
+ body . newPassword ,
254
+ userDetail . userId
255
+ ) ;
256
+
257
+ return APIResponse . success (
258
+ response ,
259
+ apiId ,
260
+ { } ,
261
+ HttpStatus . OK ,
262
+ API_RESPONSES . FORGOT_PASSWORD_SUCCESS
263
+ ) ;
264
+
265
+ } catch ( error ) {
266
+ console . error ( 'Error in learnerforgotPassword:' , error ) ;
267
+ return APIResponse . error (
268
+ response ,
269
+ apiId ,
270
+ API_RESPONSES . INTERNAL_SERVER_ERROR ,
271
+ `Error: ${ error . message || error } ` ,
272
+ error . status || HttpStatus . INTERNAL_SERVER_ERROR
273
+ ) ;
274
+ }
275
+ }
276
+
191
277
// Utility function to check user-tenant mapping
192
278
async validateUserandTenantMapping ( userId : string , tenantId : string ) {
193
279
let userTenantMapping = await this . userTenantMappingRepository . find ( {
0 commit comments