Skip to content

Commit

Permalink
DTSAM-471 filter soft deleted judicial users (#2056)
Browse files Browse the repository at this point in the history
* DTSAM-471 filter soft deleted judicial users

* DTSAM-471 reduce code complexity + increase code coverage

---------

Co-authored-by: Matt Nayler <57350764+mattnayler@users.noreply.github.com>
Co-authored-by: mikebrownccd <104495891+mikebrownccd@users.noreply.github.com>
  • Loading branch information
3 people authored Sep 10, 2024
1 parent ca70cc8 commit 91055f5
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public class ProviderTestConfiguration {
@Bean
@Primary
public RetrieveDataService getRetrieveDataService() {
return new RetrieveDataService(getParseRequestService(), crdService, jrdService);
return new RetrieveDataService(getParseRequestService(), crdService, jrdService, true);
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -20,6 +24,7 @@
import uk.gov.hmcts.reform.orgrolemapping.apihelper.Constants;
import uk.gov.hmcts.reform.orgrolemapping.controller.utils.MockUtils;
import uk.gov.hmcts.reform.orgrolemapping.controller.utils.WiremockFixtures;
import uk.gov.hmcts.reform.orgrolemapping.domain.model.JudicialProfileV2;
import uk.gov.hmcts.reform.orgrolemapping.domain.model.JudicialRefreshRequest;
import uk.gov.hmcts.reform.orgrolemapping.domain.model.RoleAssignmentRequestResource;
import uk.gov.hmcts.reform.orgrolemapping.domain.model.UserAccessProfile;
Expand All @@ -38,12 +43,16 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
Expand All @@ -54,7 +63,8 @@
import static uk.gov.hmcts.reform.orgrolemapping.helper.IntTestDataBuilder.buildJudicialProfilesResponseV2;

@TestPropertySource(properties = {
"refresh.BulkAssignment.includeJudicialBookings=true"
"refresh.BulkAssignment.includeJudicialBookings=true",
"refresh.judicial.filterSoftDeletedUsers=true"
})
public class RefreshControllerJudicialRefreshIntegrationTest extends BaseTestIntegration {

Expand Down Expand Up @@ -93,6 +103,9 @@ public class RefreshControllerJudicialRefreshIntegrationTest extends BaseTestInt
@Mock
private SecurityContext securityContext;

@Captor
private ArgumentCaptor<Map<String, Set<UserAccessProfile>>> usersAccessProfilesCaptor;

private static final MediaType JSON_CONTENT_TYPE = new MediaType(
MediaType.APPLICATION_JSON.getType(),
MediaType.APPLICATION_JSON.getSubtype(),
Expand Down Expand Up @@ -130,6 +143,40 @@ public void shouldProcessRefreshRoleAssignmentsWithJudicialProfilesV2() throws E
logger.info(" -- Refresh Role Assignment record updated successfully -- ");
}

@ParameterizedTest
@ValueSource(booleans = {true, false})
public void shouldProcessRefreshRoleAssignmentsWithJudicialProfilesV2_deletedFlag(Boolean deletedFlagStatus)
throws Exception {
logger.info(" Refresh role assignments when judicial user deleted flag {}", deletedFlagStatus);
var uuid = UUID.randomUUID().toString();

ResponseEntity<List<JudicialProfileV2>> res = buildJudicialProfilesResponseV2(uuid);
res.getBody().get(0).setDeletedFlag(deletedFlagStatus.toString());

doReturn(res).when(jrdFeignClient).getJudicialDetailsById(any(), any());
doReturn(buildJudicialBookingsResponse(uuid)).when(jbsFeignClient).getJudicialBookingByUserIds(any());
mockRequestMappingServiceBookingParamWithStatus(HttpStatus.CREATED);

MvcResult result = mockMvc.perform(post(JUDICIAL_REFRESH_URL)
.contentType(JSON_CONTENT_TYPE)
.headers(getHttpHeaders(S2S_XUI))
.content(mapper.writeValueAsBytes(JudicialRefreshRequest.builder()
.refreshRequest(IntTestDataBuilder.buildUserRequest()).build())))
.andExpect(status().is(200))
.andReturn();

verify(requestMappingService, times(1))
.createJudicialAssignments(usersAccessProfilesCaptor.capture(), any());

Map<String, Set<UserAccessProfile>> usersAccessProfiles = usersAccessProfilesCaptor.getValue();
assertEquals(deletedFlagStatus, usersAccessProfiles.get(uuid).isEmpty());

var contentAsString = result.getResponse().getContentAsString();
assertTrue(contentAsString.contains(Constants.SUCCESS_ROLE_REFRESH));
logger.info(" -- Refresh Role Assignment record updated successfully when judicial user deleted flag {} -- ",
deletedFlagStatus);
}

@Test
public void shouldFailProcessRefreshRoleAssignmentsWithJudicialProfiles_withFailedRoleAssignmentsV2()
throws Exception {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.slf4j.Logger;
Expand Down Expand Up @@ -56,6 +58,8 @@
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
Expand Down Expand Up @@ -98,6 +102,7 @@
"refresh.Job.authorisedServices=" + S2S_ORM + "," + S2S_RARB,
"refresh.Job.includeJudicialBookings=true",
"refresh.Job.pageSize=" + TEST_PAGE_SIZE,
"refresh.judicial.filterSoftDeletedUsers=true",
"testing.support.enabled=true" // NB: needed for access to test support URLs
})
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
Expand Down Expand Up @@ -155,6 +160,9 @@ public class RefreshControllerRefreshJobIntegrationTest extends BaseTestIntegrat
@Mock
private SecurityContext securityContext;

@Captor
private ArgumentCaptor<Map<String, Set<UserAccessProfile>>> usersAccessProfilesCaptor;

Lock sequential = new ReentrantLock();

private static final MediaType JSON_CONTENT_TYPE = new MediaType(
Expand Down Expand Up @@ -568,6 +576,50 @@ public void shouldProcessRefreshRoleAssignmentsWithJobIdToAborted_Judicial() thr
assertThat(refreshJob.getLog(), containsString(String.join(",", refreshJob.getUserIds())));
}

@Order(17)
@ParameterizedTest
@ValueSource(booleans = {true, false})
public void shouldProcessRefreshRoleAssignments_deletedFlag(Boolean deletedFlagStatus) throws Exception {
when(securityUtils.getServiceName()).thenReturn(AUTHORISED_JOB_SERVICE);

logger.info(" RefreshJob record with judicial user deleted flag {}", deletedFlagStatus);
String[] userIds = buildUserIdList(1);

ResponseEntity<List<JudicialProfileV2>> res = buildJudicialProfilesResponseV2(userIds);
res.getBody().get(0).setDeletedFlag(deletedFlagStatus.toString());
doReturn(res).when(jrdFeignClient).getJudicialDetailsById(any(), any());

mockJBSService(userIds);
mockRequestMappingServiceWithJudicialStatus(HttpStatus.CREATED);

Long jobId = createRefreshJobJudicialTargetedUserList(userIds);
UserRequest userRequest = buildUserRequestWithUserIds(userIds);

mockMvc.perform(post(REFRESH_JOB_URL)
.contentType(JSON_CONTENT_TYPE)
.headers(getHttpHeaders(AUTHORISED_JOB_SERVICE))
.param("jobId", jobId.toString())
.content(mapper.writeValueAsBytes(userRequest)))
.andExpect(status().is(202))
.andReturn();

await().pollDelay(WAIT_FOR_ASYNC_TO_COMPLETE, TimeUnit.SECONDS)
.timeout(WAIT_FOR_ASYNC_TO_TIMEOUT, TimeUnit.SECONDS)
.untilAsserted(() -> Assertions.assertTrue(isRefreshJobInStatus(jobId, COMPLETED)));

logger.info(" -- Refresh Role Assignment record updated successfully -- ");
RefreshJob refreshJob = callTestSupportGetJobApi(jobId);
assertEquals(COMPLETED, refreshJob.getStatus());
assertNotNull(refreshJob.getLog());

verify(jrdFeignClient, times(1)).getJudicialDetailsById(any(), any());
verify(jbsFeignClient, deletedFlagStatus ? times(0) : times(1)).getJudicialBookingByUserIds(any());
verify(requestMappingService, times(1)).createJudicialAssignments(usersAccessProfilesCaptor.capture(), any());

Map<String, Set<UserAccessProfile>> usersAccessProfiles = usersAccessProfilesCaptor.getValue();
assertEquals(deletedFlagStatus, usersAccessProfiles.get(userIds[0]).isEmpty());
}

@NotNull
private ResponseEntity<List<CaseWorkerProfilesResponse>> buildUserProfileResponse() {
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class JudicialProfileV2 implements Serializable, UserAccessProfile {
private String initials;
private String retirementDate;
private String activeFlag;
private String deletedFlag;
private List<AppointmentV2> appointments;
private List<AuthorisationV2> authorisations;
private List<RoleV2> roles;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import feign.FeignException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
Expand Down Expand Up @@ -56,13 +57,16 @@ public class RetrieveDataService {
private final ParseRequestService parseRequestService;
private final CRDService crdService;
private final JRDService jrdService;
private final boolean filterSoftDeletedUsers;

public RetrieveDataService(ParseRequestService parseRequestService,
CRDService crdService,
JRDService jrdService) {
JRDService jrdService,
@Value("${refresh.judicial.filterSoftDeletedUsers}") boolean filterSoftDeletedUsers) {
this.parseRequestService = parseRequestService;
this.crdService = crdService;
this.jrdService = jrdService;
this.filterSoftDeletedUsers = filterSoftDeletedUsers;
}

public Map<String, Set<UserAccessProfile>> retrieveProfiles(UserRequest userRequest, UserType userType)
Expand Down Expand Up @@ -171,14 +175,7 @@ private void getAccessProfile(UserRequest userRequest, UserType userType, Atomic
caseWorkerProfiles.forEach(userProfile -> usersAccessProfiles.put(userProfile.getId(),
AssignmentRequestBuilder.convertUserProfileToCaseworkerAccessProfile(userProfile)));
} else if (!CollectionUtils.isEmpty(validProfiles) && userType.equals(UserType.JUDICIAL)) {
validProfiles.forEach(userProfile -> {
JudicialProfileV2 judicialProfile = (JudicialProfileV2) userProfile;
usersAccessProfiles.put(judicialProfile.getSidamId(),
convertProfileToJudicialAccessProfileV2(judicialProfile));
});
Set<JudicialProfileV2> invalidJProfiles = (Set<JudicialProfileV2>)(Set<?>) invalidProfiles;
invalidJProfiles.forEach(profile ->
usersAccessProfiles.put(profile.getSidamId(), Collections.emptySet()));
addJudicialProfilesToUsersAccessProfiles(validProfiles, usersAccessProfiles, invalidProfiles);
}
Map<String, Integer> userAccessProfileCount = new HashMap<>();
usersAccessProfiles.forEach((k, v) -> {
Expand All @@ -198,4 +195,35 @@ private void getAccessProfile(UserRequest userRequest, UserType userType, Atomic
}
}

@SuppressWarnings("unchecked")
private void addJudicialProfilesToUsersAccessProfiles(List<Object> validProfiles,
Map<String, Set<UserAccessProfile>> usersAccessProfiles,
Set<Object> invalidProfiles) {
List<String> softDeletedUsers = new ArrayList<>();

validProfiles.forEach(userProfile -> {
JudicialProfileV2 judicialProfile = (JudicialProfileV2) userProfile;
boolean isJudicialUserSoftDeleted = Boolean.parseBoolean(judicialProfile.getDeletedFlag());

if (isJudicialUserSoftDeleted) {
softDeletedUsers.add(judicialProfile.getSidamId());
}

if (filterSoftDeletedUsers && isJudicialUserSoftDeleted) {
usersAccessProfiles.put(judicialProfile.getSidamId(), Collections.emptySet());
} else {
usersAccessProfiles.put(judicialProfile.getSidamId(),
convertProfileToJudicialAccessProfileV2(judicialProfile));
}
});

if (!softDeletedUsers.isEmpty()) {
log.info("Soft deleted JRD users :: {}", softDeletedUsers);
}

Set<JudicialProfileV2> invalidJProfiles = (Set<JudicialProfileV2>)(Set<?>) invalidProfiles;
invalidJProfiles.forEach(profile ->
usersAccessProfiles.put(profile.getSidamId(), Collections.emptySet()));
}

}
2 changes: 2 additions & 0 deletions src/main/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ refresh:
includeJudicialBookings: ${REFRESH_JOB_INCLUDE_BOOKINGS:false}
BulkAssignment:
includeJudicialBookings: ${REFRESH_BULK_ASSIGNMENT_INCLUDE_BOOKINGS:false}
judicial:
filterSoftDeletedUsers: ${REFRESH_JUDICIAL_FILTER_SOFT_DELETED_USERS:false}

testing:
support:
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/judicialProfileSampleV2.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"initials": "some initials",
"retirement_date": "2040-01-01",
"active_flag": "true",
"deleted_flag": "false",
"appointments": [
{
"base_location_id": "1351",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

import feign.FeignException;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
Expand All @@ -51,7 +53,7 @@ class RetrieveDataServiceTest {
private final JRDService jrdService = Mockito.mock(JRDService.class);
private final ParseRequestService parseRequestService = Mockito.mock(ParseRequestService.class);

RetrieveDataService sut = new RetrieveDataService(parseRequestService, crdService, jrdService);
RetrieveDataService sut = new RetrieveDataService(parseRequestService, crdService, jrdService, true);

@Test
void retrieveCaseWorkerProfilesTest() {
Expand Down Expand Up @@ -208,6 +210,30 @@ void shouldReturnJudicialProfileV2_withAppointmentsFlag() {
});
}

@ParameterizedTest
@CsvSource({
"true,true,0",
"true,false,2",
"false,true,2",
"false,false,2"
})
void shouldReturnJudicialProfileV2_deletedFlag(Boolean filterSoftDeletedUsersEnabled,
Boolean deletedFlagStatus,
int expectedUserAccessProfileCount) throws IOException {
sut = new RetrieveDataService(parseRequestService, crdService, jrdService, filterSoftDeletedUsersEnabled);

JudicialProfileV2 profile = TestDataBuilder.buildJudicialProfileV2();
profile.setDeletedFlag(deletedFlagStatus.toString());

doReturn(ResponseEntity.ok(List.of(profile))).when(jrdService).fetchJudicialProfiles(any());

Map<String, Set<UserAccessProfile>> response
= sut.retrieveProfiles(TestDataBuilder.buildUserRequest(), UserType.JUDICIAL);

assertNotNull(response);
assertEquals(expectedUserAccessProfileCount, response.get(profile.getSidamId()).size());
}

@Test
void shouldReturnZeroJudicialProfileV2() {
List<JudicialProfileV2> judicialProfiles = Collections.emptyList();
Expand Down

0 comments on commit 91055f5

Please sign in to comment.