search narrowing interceptor responds with 403 Forbidden instead of creating an impossible query
This commit is contained in:
parent
d4bb48c551
commit
e52d11b5ba
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
type: add
|
||||
issue: 3018
|
||||
jira: SMILE-782
|
||||
title: "Previously, when a search query explicitly included a search parameter that was for the same resource type but a
|
||||
different resource instance from the one specified in the token, the search narrowing interceptor would include both search
|
||||
parameters in the final query, resulting in an empty bundle being returned to the caller. Now, such a call will result in
|
||||
a 403 Forbidden error, making it more clear why no resources were returned."
|
|
@ -25,6 +25,7 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
|||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.interceptor.api.Hook;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.QualifiedParamList;
|
||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
|
@ -164,15 +165,13 @@ public class SearchNarrowingInterceptor {
|
|||
|
||||
/*
|
||||
* If none of the values that were requested by the client overlap at all
|
||||
* with the values that the user is allowed to see, we'll just add the permitted
|
||||
* list as a new list. Ultimately this scenario actually means that the client
|
||||
* shouldn't get *any* results back, and adding a new AND parameter (that doesn't
|
||||
* overlap at all with the others) is one way of ensuring that.
|
||||
* with the values that the user is allowed to see, the client shouldn't
|
||||
* get *any* results back. We return an error code indicating that the
|
||||
* caller is forbidden from accessing the resources they requested.
|
||||
*/
|
||||
if (!restrictedExistingList) {
|
||||
String[] newValues = Arrays.copyOf(existingValues, existingValues.length + 1);
|
||||
newValues[existingValues.length] = ParameterUtil.escapeAndJoinOrList(nextAllowedValues);
|
||||
newParameters.put(nextParamName, newValues);
|
||||
theResponse.setStatus(Constants.STATUS_HTTP_403_FORBIDDEN);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import ca.uhn.fhir.rest.annotation.OptionalParam;
|
|||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.annotation.Transaction;
|
||||
import ca.uhn.fhir.rest.annotation.TransactionParam;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||
import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum;
|
||||
|
@ -17,6 +18,7 @@ import ca.uhn.fhir.rest.param.TokenAndListParam;
|
|||
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ForbiddenOperationException;
|
||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
|
@ -44,6 +46,7 @@ import java.util.stream.Collectors;
|
|||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
public class SearchNarrowingInterceptorTest {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(SearchNarrowingInterceptorTest.class);
|
||||
|
@ -226,19 +229,20 @@ public class SearchNarrowingInterceptorTest {
|
|||
|
||||
ourNextCompartmentList = new AuthorizedList().addCompartments("Patient/123", "Patient/456");
|
||||
|
||||
ourClient
|
||||
.search()
|
||||
.forResource("Observation")
|
||||
.where(Observation.PATIENT.hasAnyOfIds("Patient/111", "Patient/777"))
|
||||
.and(Observation.PATIENT.hasAnyOfIds("Patient/111", "Patient/888"))
|
||||
.execute();
|
||||
try {
|
||||
ourClient
|
||||
.search()
|
||||
.forResource("Observation")
|
||||
.where(Observation.PATIENT.hasAnyOfIds("Patient/111", "Patient/777"))
|
||||
.and(Observation.PATIENT.hasAnyOfIds("Patient/111", "Patient/888"))
|
||||
.execute();
|
||||
|
||||
assertEquals("Observation.search", ourLastHitMethod);
|
||||
assertNull(ourLastIdParam);
|
||||
assertNull(ourLastCodeParam);
|
||||
assertNull(ourLastSubjectParam);
|
||||
assertNull(ourLastPerformerParam);
|
||||
assertThat(toStrings(ourLastPatientParam), Matchers.contains("Patient/111,Patient/777", "Patient/111,Patient/888", "Patient/123,Patient/456"));
|
||||
fail("Expected a 403 error");
|
||||
} catch (ForbiddenOperationException e) {
|
||||
assertEquals(Constants.STATUS_HTTP_403_FORBIDDEN, e.getStatusCode());
|
||||
}
|
||||
|
||||
assertNull(ourLastHitMethod);
|
||||
}
|
||||
|
||||
private List<String> toStrings(BaseAndListParam<? extends IQueryParameterOr<?>> theParams) {
|
||||
|
|
Loading…
Reference in New Issue