Allow absolute links for refs with an identifier (#5295)

* Allow absolute links for refs with an identifier

* Add changelog

* Update hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_0_0/5295-fix-absolute-refs-with-identifier.yaml

Co-authored-by: Kevin Dougan SmileCDR <72025369+KevinDougan-SmileCDR@users.noreply.github.com>

* Remove redundant class

* Review comments

---------

Co-authored-by: Kevin Dougan SmileCDR <72025369+KevinDougan-SmileCDR@users.noreply.github.com>
This commit is contained in:
James Agnew 2023-09-13 05:55:02 -04:00 committed by GitHub
parent f97eadadc6
commit 564beb7211
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 62 additions and 2 deletions

View File

@ -0,0 +1,6 @@
---
type: fix
issue: 5295
title: "A regression in the HAPI FHIR 6.6.0 JPA server meant that absolute resource
references which also contained an identifier were rejected even if the server
was configured to allow absolute references. This has been corrected."

View File

@ -64,6 +64,7 @@ import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.IBaseReference; import org.hl7.fhir.instance.model.api.IBaseReference;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.IdType;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import java.util.ArrayList; import java.util.ArrayList;
@ -692,8 +693,20 @@ public class SearchParamExtractorService {
return; return;
} }
final boolean hasNoIdentifier = !nextReference.hasIdentifier(); String baseUrl = nextId.getBaseUrl();
final String baseUrl = hasNoIdentifier ? nextId.getBaseUrl() : null;
// If this is a conditional URL, the part after the question mark
// can include URLs (e.g. token system URLs) and these really confuse
// the IdType parser because a conditional URL isn't actually a valid
// FHIR ID. So in order to truly determine whether we're dealing with
// an absolute reference, we strip the query part and reparse
// the reference.
int questionMarkIndex = nextId.getValue().indexOf('?');
if (questionMarkIndex != -1) {
IdType preQueryId = new IdType(nextId.getValue().substring(0, questionMarkIndex - 1));
baseUrl = preQueryId.getBaseUrl();
}
String typeString = nextId.getResourceType(); String typeString = nextId.getResourceType();
if (isBlank(typeString)) { if (isBlank(typeString)) {
String msg = "Invalid resource reference found at path[" + path + "] - Does not contain resource type - " String msg = "Invalid resource reference found at path[" + path + "] - Does not contain resource type - "

View File

@ -20,12 +20,14 @@ import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.ValueSource; import org.junit.jupiter.params.provider.ValueSource;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.io.IOException;
import java.util.UUID; import java.util.UUID;
import static org.apache.commons.lang3.StringUtils.countMatches; import static org.apache.commons.lang3.StringUtils.countMatches;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.endsWith; import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.in;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
@ -40,6 +42,7 @@ public class FhirSystemDaoTransactionR5Test extends BaseJpaR5Test {
myStorageSettings.setMatchUrlCacheEnabled(defaults.isMatchUrlCacheEnabled()); myStorageSettings.setMatchUrlCacheEnabled(defaults.isMatchUrlCacheEnabled());
myStorageSettings.setDeleteEnabled(defaults.isDeleteEnabled()); myStorageSettings.setDeleteEnabled(defaults.isDeleteEnabled());
myStorageSettings.setInlineResourceTextBelowSize(defaults.getInlineResourceTextBelowSize()); myStorageSettings.setInlineResourceTextBelowSize(defaults.getInlineResourceTextBelowSize());
myStorageSettings.setAllowExternalReferences(defaults.isAllowExternalReferences());
} }
@ -503,6 +506,17 @@ public class FhirSystemDaoTransactionR5Test extends BaseJpaR5Test {
} }
@Test
public void testExternalReference() throws IOException {
myStorageSettings.setAllowExternalReferences(true);
Bundle input = loadResourceFromClasspath(Bundle.class, "docref-test-bundle.json");
Bundle output = mySystemDao.transaction(mySrd, input);
assertEquals(1, output.getEntry().size());
}
@Test @Test
public void testConditionalDeleteAndConditionalUpdateOnSameResource_MultipleMatchesAlreadyExist() { public void testConditionalDeleteAndConditionalUpdateOnSameResource_MultipleMatchesAlreadyExist() {

View File

@ -0,0 +1,27 @@
{
"resourceType": "Bundle",
"type": "transaction",
"entry": [
{
"fullUrl": "Provenance/1.2.40.0.13.1.1.584109161.20230630175432428.38899",
"resource": {
"resourceType": "Provenance",
"id": "1.2.40.0.13.1.1.584109161.20230630175432428.38899",
"entity": [
{
"what": {
"reference": "https://somehost:8443/mhd/r4/responder/DocumentReference/urn:oid:1.2.40.0.13.1.1.584109161.20230630175432428.38899",
"identifier": {
"value": "urn:oid:1.2.40.0.13.1.1.584109161.20230630175432428.38899"
}
}
}
]
},
"request": {
"method": "PUT",
"url": "Provenance/1.2.40.0.13.1.1.584109161.20230630175432428.38899"
}
}
]
}