From 74d7da2ec9720df2909b6c07ee2db27c886e55d7 Mon Sep 17 00:00:00 2001 From: rachelswart <99667350+rachelswart@users.noreply.github.com> Date: Tue, 16 Jan 2024 16:24:26 +0000 Subject: [PATCH 1/5] TMI2-556: Fix spotlight oauth query (#172) * only get latest success or failure audit * removed old query * pr comments * added space --- .../repository/SpotlightOAuthAuditRepository.java | 7 ++++++- .../gapuserservice/service/SpotlightService.java | 6 ++++-- .../gapuserservice/web/SpotlightController.java | 2 +- .../service/SpotlightServiceTest.java | 13 ------------- .../web/SpotlightControllerTest.java | 14 +++++++++++--- 5 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/main/java/gov/cabinetofice/gapuserservice/repository/SpotlightOAuthAuditRepository.java b/src/main/java/gov/cabinetofice/gapuserservice/repository/SpotlightOAuthAuditRepository.java index b98138e3..35af9144 100644 --- a/src/main/java/gov/cabinetofice/gapuserservice/repository/SpotlightOAuthAuditRepository.java +++ b/src/main/java/gov/cabinetofice/gapuserservice/repository/SpotlightOAuthAuditRepository.java @@ -1,10 +1,15 @@ package gov.cabinetofice.gapuserservice.repository; +import gov.cabinetofice.gapuserservice.enums.SpotlightOAuthAuditStatus; import gov.cabinetofice.gapuserservice.model.SpotlightOAuthAudit; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.Collection; + @Repository public interface SpotlightOAuthAuditRepository extends JpaRepository { - SpotlightOAuthAudit findFirstByOrderByIdDesc(); + + SpotlightOAuthAudit findFirstByStatusInOrderByIdDesc(Collection statuses); + } \ No newline at end of file diff --git a/src/main/java/gov/cabinetofice/gapuserservice/service/SpotlightService.java b/src/main/java/gov/cabinetofice/gapuserservice/service/SpotlightService.java index 4b885940..2c988cb5 100644 --- a/src/main/java/gov/cabinetofice/gapuserservice/service/SpotlightService.java +++ b/src/main/java/gov/cabinetofice/gapuserservice/service/SpotlightService.java @@ -3,6 +3,7 @@ import com.nimbusds.jose.shaded.gson.JsonObject; import com.nimbusds.jose.shaded.gson.JsonParser; import gov.cabinetofice.gapuserservice.config.SpotlightConfig; +import gov.cabinetofice.gapuserservice.enums.SpotlightOAuthAuditStatus; import gov.cabinetofice.gapuserservice.exceptions.InvalidRequestException; import gov.cabinetofice.gapuserservice.exceptions.SpotlightInvalidStateException; import gov.cabinetofice.gapuserservice.model.SpotlightOAuthAudit; @@ -26,6 +27,7 @@ import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Base64; +import java.util.List; @RequiredArgsConstructor @Service @@ -47,8 +49,8 @@ public class SpotlightService { private final static String ACCESS_TOKEN_NAME = "access_token"; private final static String REFRESH_TOKEN_NAME = "refresh_token"; - public SpotlightOAuthAudit getLatestAudit() { - return spotlightOAuthAuditRepository.findFirstByOrderByIdDesc(); + public SpotlightOAuthAudit getLatestSuccessOrFailureAudit() { + return spotlightOAuthAuditRepository.findFirstByStatusInOrderByIdDesc(List.of(SpotlightOAuthAuditStatus.SUCCESS, SpotlightOAuthAuditStatus.FAILURE)); } public void saveAudit(SpotlightOAuthAudit spotlightOAuthAudit) { diff --git a/src/main/java/gov/cabinetofice/gapuserservice/web/SpotlightController.java b/src/main/java/gov/cabinetofice/gapuserservice/web/SpotlightController.java index 182e9520..ec4b7066 100644 --- a/src/main/java/gov/cabinetofice/gapuserservice/web/SpotlightController.java +++ b/src/main/java/gov/cabinetofice/gapuserservice/web/SpotlightController.java @@ -47,7 +47,7 @@ public ResponseEntity getIntegrations(final HttpSe if (!roleService.isSuperAdmin(httpRequest)) { throw new ForbiddenException(); } - SpotlightOAuthAudit audit = spotlightService.getLatestAudit(); + SpotlightOAuthAudit audit = spotlightService.getLatestSuccessOrFailureAudit(); if (Objects.equals(null, audit)) { throw new InvalidRequestException("No audit found"); } diff --git a/src/test/java/gov/cabinetofice/gapuserservice/service/SpotlightServiceTest.java b/src/test/java/gov/cabinetofice/gapuserservice/service/SpotlightServiceTest.java index 03f169d2..f4bcfdcf 100644 --- a/src/test/java/gov/cabinetofice/gapuserservice/service/SpotlightServiceTest.java +++ b/src/test/java/gov/cabinetofice/gapuserservice/service/SpotlightServiceTest.java @@ -1,11 +1,8 @@ package gov.cabinetofice.gapuserservice.service; import gov.cabinetofice.gapuserservice.config.SpotlightConfig; -import gov.cabinetofice.gapuserservice.enums.SpotlightOAuthAuditEvent; -import gov.cabinetofice.gapuserservice.enums.SpotlightOAuthAuditStatus; import gov.cabinetofice.gapuserservice.exceptions.InvalidRequestException; import gov.cabinetofice.gapuserservice.exceptions.SpotlightInvalidStateException; -import gov.cabinetofice.gapuserservice.model.SpotlightOAuthAudit; import gov.cabinetofice.gapuserservice.repository.SpotlightOAuthAuditRepository; import gov.cabinetofice.gapuserservice.util.RestUtils; import org.apache.http.impl.client.HttpClients; @@ -135,16 +132,6 @@ void shouldThrowExceptionWhenSateValueDoesNotMatchTest() { } - @Test - void shouldGetLatestAudit() { - SpotlightOAuthAudit spotlightOAuthAudit = SpotlightOAuthAudit.builder().id(1).status( - SpotlightOAuthAuditStatus.FAILURE).event(SpotlightOAuthAuditEvent.AUTHORISE).build(); - when(spotlightOAuthAuditRepository.findFirstByOrderByIdDesc()).thenReturn(spotlightOAuthAudit); - - assertEquals(spotlightOAuthAudit, spotlightService.getLatestAudit()); - } - - @Test void shouldRefreshTokenTest() throws Exception { diff --git a/src/test/java/gov/cabinetofice/gapuserservice/web/SpotlightControllerTest.java b/src/test/java/gov/cabinetofice/gapuserservice/web/SpotlightControllerTest.java index 2bff0a72..c39fdd5d 100644 --- a/src/test/java/gov/cabinetofice/gapuserservice/web/SpotlightControllerTest.java +++ b/src/test/java/gov/cabinetofice/gapuserservice/web/SpotlightControllerTest.java @@ -172,7 +172,7 @@ void shouldThrowExceptionIfTokenExchangeFails() throws IOException { @Nested class IntegrationTest { @Test - void shouldReturnIntegrationAuditDto() throws Exception { + void shouldReturnIntegrationAuditDto() { HttpServletRequest httpRequest = mock(HttpServletRequest.class); Date date = new Date(); SpotlightOAuthAudit audit = SpotlightOAuthAudit.builder().event(SpotlightOAuthAuditEvent.AUTHORISE) @@ -181,7 +181,7 @@ void shouldReturnIntegrationAuditDto() throws Exception { SpotlightOAuthAuditEvent.AUTHORISE, SpotlightOAuthAuditStatus.FAILURE, date); when(roleService.isSuperAdmin(any(HttpServletRequest.class))).thenReturn(true); - when(spotlightService.getLatestAudit()).thenReturn(audit); + when(spotlightService.getLatestSuccessOrFailureAudit()).thenReturn(audit); assertEquals(SpotlightController.getIntegrations(httpRequest), ResponseEntity.ok(auditDto)); } @@ -189,10 +189,18 @@ void shouldReturnIntegrationAuditDto() throws Exception { void shouldThrowInvalidRequestWhenNoIntegrationAuditFound() { HttpServletRequest httpRequest = mock(HttpServletRequest.class); when(roleService.isSuperAdmin(any(HttpServletRequest.class))).thenReturn(true); - when(spotlightService.getLatestAudit()).thenReturn(null); + when(spotlightService.getLatestSuccessOrFailureAudit()).thenReturn(null); assertThrows(InvalidRequestException.class, () -> SpotlightController.getIntegrations(httpRequest)); } + + @Test + void shouldThrowForbiddenExceptionWhenUserIsNotSuperAdmin() { + HttpServletRequest httpRequest = mock(HttpServletRequest.class); + when(roleService.isSuperAdmin(any(HttpServletRequest.class))).thenReturn(false); + + assertThrows(ForbiddenException.class, () -> SpotlightController.getIntegrations(httpRequest)); + } } @Nested From 10e21a50a45af57dd160c958d48a1fce86fe2f63 Mon Sep 17 00:00:00 2001 From: john-tco <135222889+john-tco@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:40:01 +0000 Subject: [PATCH 2/5] add getEmailFromSub (#175) --- .../gapuserservice/web/UserController.java | 7 +++-- .../web/UserControllerTest.java | 26 +++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/main/java/gov/cabinetofice/gapuserservice/web/UserController.java b/src/main/java/gov/cabinetofice/gapuserservice/web/UserController.java index 85c3e75f..ea5d1abc 100644 --- a/src/main/java/gov/cabinetofice/gapuserservice/web/UserController.java +++ b/src/main/java/gov/cabinetofice/gapuserservice/web/UserController.java @@ -80,6 +80,11 @@ public ResponseEntity getUserByUserSub(@RequestParam("userS return ResponseEntity.ok(new UserAndRelationsDto(oneLoginUserService.getUserByUserSub(userSub))); } + @GetMapping("/user/{userSub}/email") + public ResponseEntity getEmailFromSub(HttpServletRequest httpRequest, @PathVariable("userSub") String userSub) { + return ResponseEntity.ok(oneLoginUserService.getUserBySub(userSub).getEmailAddress()); + } + @PatchMapping("/user/{userId}/department") public ResponseEntity updateDepartment(HttpServletRequest httpRequest, @PathVariable("userId") Integer userId, @Validated @RequestBody ChangeDepartmentDto changeDepartmentDto) { @@ -166,7 +171,5 @@ public ResponseEntity getUserByEmail(@PathVariable("email") String emai .orElseGet(() -> new UserDto(oneLoginUserService.getUserByEmail(email))) ); } - - } diff --git a/src/test/java/gov/cabinetofice/gapuserservice/web/UserControllerTest.java b/src/test/java/gov/cabinetofice/gapuserservice/web/UserControllerTest.java index 303003cb..87eae9b7 100644 --- a/src/test/java/gov/cabinetofice/gapuserservice/web/UserControllerTest.java +++ b/src/test/java/gov/cabinetofice/gapuserservice/web/UserControllerTest.java @@ -3,6 +3,7 @@ import gov.cabinetofice.gapuserservice.dto.*; import gov.cabinetofice.gapuserservice.exceptions.ForbiddenException; import gov.cabinetofice.gapuserservice.exceptions.InvalidRequestException; +import gov.cabinetofice.gapuserservice.exceptions.UserNotFoundException; import gov.cabinetofice.gapuserservice.model.Role; import gov.cabinetofice.gapuserservice.model.RoleEnum; import gov.cabinetofice.gapuserservice.model.User; @@ -252,4 +253,29 @@ void testGetUserByEmailWhenRoleIsAbsent() { assertThat(methodResponse.getBody()).isEqualTo(mockUserDto); } + @Test + void testGetEmailFromSub() { + String userSub = "1"; + String userEmail = "test@test.com"; + User mockUser = User.builder().sub(userSub).gapUserId(1) + .emailAddress(userEmail).build(); + when(oneLoginUserService.getUserBySub(userSub)).thenReturn(mockUser); + HttpServletRequest mockRequest = mock(HttpServletRequest.class); + final ResponseEntity methodResponse = controller.getEmailFromSub(mockRequest, userSub); + + assertThat(methodResponse.getBody()).isEqualTo(userEmail); + verify(oneLoginUserService, times(1)).getUserBySub(userSub); + } + + @Test + void testGetEmailFromSub_UserNotFound() { + String userSub = "2"; + when(oneLoginUserService.getUserBySub(userSub)).thenThrow(UserNotFoundException.class); + HttpServletRequest mockRequest = mock(HttpServletRequest.class); + + assertThrows(UserNotFoundException.class, () -> { + controller.getEmailFromSub(mockRequest, userSub); + }); + verify(oneLoginUserService, times(1)).getUserBySub(userSub); + } } \ No newline at end of file From f8e124c12cc8b9d2c0a0b9a146de1b1d3e7cd028 Mon Sep 17 00:00:00 2001 From: dylanwrightCO <135221918+dylanwrightCO@users.noreply.github.com> Date: Thu, 1 Feb 2024 15:46:49 +0000 Subject: [PATCH 3/5] Feat/tmi2 611 (#179) * Adds support for technical support user --------- Co-authored-by: Connor Macqueen <138442814+ConnorTCO@users.noreply.github.com> Co-authored-by: Dylan Wright Co-authored-by: Gavin Cook --- .github/workflows/promoteToProd.yml | 11 ++-- .github/workflows/pushImage.yml | 24 +++++--- .../dto/CreateTechSupportUserDto.java | 7 +++ .../dto/UpdateUserRolesRequestDto.java | 9 +++ .../gapuserservice/model/RoleEnum.java | 20 +++++-- .../service/user/OneLoginUserService.java | 52 +++++++++++++++-- .../gapuserservice/web/UserController.java | 9 ++- .../service/user/OneLoginUserServiceTest.java | 48 +++++++++++---- .../web/UserControllerTest.java | 58 +++++++++++++++---- 9 files changed, 188 insertions(+), 50 deletions(-) create mode 100644 src/main/java/gov/cabinetofice/gapuserservice/dto/CreateTechSupportUserDto.java create mode 100644 src/main/java/gov/cabinetofice/gapuserservice/dto/UpdateUserRolesRequestDto.java diff --git a/.github/workflows/promoteToProd.yml b/.github/workflows/promoteToProd.yml index 780345f6..daf0a24c 100644 --- a/.github/workflows/promoteToProd.yml +++ b/.github/workflows/promoteToProd.yml @@ -14,13 +14,16 @@ jobs: promoteToProd: environment: AWS runs-on: ubuntu-latest + permissions: + id-token: write + contents: read steps: - - name: Setup AWS credentials - uses: aws-actions/configure-aws-credentials@v1-node16 + - uses: aws-actions/configure-aws-credentials@v3 + name: Configure AWS credentials with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + role-to-assume: ${{ secrets.AWS_ROLE_ARN }} + role-session-name: github-gap-automated-tests aws-region: ${{ env.AWS_REGION }} - name: Login to AWS ECR diff --git a/.github/workflows/pushImage.yml b/.github/workflows/pushImage.yml index 21616392..a19a68fb 100644 --- a/.github/workflows/pushImage.yml +++ b/.github/workflows/pushImage.yml @@ -55,7 +55,10 @@ jobs: if: github.ref == 'refs/heads/develop' || startsWith(github.ref, 'refs/heads/release') runs-on: ubuntu-latest - + permissions: + id-token: write + contents: read + outputs: docker-image-name: ${{ steps.docker-image-name.outputs.name }} @@ -72,11 +75,11 @@ jobs: distribution: "temurin" cache: maven - - name: Setup AWS credentials - uses: aws-actions/configure-aws-credentials@v1-node16 + - uses: aws-actions/configure-aws-credentials@v3 + name: Configure AWS credentials with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + role-to-assume: ${{ secrets.AWS_ROLE_ARN }} + role-session-name: github-gap-automated-tests aws-region: ${{ env.AWS_REGION }} - name: Login to AWS ECR @@ -118,6 +121,9 @@ jobs: deploy: environment: AWS runs-on: ubuntu-latest + permissions: + id-token: write + contents: read needs: [build, test] steps: @@ -126,11 +132,11 @@ jobs: # Fetch all commits since we use the total commit count to determine the build version fetch-depth: 0 - - name: Setup AWS credentials - uses: aws-actions/configure-aws-credentials@v1-node16 + - uses: aws-actions/configure-aws-credentials@v3 + name: Configure AWS credentials with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + role-to-assume: ${{ secrets.AWS_ROLE_ARN }} + role-session-name: github-gap-automated-tests aws-region: ${{ env.AWS_REGION }} - name: Login to AWS ECR diff --git a/src/main/java/gov/cabinetofice/gapuserservice/dto/CreateTechSupportUserDto.java b/src/main/java/gov/cabinetofice/gapuserservice/dto/CreateTechSupportUserDto.java new file mode 100644 index 00000000..62bf6725 --- /dev/null +++ b/src/main/java/gov/cabinetofice/gapuserservice/dto/CreateTechSupportUserDto.java @@ -0,0 +1,7 @@ +package gov.cabinetofice.gapuserservice.dto; + +import lombok.Builder; + +@Builder +public record CreateTechSupportUserDto(String userSub, Integer departmentId) { +} diff --git a/src/main/java/gov/cabinetofice/gapuserservice/dto/UpdateUserRolesRequestDto.java b/src/main/java/gov/cabinetofice/gapuserservice/dto/UpdateUserRolesRequestDto.java new file mode 100644 index 00000000..5df63bc5 --- /dev/null +++ b/src/main/java/gov/cabinetofice/gapuserservice/dto/UpdateUserRolesRequestDto.java @@ -0,0 +1,9 @@ +package gov.cabinetofice.gapuserservice.dto; + +import lombok.Builder; + +import java.util.List; + +@Builder +public record UpdateUserRolesRequestDto(Integer departmentId, List newUserRoles) { +} diff --git a/src/main/java/gov/cabinetofice/gapuserservice/model/RoleEnum.java b/src/main/java/gov/cabinetofice/gapuserservice/model/RoleEnum.java index 14183710..376f7a62 100644 --- a/src/main/java/gov/cabinetofice/gapuserservice/model/RoleEnum.java +++ b/src/main/java/gov/cabinetofice/gapuserservice/model/RoleEnum.java @@ -1,9 +1,17 @@ package gov.cabinetofice.gapuserservice.model; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor public enum RoleEnum { - SUPER_ADMIN, - ADMIN, - APPLICANT, - FIND, - TECHNICAL_SUPPORT, -} + SUPER_ADMIN(4), + ADMIN(3), + APPLICANT(2), + FIND(1), + TECHNICAL_SUPPORT(5), + ; + + final int roleId; +} \ No newline at end of file diff --git a/src/main/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserService.java b/src/main/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserService.java index cf054042..af97f49c 100644 --- a/src/main/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserService.java +++ b/src/main/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserService.java @@ -31,6 +31,7 @@ import org.springframework.http.MediaType; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; @@ -194,16 +195,19 @@ public User updateDepartment(Integer id, Integer departmentId, String jwt) { return userRepository.save(user); } - public User updateRoles(Integer id, List newRoles) { + public User updateRoles(Integer id, UpdateUserRolesRequestDto updateUserRolesRequestDto, String jwt) { User user = userRepository.findById(id).orElseThrow(() -> new RuntimeException("User not found")); + + handleTechSupportRoleChange(user, updateUserRolesRequestDto, jwt); + user.removeAllRoles(); - if (newRoles == null || newRoles.isEmpty()) { + if (updateUserRolesRequestDto.newUserRoles().isEmpty()) { userRepository.save(user); return user; } - for (Integer roleId : newRoles) { + for (Integer roleId : updateUserRolesRequestDto.newUserRoles()) { Role role = roleRepository.findById(roleId).orElseThrow(); user.addRole(role); } @@ -216,6 +220,18 @@ public User updateRoles(Integer id, List newRoles) { return user; } + private void handleTechSupportRoleChange(User user, UpdateUserRolesRequestDto updateUserRolesRequestDto, String jwt) { + if (updateUserRolesRequestDto.newUserRoles().contains(RoleEnum.TECHNICAL_SUPPORT.getRoleId()) + && !user.isTechnicalSupport()) { + addTechSupportUserToApply(user, updateUserRolesRequestDto.departmentId(), jwt); + } else { + if (user.isTechnicalSupport() && !updateUserRolesRequestDto.newUserRoles() + .contains(RoleEnum.TECHNICAL_SUPPORT.getRoleId())) { + deleteTechSupportUserFromApply(user.getSub(), jwt); + } + } + } + private void addRoleIfNotPresent(User user, RoleEnum roleName) { if (user.getRoles().stream().noneMatch(role -> role.getName().equals(roleName))) { Role role = roleRepository.findByName(roleName).orElseThrow(() -> new RoleNotFoundException( @@ -250,6 +266,33 @@ public void deleteUser(Integer id, String jwt) { userRepository.deleteById(id); } + public void addTechSupportUserToApply(User user, Integer departmentId, String jwt) { + webClientBuilder.build() + .post() + .uri(adminBackend.concat("/users/tech-support-user")) + .contentType(MediaType.APPLICATION_JSON) + .body(BodyInserters.fromValue(CreateTechSupportUserDto.builder() + .userSub(user.getSub()).departmentId(departmentId).build())) + .header(AUTHORIZATION_HEADER_NAME, BEARER_HEADER_PREFIX + jwt) + .retrieve() + .bodyToMono(Void.class) + .block(); + } + + public void deleteTechSupportUserFromApply(String sub, String jwt) { + webClientBuilder.build() + .delete() + .uri(adminBackend.concat("/users/tech-support-user/".concat(sub))) + .header(AUTHORIZATION_HEADER_NAME, BEARER_HEADER_PREFIX + jwt) + .retrieve() + .onStatus(httpStatus -> !httpStatus.equals(HttpStatus.OK), clientResponse -> { + log.error("Unable to delete tech support user with sub {}, HTTP status code {}", sub, clientResponse.statusCode()); + return Mono.empty(); + }) + .bodyToMono(Void.class) + .block(); + } + private void deleteUserFromApply(String jwt, User user) { String query = user.hasSub() ? "?oneLoginSub=" + user.getSub() : "?colaSub=" + user.getColaSub(); @@ -408,7 +451,8 @@ public List getUserEmailsBySubs(List subs) { return users.stream().map(user -> UserEmailDto.builder() .emailAddress(awsEncryptionService.encryptField(user.getEmailAddress())) .sub(user.getSub()) - .build()).collect(Collectors.toList()); + .build()) + .toList(); } @PreAuthorize("hasRole('SUPER_ADMIN')") diff --git a/src/main/java/gov/cabinetofice/gapuserservice/web/UserController.java b/src/main/java/gov/cabinetofice/gapuserservice/web/UserController.java index ea5d1abc..2e954bdd 100644 --- a/src/main/java/gov/cabinetofice/gapuserservice/web/UserController.java +++ b/src/main/java/gov/cabinetofice/gapuserservice/web/UserController.java @@ -118,13 +118,16 @@ public ResponseEntity getChangeDepartmentPage(HttpServl } @PatchMapping("/user/{id}/role") - public ResponseEntity updateRoles(HttpServletRequest httpRequest, @RequestBody() List roleIds, + public ResponseEntity updateRoles(HttpServletRequest httpRequest, + @RequestBody() UpdateUserRolesRequestDto updateUserRolesRequestDto, @PathVariable("id") Integer id) { if (!roleService.isSuperAdmin(httpRequest)) { throw new ForbiddenException(); } - boolean isARequestToBlockUser = roleIds.isEmpty(); + final Cookie customJWTCookie = getCustomJwtCookieFromRequest(httpRequest, userServiceCookieName); + + boolean isARequestToBlockUser = updateUserRolesRequestDto.newUserRoles().isEmpty(); Optional user = jwtService.getUserFromJwt(httpRequest); if (user.isEmpty()) { @@ -134,7 +137,7 @@ public ResponseEntity updateRoles(HttpServletRequest httpRequest, @Reque throw new UnsupportedOperationException("You can't block yourself"); } - oneLoginUserService.updateRoles(id, roleIds); + oneLoginUserService.updateRoles(id, updateUserRolesRequestDto, customJWTCookie.getValue()); return ResponseEntity.ok("success"); } diff --git a/src/test/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserServiceTest.java b/src/test/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserServiceTest.java index 472618c3..8be7d006 100644 --- a/src/test/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserServiceTest.java +++ b/src/test/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserServiceTest.java @@ -71,11 +71,12 @@ void setUp() { @Test void shouldReturnUpdatedUserWhenValidIdAndRolesAreGiven() { Integer userId = 1; - List newRoles = List.of(1, 2); List currentUserRoles = List.of(Role.builder().name(RoleEnum.FIND).id(1).build()); User user = spy(User.builder().gapUserId(1).sub("sub").roles(currentUserRoles).build()); Role role1 = Role.builder().id(1).name(RoleEnum.FIND).description("a desc").build(); Role role2 = Role.builder().id(2).name(RoleEnum.APPLICANT).description("a desc 2").build(); + UpdateUserRolesRequestDto updateUserRolesRequestDto = UpdateUserRolesRequestDto.builder() + .newUserRoles(Arrays.asList(1, 2)).build(); doNothing().when(user).removeAllRoles(); doNothing().when(user).addRole(role2); @@ -86,7 +87,7 @@ void shouldReturnUpdatedUserWhenValidIdAndRolesAreGiven() { when(roleRepository.findById(2)).thenReturn(Optional.of(role2)); when(roleRepository.findByName(RoleEnum.APPLICANT)).thenReturn(Optional.of(role2)); - User updatedUser = oneLoginUserService.updateRoles(1, newRoles); + User updatedUser = oneLoginUserService.updateRoles(1, updateUserRolesRequestDto, "jwt"); Mockito.verify(roleRepository, times(2)).findById(anyInt()); Mockito.verify(roleRepository, times(1)).findByName(any(RoleEnum.class)); @@ -446,13 +447,15 @@ void testDeleteUser_DeletesUser() { void updateRolesShouldAddApplicantAndFindRolesWhenNoRolesPresent() { Integer userId = 1; User user = User.builder().gapUserId(userId).build(); - List newRoles = List.of(3, 4); + UpdateUserRolesRequestDto updateUserRolesRequestDto = UpdateUserRolesRequestDto.builder() + .newUserRoles(Arrays.asList(3, 4)).build(); + when(userRepository.findById(userId)).thenReturn(Optional.of(user)); when(roleRepository.findById(3)).thenReturn(Optional.of(Role.builder().name(RoleEnum.ADMIN).build())); when(roleRepository.findById(4)).thenReturn(Optional.of(Role.builder().name(RoleEnum.SUPER_ADMIN).build())); when(roleRepository.findByName(RoleEnum.APPLICANT)).thenReturn(Optional.of(Role.builder().name(RoleEnum.APPLICANT).build())); when(roleRepository.findByName(RoleEnum.FIND)).thenReturn(Optional.of(Role.builder().name(RoleEnum.FIND).build())); - User updatedUser = oneLoginUserService.updateRoles(userId, newRoles); + User updatedUser = oneLoginUserService.updateRoles(userId, updateUserRolesRequestDto, "jwt"); assertThat(updatedUser.getRoles()).hasSize(4); assertThat(updatedUser.getRoles().stream().anyMatch(role -> role.getName().equals(RoleEnum.APPLICANT))).isTrue(); @@ -514,12 +517,14 @@ void testValidateSessionsRolesThrowsInvalidExceptionWithEmptyUser() { @Test void updateRolesShouldSetDepartmentToNullIfNotSuperAdminOrAdmin() { Integer userId = 1; - List newRoles = List.of(1, 2); User user = User.builder().gapUserId(userId).department(Department.builder().name("test").build()).build(); + UpdateUserRolesRequestDto updateUserRolesRequestDto = UpdateUserRolesRequestDto.builder() + .newUserRoles(Arrays.asList(1, 2)).build(); + when(userRepository.findById(userId)).thenReturn(Optional.of(user)); when(roleRepository.findById(1)).thenReturn(Optional.of(Role.builder().name(RoleEnum.APPLICANT).build())); when(roleRepository.findById(2)).thenReturn(Optional.of(Role.builder().name(RoleEnum.FIND).build())); - User updatedUser = oneLoginUserService.updateRoles(1, newRoles); + User updatedUser = oneLoginUserService.updateRoles(1, updateUserRolesRequestDto, "jwt"); assertThat(updatedUser.getDepartment()).isNull(); } @@ -527,13 +532,15 @@ void updateRolesShouldSetDepartmentToNullIfNotSuperAdminOrAdmin() { @Test void updateRolesShouldNotSetDepartmentToNullIfUserHasMoreThanTwoRoles() { Integer userId = 1; - List newRoles = List.of(1, 2, 3); User user = User.builder().gapUserId(userId).department(Department.builder().name("test").build()).build(); + UpdateUserRolesRequestDto updateUserRolesRequestDto = UpdateUserRolesRequestDto.builder() + .newUserRoles(Arrays.asList(1, 2, 3)).build(); + when(userRepository.findById(userId)).thenReturn(Optional.of(user)); when(roleRepository.findById(1)).thenReturn(Optional.of(Role.builder().name(RoleEnum.APPLICANT).build())); when(roleRepository.findById(2)).thenReturn(Optional.of(Role.builder().name(RoleEnum.FIND).build())); when(roleRepository.findById(3)).thenReturn(Optional.of(Role.builder().name(RoleEnum.ADMIN).build())); - User updatedUser = oneLoginUserService.updateRoles(1, newRoles); + User updatedUser = oneLoginUserService.updateRoles(1, updateUserRolesRequestDto, "jwt"); assertThat(updatedUser.getDepartment()).isNotNull(); } @@ -541,14 +548,31 @@ void updateRolesShouldNotSetDepartmentToNullIfUserHasMoreThanTwoRoles() { @Test void updateRolesShouldNotSetDepartmentToNullIfUserIsAdminOrSuperAdmin() { Integer userId = 1; - List newRoles = List.of(3, 4); User user = User.builder().gapUserId(userId).department(Department.builder().name("test").build()).build(); + UpdateUserRolesRequestDto updateUserRolesRequestDto = UpdateUserRolesRequestDto.builder() + .newUserRoles(Arrays.asList(1, 2, 3, 4, 5)).build(); + + final WebClient webClient = mock(WebClient.class); + final WebClient.RequestHeadersSpec requestHeadersSpec = mock(WebClient.RequestHeadersSpec.class); + final WebClient.RequestBodyUriSpec requestBodyUriSpec = mock(WebClient.RequestBodyUriSpec.class); + final WebClient.ResponseSpec responseSpec = mock(WebClient.ResponseSpec.class); + + when(webClientBuilder.build()).thenReturn(webClient); + when(webClient.post()).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.uri(anyString())).thenReturn(requestBodyUriSpec); + when(requestHeadersSpec.header(anyString(), anyString())).thenReturn(requestHeadersSpec); + when(requestBodyUriSpec.contentType(any())).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.body(any())).thenReturn(requestHeadersSpec); + when(requestHeadersSpec.retrieve()).thenReturn(responseSpec); + when(responseSpec.bodyToMono(Void.class)).thenReturn(Mono.empty()); + when(userRepository.findById(userId)).thenReturn(Optional.of(user)); + when(roleRepository.findById(1)).thenReturn(Optional.of(Role.builder().name(RoleEnum.FIND).build())); + when(roleRepository.findById(2)).thenReturn(Optional.of(Role.builder().name(RoleEnum.APPLICANT).build())); when(roleRepository.findById(3)).thenReturn(Optional.of(Role.builder().name(RoleEnum.ADMIN).build())); when(roleRepository.findById(4)).thenReturn(Optional.of(Role.builder().name(RoleEnum.SUPER_ADMIN).build())); - when(roleRepository.findByName(RoleEnum.FIND)).thenReturn(Optional.of(Role.builder().name(RoleEnum.FIND).id(1).build())); - when(roleRepository.findByName(RoleEnum.APPLICANT)).thenReturn(Optional.of(Role.builder().name(RoleEnum.APPLICANT).id(2).build())); - User updatedUser = oneLoginUserService.updateRoles(1, newRoles); + when(roleRepository.findById(5)).thenReturn(Optional.of(Role.builder().name(RoleEnum.TECHNICAL_SUPPORT).build())); + User updatedUser = oneLoginUserService.updateRoles(1, updateUserRolesRequestDto, "jwt"); assertThat(updatedUser.getDepartment()).isNotNull(); } diff --git a/src/test/java/gov/cabinetofice/gapuserservice/web/UserControllerTest.java b/src/test/java/gov/cabinetofice/gapuserservice/web/UserControllerTest.java index 87eae9b7..2e98d46d 100644 --- a/src/test/java/gov/cabinetofice/gapuserservice/web/UserControllerTest.java +++ b/src/test/java/gov/cabinetofice/gapuserservice/web/UserControllerTest.java @@ -14,20 +14,20 @@ import gov.cabinetofice.gapuserservice.service.user.OneLoginUserService; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; +import org.junit.jupiter.api.AfterEach; 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.MockedStatic; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.http.ResponseEntity; import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.web.util.WebUtils; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Optional; +import java.util.*; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -52,17 +52,30 @@ class UserControllerTest { @Mock private SecretAuthService secretAuthService; + private static MockedStatic mockedWebUtils; + @BeforeEach void setUp() { + mockedWebUtils = mockStatic(WebUtils.class); ReflectionTestUtils.setField(controller, "userServiceCookieName", "userServiceCookieName"); } + @AfterEach + public void close() { + mockedWebUtils.close(); + } + @Test void updateRolesForUserId() { final HttpServletRequest httpRequest = mock(HttpServletRequest.class); + UpdateUserRolesRequestDto updateUserRolesRequestDto = UpdateUserRolesRequestDto.builder() + .newUserRoles(Arrays.asList(1, 2, 3, 4, 5)).build(); + + mockedWebUtils.when(() -> WebUtils.getCookie(httpRequest, "userServiceCookieName")) + .thenReturn(new Cookie("userServiceCookieName", "jwt")); when(roleService.isSuperAdmin(httpRequest)).thenReturn(true); when(customJwtService.getUserFromJwt(httpRequest)).thenReturn(Optional.of(User.builder().gapUserId(2).build())); - final ResponseEntity methodResponse = controller.updateRoles(httpRequest, List.of(1, 2), 1); + final ResponseEntity methodResponse = controller.updateRoles(httpRequest,updateUserRolesRequestDto, 1); assertThat(methodResponse).isEqualTo(ResponseEntity.ok("success")); } @@ -71,20 +84,32 @@ void updateRolesForUserId() { void testSuperAdminCannotBlockThemselves() { final HttpServletRequest httpRequest = mock(HttpServletRequest.class); when(roleService.isSuperAdmin(httpRequest)).thenReturn(true); - final ArrayList noRoles = new ArrayList<>(); + mockedWebUtils.when(() -> WebUtils.getCookie(httpRequest, "userServiceCookieName")) + .thenReturn(new Cookie("userServiceCookieName", "jwt")); + + UpdateUserRolesRequestDto updateUserRolesRequestDto = UpdateUserRolesRequestDto.builder() + .newUserRoles(new ArrayList<>()).build(); + when(customJwtService.getUserFromJwt(httpRequest)).thenReturn(Optional.of(User.builder().gapUserId(1).build())); - assertThrows(UnsupportedOperationException.class, () -> controller.updateRoles(httpRequest, noRoles, 1)); + assertThrows(UnsupportedOperationException.class, () -> controller.updateRoles(httpRequest, + updateUserRolesRequestDto, 1)); } @Test void testSuperAdminThrowsInvalidRequestWithNoUser() { final HttpServletRequest httpRequest = mock(HttpServletRequest.class); - final ArrayList noRoles = new ArrayList<>(); + UpdateUserRolesRequestDto updateUserRolesRequestDto = UpdateUserRolesRequestDto.builder() + .newUserRoles(new ArrayList<>()).departmentId(1).build(); + + mockedWebUtils.when(() -> WebUtils.getCookie(httpRequest, "userServiceCookieName")) + .thenReturn(new Cookie("userServiceCookieName", "jwt")); + when(roleService.isSuperAdmin(httpRequest)).thenReturn(true); when(customJwtService.getUserFromJwt(httpRequest)).thenReturn(Optional.empty()); - assertThrows(InvalidRequestException.class, () -> controller.updateRoles(httpRequest, noRoles, 1)); + assertThrows(InvalidRequestException.class, () -> controller.updateRoles(httpRequest, + updateUserRolesRequestDto, 1)); } @Test @@ -125,7 +150,10 @@ void shouldReturnChangeDepartmentPageDtoWhenValidIdIsGiven() { @Test void shouldDeleteUserWhenValidIdIsGiven() { final HttpServletRequest httpRequest = mock(HttpServletRequest.class); - when(httpRequest.getCookies()).thenReturn(new Cookie[]{new Cookie("userServiceCookieName", "1")}); + + mockedWebUtils.when(() -> WebUtils.getCookie(httpRequest, "userServiceCookieName")) + .thenReturn(new Cookie("userServiceCookieName", "jwt")); + when(roleService.isSuperAdmin(httpRequest)).thenReturn(true); when(customJwtService.getUserFromJwt(httpRequest)).thenReturn(Optional.of(User.builder().gapUserId(2).build())); final ResponseEntity methodResponse = controller.deleteUser(httpRequest, 1); @@ -136,7 +164,10 @@ void shouldDeleteUserWhenValidIdIsGiven() { @Test void shouldThrowErrorWhenAdminTriesToDeleteThemselves() { final HttpServletRequest httpRequest = mock(HttpServletRequest.class); - when(httpRequest.getCookies()).thenReturn(new Cookie[]{new Cookie("userServiceCookieName", "1")}); + + mockedWebUtils.when(() -> WebUtils.getCookie(httpRequest, "userServiceCookieName")) + .thenReturn(new Cookie("userServiceCookieName", "jwt")); + when(roleService.isSuperAdmin(httpRequest)).thenReturn(true); when(customJwtService.getUserFromJwt(httpRequest)).thenReturn(Optional.of(User.builder().gapUserId(1).build())); @@ -146,7 +177,10 @@ void shouldThrowErrorWhenAdminTriesToDeleteThemselves() { @Test void shouldThrowErrorWhenUserIsEmpty() { final HttpServletRequest httpRequest = mock(HttpServletRequest.class); - when(httpRequest.getCookies()).thenReturn(new Cookie[]{new Cookie("userServiceCookieName", "1")}); + + mockedWebUtils.when(() -> WebUtils.getCookie(httpRequest, "userServiceCookieName")) + .thenReturn(new Cookie("userServiceCookieName", "jwt")); + when(roleService.isSuperAdmin(httpRequest)).thenReturn(true); when(customJwtService.getUserFromJwt(httpRequest)).thenReturn(Optional.empty()); From 258c0577ff968d1a012f5edf23967aef45cf25ef Mon Sep 17 00:00:00 2001 From: dylanwrightCO <135221918+dylanwrightCO@users.noreply.github.com> Date: Fri, 2 Feb 2024 10:56:17 +0000 Subject: [PATCH 4/5] Updates createtechSupportUserDto to have department name (#180) Co-authored-by: Dylan Wright --- .../gapuserservice/dto/CreateTechSupportUserDto.java | 2 +- .../gapuserservice/service/user/OneLoginUserService.java | 9 ++++++--- .../service/user/OneLoginUserServiceTest.java | 4 +++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/gov/cabinetofice/gapuserservice/dto/CreateTechSupportUserDto.java b/src/main/java/gov/cabinetofice/gapuserservice/dto/CreateTechSupportUserDto.java index 62bf6725..8f775eff 100644 --- a/src/main/java/gov/cabinetofice/gapuserservice/dto/CreateTechSupportUserDto.java +++ b/src/main/java/gov/cabinetofice/gapuserservice/dto/CreateTechSupportUserDto.java @@ -3,5 +3,5 @@ import lombok.Builder; @Builder -public record CreateTechSupportUserDto(String userSub, Integer departmentId) { +public record CreateTechSupportUserDto(String userSub, String departmentName) { } diff --git a/src/main/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserService.java b/src/main/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserService.java index af97f49c..ce6798b7 100644 --- a/src/main/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserService.java +++ b/src/main/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserService.java @@ -223,7 +223,10 @@ public User updateRoles(Integer id, UpdateUserRolesRequestDto updateUserRolesReq private void handleTechSupportRoleChange(User user, UpdateUserRolesRequestDto updateUserRolesRequestDto, String jwt) { if (updateUserRolesRequestDto.newUserRoles().contains(RoleEnum.TECHNICAL_SUPPORT.getRoleId()) && !user.isTechnicalSupport()) { - addTechSupportUserToApply(user, updateUserRolesRequestDto.departmentId(), jwt); + Department department = departmentRepository.findById(updateUserRolesRequestDto.departmentId()) + .orElseThrow(() -> new DepartmentNotFoundException + ("Department not found with id: " + updateUserRolesRequestDto.departmentId())); + addTechSupportUserToApply(user, department.getName(), jwt); } else { if (user.isTechnicalSupport() && !updateUserRolesRequestDto.newUserRoles() .contains(RoleEnum.TECHNICAL_SUPPORT.getRoleId())) { @@ -266,13 +269,13 @@ public void deleteUser(Integer id, String jwt) { userRepository.deleteById(id); } - public void addTechSupportUserToApply(User user, Integer departmentId, String jwt) { + public void addTechSupportUserToApply(User user, String departmentName, String jwt) { webClientBuilder.build() .post() .uri(adminBackend.concat("/users/tech-support-user")) .contentType(MediaType.APPLICATION_JSON) .body(BodyInserters.fromValue(CreateTechSupportUserDto.builder() - .userSub(user.getSub()).departmentId(departmentId).build())) + .userSub(user.getSub()).departmentName(departmentName).build())) .header(AUTHORIZATION_HEADER_NAME, BEARER_HEADER_PREFIX + jwt) .retrieve() .bodyToMono(Void.class) diff --git a/src/test/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserServiceTest.java b/src/test/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserServiceTest.java index 8be7d006..fa9b4898 100644 --- a/src/test/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserServiceTest.java +++ b/src/test/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserServiceTest.java @@ -548,7 +548,8 @@ void updateRolesShouldNotSetDepartmentToNullIfUserHasMoreThanTwoRoles() { @Test void updateRolesShouldNotSetDepartmentToNullIfUserIsAdminOrSuperAdmin() { Integer userId = 1; - User user = User.builder().gapUserId(userId).department(Department.builder().name("test").build()).build(); + Department department = Department.builder().id(1).name("test").build(); + User user = User.builder().gapUserId(userId).department(department).build(); UpdateUserRolesRequestDto updateUserRolesRequestDto = UpdateUserRolesRequestDto.builder() .newUserRoles(Arrays.asList(1, 2, 3, 4, 5)).build(); @@ -568,6 +569,7 @@ void updateRolesShouldNotSetDepartmentToNullIfUserIsAdminOrSuperAdmin() { when(userRepository.findById(userId)).thenReturn(Optional.of(user)); when(roleRepository.findById(1)).thenReturn(Optional.of(Role.builder().name(RoleEnum.FIND).build())); + when(departmentRepository.findById(updateUserRolesRequestDto.departmentId())).thenReturn(Optional.of(department)); when(roleRepository.findById(2)).thenReturn(Optional.of(Role.builder().name(RoleEnum.APPLICANT).build())); when(roleRepository.findById(3)).thenReturn(Optional.of(Role.builder().name(RoleEnum.ADMIN).build())); when(roleRepository.findById(4)).thenReturn(Optional.of(Role.builder().name(RoleEnum.SUPER_ADMIN).build())); From 10386d82b68529b4df531e2ce7ad2f4f24d1b250 Mon Sep 17 00:00:00 2001 From: dylanwrightCO <135221918+dylanwrightCO@users.noreply.github.com> Date: Fri, 2 Feb 2024 11:48:50 +0000 Subject: [PATCH 5/5] Adds check for null department when changing tech support user role (#181) Co-authored-by: Dylan Wright --- .../gapuserservice/service/user/OneLoginUserService.java | 6 +++++- .../service/user/OneLoginUserServiceTest.java | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserService.java b/src/main/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserService.java index ce6798b7..e47814b8 100644 --- a/src/main/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserService.java +++ b/src/main/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserService.java @@ -223,7 +223,11 @@ public User updateRoles(Integer id, UpdateUserRolesRequestDto updateUserRolesReq private void handleTechSupportRoleChange(User user, UpdateUserRolesRequestDto updateUserRolesRequestDto, String jwt) { if (updateUserRolesRequestDto.newUserRoles().contains(RoleEnum.TECHNICAL_SUPPORT.getRoleId()) && !user.isTechnicalSupport()) { - Department department = departmentRepository.findById(updateUserRolesRequestDto.departmentId()) + + Integer departmentId = updateUserRolesRequestDto.departmentId() == null + ? user.getDepartment().getId() : updateUserRolesRequestDto.departmentId(); + + Department department = departmentRepository.findById(departmentId) .orElseThrow(() -> new DepartmentNotFoundException ("Department not found with id: " + updateUserRolesRequestDto.departmentId())); addTechSupportUserToApply(user, department.getName(), jwt); diff --git a/src/test/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserServiceTest.java b/src/test/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserServiceTest.java index fa9b4898..09c20339 100644 --- a/src/test/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserServiceTest.java +++ b/src/test/java/gov/cabinetofice/gapuserservice/service/user/OneLoginUserServiceTest.java @@ -569,7 +569,7 @@ void updateRolesShouldNotSetDepartmentToNullIfUserIsAdminOrSuperAdmin() { when(userRepository.findById(userId)).thenReturn(Optional.of(user)); when(roleRepository.findById(1)).thenReturn(Optional.of(Role.builder().name(RoleEnum.FIND).build())); - when(departmentRepository.findById(updateUserRolesRequestDto.departmentId())).thenReturn(Optional.of(department)); + when(departmentRepository.findById(1)).thenReturn(Optional.of(department)); when(roleRepository.findById(2)).thenReturn(Optional.of(Role.builder().name(RoleEnum.APPLICANT).build())); when(roleRepository.findById(3)).thenReturn(Optional.of(Role.builder().name(RoleEnum.ADMIN).build())); when(roleRepository.findById(4)).thenReturn(Optional.of(Role.builder().name(RoleEnum.SUPER_ADMIN).build()));