diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/GraphQLMethodBinding.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/GraphQLMethodBinding.java index a86475c1a4a..d0b46be35b0 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/GraphQLMethodBinding.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/GraphQLMethodBinding.java @@ -29,8 +29,11 @@ import ca.uhn.fhir.rest.api.server.IRestfulServer; import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.ResponseDetails; import ca.uhn.fhir.rest.param.ParameterUtil; +import ca.uhn.fhir.rest.param.TokenParam; import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; +import org.hl7.fhir.instance.model.api.IBaseCoding; +import org.hl7.fhir.instance.model.api.IBaseResource; import javax.annotation.Nonnull; import javax.servlet.http.HttpServletRequest; @@ -91,21 +94,41 @@ public class GraphQLMethodBinding extends BaseMethodBinding { String responseString = (String) response; + HttpServletRequest servletRequest=null; + HttpServletResponse servletResponse=null; + if (theRequest instanceof ServletRequestDetails) { + servletRequest = ((ServletRequestDetails) theRequest).getServletRequest(); + servletResponse = ((ServletRequestDetails) theRequest).getServletResponse(); + } + // Interceptor call: SERVER_OUTGOING_GRAPHQL_RESPONSE HookParams params = new HookParams() .add(RequestDetails.class, theRequest) .addIfMatchesType(ServletRequestDetails.class, theRequest) .add(String.class, theRequest.getParameters().get(Constants.PARAM_GRAPHQL_QUERY)[0]) .add(String.class, responseString); - if (theRequest.getInterceptorBroadcaster().callHooks(Pointcut.SERVER_OUTGOING_GRAPHQL_RESPONSE, params)) { - - // Write the response - Writer writer = theRequest.getResponse().getResponseWriter(statusCode, statusMessage, contentType, charset, respondGzip); - writer.write(responseString); - writer.close(); - + if (!theRequest.getInterceptorBroadcaster().callHooks(Pointcut.SERVER_OUTGOING_GRAPHQL_RESPONSE, params)) { + return null; } + // Interceptor call: SERVER_OUTGOING_RESPONSE + params = new HookParams() + .add(RequestDetails.class, theRequest) + .addIfMatchesType(ServletRequestDetails.class, theRequest) + .add(IBaseResource.class, null) + .add(ResponseDetails.class, new ResponseDetails()) + .add(HttpServletRequest.class, servletRequest) + .add(HttpServletResponse.class, servletResponse); + if (!theRequest.getInterceptorBroadcaster().callHooks(Pointcut.SERVER_OUTGOING_RESPONSE, params)) { + return null; + } + + // Write the response + Writer writer = theRequest.getResponse().getResponseWriter(statusCode, statusMessage, contentType, charset, respondGzip); + writer.write(responseString); + writer.close(); + + return null; } } diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptorR4Test.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptorR4Test.java index bd3e9a6087b..c3c99797e1d 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptorR4Test.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptorR4Test.java @@ -19,7 +19,9 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.rest.server.tenant.UrlBaseTenantIdentificationStrategy; +import ca.uhn.fhir.test.utilities.JettyUtil; import ca.uhn.fhir.util.TestUtil; +import ca.uhn.fhir.util.UrlUtil; import com.google.common.base.Charsets; import com.google.common.collect.Lists; import org.apache.commons.io.IOUtils; @@ -34,9 +36,9 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.servlet.ServletHolder; -import org.hl7.fhir.r4.model.*; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; +import org.hl7.fhir.r4.model.*; import org.junit.*; import java.io.IOException; @@ -51,8 +53,6 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.*; -import ca.uhn.fhir.test.utilities.JettyUtil; - public class AuthorizationInterceptorR4Test { private static final String ERR403 = "{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"severity\":\"error\",\"code\":\"processing\",\"diagnostics\":\"Access denied by default policy (no applicable rules)\"}]}"; @@ -1893,6 +1893,55 @@ public class AuthorizationInterceptorR4Test { assertFalse(ourHitMethod); } + @Test + public void testGraphQLAllowed() throws Exception { + ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) { + @Override + public List buildRuleList(RequestDetails theRequestDetails) { + return new RuleBuilder() + .allow("Rule 1").graphQL().any().andThen() + .build(); + } + }); + + HttpGet httpGet; + HttpResponse status; + String response; + + ourReturn = Collections.singletonList(createPatient(2)); + ourHitMethod = false; + httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$graphql?query=" + UrlUtil.escapeUrlParam("{name}")); + status = ourClient.execute(httpGet); + extractResponseAndClose(status); + assertEquals(200, status.getStatusLine().getStatusCode()); + assertTrue(ourHitMethod); + + } + + @Test + public void testGraphQLDenied() throws Exception { + ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) { + @Override + public List buildRuleList(RequestDetails theRequestDetails) { + return new RuleBuilder() + .build(); + } + }); + + HttpGet httpGet; + HttpResponse status; + String response; + + ourReturn = Collections.singletonList(createPatient(2)); + ourHitMethod = false; + httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$graphql?query=" + UrlUtil.escapeUrlParam("{name}")); + status = ourClient.execute(httpGet); + extractResponseAndClose(status); + assertEquals(403, status.getStatusLine().getStatusCode()); + assertTrue(ourHitMethod); + + } + @Test public void testReadByAnyId() throws Exception { ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) { @@ -3732,6 +3781,11 @@ public class AuthorizationInterceptorR4Test { return (Parameters) new Parameters().setId("1"); } + @GraphQL + public String processGraphQlRequest(ServletRequestDetails theRequestDetails, @IdParam IIdType theId, @GraphQLQuery String theQuery) { + ourHitMethod = true; + return "{'foo':'bar'}"; + } @Transaction() public Bundle search(ServletRequestDetails theRequestDetails, IInterceptorBroadcaster theInterceptorBroadcaster, @TransactionParam Bundle theInput) { @@ -3779,7 +3833,7 @@ public class AuthorizationInterceptorR4Test { proxyHandler.addServletWithMapping(servletHolder, "/*"); ourServer.setHandler(proxyHandler); JettyUtil.startServer(ourServer); - ourPort = JettyUtil.getPortForStartedServer(ourServer); + ourPort = JettyUtil.getPortForStartedServer(ourServer); PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS); HttpClientBuilder builder = HttpClientBuilder.create();