Merge pull request #2355 from hapifhir/mb-20210203-date-param-validation
Improve date parameter validation
This commit is contained in:
commit
6640395d6b
|
@ -20,6 +20,8 @@ package ca.uhn.fhir.rest.param;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
||||
public abstract class BaseParamWithPrefix<T extends BaseParam> extends BaseParam {
|
||||
|
@ -58,8 +60,9 @@ public abstract class BaseParamWithPrefix<T extends BaseParam> extends BaseParam
|
|||
if (!isBlank(prefix)) {
|
||||
|
||||
myPrefix = ParamPrefixEnum.forValue(prefix);
|
||||
|
||||
|
||||
if (myPrefix == null) {
|
||||
// prefix doesn't match standard values. Try legacy values
|
||||
switch (prefix) {
|
||||
case ">=":
|
||||
myPrefix = ParamPrefixEnum.GREATERTHAN_OR_EQUALS;
|
||||
|
@ -76,15 +79,13 @@ public abstract class BaseParamWithPrefix<T extends BaseParam> extends BaseParam
|
|||
case "~":
|
||||
myPrefix = ParamPrefixEnum.APPROXIMATE;
|
||||
break;
|
||||
default :
|
||||
ourLog.warn("Invalid prefix being ignored: {}", prefix);
|
||||
case "=":
|
||||
myPrefix = ParamPrefixEnum.EQUAL;
|
||||
break;
|
||||
default :
|
||||
throw new DataFormatException("Invalid prefix: \"" + prefix + "\"");
|
||||
}
|
||||
|
||||
if (myPrefix != null) {
|
||||
ourLog.warn("Date parameter has legacy prefix '{}' which has been removed from FHIR. This should be replaced with '{}'", prefix, myPrefix);
|
||||
}
|
||||
|
||||
ourLog.warn("Date parameter has legacy prefix '{}' which has been removed from FHIR. This should be replaced with '{}'", prefix, myPrefix.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -107,4 +108,5 @@ public abstract class BaseParamWithPrefix<T extends BaseParam> extends BaseParam
|
|||
myPrefix = thePrefix;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,23 +2,91 @@ package ca.uhn.fhir.rest.param;
|
|||
|
||||
import ca.uhn.fhir.model.primitive.DateTimeDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.Month;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import static ca.uhn.fhir.rest.param.ParamPrefixEnum.APPROXIMATE;
|
||||
import static ca.uhn.fhir.rest.param.ParamPrefixEnum.EQUAL;
|
||||
import static ca.uhn.fhir.rest.param.ParamPrefixEnum.NOT_EQUAL;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class DateParamTest {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DateParamTest.class);
|
||||
|
||||
|
||||
@Test
|
||||
public void testBasicDateParse() {
|
||||
DateParam input = new DateParam("2020-01-01");
|
||||
|
||||
// too bad value is a j.u.Date instead of a new JSR-310 type
|
||||
// DataParam parses using default tz, so go backwards.
|
||||
ZonedDateTime zonedDateTime = input.getValue().toInstant().atZone(ZoneId.systemDefault());
|
||||
assertEquals(2020,zonedDateTime.getYear());
|
||||
assertEquals(Month.JANUARY,zonedDateTime.getMonth());
|
||||
assertEquals(1,zonedDateTime.getDayOfMonth());
|
||||
assertNull(input.getPrefix());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadDateFormat() {
|
||||
try {
|
||||
new DateParam("09-30-1960");
|
||||
fail();
|
||||
} catch (DataFormatException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrefixParse() {
|
||||
DateParam input = new DateParam("gt2020-01-01");
|
||||
|
||||
assertEquals(ParamPrefixEnum.GREATERTHAN, input.getPrefix());
|
||||
}
|
||||
|
||||
/**
|
||||
* We support legacy prefixes in addition to the standard ParamPrefixEnum values.
|
||||
*
|
||||
* Testing here since BaseParamWithPrefix is abstract.
|
||||
*/
|
||||
@Test
|
||||
public void testLegacyPrefixParse() {
|
||||
assertEquals(ParamPrefixEnum.GREATERTHAN_OR_EQUALS, translateLegacyPrefix(">="));
|
||||
assertEquals(ParamPrefixEnum.GREATERTHAN, translateLegacyPrefix(">"));
|
||||
assertEquals(ParamPrefixEnum.LESSTHAN_OR_EQUALS, translateLegacyPrefix("<="));
|
||||
assertEquals(ParamPrefixEnum.LESSTHAN, translateLegacyPrefix("<"));
|
||||
assertEquals(ParamPrefixEnum.APPROXIMATE, translateLegacyPrefix("~"));
|
||||
assertEquals(ParamPrefixEnum.EQUAL, translateLegacyPrefix("="));
|
||||
}
|
||||
|
||||
private ParamPrefixEnum translateLegacyPrefix(String legacyPrefix) {
|
||||
DateParam input = new DateParam(legacyPrefix + "2020-01-01");
|
||||
return input.getPrefix();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJunkDateIssue2361() {
|
||||
// Issue 2361 - the string "junk" wasn't returning 400 as expected.
|
||||
// Parsed as a prefix instead, and discarded.
|
||||
// https://github.com/hapifhir/hapi-fhir/issues/2361
|
||||
try {
|
||||
new DateParam("junk");
|
||||
fail();
|
||||
} catch (DataFormatException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
// merged from ca.uhn.fhir.rest.param.DateParamTest
|
||||
@Test
|
||||
public void testConstructors() {
|
||||
new DateParam();
|
||||
|
@ -32,19 +100,17 @@ public class DateParamTest {
|
|||
|
||||
@Test
|
||||
public void testParse() {
|
||||
Date date = new Date();
|
||||
|
||||
DateParam param = new DateParam();
|
||||
param.setValueAsString("gt2016-06-09T20:38:14.591-05:00");
|
||||
|
||||
assertEquals(ParamPrefixEnum.GREATERTHAN, param.getPrefix());
|
||||
assertEquals("2016-06-09T20:38:14.591-05:00", param.getValueAsString());
|
||||
|
||||
ourLog.info("PRE: " + param.getValue());
|
||||
ourLog.info("PRE: " + param.getValue().getTime());
|
||||
ourLog.debug("PRE: " + param.getValue());
|
||||
ourLog.debug("PRE: " + param.getValue().getTime());
|
||||
InstantDt dt = new InstantDt(new Date(param.getValue().getTime()));
|
||||
dt.setTimeZone(TimeZone.getTimeZone("America/Toronto"));
|
||||
ourLog.info("POST: " + dt.getValue());
|
||||
ourLog.debug("POST: " + dt.getValue());
|
||||
assertEquals("2016-06-09T21:38:14.591-04:00", dt.getValueAsString());
|
||||
}
|
||||
|
||||
|
@ -53,15 +119,15 @@ public class DateParamTest {
|
|||
DateParam param = new DateParam();
|
||||
param.setValueAsString("2016-06-09T20:38Z");
|
||||
|
||||
assertEquals(null, param.getPrefix());
|
||||
assertNull(param.getPrefix());
|
||||
assertEquals("2016-06-09T20:38Z", param.getValueAsString());
|
||||
|
||||
ourLog.info("PRE: " + param.getValue());
|
||||
ourLog.info("PRE: " + param.getValue().getTime());
|
||||
ourLog.debug("PRE: " + param.getValue());
|
||||
ourLog.debug("PRE: " + param.getValue().getTime());
|
||||
|
||||
InstantDt dt = new InstantDt(new Date(param.getValue().getTime()));
|
||||
dt.setTimeZone(TimeZone.getTimeZone("America/Toronto"));
|
||||
ourLog.info("POST: " + dt.getValue());
|
||||
ourLog.debug("POST: " + dt.getValue());
|
||||
assertEquals("2016-06-09T16:38:00.000-04:00", dt.getValueAsString());
|
||||
}
|
||||
|
||||
|
@ -70,15 +136,15 @@ public class DateParamTest {
|
|||
DateParam param = new DateParam();
|
||||
param.setValueAsString("2016-06-09T20:38");
|
||||
|
||||
assertEquals(null, param.getPrefix());
|
||||
assertNull(param.getPrefix());
|
||||
assertEquals("2016-06-09T20:38", param.getValueAsString());
|
||||
|
||||
ourLog.info("PRE: " + param.getValue());
|
||||
ourLog.info("PRE: " + param.getValue().getTime());
|
||||
ourLog.debug("PRE: " + param.getValue());
|
||||
ourLog.debug("PRE: " + param.getValue().getTime());
|
||||
|
||||
InstantDt dt = new InstantDt(new Date(param.getValue().getTime()));
|
||||
dt.setTimeZone(TimeZone.getTimeZone("America/Toronto"));
|
||||
ourLog.info("POST: " + dt.getValue());
|
||||
ourLog.debug("POST: " + dt.getValue());
|
||||
assertThat(dt.getValueAsString(), startsWith("2016-06-09T"));
|
||||
assertThat(dt.getValueAsString(), endsWith("8:00.000-04:00"));
|
||||
}
|
||||
|
@ -91,12 +157,12 @@ public class DateParamTest {
|
|||
assertEquals(ParamPrefixEnum.GREATERTHAN, param.getPrefix());
|
||||
assertEquals("2016-06-09T20:38Z", param.getValueAsString());
|
||||
|
||||
ourLog.info("PRE: " + param.getValue());
|
||||
ourLog.info("PRE: " + param.getValue().getTime());
|
||||
ourLog.debug("PRE: " + param.getValue());
|
||||
ourLog.debug("PRE: " + param.getValue().getTime());
|
||||
|
||||
InstantDt dt = new InstantDt(new Date(param.getValue().getTime()));
|
||||
dt.setTimeZone(TimeZone.getTimeZone("America/Toronto"));
|
||||
ourLog.info("POST: " + dt.getValue());
|
||||
ourLog.debug("POST: " + dt.getValue());
|
||||
assertEquals("2016-06-09T16:38:00.000-04:00", dt.getValueAsString());
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
type: fix
|
||||
issue: 2361
|
||||
title: "Unrecognized search param prefix strings were silently discarded. This is now an error."
|
|
@ -436,7 +436,7 @@ public class GenericClientTest {
|
|||
.encodedJson()
|
||||
.execute();
|
||||
} catch (FhirClientConnectionException e) {
|
||||
assertEquals(0, e.getStatusCode());
|
||||
assertEquals(500, e.getStatusCode());
|
||||
assertThat(e.getMessage(), containsString("Failed to parse response from server when performing DELETE to URL"));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue