diff --git a/pom.xml b/pom.xml index 7b13e4cf7..ebcb08cea 100644 --- a/pom.xml +++ b/pom.xml @@ -66,9 +66,9 @@ 17.0.75 1.0.6 6.4.1 - 17.104.136 + 17.104.137 17.104.3 - 17.104.176 + 17.104.180 17.104.50 17.104.102 17.104.48 diff --git a/progression-command/progression-command-api/src/main/java/uk/gov/moj/cpp/progression/command/InitiateCourtApplicationProceedingsCommandApi.java b/progression-command/progression-command-api/src/main/java/uk/gov/moj/cpp/progression/command/InitiateCourtApplicationProceedingsCommandApi.java index ecf798e9e..1c8ac5bbc 100644 --- a/progression-command/progression-command-api/src/main/java/uk/gov/moj/cpp/progression/command/InitiateCourtApplicationProceedingsCommandApi.java +++ b/progression-command/progression-command-api/src/main/java/uk/gov/moj/cpp/progression/command/InitiateCourtApplicationProceedingsCommandApi.java @@ -1,8 +1,13 @@ package uk.gov.moj.cpp.progression.command; +import static java.util.Optional.empty; +import static java.util.Optional.of; +import static java.util.UUID.fromString; +import static org.apache.commons.collections.CollectionUtils.isNotEmpty; import static uk.gov.justice.core.courts.LinkType.STANDALONE; import static uk.gov.justice.services.core.annotation.Component.COMMAND_API; import static uk.gov.justice.services.messaging.Envelope.metadataFrom; +import static uk.gov.moj.cpp.progression.command.api.UserDetailsLoader.getAllowedHearingTypes; import static uk.gov.moj.cpp.progression.command.api.UserDetailsLoader.isUserHasPermissionForApplicationTypeCode; import uk.gov.justice.services.adapter.rest.exception.BadRequestException; @@ -14,6 +19,9 @@ import uk.gov.justice.services.messaging.Envelope; import uk.gov.justice.services.messaging.JsonEnvelope; +import java.util.List; +import java.util.Optional; +import java.util.UUID; import java.util.regex.Pattern; import javax.inject.Inject; @@ -24,6 +32,7 @@ public class InitiateCourtApplicationProceedingsCommandApi { private static final Pattern URN_PATTERN = Pattern.compile("^[A-Z0-9]{11}$"); private static final String LINK_TYPE = "linkType"; + public static final String COURT_APPLICATION = "courtApplication"; @Inject private Sender sender; @@ -38,17 +47,46 @@ public void initiateCourtApplicationProceedings(final JsonEnvelope command) { throw new ForbiddenRequestException("User is not authorised to use this application type!"); } - validateInputsForApplication(command.payloadAsJsonObject()); + validateInputsForApplication(command); this.sender.send(Envelope.envelopeFrom(metadataFrom(command.metadata()).withName("progression.command.initiate-court-proceedings-for-application").build(), command.payloadAsJsonObject())); } - private void validateInputsForApplication(final JsonObject jsonObject) { - final JsonObject courtApplication = jsonObject.getJsonObject("courtApplication"); + private void validateDefaultHearingType(final JsonEnvelope command) { + final JsonObject payload = command.payloadAsJsonObject(); + final JsonObject courtApplication = payload.getJsonObject(COURT_APPLICATION); + if (!standaloneApplication(courtApplication)) { + return; + } + + final String applicationTypeId = courtApplication.getJsonObject("type").getString("id"); + final List allowedHearingTypes = getAllowedHearingTypes(command.metadata(), requester, applicationTypeId); + if (isNotEmpty(allowedHearingTypes)) { + final Optional submittedHearingTypeId = submittedHearingTypeId(payload); + if (!submittedHearingTypeId.isPresent() || !allowedHearingTypes.contains(submittedHearingTypeId.get())) { + throw new BadRequestException("Hearing type must be one of the allowed hearing types for this application type!"); + } + } + } + + private Optional submittedHearingTypeId(final JsonObject payload) { + if (!payload.containsKey("courtHearing")) { + return empty(); + } + final JsonObject courtHearing = payload.getJsonObject("courtHearing"); + if (!courtHearing.containsKey("hearingType")) { + return empty(); + } + return of(fromString(courtHearing.getJsonObject("hearingType").getString("id"))); + } + + private void validateInputsForApplication(final JsonEnvelope command) { + final JsonObject courtApplication = command.payloadAsJsonObject().getJsonObject(COURT_APPLICATION); if (standaloneApplication(courtApplication) && courtApplication.containsKey("applicationReference") && isNotValidUrn(courtApplication.getString("applicationReference"))) { throw new BadRequestException("Entered URN is not valid!"); } + validateDefaultHearingType(command); } private boolean standaloneApplication(final JsonObject courtApplication) { @@ -60,7 +98,7 @@ private boolean isNotValidUrn(final String applicationReference) { } private boolean isUserNotAuthorised(final JsonEnvelope command) { - final String applicationTypeCode = command.payloadAsJsonObject().getJsonObject("courtApplication").getJsonObject("type").getString("code"); + final String applicationTypeCode = command.payloadAsJsonObject().getJsonObject(COURT_APPLICATION).getJsonObject("type").getString("code"); return !isUserHasPermissionForApplicationTypeCode(command.metadata(), requester, applicationTypeCode); } diff --git a/progression-command/progression-command-api/src/main/java/uk/gov/moj/cpp/progression/command/api/UserDetailsLoader.java b/progression-command/progression-command-api/src/main/java/uk/gov/moj/cpp/progression/command/api/UserDetailsLoader.java index ea21b2c93..8fdd9812d 100644 --- a/progression-command/progression-command-api/src/main/java/uk/gov/moj/cpp/progression/command/api/UserDetailsLoader.java +++ b/progression-command/progression-command-api/src/main/java/uk/gov/moj/cpp/progression/command/api/UserDetailsLoader.java @@ -1,6 +1,7 @@ package uk.gov.moj.cpp.progression.command.api; import static java.lang.String.format; +import static java.util.Objects.isNull; import static java.util.Objects.nonNull; import static java.util.UUID.fromString; import static javax.json.Json.createObjectBuilder; @@ -9,6 +10,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import uk.gov.justice.services.core.requester.Requester; import uk.gov.justice.services.messaging.Envelope; import uk.gov.justice.services.messaging.JsonEnvelope; @@ -20,12 +22,14 @@ import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.UUID; import java.util.stream.Collectors; import javax.json.Json; import javax.json.JsonArray; import javax.json.JsonObject; +import javax.json.JsonString; import javax.json.JsonValue; public class UserDetailsLoader { @@ -37,6 +41,8 @@ public class UserDetailsLoader { public static final String TARGET = "target"; public static final String OBJECT = "object"; public static final String ACTION = "action"; + public static final String ACTIVE = "active"; + public static final String HEARING_TYPE = "HearingType"; public static final String ORGANISATION_ID = "organisationId"; public static final String ORGANISATION_NAME = "organisationName"; public static final String USER_ID_NOT_SUPPLIED_FOR_THE_USER_GROUPS_LOOK_UP = "User id Not Supplied for the UserGroups look up"; @@ -69,7 +75,7 @@ public List getPermissions(final Metadata metadata, final Requester final JsonEnvelope requestEnvelope = envelopeFrom(metadataWithActionName, getOrganisationForUserRequest); final Envelope response = requester.requestAsAdmin(requestEnvelope, JsonObject.class); - if (!response.payload().containsKey(PERMISSIONS)) { + if (!response.payload().containsKey(PERMISSIONS)) { return Collections.emptyList(); } final JsonArray permissionsJsonArray = response.payload().getJsonArray(PERMISSIONS); @@ -79,7 +85,7 @@ public List getPermissions(final Metadata metadata, final Requester } return permissionsJsonArray.stream() - .map(p -> (JsonObject)p) + .map(p -> (JsonObject) p) .map(permission -> Permission.permission() .withAction(JsonObjects.getString(permission, ACTION).orElse(null)) @@ -90,8 +96,49 @@ public List getPermissions(final Metadata metadata, final Requester ).collect(Collectors.toList()); } + public static List getAllowedHearingTypes(final Metadata metadata, final Requester requester, final String applicationTypeId) { + final JsonObject request = Json.createObjectBuilder() + .add(OBJECT, HEARING_TYPE) + .add(SOURCE, applicationTypeId) + .build(); + final MetadataBuilder metadataWithActionName = Envelope.metadataFrom(metadata).withName("usersgroups.permissions"); + + final JsonEnvelope requestEnvelope = envelopeFrom(metadataWithActionName, request); + final Envelope response = requester.requestAsAdmin(requestEnvelope, JsonObject.class); + + final JsonObject payload = response.payload(); + if (isNull(payload) || !payload.containsKey(PERMISSIONS)) { + return Collections.emptyList(); + } + final JsonArray permissionsJsonArray = payload.getJsonArray(PERMISSIONS); + if (isNull(permissionsJsonArray)) { + return Collections.emptyList(); + } + + return permissionsJsonArray.stream() + .map(p -> (JsonObject) p) + .filter(UserDetailsLoader::isActive) + .map(permission -> getNullableUUID(permission, TARGET)) + .filter(Objects::nonNull) + .toList(); + } + + private static boolean isActive(final JsonObject permission) { + if (!permission.containsKey(ACTIVE)) { + return false; + } + final JsonValue value = permission.get(ACTIVE); + if (value.getValueType() == JsonValue.ValueType.TRUE) { + return true; + } + if (value.getValueType() == JsonValue.ValueType.STRING) { + return Boolean.parseBoolean(((JsonString) value).getString()); + } + return false; + } + private static UUID getNullableUUID(final JsonObject permission, final String attribute) { - final String uuidString = JsonObjects.getString( permission, attribute).orElse(null); + final String uuidString = JsonObjects.getString(permission, attribute).orElse(null); if (nonNull(uuidString)) { return fromString(uuidString); } else { @@ -110,7 +157,7 @@ protected UserOrganisationDetails getOrganisationDetailsForUser(final Envelope response = requester.requestAsAdmin(usersAndGroupsRequestEnvelope, JsonObject.class); final JsonObject organisationDetails = response.payload(); - if(nonNull(organisationDetails) && organisationDetails.containsKey(ORGANISATION_ID)) { + if (nonNull(organisationDetails) && organisationDetails.containsKey(ORGANISATION_ID)) { return new UserOrganisationDetails(fromString(organisationDetails.getString(ORGANISATION_ID)), organisationDetails.getString(ORGANISATION_NAME)); } @@ -123,7 +170,7 @@ public boolean isPermitted(final JsonEnvelope query, final Requester requester) .orElseThrow(() -> new IllegalStateException(USER_ID_NOT_SUPPLIED_FOR_THE_USER_GROUPS_LOOK_UP)); final UserOrganisationDetails organisationDetailsForUser = getOrganisationDetailsForUser(query, requester, userId); final List permissions = getPermissions(query.metadata(), requester, query.payloadAsJsonObject().getString(DEFENDANT_ID)); - if(permissions.isEmpty()) { + if (permissions.isEmpty()) { return false; } diff --git a/progression-command/progression-command-api/src/test/java/uk/gov/moj/cpp/progression/command/InitiateCourtApplicationProceedingsCommandApiTest.java b/progression-command/progression-command-api/src/test/java/uk/gov/moj/cpp/progression/command/InitiateCourtApplicationProceedingsCommandApiTest.java index 37b03dfb3..ff5dca926 100644 --- a/progression-command/progression-command-api/src/test/java/uk/gov/moj/cpp/progression/command/InitiateCourtApplicationProceedingsCommandApiTest.java +++ b/progression-command/progression-command-api/src/test/java/uk/gov/moj/cpp/progression/command/InitiateCourtApplicationProceedingsCommandApiTest.java @@ -1,6 +1,7 @@ package uk.gov.moj.cpp.progression.command; import static java.util.UUID.randomUUID; +import static javax.json.Json.createArrayBuilder; import static javax.json.Json.createObjectBuilder; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; @@ -22,7 +23,9 @@ import uk.gov.justice.services.messaging.spi.DefaultEnvelope; import uk.gov.justice.services.messaging.spi.DefaultJsonEnvelopeProvider; +import javax.json.JsonArrayBuilder; import javax.json.JsonObject; +import javax.json.JsonObjectBuilder; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -54,6 +57,7 @@ public void shouldInitialCourtProceedingsForCourtApplicationWhenNoApplicationRef final Envelope queryResponseEnvelope = mock(Envelope.class); when(queryResponseEnvelope.payload()).thenReturn(createObjectBuilder().add("hasPermission", true).build()); when(requester.request(any(), any())).thenReturn(queryResponseEnvelope); + stubEmptyPermissions(); initiateCourtApplicationProceedingsCommandApi.initiateCourtApplicationProceedings(commandEnvelope); @@ -73,6 +77,7 @@ public void shouldInitialCourtProceedingsForCourtApplicationWhenApplicationRefer .add("courtApplication", createObjectBuilder() .add("id", randomUUID().toString()) .add("type", createObjectBuilder() + .add("id", randomUUID().toString()) .add("code", "anyCode") .add("linkType", "STANDALONE")) .add("applicationReference", validURN) @@ -84,6 +89,7 @@ public void shouldInitialCourtProceedingsForCourtApplicationWhenApplicationRefer final Envelope queryResponseEnvelope = mock(Envelope.class); when(queryResponseEnvelope.payload()).thenReturn(createObjectBuilder().add("hasPermission", true).build()); when(requester.request(any(), any())).thenReturn(queryResponseEnvelope); + stubEmptyPermissions(); initiateCourtApplicationProceedingsCommandApi.initiateCourtApplicationProceedings(commandEnvelope); @@ -227,11 +233,144 @@ public void shouldCallAddBreachApplication() { assertThat(newCommand.payload(), equalTo(commandEnvelope.payloadAsJsonObject())); } + @Test + public void shouldSendCommandWhenSubmittedHearingTypeIsAllowed() { + final String applicationTypeId = randomUUID().toString(); + final String hearingTypeId = randomUUID().toString(); + final JsonEnvelope commandEnvelope = buildStandaloneEnvelope(applicationTypeId, hearingTypeId); + + stubHasPermission(true); + stubPermissions(allowedHearingTypePermissions(applicationTypeId, hearingTypeId)); + + initiateCourtApplicationProceedingsCommandApi.initiateCourtApplicationProceedings(commandEnvelope); + + verify(sender, times(1)).send(envelopeCaptor.capture()); + assertThat(envelopeCaptor.getValue().metadata().name(), is("progression.command.initiate-court-proceedings-for-application")); + } + + @Test + public void shouldSendCommandWhenSubmittedHearingTypeIsOneOfMultipleAllowed() { + final String applicationTypeId = randomUUID().toString(); + final String submittedHearingTypeId = randomUUID().toString(); + final JsonEnvelope commandEnvelope = buildStandaloneEnvelope(applicationTypeId, submittedHearingTypeId); + + stubHasPermission(true); + stubPermissions(allowedHearingTypePermissions(applicationTypeId, + randomUUID().toString(), submittedHearingTypeId, randomUUID().toString())); + + initiateCourtApplicationProceedingsCommandApi.initiateCourtApplicationProceedings(commandEnvelope); + + verify(sender, times(1)).send(envelopeCaptor.capture()); + assertThat(envelopeCaptor.getValue().metadata().name(), is("progression.command.initiate-court-proceedings-for-application")); + } + + @Test + public void shouldThrowBadRequestWhenSubmittedHearingTypeIsNotAllowed() { + final String applicationTypeId = randomUUID().toString(); + final JsonEnvelope commandEnvelope = buildStandaloneEnvelope(applicationTypeId, randomUUID().toString()); + + stubHasPermission(true); + stubPermissions(allowedHearingTypePermissions(applicationTypeId, randomUUID().toString(), randomUUID().toString())); + + assertThrows(BadRequestException.class, () -> initiateCourtApplicationProceedingsCommandApi.initiateCourtApplicationProceedings(commandEnvelope)); + } + + @Test + public void shouldThrowBadRequestWhenHearingTypeAbsentButAllowedHearingTypesExist() { + final String applicationTypeId = randomUUID().toString(); + final JsonEnvelope commandEnvelope = buildStandaloneEnvelope(applicationTypeId, null); + + stubHasPermission(true); + stubPermissions(allowedHearingTypePermissions(applicationTypeId, randomUUID().toString())); + + assertThrows(BadRequestException.class, () -> initiateCourtApplicationProceedingsCommandApi.initiateCourtApplicationProceedings(commandEnvelope)); + } + + @Test + public void shouldSendCommandWhenNoAllowedHearingTypeMappingExists() { + final String applicationTypeId = randomUUID().toString(); + final JsonEnvelope commandEnvelope = buildStandaloneEnvelope(applicationTypeId, randomUUID().toString()); + + stubHasPermission(true); + stubEmptyPermissions(); + + initiateCourtApplicationProceedingsCommandApi.initiateCourtApplicationProceedings(commandEnvelope); + + verify(sender, times(1)).send(envelopeCaptor.capture()); + assertThat(envelopeCaptor.getValue().metadata().name(), is("progression.command.initiate-court-proceedings-for-application")); + } + + @Test + public void shouldNotEnforceHearingTypeForNonStandaloneApplication() { + final JsonObject payload = createObjectBuilder() + .add("courtApplication", createObjectBuilder() + .add("id", randomUUID().toString()) + .add("type", createObjectBuilder() + .add("id", randomUUID().toString()) + .add("code", "anyCode") + .add("linkType", "LINKED")) + .build()) + .build(); + final JsonEnvelope commandEnvelope = buildEnvelope(payload); + + stubHasPermission(true); + + initiateCourtApplicationProceedingsCommandApi.initiateCourtApplicationProceedings(commandEnvelope); + + verify(sender, times(1)).send(envelopeCaptor.capture()); + assertThat(envelopeCaptor.getValue().metadata().name(), is("progression.command.initiate-court-proceedings-for-application")); + } + + private JsonEnvelope buildStandaloneEnvelope(final String applicationTypeId, final String hearingTypeId) { + final JsonObjectBuilder courtApplication = createObjectBuilder() + .add("id", randomUUID().toString()) + .add("type", createObjectBuilder() + .add("id", applicationTypeId) + .add("code", "anyCode") + .add("linkType", "STANDALONE")); + final JsonObjectBuilder payload = createObjectBuilder().add("courtApplication", courtApplication); + if (hearingTypeId != null) { + payload.add("courtHearing", createObjectBuilder() + .add("hearingType", createObjectBuilder().add("id", hearingTypeId))); + } + return buildEnvelope(payload.build()); + } + + private JsonObject allowedHearingTypePermissions(final String source, final String... targets) { + final JsonArrayBuilder permissions = createArrayBuilder(); + for (final String target : targets) { + permissions.add(createObjectBuilder() + .add("object", "HearingType") + .add("action", "Locked") + .add("active", true) + .add("source", source) + .add("target", target)); + } + return createObjectBuilder().add("permissions", permissions).build(); + } + + private void stubHasPermission(final boolean value) { + final Envelope queryResponseEnvelope = mock(Envelope.class); + when(queryResponseEnvelope.payload()).thenReturn(createObjectBuilder().add("hasPermission", value).build()); + when(requester.request(any(), any())).thenReturn(queryResponseEnvelope); + } + + private void stubPermissions(final JsonObject permissionsPayload) { + final Envelope permissionsEnvelope = mock(Envelope.class); + when(permissionsEnvelope.payload()).thenReturn(permissionsPayload); + when(requester.requestAsAdmin(any(), any())).thenReturn(permissionsEnvelope); + } + + private void stubEmptyPermissions() { + stubPermissions(createObjectBuilder().build()); + } + private JsonEnvelope buildEnvelope() { final JsonObject payload = createObjectBuilder() .add("courtApplication", createObjectBuilder() .add("id", randomUUID().toString()) .add("type", createObjectBuilder() + .add("id", randomUUID().toString()) .add("code", "anyCode") .add("linkType", "STANDALONE")) .build()) diff --git a/progression-integration-test/src/test/java/uk/gov/moj/cpp/progression/AbstractIT.java b/progression-integration-test/src/test/java/uk/gov/moj/cpp/progression/AbstractIT.java index a179c7f70..c5fecb0dc 100644 --- a/progression-integration-test/src/test/java/uk/gov/moj/cpp/progression/AbstractIT.java +++ b/progression-integration-test/src/test/java/uk/gov/moj/cpp/progression/AbstractIT.java @@ -24,6 +24,7 @@ import static uk.gov.moj.cpp.progression.stub.SysDocGeneratorStub.stubAsyncDocumentGeneratorEndPoint; import static uk.gov.moj.cpp.progression.stub.UnifiedSearchStub.stubUnifiedSearchQueryExactMatchWithEmptyResults; import static uk.gov.moj.cpp.progression.stub.UnifiedSearchStub.stubUnifiedSearchQueryPartialMatch; +import static uk.gov.moj.cpp.progression.stub.UsersAndGroupsStub.stubEmptyPermissionsQuery; import static uk.gov.moj.cpp.progression.util.WireMockStubUtils.setupAsAuthorisedUser; import static uk.gov.moj.cpp.progression.util.WireMockStubUtils.setupAsSystemUser; import static uk.gov.moj.cpp.progression.util.WireMockStubUtils.setupHearingQueryStub; @@ -103,6 +104,7 @@ protected static void defaultStubs() { setupAsSystemUser(USER_ID_VALUE_AS_ADMIN); setupUsersGroupQueryStub(); setupUsersGroupPermissionsForApplicationTypeStub(true); + stubEmptyPermissionsQuery(); stubQueryLocalJusticeArea("/restResource/referencedata.query.local-justice-areas.json"); stubQueryCourtsCodeData("/restResource/referencedata.query.local-justice-area-court-prosecutor-mapping-courts.json"); stubQueryOrganisationUnitsData("/restResource/referencedata.query.organisationunits.json"); diff --git a/progression-integration-test/src/test/java/uk/gov/moj/cpp/progression/CreateCourtApplicationIT.java b/progression-integration-test/src/test/java/uk/gov/moj/cpp/progression/CreateCourtApplicationIT.java index 43baaa545..40d495f50 100644 --- a/progression-integration-test/src/test/java/uk/gov/moj/cpp/progression/CreateCourtApplicationIT.java +++ b/progression-integration-test/src/test/java/uk/gov/moj/cpp/progression/CreateCourtApplicationIT.java @@ -3,6 +3,8 @@ import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasNoJsonPath; import static com.jayway.jsonpath.matchers.JsonPathMatchers.withJsonPath; import static java.util.UUID.randomUUID; +import static org.apache.http.HttpStatus.SC_BAD_REQUEST; +import static org.apache.http.HttpStatus.SC_ACCEPTED; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; @@ -17,6 +19,7 @@ import static uk.gov.moj.cpp.progression.helper.PreAndPostConditionHelper.pollProsecutionCasesProgressionFor; import static uk.gov.moj.cpp.progression.helper.QueueUtil.retrieveMessageBody; import static uk.gov.moj.cpp.progression.stub.ListingStub.verifyPostListCourtHearing; +import static uk.gov.moj.cpp.progression.stub.UsersAndGroupsStub.stubHearingTypePermission; import static uk.gov.moj.cpp.progression.util.ReferProsecutionCaseToCrownCourtHelper.getProsecutionCaseMatchers; import uk.gov.justice.services.integrationtest.utils.jms.JmsMessageConsumerClient; @@ -26,6 +29,7 @@ import javax.json.JsonObject; +import io.restassured.response.Response; import org.hamcrest.Matcher; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -156,6 +160,28 @@ public void shouldPreserveOffencesWhenApplicationSourceIsMHAndCaseIsInactive() t pollForApplication(applicationId, matchers); } + @Test + public void shouldRejectStandaloneApplicationWhenHearingTypeIsNotAnAllowedHearingType() throws Exception { + // The standalone fixture carries applicationType id e857c8ea-... and hearingType id 8cdfd3da-... + final String standaloneApplicationTypeId = "e857c8ea-cd95-47d1-842f-2d618e77a9b5"; + + // Allowed hearing type for this application type differs from the one in the fixture, + // so the initiate-court-proceedings-for-application command must be rejected. + stubHearingTypePermission(standaloneApplicationTypeId, randomUUID().toString()); + + Response response = initiateCourtProceedingsForCourtApplication(randomUUID().toString(), + "applications/progression.initiate-court-proceedings-for-standalone-application.json"); + + assertThat(response.getStatusCode(), is(SC_BAD_REQUEST)); + + response = initiateCourtProceedingsForCourtApplication(randomUUID().toString(), + "applications/progression.initiate-court-proceedings-for-standalone-application.json"); + + stubHearingTypePermission(standaloneApplicationTypeId, "8cdfd3da-8900-42ca-9835-9f29d1e03cd6"); + + assertThat(response.getStatusCode(), is(SC_ACCEPTED)); + } + private void verifyCourtApplicationCreatedEventPublished(final String applicationId) { final Optional message = retrieveMessageBody(consumerForCourtApplicationCreated); assertTrue(message.isPresent(), "Expected court-application-created event on JMS topic"); diff --git a/progression-integration-test/src/test/java/uk/gov/moj/cpp/progression/stub/UsersAndGroupsStub.java b/progression-integration-test/src/test/java/uk/gov/moj/cpp/progression/stub/UsersAndGroupsStub.java index ff4e7860e..b7a7b59ec 100644 --- a/progression-integration-test/src/test/java/uk/gov/moj/cpp/progression/stub/UsersAndGroupsStub.java +++ b/progression-integration-test/src/test/java/uk/gov/moj/cpp/progression/stub/UsersAndGroupsStub.java @@ -178,4 +178,47 @@ public static void stubUserWithPermission(final String userId, final String body .withBody(body))); } + public static final String PERMISSIONS_QUERY = BASE_QUERY + "/permissions"; + public static final String PERMISSIONS_QUERY_MEDIA_TYPE = "application/vnd.usersgroups.permissions+json"; + + /** + * Default stub for the usersgroups.permissions query, returning no permissions. Registered in + * {@code defaultStubs()} so that every command that now consults this query (e.g. the + * initiate-court-proceedings-for-application hearing-type validation) behaves as "no locked + * mapping" unless a test overrides it with {@link #stubLockedHearingTypePermission}. + */ + public static void stubEmptyPermissionsQuery() { + stubFor(get(urlPathEqualTo(PERMISSIONS_QUERY)) + .willReturn(aResponse().withStatus(OK.getStatusCode()) + .withHeader(ID, randomUUID().toString()) + .withHeader(CONTENT_TYPE, PERMISSIONS_QUERY_MEDIA_TYPE) + .withBody(Json.createObjectBuilder() + .add("permissions", Json.createArrayBuilder()) + .build().toString()))); + } + + /** + * Stubs the usersgroups.permissions query to return a single active HearingType permission + * mapping the given application type ({@code source}) to the allowed hearing type ({@code target}). + */ + public static void stubHearingTypePermission(final String source, final String target) { + final String body = Json.createObjectBuilder() + .add("permissions", Json.createArrayBuilder() + .add(Json.createObjectBuilder() + .add("permissionId", randomUUID().toString()) + .add("object", "HearingType") + .add("action", "Locked") + .add("active", true) + .add("source", source) + .add("target", target))) + .build().toString(); + + removeStub(get(urlPathEqualTo(PERMISSIONS_QUERY))); + stubFor(get(urlPathEqualTo(PERMISSIONS_QUERY)) + .willReturn(aResponse().withStatus(OK.getStatusCode()) + .withHeader(ID, randomUUID().toString()) + .withHeader(CONTENT_TYPE, PERMISSIONS_QUERY_MEDIA_TYPE) + .withBody(body))); + } + }