@@ -188,6 +188,92 @@ export class PostgresUserService implements IServicelocator {
188188 }
189189 }
190190
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+
191277 // Utility function to check user-tenant mapping
192278 async validateUserandTenantMapping ( userId : string , tenantId : string ) {
193279 let userTenantMapping = await this . userTenantMappingRepository . find ( {
0 commit comments