diff --git a/fhir-model/src/main/java/com/ibm/fhir/model/util/ModelSupport.java b/fhir-model/src/main/java/com/ibm/fhir/model/util/ModelSupport.java index 4b225b08801..e5369b1c628 100644 --- a/fhir-model/src/main/java/com/ibm/fhir/model/util/ModelSupport.java +++ b/fhir-model/src/main/java/com/ibm/fhir/model/util/ModelSupport.java @@ -112,61 +112,64 @@ public final class ModelSupport { private static final Map, Class> CONCRETE_TYPE_MAP = buildConcreteTypeMap(); private static final Map, Map> MODEL_CLASS_ELEMENT_INFO_MAP = buildModelClassElementInfoMap(); private static final Map> RESOURCE_TYPE_MAP = buildResourceTypeMap(); + private static final Set> CONCRETE_RESOURCE_TYPES = getResourceTypes().stream() + .filter(rt -> !isAbstract(rt)) + .collect(Collectors.toSet()); private static final Map, Set> MODEL_CLASS_CONSTRAINT_MAP = buildModelClassConstraintMap(); // LinkedHashSet is used just to preserve the order, for convenience only private static final Set> CHOICE_ELEMENT_TYPES = new LinkedHashSet<>(Arrays.asList( - Base64Binary.class, - com.ibm.fhir.model.type.Boolean.class, - Canonical.class, - Code.class, - Date.class, - DateTime.class, - Decimal.class, - Id.class, - Instant.class, - com.ibm.fhir.model.type.Integer.class, - Markdown.class, - Oid.class, - PositiveInt.class, - com.ibm.fhir.model.type.String.class, - Time.class, - UnsignedInt.class, - Uri.class, - Url.class, - Uuid.class, - Address.class, - Age.class, - Annotation.class, - Attachment.class, - CodeableConcept.class, - Coding.class, - ContactPoint.class, - Count.class, - Distance.class, - Duration.class, - HumanName.class, - Identifier.class, - Money.class, - MoneyQuantity.class, // profiled type - Period.class, - Quantity.class, - Range.class, - Ratio.class, - Reference.class, - SampledData.class, - SimpleQuantity.class, // profiled type - Signature.class, - Timing.class, - ContactDetail.class, - Contributor.class, - DataRequirement.class, - Expression.class, - ParameterDefinition.class, - RelatedArtifact.class, - TriggerDefinition.class, - UsageContext.class, - Dosage.class, - Meta.class)); + Base64Binary.class, + com.ibm.fhir.model.type.Boolean.class, + Canonical.class, + Code.class, + Date.class, + DateTime.class, + Decimal.class, + Id.class, + Instant.class, + com.ibm.fhir.model.type.Integer.class, + Markdown.class, + Oid.class, + PositiveInt.class, + com.ibm.fhir.model.type.String.class, + Time.class, + UnsignedInt.class, + Uri.class, + Url.class, + Uuid.class, + Address.class, + Age.class, + Annotation.class, + Attachment.class, + CodeableConcept.class, + Coding.class, + ContactPoint.class, + Count.class, + Distance.class, + Duration.class, + HumanName.class, + Identifier.class, + Money.class, + MoneyQuantity.class, // profiled type + Period.class, + Quantity.class, + Range.class, + Ratio.class, + Reference.class, + SampledData.class, + SimpleQuantity.class, // profiled type + Signature.class, + Timing.class, + ContactDetail.class, + Contributor.class, + DataRequirement.class, + Expression.class, + ParameterDefinition.class, + RelatedArtifact.class, + TriggerDefinition.class, + UsageContext.class, + Dosage.class, + Meta.class)); private static final Set> DATA_TYPES; static { // LinkedHashSet is used just to preserve the order, for convenience only @@ -645,6 +648,17 @@ public static Collection> getResourceTypes() { return RESOURCE_TYPE_MAP.values(); } + /** + * @return a collection of FHIR resource type model classes + */ + public static Collection> getResourceTypes(boolean includeAbstractTypes) { + if (includeAbstractTypes) { + return RESOURCE_TYPE_MAP.values(); + } else { + return CONCRETE_RESOURCE_TYPES; + } + } + /** * @return the set of classes for the FHIR elements */ @@ -865,6 +879,15 @@ public static boolean isResourceType(Class modelClass) { return Resource.class.isAssignableFrom(modelClass); } + /** + * @param modelClass + * a model class which represents a FHIR resource or element + * @return true if {@code modelClass} is an abstract FHIR model class; otherwise false + */ + public static boolean isAbstract(Class modelClass) { + return Modifier.isAbstract(modelClass.getModifiers()); + } + /** * @param name * the resource type name in titlecase to match the corresponding model class name diff --git a/fhir-server/src/main/java/com/ibm/fhir/server/resources/Capabilities.java b/fhir-server/src/main/java/com/ibm/fhir/server/resources/Capabilities.java index 8f75c8c94bd..03559e0506e 100644 --- a/fhir-server/src/main/java/com/ibm/fhir/server/resources/Capabilities.java +++ b/fhir-server/src/main/java/com/ibm/fhir/server/resources/Capabilities.java @@ -55,6 +55,7 @@ import com.ibm.fhir.model.resource.CapabilityStatement.Rest.Resource.Operation; import com.ibm.fhir.model.resource.DomainResource; import com.ibm.fhir.model.resource.OperationDefinition; +import com.ibm.fhir.model.resource.Resource; import com.ibm.fhir.model.resource.SearchParameter; import com.ibm.fhir.model.type.Canonical; import com.ibm.fhir.model.type.Code; @@ -98,7 +99,9 @@ public class Capabilities extends FHIRResource { private static final String BASE_CAPABILITY_URL = "http://hl7.org/fhir/CapabilityStatement/base"; private static final String BASE_2_CAPABILITY_URL = "http://hl7.org/fhir/CapabilityStatement/base2"; private static final List ALL_INTERACTIONS = Arrays.asList("create", "read", "vread", "update", "patch", "delete", "history", "search"); - private static final List ALL_RESOURCE_TYPES = Arrays.asList(ResourceType.ValueSet.values()); + private static final List ALL_RESOURCE_TYPES = ModelSupport.getResourceTypes(false).stream() + .map(rt -> ResourceType.ValueSet.from(rt.getSimpleName())) + .collect(Collectors.toList()); // Error Messages private static final String ERROR_MSG = "Caught exception while processing 'metadata' request."; @@ -450,10 +453,14 @@ private List getSupportedResourceTypes(PropertyGroup rsrc List rsrcsEntries = rsrcsGroup.getProperties(); if (rsrcsEntries != null && !rsrcsEntries.isEmpty()) { for (PropertyEntry rsrcsEntry : rsrcsEntries) { - + String name = rsrcsEntry.getName(); // Ensure we skip over the special property "open" and process only the others - if (!FHIRConfiguration.PROPERTY_FIELD_RESOURCES_OPEN.equals(rsrcsEntry.getName())) { - resourceTypes.add(ResourceType.ValueSet.from(rsrcsEntry.getName())); + if (!FHIRConfiguration.PROPERTY_FIELD_RESOURCES_OPEN.equals(name)) { + // Skip the abstract types Resource and DomainResource + if (!Resource.class.equals(ModelSupport.getResourceType(name)) && + !DomainResource.class.equals(ModelSupport.getResourceType(name))) { + resourceTypes.add(ResourceType.ValueSet.from(name)); + } } } } diff --git a/fhir-server/src/main/java/com/ibm/fhir/server/resources/WellKnown.java b/fhir-server/src/main/java/com/ibm/fhir/server/resources/WellKnown.java index 1825e9751fd..43fa07c7416 100644 --- a/fhir-server/src/main/java/com/ibm/fhir/server/resources/WellKnown.java +++ b/fhir-server/src/main/java/com/ibm/fhir/server/resources/WellKnown.java @@ -17,6 +17,7 @@ import static com.ibm.fhir.server.util.IssueTypeToHttpStatusMapper.issueListToStatus; import java.net.URI; +import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.logging.Level; @@ -107,6 +108,10 @@ private JsonObject buildSmartConfig() throws Exception { revokeURLTemplate = FHIRConfigHelper.getStringProperty(PROPERTY_SECURITY_OAUTH_REVOKE_URL, ""); supportedScopes = FHIRConfigHelper.getStringListProperty(PROPERTY_SECURITY_OAUTH_SMART_SCOPES); capabilities = FHIRConfigHelper.getStringListProperty(PROPERTY_SECURITY_OAUTH_SMART_CAPABILITIES); + if (capabilities == null) { + // Set an empty list since capabilities is a required field + capabilities = new ArrayList<>(); + } } catch (Exception e) { log.log(Level.SEVERE, "An error occurred while reading the OAuth/SMART properties", e); } diff --git a/fhir-server/src/test/java/com/ibm/fhir/server/resources/CapabilitiesTest.java b/fhir-server/src/test/java/com/ibm/fhir/server/resources/CapabilitiesTest.java new file mode 100644 index 00000000000..1cffb7dd48f --- /dev/null +++ b/fhir-server/src/test/java/com/ibm/fhir/server/resources/CapabilitiesTest.java @@ -0,0 +1,123 @@ +/* + * (C) Copyright IBM Corp. 2020 + * + * SPDX-License-Identifier: Apache-2.0 + */ +package com.ibm.fhir.server.resources; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +import java.util.List; +import java.util.Optional; + +import javax.ws.rs.core.Response; + +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import com.ibm.fhir.config.FHIRConfiguration; +import com.ibm.fhir.config.FHIRRequestContext; +import com.ibm.fhir.exception.FHIRException; +import com.ibm.fhir.model.resource.CapabilityStatement; +import com.ibm.fhir.model.resource.CapabilityStatement.Rest.Resource.Interaction; +import com.ibm.fhir.model.type.code.ResourceType; +import com.ibm.fhir.server.test.MockHttpServletRequest; +import com.ibm.fhir.server.test.MockServletContext; + +public class CapabilitiesTest { + + @BeforeClass + void setup() { + FHIRConfiguration.setConfigHome("target/test-classes"); + } + + @AfterClass + void tearDown() throws FHIRException { + FHIRConfiguration.setConfigHome(""); + FHIRRequestContext.get().setTenantId("default"); + } + + @Test + void testBuildCapabilityStatement_resources_omitted() throws Exception { + FHIRRequestContext.get().setTenantId("omitted"); + FHIRRequestContext.get().setOriginalRequestUri("http://example.com/metadata"); + CapabilitiesChild c = new CapabilitiesChild(); + + Response capabilities = c.capabilities(); + CapabilityStatement capabilityStatement = capabilities.readEntity(CapabilityStatement.class); + + assertEquals(capabilityStatement.getRest().size(), 1, "Number of REST Elements"); + CapabilityStatement.Rest restDefinition = capabilityStatement.getRest().get(0); + + assertRestDefinition(restDefinition, 146, 8, 8); + } + + @Test + void testBuildCapabilityStatement_resources_empty() throws Exception { + FHIRRequestContext.get().setTenantId("empty"); + FHIRRequestContext.get().setOriginalRequestUri("http://example.com/metadata"); + CapabilitiesChild c = new CapabilitiesChild(); + + Response capabilities = c.capabilities(); + CapabilityStatement capabilityStatement = capabilities.readEntity(CapabilityStatement.class); + + assertEquals(capabilityStatement.getRest().size(), 1, "Number of REST Elements"); + CapabilityStatement.Rest restDefinition = capabilityStatement.getRest().get(0); + + assertRestDefinition(restDefinition, 146, 0, 0); + } + + @Test + void testBuildCapabilityStatement_resources_filtered() throws Exception { + FHIRRequestContext.get().setTenantId("smart-enabled"); + FHIRRequestContext.get().setOriginalRequestUri("http://example.com/metadata"); + CapabilitiesChild c = new CapabilitiesChild(); + + Response capabilities = c.capabilities(); + CapabilityStatement capabilityStatement = capabilities.readEntity(CapabilityStatement.class); + + assertEquals(capabilityStatement.getRest().size(), 1, "Number of REST Elements"); + CapabilityStatement.Rest restDefinition = capabilityStatement.getRest().get(0); + + assertRestDefinition(restDefinition, 2, 2, 4); + } + + private void assertRestDefinition(CapabilityStatement.Rest restDefinition, int numOfResources, int patientInteractions, int practitionerInteractions) { + assertEquals(restDefinition.getResource().size(), numOfResources, "Number of supported resources"); + assertFalse(restDefinition.getResource().stream().anyMatch(r -> r.getType().getValueAsEnumConstant() == ResourceType.ValueSet.RESOURCE)); + assertFalse(restDefinition.getResource().stream().anyMatch(r -> r.getType().getValueAsEnumConstant() == ResourceType.ValueSet.DOMAIN_RESOURCE)); + + assertInteractions(restDefinition, ResourceType.ValueSet.PATIENT, patientInteractions); + assertInteractions(restDefinition, ResourceType.ValueSet.PRACTITIONER, practitionerInteractions); + } + + private void assertInteractions(CapabilityStatement.Rest restDefinition, ResourceType.ValueSet resourceType, int numOfInteractions) { + Optional resource = restDefinition.getResource().stream() + .filter(r -> r.getType().getValueAsEnumConstant() == resourceType) + .findFirst(); + assertTrue(resource.isPresent()); + + List interactions = resource.get().getInteraction(); + assertEquals(interactions.size(), numOfInteractions, "Number of supported interactions for the Patient resource type"); + } + + /** + * This class is required because Capabilities uses a few protected fields + * that are normally injected by JAX-RS and so this is the only way to set them. + */ + private static class CapabilitiesChild extends Capabilities { + public CapabilitiesChild() throws Exception { + super(); + this.context = new MockServletContext(); + } + + @Override + public Response capabilities() { + httpServletRequest = new MockHttpServletRequest(); + return super.capabilities(); + } + } +} diff --git a/fhir-server/src/test/java/com/ibm/fhir/server/resources/WellKnownTest.java b/fhir-server/src/test/java/com/ibm/fhir/server/resources/WellKnownTest.java new file mode 100644 index 00000000000..32ceef62553 --- /dev/null +++ b/fhir-server/src/test/java/com/ibm/fhir/server/resources/WellKnownTest.java @@ -0,0 +1,99 @@ +/* + * (C) Copyright IBM Corp. 2020 + * + * SPDX-License-Identifier: Apache-2.0 + */ +package com.ibm.fhir.server.resources; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; + +import javax.json.JsonObject; +import javax.ws.rs.core.Response; + +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import com.ibm.fhir.config.FHIRConfiguration; +import com.ibm.fhir.config.FHIRRequestContext; +import com.ibm.fhir.exception.FHIRException; +import com.ibm.fhir.server.test.MockHttpServletRequest; +import com.ibm.fhir.server.test.MockServletContext; + +public class WellKnownTest { + + @BeforeClass + void setup() { + FHIRConfiguration.setConfigHome("target/test-classes"); + } + + @AfterClass + void tearDown() throws FHIRException { + FHIRConfiguration.setConfigHome(""); + FHIRRequestContext.get().setTenantId("default"); + } + + @Test + void testSmartCapabilities_smart_enabled() throws Exception { + FHIRRequestContext.get().setTenantId("smart-enabled"); + FHIRRequestContext.get().setOriginalRequestUri("http://example.com/.well-known/smart-configuration"); + WellKnownChild c = new WellKnownChild(); + + Response capabilities = c.smartConfig(); + JsonObject smartSupport = capabilities.readEntity(JsonObject.class); + assertTrue(!smartSupport.getString("authorization_endpoint").isEmpty()); + assertTrue(!smartSupport.getString("token_endpoint").isEmpty()); + assertEquals(smartSupport.getJsonArray("scopes_supported").size(), 6, "Number of SMART scopes"); + assertEquals(smartSupport.getJsonArray("capabilities").size(), 7, "Number of SMART capabilities"); + } + + @Test + void testSmartCapabilities_smart_omitted() throws Exception { + FHIRRequestContext.get().setTenantId("omitted"); + FHIRRequestContext.get().setOriginalRequestUri("http://example.com/.well-known/smart-configuration"); + WellKnownChild c = new WellKnownChild(); + + Response capabilities = c.smartConfig(); + JsonObject smartSupport = capabilities.readEntity(JsonObject.class); + assertTrue(smartSupport.getString("authorization_endpoint").isEmpty()); + assertTrue(smartSupport.getString("token_endpoint").isEmpty()); + assertNull(smartSupport.getJsonArray("scopes_supported")); + assertEquals(smartSupport.getJsonArray("capabilities").size(), 0, "Number of SMART capabilities"); + } + + @Test + void testSmartCapabilities_smart_empty() throws Exception { + FHIRRequestContext.get().setTenantId("empty"); + FHIRRequestContext.get().setOriginalRequestUri("http://example.com/.well-known/smart-configuration"); + WellKnownChild c = new WellKnownChild(); + + Response capabilities = c.smartConfig(); + JsonObject smartSupport = capabilities.readEntity(JsonObject.class); + System.out.println(smartSupport); + assertTrue(smartSupport.getString("authorization_endpoint").isEmpty()); + assertTrue(smartSupport.getString("token_endpoint").isEmpty()); + assertNull(smartSupport.getJsonArray("scopes_supported")); + assertEquals(smartSupport.getJsonArray("capabilities").size(), 0, "Number of SMART capabilities"); + } + + /** + * This class is required because the WellKnown class uses a few protected fields + * that are normally injected by JAX-RS and so this is the only way to set them. + */ + private static class WellKnownChild extends WellKnown { + public WellKnownChild() throws Exception { + super(); + this.context = new MockServletContext(); + } + + @Override + public Response smartConfig() throws ClassNotFoundException { + httpServletRequest = new MockHttpServletRequest(); + return super.smartConfig(); + } + } +} + + diff --git a/fhir-server/src/test/java/com/ibm/fhir/server/test/MockHttpServletRequest.java b/fhir-server/src/test/java/com/ibm/fhir/server/test/MockHttpServletRequest.java new file mode 100644 index 00000000000..5567ab5ba64 --- /dev/null +++ b/fhir-server/src/test/java/com/ibm/fhir/server/test/MockHttpServletRequest.java @@ -0,0 +1,447 @@ +/* + * (C) Copyright IBM Corp. 2020 + * + * SPDX-License-Identifier: Apache-2.0 + */ +package com.ibm.fhir.server.test; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.Principal; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Map; + +import javax.servlet.AsyncContext; +import javax.servlet.DispatcherType; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpUpgradeHandler; +import javax.servlet.http.Part; + +public class MockHttpServletRequest implements HttpServletRequest { + + @Override + public StringBuffer getRequestURL() { + return new StringBuffer("http://example.com"); + } + + @Override + public Object getAttribute(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Enumeration getAttributeNames() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getCharacterEncoding() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setCharacterEncoding(String env) throws UnsupportedEncodingException { + // TODO Auto-generated method stub + + } + + @Override + public int getContentLength() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public long getContentLengthLong() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getContentType() { + // TODO Auto-generated method stub + return null; + } + + @Override + public ServletInputStream getInputStream() throws IOException { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getParameter(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Enumeration getParameterNames() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String[] getParameterValues(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Map getParameterMap() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getProtocol() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getScheme() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getServerName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getServerPort() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public BufferedReader getReader() throws IOException { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getRemoteAddr() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getRemoteHost() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setAttribute(String name, Object o) { + // TODO Auto-generated method stub + + } + + @Override + public void removeAttribute(String name) { + // TODO Auto-generated method stub + + } + + @Override + public Locale getLocale() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Enumeration getLocales() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isSecure() { + // TODO Auto-generated method stub + return false; + } + + @Override + public RequestDispatcher getRequestDispatcher(String path) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getRealPath(String path) { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getRemotePort() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getLocalName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getLocalAddr() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getLocalPort() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public ServletContext getServletContext() { + // TODO Auto-generated method stub + return null; + } + + @Override + public AsyncContext startAsync() throws IllegalStateException { + // TODO Auto-generated method stub + return null; + } + + @Override + public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isAsyncStarted() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isAsyncSupported() { + // TODO Auto-generated method stub + return false; + } + + @Override + public AsyncContext getAsyncContext() { + // TODO Auto-generated method stub + return null; + } + + @Override + public DispatcherType getDispatcherType() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getAuthType() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Cookie[] getCookies() { + // TODO Auto-generated method stub + return null; + } + + @Override + public long getDateHeader(String name) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getHeader(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Enumeration getHeaders(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Enumeration getHeaderNames() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getIntHeader(String name) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getMethod() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getPathInfo() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getPathTranslated() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getContextPath() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getQueryString() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getRemoteUser() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isUserInRole(String role) { + // TODO Auto-generated method stub + return false; + } + + @Override + public Principal getUserPrincipal() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getRequestedSessionId() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getRequestURI() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getServletPath() { + // TODO Auto-generated method stub + return null; + } + + @Override + public HttpSession getSession(boolean create) { + // TODO Auto-generated method stub + return null; + } + + @Override + public HttpSession getSession() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String changeSessionId() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isRequestedSessionIdValid() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isRequestedSessionIdFromCookie() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isRequestedSessionIdFromURL() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isRequestedSessionIdFromUrl() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { + // TODO Auto-generated method stub + return false; + } + + @Override + public void login(String username, String password) throws ServletException { + // TODO Auto-generated method stub + + } + + @Override + public void logout() throws ServletException { + // TODO Auto-generated method stub + + } + + @Override + public Collection getParts() throws IOException, ServletException { + // TODO Auto-generated method stub + return null; + } + + @Override + public Part getPart(String name) throws IOException, ServletException { + // TODO Auto-generated method stub + return null; + } + + @Override + public T upgrade(Class handlerClass) throws IOException, ServletException { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/fhir-server/src/test/java/com/ibm/fhir/server/test/MockServletContext.java b/fhir-server/src/test/java/com/ibm/fhir/server/test/MockServletContext.java new file mode 100644 index 00000000000..cdbcb6fd40d --- /dev/null +++ b/fhir-server/src/test/java/com/ibm/fhir/server/test/MockServletContext.java @@ -0,0 +1,409 @@ +/* + * (C) Copyright IBM Corp. 2020 + * + * SPDX-License-Identifier: Apache-2.0 + */ +package com.ibm.fhir.server.test; + +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Enumeration; +import java.util.EventListener; +import java.util.Map; +import java.util.Set; + +import javax.servlet.Filter; +import javax.servlet.FilterRegistration; +import javax.servlet.FilterRegistration.Dynamic; +import javax.servlet.RequestDispatcher; +import javax.servlet.Servlet; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; +import javax.servlet.SessionCookieConfig; +import javax.servlet.SessionTrackingMode; +import javax.servlet.descriptor.JspConfigDescriptor; + +import com.ibm.fhir.persistence.FHIRPersistence; +import com.ibm.fhir.persistence.exception.FHIRPersistenceException; +import com.ibm.fhir.persistence.helper.FHIRPersistenceHelper; +import com.ibm.fhir.persistence.helper.PersistenceHelper; +import com.ibm.fhir.server.listener.FHIRServletContextListener; + +/** + * + */ +public class MockServletContext implements ServletContext { + + @Override + public Object getAttribute(String name) { + if (FHIRServletContextListener.FHIR_SERVER_INIT_COMPLETE.equals(name)) { + return true; + } + + if (FHIRPersistenceHelper.class.getName().equals(name)) { + return new PersistenceHelper() { + @Override + public FHIRPersistence getFHIRPersistenceImplementation() throws FHIRPersistenceException { + return new MockPersistenceImpl(); + } + @Override + public FHIRPersistence getFHIRPersistenceImplementation(String factoryPropertyName) throws FHIRPersistenceException { + return new MockPersistenceImpl(); + } + }; + } + + return null; + } + + // All below methods are auto-generated stubs + @Override + public void setSessionTrackingModes(Set sessionTrackingModes) { + // TODO Auto-generated method stub + + } + + @Override + public void setSessionTimeout(int sessionTimeout) { + // TODO Auto-generated method stub + + } + + @Override + public void setResponseCharacterEncoding(String encoding) { + // TODO Auto-generated method stub + + } + + @Override + public void setRequestCharacterEncoding(String encoding) { + // TODO Auto-generated method stub + + } + + @Override + public boolean setInitParameter(String name, String value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public void setAttribute(String name, Object object) { + // TODO Auto-generated method stub + + } + + @Override + public void removeAttribute(String name) { + // TODO Auto-generated method stub + + } + + @Override + public void log(String message, Throwable throwable) { + // TODO Auto-generated method stub + + } + + @Override + public void log(Exception exception, String msg) { + // TODO Auto-generated method stub + + } + + @Override + public void log(String msg) { + // TODO Auto-generated method stub + + } + + @Override + public String getVirtualServerName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getSessionTimeout() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public SessionCookieConfig getSessionCookieConfig() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Enumeration getServlets() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Map getServletRegistrations() { + // TODO Auto-generated method stub + return null; + } + + @Override + public ServletRegistration getServletRegistration(String servletName) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Enumeration getServletNames() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getServletContextName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Servlet getServlet(String name) throws ServletException { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getServerInfo() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getResponseCharacterEncoding() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getResourcePaths(String path) { + // TODO Auto-generated method stub + return null; + } + + @Override + public InputStream getResourceAsStream(String path) { + // TODO Auto-generated method stub + return null; + } + + @Override + public URL getResource(String path) throws MalformedURLException { + // TODO Auto-generated method stub + return null; + } + + @Override + public RequestDispatcher getRequestDispatcher(String path) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getRequestCharacterEncoding() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getRealPath(String path) { + // TODO Auto-generated method stub + return null; + } + + @Override + public RequestDispatcher getNamedDispatcher(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getMinorVersion() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getMimeType(String file) { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getMajorVersion() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public JspConfigDescriptor getJspConfigDescriptor() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Enumeration getInitParameterNames() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getInitParameter(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Map getFilterRegistrations() { + // TODO Auto-generated method stub + return null; + } + + @Override + public FilterRegistration getFilterRegistration(String filterName) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getEffectiveSessionTrackingModes() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getEffectiveMinorVersion() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public int getEffectiveMajorVersion() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public Set getDefaultSessionTrackingModes() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getContextPath() { + // TODO Auto-generated method stub + return null; + } + + @Override + public ServletContext getContext(String uripath) { + // TODO Auto-generated method stub + return null; + } + + @Override + public ClassLoader getClassLoader() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Enumeration getAttributeNames() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void declareRoles(String... roleNames) { + // TODO Auto-generated method stub + + } + + @Override + public T createServlet(Class clazz) throws ServletException { + // TODO Auto-generated method stub + return null; + } + + @Override + public T createListener(Class clazz) throws ServletException { + // TODO Auto-generated method stub + return null; + } + + @Override + public T createFilter(Class clazz) throws ServletException { + // TODO Auto-generated method stub + return null; + } + + @Override + public javax.servlet.ServletRegistration.Dynamic addServlet(String servletName, Class servletClass) { + // TODO Auto-generated method stub + return null; + } + + @Override + public javax.servlet.ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet) { + // TODO Auto-generated method stub + return null; + } + + @Override + public javax.servlet.ServletRegistration.Dynamic addServlet(String servletName, String className) { + // TODO Auto-generated method stub + return null; + } + + @Override + public void addListener(Class listenerClass) { + // TODO Auto-generated method stub + + } + + @Override + public void addListener(T t) { + // TODO Auto-generated method stub + + } + + @Override + public void addListener(String className) { + // TODO Auto-generated method stub + + } + + @Override + public javax.servlet.ServletRegistration.Dynamic addJspFile(String servletName, String jspFile) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Dynamic addFilter(String filterName, Class filterClass) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Dynamic addFilter(String filterName, Filter filter) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Dynamic addFilter(String filterName, String className) { + // TODO Auto-generated method stub + return null; + } +} diff --git a/fhir-server/src/test/resources/config/default/fhir-server-config.json b/fhir-server/src/test/resources/config/default/fhir-server-config.json new file mode 100644 index 00000000000..ad811b6e62c --- /dev/null +++ b/fhir-server/src/test/resources/config/default/fhir-server-config.json @@ -0,0 +1,20 @@ +{ + "__comment": "FHIR Server configuration", + "fhirServer": { + "core": { + "tenantIdHeaderName": "X-FHIR-TENANT-ID", + "datastoreIdHeaderName": "X-FHIR-DSID", + "checkReferenceTypes": true, + "conditionalDeleteMaxNumber": 10, + "serverRegistryResourceProviderEnabled": true + }, + "resources": { + "open": true + }, + "audit": { + "serviceClassName" : "com.ibm.fhir.audit.logging.impl.DisabledAuditLogService", + "serviceProperties" : { + } + } + } +} diff --git a/fhir-server/src/test/resources/config/empty/fhir-server-config.json b/fhir-server/src/test/resources/config/empty/fhir-server-config.json new file mode 100644 index 00000000000..fe15a9ce7ad --- /dev/null +++ b/fhir-server/src/test/resources/config/empty/fhir-server-config.json @@ -0,0 +1,36 @@ +{ + "__comment": "FHIR Server configuration", + "fhirServer": { + "resources": { + "open": true, + "Patient": { + "interactions": [], + "searchParameters": {} + }, + "Resource": { + "interactions": [], + "searchParameters": {} + } + }, + "security": { + "cors": true, + "basic": { + "enabled": true + }, + "certificates": { + "enabled": true + }, + "oauth": { + "enabled": true, + "regUrl": "", + "authUrl": "", + "tokenUrl": "", + "smart": { + "enabled": true, + "scopes": [], + "capabilities": [] + } + } + } + } +} diff --git a/fhir-server/src/test/resources/config/omitted/fhir-server-config.json b/fhir-server/src/test/resources/config/omitted/fhir-server-config.json new file mode 100644 index 00000000000..79df99588c7 --- /dev/null +++ b/fhir-server/src/test/resources/config/omitted/fhir-server-config.json @@ -0,0 +1,5 @@ +{ + "__comment": "FHIR Server configuration", + "fhirServer": { + } +} diff --git a/fhir-server/src/test/resources/config/smart-enabled/fhir-server-config.json b/fhir-server/src/test/resources/config/smart-enabled/fhir-server-config.json new file mode 100644 index 00000000000..ee27635dfc6 --- /dev/null +++ b/fhir-server/src/test/resources/config/smart-enabled/fhir-server-config.json @@ -0,0 +1,74 @@ +{ + "__comment": "FHIR Server configuration", + "fhirServer": { + "resources": { + "open": false, + "Patient": { + "interactions": ["read", "search"], + "searchParameters": { + "_id": { + "url": "http://hl7.org/fhir/SearchParameter/Resource-id" + }, + "birthdate": { + "url": "http://hl7.org/fhir/SearchParameter/individual-birthdate" + }, + "gender": { + "url": "http://hl7.org/fhir/SearchParameter/individual-gender" + }, + "identifier": { + "url": "http://hl7.org/fhir/SearchParameter/Patient-identifier" + }, + "name": { + "url": "http://hl7.org/fhir/SearchParameter/Patient-name" + } + } + }, + "Practitioner": { + "searchParameters": { + "name": { + "url": "http://hl7.org/fhir/SearchParameter/Practitioner-name" + }, + "identifier": { + "url": "http://hl7.org/fhir/SearchParameter/Practitioner-identifier" + } + } + }, + "Resource": { + "interactions": ["read", "vread", "history", "search"], + "searchParameters": { + "_id": { + "url": "http://hl7.org/fhir/SearchParameter/Resource-id" + } + } + } + }, + "security": { + "cors": true, + "basic": { + "enabled": false + }, + "certificates": { + "enabled": false + }, + "oauth": { + "enabled": true, + "regUrl": "https://:9443/oauth2/endpoint/oauth2-provider/registration", + "authUrl": "https://:9443/oauth2/endpoint/oauth2-provider/authorize", + "tokenUrl": "https://:9443/oauth2/endpoint/oauth2-provider/token", + "smart": { + "enabled": true, + "scopes": ["openid", "profile", "fhirUser", "launch/patient", "patient/*.*", "offline_access"], + "capabilities": [ + "sso-openid-connect", + "launch-standalone", + "client-public", + "client-confidential-symmetric", + "permission-offline", + "context-standalone-patient", + "permission-patient" + ] + } + } + } + } +}