diff --git a/build.gradle b/build.gradle index 6f6d210560..c9b0a21d5f 100644 --- a/build.gradle +++ b/build.gradle @@ -499,6 +499,8 @@ dependencies { implementation group: 'org.json', name: 'json', version: '20231013' implementation group: 'jakarta.enterprise', name: 'jakarta.enterprise.cdi-api', version: '4.0.1' + implementation group: 'com.github.ben-manes.caffeine', name: 'caffeine', version: '3.1.8' + annotationProcessor group: 'org.projectlombok', name: 'lombok', version: versions.lombok testImplementation 'com.github.hmcts:fortify-client:1.3.0:all' diff --git a/src/functionalTest/java/uk/gov/hmcts/sptribs/testutil/IdamTokenGenerator.java b/src/functionalTest/java/uk/gov/hmcts/sptribs/testutil/IdamTokenGenerator.java index 8886101d61..5e234ffae2 100644 --- a/src/functionalTest/java/uk/gov/hmcts/sptribs/testutil/IdamTokenGenerator.java +++ b/src/functionalTest/java/uk/gov/hmcts/sptribs/testutil/IdamTokenGenerator.java @@ -1,5 +1,7 @@ package uk.gov.hmcts.sptribs.testutil; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -7,6 +9,8 @@ import uk.gov.hmcts.reform.idam.client.IdamClient; import uk.gov.hmcts.reform.idam.client.models.UserDetails; +import java.util.concurrent.TimeUnit; + @TestPropertySource("classpath:application.yaml") @Service public class IdamTokenGenerator { @@ -38,24 +42,51 @@ public class IdamTokenGenerator { @Autowired private IdamClient idamClient; + private final Cache cache = Caffeine.newBuilder().expireAfterWrite(2, TimeUnit.HOURS).build(); + public String generateIdamTokenForSolicitor() { - return idamClient.getAccessToken(solicitorUsername, solicitorPassword); + String solicitorUserToken = cache.getIfPresent(solicitorUsername); + if (solicitorUserToken == null) { + solicitorUserToken = idamClient.getAccessToken(solicitorUsername, solicitorPassword); + cache.put(solicitorUsername, solicitorUserToken); + } + return solicitorUserToken; } public String generateIdamTokenForCaseworker() { - return idamClient.getAccessToken(caseworkerUsername, caseworkerPassword); + String caseworkerUserToken = cache.getIfPresent(caseworkerUsername); + if (caseworkerUserToken == null) { + caseworkerUserToken = idamClient.getAccessToken(caseworkerUsername, caseworkerPassword); + cache.put(caseworkerUsername, caseworkerUserToken); + } + return caseworkerUserToken; } - public String generateIdamTokenForSystem() { - return idamClient.getAccessToken(systemUpdateUsername, systemUpdatePassword); + public String generateIdamTokenForSystemUser() { + String systemUserToken = cache.getIfPresent(systemUpdateUsername); + if (systemUserToken == null) { + systemUserToken = idamClient.getAccessToken(systemUpdateUsername, systemUpdatePassword); + cache.put(systemUpdateUsername, systemUserToken); + } + return systemUserToken; } - public String generateIdamTokenForUser(String username, String password) { - return idamClient.getAccessToken(username, password); + public String generateIdamTokenForCitizen() { + String citizenUserToken = cache.getIfPresent(citizenUsername); + if (citizenUserToken == null) { + citizenUserToken = idamClient.getAccessToken(citizenUsername, citizenPassword); + cache.put(citizenUsername, citizenUserToken); + } + return citizenUserToken; } - public String generateIdamTokenForCitizen() { - return idamClient.getAccessToken(citizenUsername, citizenPassword); + public String generateIdamTokenForUser(String username, String password) { + String userToken = cache.getIfPresent(username); + if (userToken == null) { + userToken = idamClient.getAccessToken(username, password); + cache.put(username, userToken); + } + return userToken; } public UserDetails getUserDetailsFor(final String token) { diff --git a/src/main/java/uk/gov/hmcts/sptribs/idam/IdamService.java b/src/main/java/uk/gov/hmcts/sptribs/idam/IdamService.java index 7d16d875c3..5270b9e4a2 100644 --- a/src/main/java/uk/gov/hmcts/sptribs/idam/IdamService.java +++ b/src/main/java/uk/gov/hmcts/sptribs/idam/IdamService.java @@ -1,5 +1,7 @@ package uk.gov.hmcts.sptribs.idam; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -8,6 +10,8 @@ import uk.gov.hmcts.reform.idam.client.models.User; import uk.gov.hmcts.reform.idam.client.models.UserDetails; +import java.util.concurrent.TimeUnit; + import static uk.gov.hmcts.sptribs.common.config.ControllerConstants.BEARER_PREFIX; @Service @@ -19,6 +23,8 @@ public class IdamService { private final IdamClient idamClient; + private final Cache cache = Caffeine.newBuilder().expireAfterWrite(2, TimeUnit.HOURS).build(); + @Autowired public IdamService( @Value("${idam.systemupdate.username}") String systemUpdateUserName, @@ -37,11 +43,16 @@ public User retrieveUser(String authorisation) { } public User retrieveSystemUpdateUserDetails() { - return retrieveUser(getIdamOauth2Token(systemUpdateUserName, systemUpdatePassword)); + return retrieveUser(getCachedIdamOauth2Token(systemUpdateUserName, systemUpdatePassword)); } - private String getIdamOauth2Token(String username, String password) { - return idamClient.getAccessToken(username, password); + private String getCachedIdamOauth2Token(String username, String password) { + String userToken = cache.getIfPresent(username); + if (userToken == null) { + userToken = idamClient.getAccessToken(username, password); + cache.put(username, userToken); + } + return userToken; } private String getBearerToken(String token) { diff --git a/src/test/java/uk/gov/hmcts/sptribs/idam/IdamServiceTest.java b/src/test/java/uk/gov/hmcts/sptribs/idam/IdamServiceTest.java index 0258b940cb..43a5f47e6a 100644 --- a/src/test/java/uk/gov/hmcts/sptribs/idam/IdamServiceTest.java +++ b/src/test/java/uk/gov/hmcts/sptribs/idam/IdamServiceTest.java @@ -1,6 +1,7 @@ package uk.gov.hmcts.sptribs.idam; import feign.FeignException; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -35,13 +36,30 @@ public class IdamServiceTest { @Mock private IdamClient idamClient; + @BeforeEach + public void setUp() { + ReflectionTestUtils.setField(idamService, "systemUpdateUserName", TEST_SYSTEM_UPDATE_USER_EMAIL); + ReflectionTestUtils.setField(idamService, "systemUpdatePassword", TEST_SYSTEM_USER_PASSWORD); + } + + @Test + void shouldRetrieveUserDetails() { + final String bearerToken = TEST_SERVICE_AUTH_TOKEN; + final UserDetails userDetails = userDetails(); + + when(idamClient.getUserDetails(bearerToken)).thenReturn(userDetails()); + + final User result = idamService.retrieveUser(bearerToken); + + assertEquals(userDetails, result.getUserDetails()); + assertEquals(bearerToken, result.getAuthToken()); + } + @Test public void shouldRetrieveUserWhenValidAuthorizationTokenIsPassed() { - //Given when(idamClient.getUserDetails(SYSTEM_UPDATE_AUTH_TOKEN)) .thenReturn(userDetails()); - //When&Then assertThatCode(() -> idamService.retrieveUser(SYSTEM_UPDATE_AUTH_TOKEN)) .doesNotThrowAnyException(); @@ -51,7 +69,6 @@ public void shouldRetrieveUserWhenValidAuthorizationTokenIsPassed() { @Test public void shouldThrowFeignUnauthorizedExceptionWhenInValidAuthorizationTokenIsPassed() { - //When&Then doThrow(feignException(401, "Failed to retrieve Idam user")) .when(idamClient).getUserDetails("Bearer invalid_token"); @@ -62,16 +79,12 @@ public void shouldThrowFeignUnauthorizedExceptionWhenInValidAuthorizationTokenIs @Test public void shouldNotThrowExceptionAndRetrieveSystemUpdateUserSuccessfully() { - //Given - setSystemUserCredentials(); - when(idamClient.getAccessToken(TEST_SYSTEM_UPDATE_USER_EMAIL, TEST_SYSTEM_USER_PASSWORD)) .thenReturn(SYSTEM_UPDATE_AUTH_TOKEN); when(idamClient.getUserDetails(SYSTEM_UPDATE_AUTH_TOKEN)) .thenReturn(userDetails()); - //When&Then assertThatCode(() -> idamService.retrieveSystemUpdateUserDetails()) .doesNotThrowAnyException(); @@ -82,39 +95,14 @@ public void shouldNotThrowExceptionAndRetrieveSystemUpdateUserSuccessfully() { @Test public void shouldThrowFeignUnauthorizedExceptionWhenSystemUpdateUserCredentialsAreInvalid() { - //Given - setSystemUserCredentials(); - doThrow(feignException(401, "Failed to retrieve Idam user")) .when(idamClient).getAccessToken(TEST_SYSTEM_UPDATE_USER_EMAIL, TEST_SYSTEM_USER_PASSWORD); - //When&Then assertThatThrownBy(() -> idamService.retrieveSystemUpdateUserDetails()) .isExactlyInstanceOf(FeignException.Unauthorized.class) .hasMessageContaining("Failed to retrieve Idam user"); } - @Test - void shouldRetrieveUserDetails() { - // Given - final String bearerToken = TEST_SERVICE_AUTH_TOKEN; - final UserDetails userDetails = userDetails(); - - // When - when(idamClient.getUserDetails(bearerToken)).thenReturn(userDetails()); - - final User result = idamService.retrieveUser(bearerToken); - - //Then - assertEquals(userDetails, result.getUserDetails()); - assertEquals(bearerToken, result.getAuthToken()); - } - - private void setSystemUserCredentials() { - ReflectionTestUtils.setField(idamService, "systemUpdateUserName", TEST_SYSTEM_UPDATE_USER_EMAIL); - ReflectionTestUtils.setField(idamService, "systemUpdatePassword", TEST_SYSTEM_USER_PASSWORD); - } - private UserDetails userDetails() { return UserDetails .builder()