diff --git a/pom.xml b/pom.xml index ffe74404..4c727f1b 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.iemr.common-API common-api - 3.8.2 + 3.12.0 war Common-API diff --git a/src/main/java/com/iemr/common/service/users/IEMRAdminUserServiceImpl.java b/src/main/java/com/iemr/common/service/users/IEMRAdminUserServiceImpl.java index e411b9ef..3b60c78b 100644 --- a/src/main/java/com/iemr/common/service/users/IEMRAdminUserServiceImpl.java +++ b/src/main/java/com/iemr/common/service/users/IEMRAdminUserServiceImpl.java @@ -26,6 +26,7 @@ import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.spec.InvalidKeySpecException; +import java.util.concurrent.CompletableFuture; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -469,7 +470,7 @@ public int setForgetPassword(User user, String loginpass, String transactionId, int count = 0; try { if (isAdmin != null && isAdmin == true) { - updateCTIPasswordForUserV1(user.getUserID(), loginpass); + updateCTIPasswordInBackground(user.getUserID(), loginpass); loginpass = securePassword.generateStrongPassword(loginpass); count = iEMRUserRepositoryCustom.updateSetForgetPassword(user.getUserID(), loginpass); } else { @@ -477,7 +478,7 @@ public int setForgetPassword(User user, String loginpass, String transactionId, .getSessionObjectForChangePassword((user.getUserID().toString() + user.getUserName())); if (tokenFromRedis.equalsIgnoreCase(transactionId)) { - updateCTIPasswordForUserV1(user.getUserID(), loginpass); + updateCTIPasswordInBackground(user.getUserID(), loginpass); loginpass = securePassword.generateStrongPassword(loginpass); count = iEMRUserRepositoryCustom.updateSetForgetPassword(user.getUserID(), loginpass); // Deleting transaction Id @@ -600,6 +601,15 @@ public void updateCTIPasswordForUser(Long userID, String password) { } } + /** + * Sends the new password to the CTI server without making the user wait: called from this class, so the + * {@code @Async} of updateCTIPasswordForUserV1 is not applied (no proxy) and an unreachable CTI server held the + * password screen until the network timeout - before the password was even saved. + */ + void updateCTIPasswordInBackground(Long userID, String password) { + CompletableFuture.runAsync(() -> updateCTIPasswordForUserV1(userID, password)); + } + @Async public void updateCTIPasswordForUserV1(Long userID, String password) { try { diff --git a/src/test/java/com/iemr/common/service/users/IEMRAdminUserServiceImplTest.java b/src/test/java/com/iemr/common/service/users/IEMRAdminUserServiceImplTest.java index de282b52..a896327f 100644 --- a/src/test/java/com/iemr/common/service/users/IEMRAdminUserServiceImplTest.java +++ b/src/test/java/com/iemr/common/service/users/IEMRAdminUserServiceImplTest.java @@ -374,6 +374,28 @@ void testSetForgetPassword_ValidTransaction() throws Exception { assertEquals(1, result); } + @Test + void testSetForgetPassword_DoesNotWaitForCtiServer() throws Exception { + // Given: the CTI server does not answer until released + java.util.concurrent.CountDownLatch ctiReleased = new java.util.concurrent.CountDownLatch(1); + when(iEMRUserRepositoryCustom.findUserByUserID(1L)).thenReturn(testUser); + when(ctiService.addUpdateUserData(anyString(), anyString())).thenAnswer(invocation -> { + ctiReleased.await(10, java.util.concurrent.TimeUnit.SECONDS); + return new OutputResponse(); + }); + when(securePassword.generateStrongPassword("newpassword")).thenReturn("hashedNewPassword"); + when(iEMRUserRepositoryCustom.updateSetForgetPassword(1L, "hashedNewPassword")).thenReturn(1); + + // When: the password is saved without waiting for CTI + int result = assertTimeoutPreemptively(java.time.Duration.ofSeconds(2), + () -> userService.setForgetPassword(testUser, "newpassword", "token123", true)); + + // Then: saved, and CTI is still updated in the background + assertEquals(1, result); + ctiReleased.countDown(); + verify(ctiService, timeout(2000)).addUpdateUserData(anyString(), eq("127.0.0.1")); + } + @Test void testSetForgetPassword_InvalidTransaction() throws Exception { // Given