Merge branch 'master' of github.com:jamesagnew/hapi-fhir

This commit is contained in:
James Agnew 2016-11-03 11:28:24 -04:00
commit 9f37646518
8 changed files with 1147 additions and 892 deletions

View File

@ -162,13 +162,16 @@ public class XhtmlDt extends BasePrimitive<List<XMLEvent>> {
int firstTagIndex = value.indexOf("<", hasProcessingInstruction ? 1 : 0);
if (firstTagIndex != -1) {
int firstTagEnd = value.indexOf(">", firstTagIndex);
int firstSlash = value.indexOf("/", firstTagIndex);
if (firstTagEnd != -1) {
if (firstSlash > firstTagEnd) {
String firstTag = value.substring(firstTagIndex, firstTagEnd);
if (!firstTag.contains(" xmlns")) {
value = value.substring(0, firstTagEnd) + DECL_XMLNS + value.substring(firstTagEnd);
}
}
}
}
return value;
}

View File

@ -65,10 +65,13 @@ class RuleImplOp extends BaseRule implements IAuthRule {
if (theOutputResource == null) {
switch (theOperation) {
case READ:
case VREAD:
appliesToResourceId = theInputResourceId;
break;
case SEARCH_SYSTEM:
case SEARCH_TYPE:
case HISTORY_INSTANCE:
case HISTORY_SYSTEM:
return new Verdict(PolicyEnum.ALLOW, this);
default:
return null;
@ -80,9 +83,21 @@ class RuleImplOp extends BaseRule implements IAuthRule {
if (theInputResource == null && theInputResourceId == null) {
return null;
}
switch (theOperation) {
case CREATE:
case UPDATE:
case ADD_TAGS:
case DELETE_TAGS:
case META_ADD:
case META_DELETE:
case PATCH:
appliesToResource = theInputResource;
appliesToResourceId = theInputResourceId;
break;
default:
return null;
}
break;
case DELETE:
if (theOperation == RestOperationTypeEnum.DELETE) {
if (theInputResource == null) {

View File

@ -51,6 +51,11 @@ import org.junit.Test;
import ca.uhn.fhir.model.api.*;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.BundleEntry;
import ca.uhn.fhir.model.api.ExtensionDt;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
import ca.uhn.fhir.model.dstu2.composite.PeriodDt;
@ -112,6 +117,23 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
assertEquals(200, resp.getStatusLine().getStatusCode());
}
/**
* See #484
*/
@Test
public void saveAndRetrieveBasicResource() throws IOException {
String input = IOUtils.toString(getClass().getResourceAsStream("/basic-stu3.xml"), StandardCharsets.UTF_8);
String respString = ourClient.transaction().withBundle(input).prettyPrint().execute();
ourLog.info(respString);
ca.uhn.fhir.model.dstu2.resource.Bundle bundle = myFhirCtx.newXmlParser().parseResource(ca.uhn.fhir.model.dstu2.resource.Bundle.class, respString);
IdDt id = new IdDt(bundle.getEntry().get(0).getResponse().getLocation());
Basic basic = ourClient.read().resource(Basic.class).withId(id).execute();
List<ExtensionDt> exts = basic.getUndeclaredExtensionsByUrl("http://localhost:1080/hapi-fhir-jpaserver-example/baseDstu2/StructureDefinition/DateID");
assertEquals(1, exts.size());
}
/**
* See #438
*/

View File

@ -0,0 +1,59 @@
<Bundle>
<meta>
<lastUpdated value="2016-10-28T16:29:43Z" />
</meta>
<type value="transaction" />
<entry>
<resource>
<Basic>
<text>
<status value="generated" />
<div />
</text>
<extension url="http://localhost:1080/hapi-fhir-jpaserver-example/baseDstu2/StructureDefinition/DateID">
<valueDate value="2016-11-01" />
</extension>
<extension url="http://localhost:1080/hapi-fhir-jpaserver-example/baseDstu2/StructureDefinition/SptSolution">
<valueCoding value="SptSolution.CatFurSPTSoln" />
</extension>
<extension url="http://localhost:1080/hapi-fhir-jpaserver-example/baseDstu2/StructureDefinition/MethodOfFollowUp">
<valueCoding value="FollowUpMethod.ClinicVisit" />
</extension>
<extension url="http://localhost:1080/hapi-fhir-jpaserver-example/baseDstu2/StructureDefinition/SPTDefinition">
<valueString value="A positive skin prick test result was defined as a mean wheal diameter of 3mm greater than that of the negative control" />
</extension>
<extension url="http://localhost:1080/hapi-fhir-jpaserver-example/baseDstu2/StructureDefinition/SubjectNo">
<valueString value="4320" />
</extension>
<extension url="http://localhost:1080/hapi-fhir-jpaserver-example/baseDstu2/StructureDefinition/AIW">
<valueInteger value="58" />
</extension>
<extension url="http://localhost:1080/hapi-fhir-jpaserver-example/baseDstu2/StructureDefinition/FollowUp">
<valueCoding value="FollowUp.MSAge1Y" />
</extension>
<extension url="http://localhost:1080/hapi-fhir-jpaserver-example/baseDstu2/StructureDefinition/Subject">
<valueCoding value="Person.StudySubject" />
</extension>
<extension url="http://localhost:1080/hapi-fhir-jpaserver-example/baseDstu2/StructureDefinition/VariableLabel">
<valueString value="Child sensitised to cat (age 1 spt)" />
</extension>
<extension url="http://localhost:1080/hapi-fhir-jpaserver-example/baseDstu2/StructureDefinition/SPTDataType">
<valueCoding value="SkinPrickTestData.SPTResult" />
</extension>
<extension url="http://localhost:1080/hapi-fhir-jpaserver-example/baseDstu2/StructureDefinition/DataSource">
<valueCoding value="DataSource.ClinicalMeasurement" />
</extension>
<extension url="http://localhost:1080/hapi-fhir-jpaserver-example/baseDstu2/StructureDefinition/ClinicalType">
<valueCoding value="ClinicalMeasurement.SkinPrickTest" />
</extension>
<extension url="http://localhost:1080/hapi-fhir-jpaserver-example/baseDstu2/StructureDefinition/DataSPTResult">
<valueCoding value="TestResult.Negative" />
</extension>
</Basic>
</resource>
<request>
<method value="POST" />
<url value="Basic" />
</request>
</entry>
</Bundle>

View File

@ -48,6 +48,7 @@ import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
import ca.uhn.fhir.model.dstu2.composite.HumanNameDt;
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
import ca.uhn.fhir.model.dstu2.resource.Basic;
import ca.uhn.fhir.model.dstu2.resource.Binary;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
import ca.uhn.fhir.model.dstu2.resource.Condition;
@ -125,7 +126,6 @@ public class JsonParserDstu2Test {
assertEquals(true, obs.getReadOnly().getValue().booleanValue());
}
/**
* See #390
*/
@ -144,6 +144,7 @@ public class JsonParserDstu2Test {
assertEquals(0, b.getEntry().size());
}
@Test
public void testEncodeAndParseExtensions() throws Exception {
@ -359,7 +360,6 @@ public class JsonParserDstu2Test {
}
@Test
public void testEncodeAndParseSecurityLabels() {
Patient p = new Patient();
@ -466,6 +466,7 @@ public class JsonParserDstu2Test {
}
/**
* Fixing #89
*/
@ -564,7 +565,6 @@ public class JsonParserDstu2Test {
}
@Test
public void testEncodeExtensionUndeclaredNonModifier() {
Observation obs = new Observation();
@ -647,6 +647,7 @@ public class JsonParserDstu2Test {
assertEquals("sub_ext_value", ((StringDt)obs.getUndeclaredExtensions().get(0).getExtension().get(0).getValue()).getValue());
}
/**
* See #428
*/
@ -1490,6 +1491,16 @@ public class JsonParserDstu2Test {
}
/**
* See #484
*/
@Test
public void testParseNarrativeWithEmptyDiv() {
String input = "{\"resourceType\":\"Basic\",\"id\":\"1\",\"text\":{\"status\":\"generated\",\"div\":\"<div/>\"}}";
Basic basic = ourCtx.newJsonParser().parseResource(Basic.class, input);
assertEquals("<div/>", basic.getText().getDivAsString());
}
/**
* See #359 - This is the base test with no nulls, other testParseNullsFOO have nulls in them
*/

View File

@ -70,7 +70,6 @@ import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.util.PortUtil;
import ca.uhn.fhir.util.TestUtil;
@ -87,7 +86,6 @@ public class AuthorizationInterceptorDstu2Test {
private static Server ourServer;
private static RestfulServer ourServlet;
@Before
public void before() {
ourCtx.setAddProfileTagWhenEncoding(AddProfileTagEnum.NEVER);
@ -331,6 +329,15 @@ public class AuthorizationInterceptorDstu2Test {
assertThat(response, containsString("Access denied by rule: Default Rule"));
assertEquals(403, status.getStatusLine().getStatusCode());
assertFalse(ourHitMethod);
ourHitMethod = false;
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$opName");
status = ourClient.execute(httpGet);
response = extractResponseAndClose(status);
ourLog.info(response);
assertThat(response, containsString("Access denied by rule: Default Rule"));
assertEquals(403, status.getStatusLine().getStatusCode());
assertFalse(ourHitMethod);
}
@Test
@ -521,6 +528,66 @@ public class AuthorizationInterceptorDstu2Test {
assertFalse(ourHitMethod);
}
@Test
public void testOperationNotAllowedWithWritePermissiom() throws Exception {
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
@Override
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
//@formatter:off
return new RuleBuilder()
.allow("RULE 1").write().allResources().withAnyId().andThen()
.build();
//@formatter:on
}
});
HttpGet httpGet;
HttpResponse status;
String response;
// Server
ourHitMethod = false;
ourReturn = Arrays.asList(createObservation(10, "Patient/2"));
httpGet = new HttpGet("http://localhost:" + ourPort + "/$opName");
status = ourClient.execute(httpGet);
response = extractResponseAndClose(status);
assertThat(response, containsString("Access denied by default policy"));
assertEquals(403, status.getStatusLine().getStatusCode());
assertFalse(ourHitMethod);
// System
ourHitMethod = false;
ourReturn = Arrays.asList(createPatient(2));
httpGet = new HttpGet("http://localhost:" + ourPort + "/$opName");
status = ourClient.execute(httpGet);
response = extractResponseAndClose(status);
ourLog.info(response);
assertEquals(403, status.getStatusLine().getStatusCode());
assertFalse(ourHitMethod);
// Type
ourHitMethod = false;
ourReturn = Arrays.asList(createPatient(2));
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$opName");
status = ourClient.execute(httpGet);
response = extractResponseAndClose(status);
ourLog.info(response);
assertEquals(403, status.getStatusLine().getStatusCode());
assertFalse(ourHitMethod);
// Instance
ourHitMethod = false;
ourReturn = Arrays.asList(createPatient(2));
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123/$opName");
status = ourClient.execute(httpGet);
response = extractResponseAndClose(status);
ourLog.info(response);
assertEquals(403, status.getStatusLine().getStatusCode());
assertFalse(ourHitMethod);
}
@Test
public void testOperationTypeLevel() throws Exception {
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
@ -617,6 +684,14 @@ public class AuthorizationInterceptorDstu2Test {
assertEquals(200, status.getStatusLine().getStatusCode());
assertTrue(ourHitMethod);
ourReturn = Arrays.asList(createPatient(2));
ourHitMethod = false;
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/_history/222");
status = ourClient.execute(httpGet);
extractResponseAndClose(status);
assertEquals(200, status.getStatusLine().getStatusCode());
assertTrue(ourHitMethod);
ourReturn = Arrays.asList(createObservation(10, "Patient/2"));
ourHitMethod = false;
httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation/10");
@ -692,7 +767,6 @@ public class AuthorizationInterceptorDstu2Test {
}
@Test
public void testReadByCompartmentWrong() throws Exception {
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
@ -952,8 +1026,6 @@ public class AuthorizationInterceptorDstu2Test {
assertFalse(ourHitMethod);
}
@Test
public void testWriteByCompartmentUpdateConditionalResolvesToInvalid() throws Exception {
ourConditionalCreateId = "1123";
@ -986,7 +1058,6 @@ public class AuthorizationInterceptorDstu2Test {
}
@Test
public void testWriteByCompartmentUpdateConditionalResolvesToValid() throws Exception {
ourConditionalCreateId = "1";
@ -1203,11 +1274,13 @@ public class AuthorizationInterceptorDstu2Test {
ourHitMethod = true;
return (Observation) ourReturn.get(0);
}
@Search()
public List<IResource> search() {
ourHitMethod = true;
return ourReturn;
}
@Update()
public MethodOutcome update(@IdParam IdDt theId, @ResourceParam Observation theResource, @ConditionalUrlParam String theConditionalUrl, RequestDetails theRequestDetails) {
ourHitMethod = true;
@ -1229,12 +1302,10 @@ public class AuthorizationInterceptorDstu2Test {
return retVal;
}
}
public static class DummyPatientResourceProvider implements IResourceProvider {
@Create()
public MethodOutcome create(@ResourceParam Patient theResource, @ConditionalUrlParam String theConditionalUrl, RequestDetails theRequestDetails) {
@ -1255,7 +1326,6 @@ public class AuthorizationInterceptorDstu2Test {
return retVal;
}
@Delete()
public MethodOutcome delete(IRequestOperationCallback theRequestOperationCallback, @IdParam IdDt theId, @ConditionalUrlParam String theConditionalUrl, RequestDetails theRequestDetails) {
ourHitMethod = true;
@ -1322,7 +1392,8 @@ public class AuthorizationInterceptorDstu2Test {
}
@Validate
public MethodOutcome validate(@ResourceParam Patient theResource, @IdParam IdDt theId, @ResourceParam String theRawResource, @ResourceParam EncodingEnum theEncoding, @Validate.Mode ValidationModeEnum theMode,
public MethodOutcome validate(@ResourceParam Patient theResource, @IdParam IdDt theId, @ResourceParam String theRawResource, @ResourceParam EncodingEnum theEncoding,
@Validate.Mode ValidationModeEnum theMode,
@Validate.Profile String theProfile, RequestDetails theRequestDetails) {
ourHitMethod = true;
OperationOutcome oo = new OperationOutcome();
@ -1341,8 +1412,7 @@ public class AuthorizationInterceptorDstu2Test {
}
public static class PlainProvider
{
public static class PlainProvider {
@Operation(name = "opName", idempotent = true)
public Parameters operation() {
@ -1350,7 +1420,6 @@ public class AuthorizationInterceptorDstu2Test {
return (Parameters) new Parameters().setId("1");
}
@Transaction()
public Bundle search(@TransactionParam Bundle theInput) {
ourHitMethod = true;

View File

@ -16,24 +16,65 @@ import static org.junit.Assert.fail;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.UUID;
import org.apache.commons.io.IOUtils;
import org.hamcrest.Matchers;
import org.hamcrest.core.StringContains;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.Address.AddressUse;
import org.hl7.fhir.dstu3.model.Address.AddressUseEnumFactory;
import org.hl7.fhir.dstu3.model.Attachment;
import org.hl7.fhir.dstu3.model.AuditEvent;
import org.hl7.fhir.dstu3.model.Basic;
import org.hl7.fhir.dstu3.model.Binary;
import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.dstu3.model.Bundle.BundleType;
import org.hl7.fhir.dstu3.model.Coding;
import org.hl7.fhir.dstu3.model.Communication;
import org.hl7.fhir.dstu3.model.Condition;
import org.hl7.fhir.dstu3.model.Condition.ConditionVerificationStatus;
import org.hl7.fhir.dstu3.model.Conformance;
import org.hl7.fhir.dstu3.model.Conformance.UnknownContentCode;
import org.hl7.fhir.dstu3.model.DateTimeType;
import org.hl7.fhir.dstu3.model.DateType;
import org.hl7.fhir.dstu3.model.DecimalType;
import org.hl7.fhir.dstu3.model.DiagnosticReport;
import org.hl7.fhir.dstu3.model.EnumFactory;
import org.hl7.fhir.dstu3.model.Enumeration;
import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender;
import org.hl7.fhir.dstu3.model.ExplanationOfBenefit;
import org.hl7.fhir.dstu3.model.Extension;
import org.hl7.fhir.dstu3.model.HumanName;
import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.dstu3.model.Identifier.IdentifierUse;
import org.hl7.fhir.dstu3.model.Linkage;
import org.hl7.fhir.dstu3.model.Medication;
import org.hl7.fhir.dstu3.model.MedicationOrder;
import org.hl7.fhir.dstu3.model.Observation;
import org.hl7.fhir.dstu3.model.Observation.ObservationStatus;
import org.hl7.fhir.dstu3.model.Parameters;
import org.hl7.fhir.dstu3.model.Patient;
import org.hl7.fhir.dstu3.model.PrimitiveType;
import org.hl7.fhir.dstu3.model.Quantity;
import org.hl7.fhir.dstu3.model.QuestionnaireResponse;
import org.hl7.fhir.dstu3.model.Reference;
import org.hl7.fhir.dstu3.model.RelatedPerson;
import org.hl7.fhir.dstu3.model.SampledData;
import org.hl7.fhir.dstu3.model.SimpleQuantity;
import org.hl7.fhir.dstu3.model.StringType;
import org.hl7.fhir.dstu3.model.UriType;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
import org.junit.*;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import com.google.common.collect.Sets;
@ -279,6 +320,7 @@ public class JsonParserDstu3Test {
}
@Test
public void testEncodeAndParseSecurityLabels() {
Patient p = new Patient();
@ -339,8 +381,6 @@ public class JsonParserDstu3Test {
assertEquals("VERSION2", label.getVersion());
}
@Test
public void testEncodeBundleNewBundleNoText() {
@ -359,6 +399,8 @@ public class JsonParserDstu3Test {
}
/**
* See #326
*/
@ -411,7 +453,6 @@ public class JsonParserDstu3Test {
assertEquals("{\"resourceType\":\"Binary\"}", output);
}
/**
* #158
*/
@ -428,6 +469,7 @@ public class JsonParserDstu3Test {
assertThat(encoded, not(containsString("tag")));
}
/**
* #158
*/
@ -1678,6 +1720,25 @@ public class JsonParserDstu3Test {
}
/**
* See #484
*/
@Test
public void testParseNarrativeWithEmptyDiv() {
String input = "{\"resourceType\":\"Basic\",\"id\":\"1\",\"text\":{\"status\":\"generated\",\"div\":\"<div/>\"}}";
Basic basic = ourCtx.newJsonParser().parseResource(Basic.class, input);
assertEquals(null, basic.getText().getDivAsString());
input = "{\"resourceType\":\"Basic\",\"id\":\"1\",\"text\":{\"status\":\"generated\",\"div\":\"<div></div>\"}}";
basic = ourCtx.newJsonParser().parseResource(Basic.class, input);
assertEquals(null, basic.getText().getDivAsString());
input = "{\"resourceType\":\"Basic\",\"id\":\"1\",\"text\":{\"status\":\"generated\",\"div\":\"<div> </div>\"}}";
basic = ourCtx.newJsonParser().parseResource(Basic.class, input);
assertEquals("<div xmlns=\"http://www.w3.org/1999/xhtml\"> </div>", basic.getText().getDivAsString());
}
/**
* See #163
*/