Skip to content

Commit

Permalink
Fix @Cacheable self invocation (#2949)
Browse files Browse the repository at this point in the history
* DTSCCI-242: Fix @Cacheable self invocation

* DTSCCI-242: Fix contract test config

* Re-enable pact tests on PR

* DTSCCI-242: Fix @Cacheable self invocation
  • Loading branch information
nigeldunne authored Aug 7, 2024
1 parent bd45c9b commit 26019e8
Show file tree
Hide file tree
Showing 8 changed files with 195 additions and 46 deletions.
1 change: 1 addition & 0 deletions Jenkinsfile_CNP
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ withPipeline("java", product, component) {
env.ENVIRONMENT = "preview"
env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
loadVaultSecrets(secrets)
enablePactAs([AppPipelineDsl.PactRoles.PROVIDER])
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import uk.gov.hmcts.cmc.claimstore.services.ClaimService;
import uk.gov.hmcts.cmc.claimstore.services.IssueDateCalculator;
import uk.gov.hmcts.cmc.claimstore.services.ResponseDeadlineCalculator;
import uk.gov.hmcts.cmc.claimstore.services.UserAuthorisationTokenService;
import uk.gov.hmcts.cmc.claimstore.services.UserInfoService;
import uk.gov.hmcts.cmc.claimstore.services.UserService;
import uk.gov.hmcts.cmc.claimstore.services.ccd.CoreCaseDataService;
import uk.gov.hmcts.cmc.launchdarkly.LaunchDarklyClient;
Expand Down Expand Up @@ -64,9 +66,19 @@ public ClaimAuthorisationRule claimAuthorisationRule() {
return new ClaimAuthorisationRule(userService());
}

@Bean
public UserInfoService userInfoService() {
return new UserInfoService(idamApi);
}

@Bean
public UserAuthorisationTokenService userAuthorisationTokenService() {
return new UserAuthorisationTokenService(idamApi, oauth2);
}

@Bean
public UserService userService() {
return new UserService(idamApi, idamCaseworkerProperties, oauth2);
return new UserService(idamApi, idamCaseworkerProperties, oauth2, userInfoService(), userAuthorisationTokenService());
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package uk.gov.hmcts.cmc.claimstore.services;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import uk.gov.hmcts.cmc.claimstore.models.idam.Oauth2;
import uk.gov.hmcts.cmc.claimstore.models.idam.TokenExchangeResponse;
import uk.gov.hmcts.cmc.claimstore.requests.idam.IdamApi;
import uk.gov.hmcts.cmc.claimstore.stereotypes.LogExecutionTime;

@Component
public class UserAuthorisationTokenService {
public static final String GRANT_TYPE_PASSWORD = "password";
public static final String DEFAULT_SCOPE = "openid profile roles";
public static final String BEARER = "Bearer ";

private final IdamApi idamApi;
private final Oauth2 oauth2;
Logger logger = LoggerFactory.getLogger(this.getClass());

public UserAuthorisationTokenService(IdamApi idamApi, Oauth2 oauth2) {
this.idamApi = idamApi;
this.oauth2 = oauth2;
}

@LogExecutionTime
@Cacheable(value = "userOIDTokenCache")
public String getAuthorisationToken(String username, String password) {
logger.info("IDAM /o/token invoked.");
TokenExchangeResponse tokenExchangeResponse = idamApi.exchangeToken(
oauth2.getClientId(),
oauth2.getClientSecret(),
oauth2.getRedirectUrl(),
GRANT_TYPE_PASSWORD,
username,
password,
DEFAULT_SCOPE);
return BEARER + tokenExchangeResponse.getAccessToken();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package uk.gov.hmcts.cmc.claimstore.services;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import uk.gov.hmcts.cmc.claimstore.models.idam.UserInfo;
import uk.gov.hmcts.cmc.claimstore.requests.idam.IdamApi;
import uk.gov.hmcts.cmc.claimstore.stereotypes.LogExecutionTime;

@Component
public class UserInfoService {

private final IdamApi idamApi;
Logger logger = LoggerFactory.getLogger(this.getClass());

public UserInfoService(IdamApi idamApi) {
this.idamApi = idamApi;
}

@LogExecutionTime
@Cacheable(value = "userInfoCache")
public UserInfo getUserInfo(String bearerToken) {
logger.info("IDAM /o/userinfo invoked");
return idamApi.retrieveUserInfo(bearerToken);
}
}
37 changes: 11 additions & 26 deletions src/main/java/uk/gov/hmcts/cmc/claimstore/services/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import uk.gov.hmcts.cmc.claimstore.config.properties.idam.IdamCaseworker;
import uk.gov.hmcts.cmc.claimstore.config.properties.idam.IdamCaseworkerProperties;
Expand All @@ -19,28 +18,32 @@ public class UserService {
public static final String AUTHORIZATION_CODE = "authorization_code";
public static final String CODE = "code";
public static final String BASIC = "Basic ";
public static final String GRANT_TYPE_PASSWORD = "password";
public static final String DEFAULT_SCOPE = "openid profile roles";
private final IdamApi idamApi;
private final IdamCaseworkerProperties idamCaseworkerProperties;
private final Oauth2 oauth2;
private final UserInfoService userInfoService;
private final UserAuthorisationTokenService userAuthorisationTokenService;
Logger logger = LoggerFactory.getLogger(this.getClass());

@Autowired
public UserService(
IdamApi idamApi,
IdamCaseworkerProperties idamCaseworkerProperties,
Oauth2 oauth2
Oauth2 oauth2,
UserInfoService userInfoService,
UserAuthorisationTokenService userAuthorisationTokenService
) {
this.idamApi = idamApi;
this.idamCaseworkerProperties = idamCaseworkerProperties;
this.oauth2 = oauth2;
this.userInfoService = userInfoService;
this.userAuthorisationTokenService = userAuthorisationTokenService;
}

@LogExecutionTime
public UserDetails getUserDetails(String authorisation) {
logger.info("User info invoked");
UserInfo userInfo = getUserInfo(authorisation);
UserInfo userInfo = userInfoService.getUserInfo(authorisation);

return UserDetails.builder()
.id(userInfo.getUid())
Expand All @@ -58,7 +61,7 @@ public User getUser(String authorisation) {

public User authenticateUser(String username, String password) {

String authorisation = getAuthorisationToken(username, password);
String authorisation = userAuthorisationTokenService.getAuthorisationToken(username, password);
UserDetails userDetails = getUserDetails(authorisation);
return new User(authorisation, userDetails);
}
Expand All @@ -74,26 +77,8 @@ public GeneratePinResponse generatePin(String name, String authorisation) {
return idamApi.generatePin(new GeneratePinRequest(name), authorisation);
}

@LogExecutionTime
@Cacheable(value = "userOIDTokenCache")
public String getAuthorisationToken(String username, String password) {
logger.info("IDAM /o/token invoked.");
TokenExchangeResponse tokenExchangeResponse = idamApi.exchangeToken(
oauth2.getClientId(),
oauth2.getClientSecret(),
oauth2.getRedirectUrl(),
GRANT_TYPE_PASSWORD,
username,
password,
DEFAULT_SCOPE);
return BEARER + tokenExchangeResponse.getAccessToken();
}

@LogExecutionTime
@Cacheable(value = "userInfoCache")
public UserInfo getUserInfo(String bearerToken) {
logger.info("IDAM /o/userinfo invoked");
return idamApi.retrieveUserInfo(bearerToken);
return userInfoService.getUserInfo(bearerToken);
}

public User authenticateUserForTests(String username, String password) {
Expand All @@ -111,7 +96,7 @@ public String getAuthorisationTokenForTests(String username, String password) {
oauth2.getClientId(),
oauth2.getRedirectUrl()
);
logger.info("IDAM /o/token invoked.");
logger.info("IDAM /o/token invoked for tests.");
TokenExchangeResponse tokenExchangeResponse = idamApi.exchangeTokenForTests(
authenticateUserResponse.getCode(),
AUTHORIZATION_CODE,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package uk.gov.hmcts.cmc.claimstore.services;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import uk.gov.hmcts.cmc.claimstore.models.idam.Oauth2;
import uk.gov.hmcts.cmc.claimstore.models.idam.TokenExchangeResponse;
import uk.gov.hmcts.cmc.claimstore.requests.idam.IdamApi;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class UserAuthorisationTokenServiceTest {
private static final String TOKEN = "I am a valid token";
public static final String BEARER = "Bearer ";
private static final String USERNAME = "Username";
private static final String PASSWORD = "Password";

@Mock
private IdamApi idamApi;
@Mock
private Oauth2 oauth2;
@InjectMocks
private UserAuthorisationTokenService userAuthorisationTokenService;

@Mock
TokenExchangeResponse tokenExchangeResponse;

@Test
void findsUserInfoForAuthToken() {
when(idamApi.exchangeToken(
any(),
any(),
any(),
any(),
eq(USERNAME),
eq(PASSWORD),
any())
).thenReturn(tokenExchangeResponse);
when(tokenExchangeResponse.getAccessToken()).thenReturn(TOKEN);

final String authorisationToken = userAuthorisationTokenService.getAuthorisationToken(USERNAME, PASSWORD);
assertEquals(BEARER + TOKEN, authorisationToken);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package uk.gov.hmcts.cmc.claimstore.services;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import uk.gov.hmcts.cmc.claimstore.requests.idam.IdamApi;

import static org.mockito.Mockito.verify;

@ExtendWith(MockitoExtension.class)
class UserInfoServiceTest {
private static final String AUTHORISATION = "Bearer I am a valid token";

@Mock
private IdamApi idamApi;
@InjectMocks
private UserInfoService userInfoService;

@Test
void findsUserInfoForAuthToken() {
userInfoService.getUserInfo(AUTHORISATION);
verify(idamApi).retrieveUserInfo(AUTHORISATION);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package uk.gov.hmcts.cmc.claimstore.services;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import uk.gov.hmcts.cmc.claimstore.config.properties.idam.IdamCaseworkerProperties;
Expand All @@ -13,6 +13,7 @@

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static uk.gov.hmcts.cmc.claimstore.events.utils.sampledata.SampleClaimIssuedEvent.PIN;
import static uk.gov.hmcts.cmc.claimstore.services.UserService.CODE;
Expand Down Expand Up @@ -45,34 +46,27 @@ class UserServiceTest {
private IdamCaseworkerProperties idamCaseworkerProperties;
@Mock
private Oauth2 oauth2;
@Mock
private UserInfoService userInfoService;
@Mock
private UserAuthorisationTokenService userAuthorisationTokenService;

@InjectMocks
private UserService userService;

@BeforeEach
void setup() {
userService = new UserService(idamApi, idamCaseworkerProperties, oauth2);
}

@Test
void findsUserInfoForAuthToken() {
when(idamApi.retrieveUserInfo(AUTHORISATION)).thenReturn(userInfo);

UserInfo found = userService.getUserInfo(AUTHORISATION);

assertThat(found.getSub()).isEqualTo(SUB);
assertThat(found.getUid()).isEqualTo(UID);
assertThat(found.getName()).isEqualTo(NAME);
assertThat(found.getGivenName()).isEqualTo(GIVEN_NAME);
assertThat(found.getFamilyName()).isEqualTo(FAMILY_NAME);
assertThat(found.getRoles()).isEqualTo(ROLES);
userService.getUserInfo(AUTHORISATION);
verify(userInfoService).getUserInfo(AUTHORISATION);
}

@Test
void findsUserDetailsForAuthToken() {
when(idamApi.retrieveUserInfo(AUTHORISATION)).thenReturn(userInfo);
when(userInfoService.getUserInfo(AUTHORISATION)).thenReturn(userInfo);

UserDetails userDetails = userService.getUserDetails(AUTHORISATION);

verify(userInfoService).getUserInfo(AUTHORISATION);
verifyUserDetails(userDetails);
}

Expand Down Expand Up @@ -111,19 +105,32 @@ void generatePinShouldGenerateValidPin() {
assertThat(response.getUserId()).isEqualTo(UID);
}

@Test
void shouldAuthenticateUser() {
when(userAuthorisationTokenService.getAuthorisationToken(USERNAME, PASSWORD)).thenReturn(AUTHORISATION);
when(userInfoService.getUserInfo(AUTHORISATION))
.thenReturn(userInfo);

User user = userService.authenticateUser(USERNAME, PASSWORD);

verify(userAuthorisationTokenService).getAuthorisationToken(USERNAME, PASSWORD);
assertThat(user.getAuthorisation()).isEqualTo(AUTHORISATION);
assertUserDetails(user.getUserDetails());
}

@Test
void authenticateUserShouldReturnUser() {

when(idamApi.authenticateUser(anyString(), eq(CODE), any(), any()))
.thenReturn(new AuthenticateUserResponse(CODE));
when(idamApi.exchangeTokenForTests(eq(CODE), eq(AUTHORIZATION_CODE), any(), any(), any()))
.thenReturn(new TokenExchangeResponse("I am a valid token"));

when(idamApi.retrieveUserInfo(AUTHORISATION))
when(userInfoService.getUserInfo(AUTHORISATION))
.thenReturn(userInfo);

User user = userService.authenticateUserForTests(USERNAME, PASSWORD);

verify(userInfoService).getUserInfo(AUTHORISATION);
assertThat(user.getAuthorisation()).isEqualTo(AUTHORISATION);
assertUserDetails(user.getUserDetails());
}
Expand Down

0 comments on commit 26019e8

Please sign in to comment.