From 744a8152d3091e2a8802749b7cfbd51425e02a77 Mon Sep 17 00:00:00 2001 From: Ricardo Campos Date: Thu, 8 Feb 2024 13:59:42 -0300 Subject: [PATCH] test: add test cases --- backend/pom.xml | 4 + .../results/config/SecurityConfig.java | 1 - .../results/security/LoggedUserService.java | 17 +- .../src/main/resources/application.properties | 6 +- .../results/endpoint/OpeningEndpointTest.java | 2 + .../UserAuthenticationHelperTest.java | 113 ++++++++++++ .../results/security/UserInfoTest.java | 142 +++++++++++++++ .../results/security/UserServiceTest.java | 168 ++++++++++++++++++ .../src/test/resources/application.properties | 4 + 9 files changed, 442 insertions(+), 15 deletions(-) create mode 100644 backend/src/test/java/ca/bc/gov/restapi/results/security/UserAuthenticationHelperTest.java create mode 100644 backend/src/test/java/ca/bc/gov/restapi/results/security/UserInfoTest.java create mode 100644 backend/src/test/java/ca/bc/gov/restapi/results/security/UserServiceTest.java diff --git a/backend/pom.xml b/backend/pom.xml index 96df1433..c16d35b9 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -162,6 +162,10 @@ h2 test + + org.springframework.security + spring-security-test + diff --git a/backend/src/main/java/ca/bc/gov/restapi/results/config/SecurityConfig.java b/backend/src/main/java/ca/bc/gov/restapi/results/config/SecurityConfig.java index f0c2678c..b38e20be 100644 --- a/backend/src/main/java/ca/bc/gov/restapi/results/config/SecurityConfig.java +++ b/backend/src/main/java/ca/bc/gov/restapi/results/config/SecurityConfig.java @@ -3,7 +3,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; - import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/backend/src/main/java/ca/bc/gov/restapi/results/security/LoggedUserService.java b/backend/src/main/java/ca/bc/gov/restapi/results/security/LoggedUserService.java index 90f55b6e..7ec5fb97 100644 --- a/backend/src/main/java/ca/bc/gov/restapi/results/security/LoggedUserService.java +++ b/backend/src/main/java/ca/bc/gov/restapi/results/security/LoggedUserService.java @@ -78,19 +78,10 @@ public String getLoggedUserIdirOrBceId() { } UserInfo userInfo = userInfoOp.get(); - switch (userInfo.identityProvider()) { - case IDIR: - { - return userInfo.idirUsername(); - } - case BUSINESS_BCEID: - { - return userInfo.businessName(); - } - default: - { - return ""; - } + if (IdentityProvider.IDIR.equals(userInfo.identityProvider())) { + return userInfo.idirUsername(); } + + return userInfo.businessName(); } } diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 9e578c39..96bd9c11 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -41,4 +41,8 @@ nr-results-team-email-address = Team.Silva@gov.bc.ca # Certificate for the Database ca.bc.gov.nrs.oracle.keystore = ${ORACLEDB_KEYSTORE:jssecacerts-path} ca.bc.gov.nrs.oracle.secret = ${ORACLEDB_SECRET:changeit} -ca.bc.gov.nrs.oracle.host = ${DATABASE_HOST} \ No newline at end of file +ca.bc.gov.nrs.oracle.host = ${DATABASE_HOST} + +# FAM +spring.security.oauth2.resourceserver.jwt.issuer-uri = ${AWS_COGNITO_ISSUER_URI:aws-cognito-any-url.com} +spring.security.oauth2.resourceserver.jwt.jwk-set-uri = ${AWS_COGNITO_ISSUER_URI:aws-cognito-any-url.com}/.well-known/jwks.json diff --git a/backend/src/test/java/ca/bc/gov/restapi/results/endpoint/OpeningEndpointTest.java b/backend/src/test/java/ca/bc/gov/restapi/results/endpoint/OpeningEndpointTest.java index 515e41b9..856929c8 100644 --- a/backend/src/test/java/ca/bc/gov/restapi/results/endpoint/OpeningEndpointTest.java +++ b/backend/src/test/java/ca/bc/gov/restapi/results/endpoint/OpeningEndpointTest.java @@ -21,9 +21,11 @@ import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.web.servlet.MockMvc; @WebMvcTest(OpeningEndpoint.class) +@WithMockUser(roles = "user_read") class OpeningEndpointTest { @Autowired private MockMvc mockMvc; diff --git a/backend/src/test/java/ca/bc/gov/restapi/results/security/UserAuthenticationHelperTest.java b/backend/src/test/java/ca/bc/gov/restapi/results/security/UserAuthenticationHelperTest.java new file mode 100644 index 00000000..8299d477 --- /dev/null +++ b/backend/src/test/java/ca/bc/gov/restapi/results/security/UserAuthenticationHelperTest.java @@ -0,0 +1,113 @@ +package ca.bc.gov.restapi.results.security; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.List; +import java.util.Optional; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +class UserAuthenticationHelperTest { + + private UserAuthenticationHelper userAuthenticationHelper; + + @BeforeEach + void setup() { + userAuthenticationHelper = new UserAuthenticationHelper(); + } + + @Test + @DisplayName("getUserInfoIdirTest") + void getUserInfoIdirTest() { + Authentication authentication = mock(Authentication.class); + SecurityContext securityContext = mock(SecurityContext.class); + SecurityContextHolder.setContext(securityContext); + + when(securityContext.getAuthentication()).thenReturn(authentication); + when(authentication.isAuthenticated()).thenReturn(true); + + Jwt.Builder builder = Jwt.withTokenValue("myTokenValue"); + builder.subject("BAGGINGS"); + builder.header("alg", "HS256"); + builder.header("typ", "JWT"); + builder.claim("email", "bilbo.baggings@gov.bc.ca"); + builder.claim("custom:idp_display_name", "from Baggings, Bilbo LWRS:EX"); + builder.claim("custom:idp_username", "BAGGINGS"); + builder.claim("custom:idp_name", "idir"); + builder.claim("cognito:username", "IDIR@BAGGINGS"); + builder.claim("client_roles", List.of("admin", "manager")); + + when(authentication.getPrincipal()).thenReturn(builder.build()); + + Optional userInfoOptional = userAuthenticationHelper.getUserInfo(); + Assertions.assertTrue(userInfoOptional.isPresent()); + + UserInfo userInfo = userInfoOptional.get(); + Assertions.assertEquals("IDIR@BAGGINGS", userInfo.id()); + Assertions.assertEquals("Bilbo", userInfo.firstName()); + Assertions.assertEquals("Baggings", userInfo.lastName()); + Assertions.assertEquals("bilbo.baggings@gov.bc.ca", userInfo.email()); + Assertions.assertEquals("from Baggings, Bilbo LWRS:EX", userInfo.displayName()); + Assertions.assertEquals("BAGGINGS", userInfo.idirUsername()); + Assertions.assertEquals(IdentityProvider.IDIR, userInfo.identityProvider()); + Assertions.assertEquals(2, userInfo.roles().size()); + } + + @Test + @DisplayName("getUserInfoBusinessBceidTest") + void getUserInfoBusinessBceidTest() { + Authentication authentication = mock(Authentication.class); + SecurityContext securityContext = mock(SecurityContext.class); + SecurityContextHolder.setContext(securityContext); + + when(securityContext.getAuthentication()).thenReturn(authentication); + when(authentication.isAuthenticated()).thenReturn(true); + + Jwt.Builder builder = Jwt.withTokenValue("myTokenValue"); + builder.subject("MORDOR-BCEID"); + builder.header("alg", "HS256"); + builder.header("typ", "JWT"); + builder.claim("email", "lord.sauron@mordor.middleearth"); + builder.claim("custom:idp_display_name", "Lord Sauron of Mordor"); + builder.claim("custom:idp_username", "MORDOR-BCEID"); + builder.claim("custom:idp_name", "bceidbusiness"); + builder.claim("cognito:username", "BCEIDBUSINESS@MORDOR-BCEID"); + + when(authentication.getPrincipal()).thenReturn(builder.build()); + + Optional userInfoOptional = userAuthenticationHelper.getUserInfo(); + Assertions.assertTrue(userInfoOptional.isPresent()); + + UserInfo userInfo = userInfoOptional.get(); + Assertions.assertEquals("BCEIDBUSINESS@MORDOR-BCEID", userInfo.id()); + Assertions.assertEquals("Lord", userInfo.firstName()); + Assertions.assertEquals("Sauron of Mordor", userInfo.lastName()); + Assertions.assertEquals("lord.sauron@mordor.middleearth", userInfo.email()); + Assertions.assertEquals("Lord Sauron of Mordor", userInfo.displayName()); + Assertions.assertEquals("MORDOR-BCEID", userInfo.businessName()); + Assertions.assertEquals(IdentityProvider.BUSINESS_BCEID, userInfo.identityProvider()); + } + + @Test + @DisplayName("getUserInfoTestNotAuthenticated") + void getUserInfoTestNotAuthenticated() { + Authentication authentication = mock(Authentication.class); + SecurityContext securityContext = mock(SecurityContext.class); + SecurityContextHolder.setContext(securityContext); + + when(securityContext.getAuthentication()).thenReturn(authentication); + + Optional userInfoOptional = userAuthenticationHelper.getUserInfo(); + Assertions.assertFalse(userInfoOptional.isPresent()); + } +} diff --git a/backend/src/test/java/ca/bc/gov/restapi/results/security/UserInfoTest.java b/backend/src/test/java/ca/bc/gov/restapi/results/security/UserInfoTest.java new file mode 100644 index 00000000..4f7b5fda --- /dev/null +++ b/backend/src/test/java/ca/bc/gov/restapi/results/security/UserInfoTest.java @@ -0,0 +1,142 @@ +package ca.bc.gov.restapi.results.security; + +import java.util.Set; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class UserInfoTest { + + @Test + @DisplayName("createUserInfo") + void createUserInfo() { + UserInfo userInfo = + new UserInfo( + "123456789@idir", + "Bilbo", + "Baggings", + "bilbo.baggings@gov.bc.ca", + "Baggings, Bilbo LWRS:EX", + "BAGGINGS", + null, + IdentityProvider.IDIR, + Set.of(), + "abcdef123456789"); + + Assertions.assertNotNull(userInfo); + Assertions.assertEquals("Bilbo", userInfo.firstName()); + Assertions.assertEquals("Baggings", userInfo.lastName()); + Assertions.assertEquals("bilbo.baggings@gov.bc.ca", userInfo.email()); + Assertions.assertEquals("Baggings, Bilbo LWRS:EX", userInfo.displayName()); + Assertions.assertEquals("BAGGINGS", userInfo.idirUsername()); + Assertions.assertNull(userInfo.businessName()); + Assertions.assertEquals(IdentityProvider.IDIR, userInfo.identityProvider()); + Assertions.assertTrue(userInfo.roles().isEmpty()); + } + + @Test + @DisplayName("createInvalidNullUser") + void createInvalidNullUser() { + // Id not null + Assertions.assertThrows( + NullPointerException.class, + () -> { + new UserInfo( + null, + "Bilbo", + "Baggings", + "bilbo.baggings@gov.bc.ca", + "Baggings, Bilbo LWRS:EX", + "BAGGINGS", + null, + IdentityProvider.IDIR, + Set.of(), + "abcdef123456789"); + }); + + // E-mail not null + Assertions.assertThrows( + NullPointerException.class, + () -> { + new UserInfo( + "123456789@idir", + "Bilbo", + "Baggings", + null, + "Baggings, Bilbo LWRS:EX", + "BAGGINGS", + null, + IdentityProvider.IDIR, + Set.of(), + "abcdef123456789"); + }); + + // Display name not null + Assertions.assertThrows( + NullPointerException.class, + () -> { + new UserInfo( + "123456789@idir", + "Bilbo", + "Baggings", + "bilbo.baggings@gov.bc.ca", + null, + "BAGGINGS", + null, + IdentityProvider.IDIR, + Set.of(), + "abcdef123456789"); + }); + + // Identity provider not null + Assertions.assertThrows( + NullPointerException.class, + () -> { + new UserInfo( + "123456789@idir", + "Bilbo", + "Baggings", + "bilbo.baggings@gov.bc.ca", + "Baggings, Bilbo LWRS:EX", + "BAGGINGS", + null, + null, + Set.of(), + "abcdef123456789"); + }); + + // Roles not null + Assertions.assertThrows( + NullPointerException.class, + () -> { + new UserInfo( + "123456789@idir", + "Bilbo", + "Baggings", + "bilbo.baggings@gov.bc.ca", + "Baggings, Bilbo LWRS:EX", + "BAGGINGS", + null, + IdentityProvider.IDIR, + null, + "abcdef123456789"); + }); + + // Token not null + Assertions.assertThrows( + NullPointerException.class, + () -> { + new UserInfo( + "123456789@idir", + "Bilbo", + "Baggings", + "bilbo.baggings@gov.bc.ca", + "Baggings, Bilbo LWRS:EX", + "BAGGINGS", + null, + IdentityProvider.IDIR, + Set.of(), + null); + }); + } +} diff --git a/backend/src/test/java/ca/bc/gov/restapi/results/security/UserServiceTest.java b/backend/src/test/java/ca/bc/gov/restapi/results/security/UserServiceTest.java new file mode 100644 index 00000000..9de777bc --- /dev/null +++ b/backend/src/test/java/ca/bc/gov/restapi/results/security/UserServiceTest.java @@ -0,0 +1,168 @@ +package ca.bc.gov.restapi.results.security; + +import static org.mockito.Mockito.when; + +import ca.bc.gov.restapi.results.exception.UserNotFoundException; +import java.util.Optional; +import java.util.Set; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +class UserServiceTest { + + @Mock UserAuthenticationHelper userAuthenticationHelper; + + private LoggedUserService loggedUserService; + + private UserInfo userInfo; + + private UserInfo createUserInfo(boolean isIdir) { + IdentityProvider provider = isIdir ? IdentityProvider.IDIR : IdentityProvider.BUSINESS_BCEID; + + return new UserInfo( + "123456789@idir", + "User", + "Test", + "user@test.com", + "Test, User: LWRS:EX", + isIdir ? "USERT" : null, + !isIdir ? "user-my-bceid" : null, + provider, + Set.of(), + "abcdef123456789"); + } + + @BeforeEach + void setup() { + loggedUserService = new LoggedUserService(userAuthenticationHelper); + userInfo = createUserInfo(true); + } + + @Test + @DisplayName("getLoggedUserEmailTest") + void getLoggedUserEmailTest() { + when(userAuthenticationHelper.getUserInfo()).thenReturn(Optional.of(userInfo)); + + String userEmail = loggedUserService.getLoggedUserEmail(); + + Assertions.assertEquals("user@test.com", userEmail); + } + + @Test + @DisplayName("getLoggedUserEmailExceptionTest") + void getLoggedUserEmailExceptionTest() { + Exception e = + Assertions.assertThrows( + UserNotFoundException.class, + () -> { + loggedUserService.getLoggedUserEmail(); + }); + + Assertions.assertEquals("404 NOT_FOUND \"User not registered!\"", e.getMessage()); + } + + @Test + @DisplayName("getLoggerUserInfoTest") + void getLoggerUserInfoTest() { + when(userAuthenticationHelper.getUserInfo()).thenReturn(Optional.of(userInfo)); + + Optional userInfoOp = loggedUserService.getLoggedUserInfo(); + + Assertions.assertTrue(userInfoOp.isPresent()); + } + + @Test + void createUserService() { + LoggedUserService loggedUserService1 = new LoggedUserService(userAuthenticationHelper); + Assertions.assertNotNull(loggedUserService1); + } + + @Test + @DisplayName("getLoggedUserTokenTest") + void getLoggedUserTokenTest() { + when(userAuthenticationHelper.getUserInfo()).thenReturn(Optional.of(userInfo)); + + String userToken = loggedUserService.getLoggedUserToken(); + + Assertions.assertEquals("abcdef123456789", userToken); + } + + @Test + @DisplayName("getLoggedUserTokenEmptyTest") + void getLoggedUserTokenEmptyTest() { + Exception e = + Assertions.assertThrows( + UserNotFoundException.class, + () -> { + loggedUserService.getLoggedUserToken(); + }); + + Assertions.assertEquals("404 NOT_FOUND \"User not registered!\"", e.getMessage()); + } + + @Test + @DisplayName("getLoggedUserIdEmptyTest") + void getLoggedUserIdEmptyTest() { + when(userAuthenticationHelper.getUserInfo()).thenReturn(Optional.empty()); + + Exception e = + Assertions.assertThrows( + UserNotFoundException.class, + () -> { + loggedUserService.getLoggedUserId(); + }); + + Assertions.assertEquals("404 NOT_FOUND \"User not registered!\"", e.getMessage()); + } + + @Test + @DisplayName("getLoggedUserIdSuccessTest") + void getLoggedUserIdSuccessTest() { + when(userAuthenticationHelper.getUserInfo()).thenReturn(Optional.of(userInfo)); + + String userId = loggedUserService.getLoggedUserId(); + + Assertions.assertEquals("123456789@idir", userId); + } + + @Test + @DisplayName("getLoggedUserIdirOrBceIdSuccessTest") + void getLoggedUserIdirOrBceIdSuccessTest() { + // IDIR + UserInfo idirUser = createUserInfo(true); + when(userAuthenticationHelper.getUserInfo()).thenReturn(Optional.of(idirUser)); + String userId = loggedUserService.getLoggedUserIdirOrBceId(); + + Assertions.assertFalse(userId.isEmpty()); + Assertions.assertEquals("USERT", idirUser.idirUsername()); + Assertions.assertNull(idirUser.businessName()); + + // BCeID + UserInfo bceIdUser = createUserInfo(false); + when(userAuthenticationHelper.getUserInfo()).thenReturn(Optional.of(bceIdUser)); + userId = loggedUserService.getLoggedUserIdirOrBceId(); + + Assertions.assertFalse(userId.isEmpty()); + Assertions.assertEquals("user-my-bceid", bceIdUser.businessName()); + Assertions.assertNull(bceIdUser.idirUsername()); + } + + @Test + @DisplayName("getLoggedUserIdirOrBceIdEmptyTest") + void getLoggedUserIdirOrBceIdEmptyTest() { + Exception e = + Assertions.assertThrows( + UserNotFoundException.class, + () -> { + loggedUserService.getLoggedUserIdirOrBceId(); + }); + + Assertions.assertEquals("404 NOT_FOUND \"User not registered!\"", e.getMessage()); + } +} diff --git a/backend/src/test/resources/application.properties b/backend/src/test/resources/application.properties index b4c6c298..16d57820 100644 --- a/backend/src/test/resources/application.properties +++ b/backend/src/test/resources/application.properties @@ -11,3 +11,7 @@ spring.jpa.database-platform=org.hibernate.dialect.H2Dialect spring.jpa.show-sql=true spring.jpa.hibernate.generate-ddl = true spring.jpa.hibernate.ddl-auto = create-drop + +# FAM +spring.security.oauth2.resourceserver.jwt.issuer-uri = https://aws-cognito-issuer-uri.aws.com +spring.security.oauth2.resourceserver.jwt.jwk-set-uri = https://aws-cognito-issuer-uri.aws.com/.well-known/jwks.json