diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2017-11-02 09:20:09 +0100 |
---|---|---|
committer | Guillaume Jambet <guillaume.jambet@gmail.com> | 2017-11-08 13:51:31 +0100 |
commit | 0b7335e7128458cdba491ec34ec8da9de1d6f06e (patch) | |
tree | 12f5d63cf0591e08d1a1d89479d7d4ce15479951 /sonar-plugin-api | |
parent | 8bc85e2ccc2c2d7f3258d70bcb92715d6814321d (diff) | |
download | sonarqube-0b7335e7128458cdba491ec34ec8da9de1d6f06e.tar.gz sonarqube-0b7335e7128458cdba491ec34ec8da9de1d6f06e.zip |
SONAR-10040 add length validation to Request api and api/projects/create
Diffstat (limited to 'sonar-plugin-api')
4 files changed, 94 insertions, 18 deletions
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/WebService.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/WebService.java index f200cfe8cf2..9d07ee5307a 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/WebService.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/WebService.java @@ -633,7 +633,8 @@ public interface WebService extends Definable<WebService.Context> { private boolean required = false; private boolean internal = false; private Set<String> possibleValues = null; - private Integer maxValuesAllowed = null; + private Integer maxValuesAllowed; + private Integer maximumLength; private NewParam(String key) { this.key = key; @@ -770,6 +771,14 @@ public interface WebService extends Definable<WebService.Context> { return this; } + /** + * @since 7.0 + */ + public NewParam setMaximumLength(@Nullable Integer maximumLength) { + this.maximumLength = maximumLength; + return this; + } + @Override public String toString() { return key; @@ -824,6 +833,7 @@ public interface WebService extends Definable<WebService.Context> { private final boolean required; private final boolean internal; private final Set<String> possibleValues; + private final Integer maximumLength; private final Integer maxValuesAllowed; protected Param(Action action, NewParam newParam) { @@ -839,6 +849,7 @@ public interface WebService extends Definable<WebService.Context> { this.internal = newParam.internal; this.possibleValues = newParam.possibleValues; this.maxValuesAllowed = newParam.maxValuesAllowed; + this.maximumLength = newParam.maximumLength; checkArgument(!required || defaultValue == null, "Default value must not be set on parameter '%s?%s' as it's marked as required", action, key); } @@ -935,6 +946,16 @@ public interface WebService extends Definable<WebService.Context> { return maxValuesAllowed; } + /** + * Specify the maximum length of the value used in this parameter + * + * @since 7.0 + */ + @CheckForNull + public Integer maximumLength() { + return maximumLength; + } + @Override public String toString() { return key; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/ValidatingRequest.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/ValidatingRequest.java index 79e76d50182..495cd8e5d82 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/ValidatingRequest.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/ValidatingRequest.java @@ -67,7 +67,22 @@ public abstract class ValidatingRequest extends Request { @Override @CheckForNull public String param(String key) { - return param(key, true); + WebService.Param definition = action.param(key); + String value = defaultString(readParam(key, definition), definition.defaultValue()); + + Integer maximumLength = definition.maximumLength(); + if (value != null && maximumLength != null) { + int valueLength = value.length(); + checkArgument(valueLength <= maximumLength, + "'%s' length (%s) is longer than the maximum authorized (%s)", + key, valueLength, maximumLength); + } + + String trimmedValue = value == null ? null : CharMatcher.WHITESPACE.trimFrom(value); + if (trimmedValue != null) { + validateValue(trimmedValue, definition); + } + return trimmedValue; } @Override @@ -90,21 +105,10 @@ public abstract class ValidatingRequest extends Request { } @CheckForNull - private String param(String key, boolean validateValue) { - WebService.Param definition = action.param(key); - String value = readParamOrDefaultValue(key, definition); - String trimmedValue = value == null ? null : CharMatcher.WHITESPACE.trimFrom(value); - if (trimmedValue != null && validateValue) { - validateValue(trimmedValue, definition); - } - return trimmedValue; - } - - @CheckForNull @Override public List<String> paramAsStrings(String key) { WebService.Param definition = action.param(key); - String value = readParamOrDefaultValue(key, definition); + String value = defaultString(readParam(key, definition), definition.defaultValue()); if (value == null) { return null; } @@ -125,12 +129,10 @@ public abstract class ValidatingRequest extends Request { } @CheckForNull - private String readParamOrDefaultValue(String key, @Nullable WebService.Param definition) { + private String readParam(String key, @Nullable WebService.Param definition) { checkArgument(definition != null, "BUG - parameter '%s' is undefined for action '%s'", key, action.key()); - String deprecatedKey = definition.deprecatedKey(); - String value = deprecatedKey != null ? defaultString(readParam(deprecatedKey), readParam(key)) : readParam(key); - return defaultString(value, definition.defaultValue()); + return deprecatedKey != null ? defaultString(readParam(deprecatedKey), readParam(key)) : readParam(key); } private List<String> readMultiParamOrDefaultValue(String key, @Nullable WebService.Param definition) { diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/RequestTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/RequestTest.java index d9395d5b598..e95cf3077db 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/RequestTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/RequestTest.java @@ -31,6 +31,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; import javax.annotation.Nullable; import org.apache.commons.io.IOUtils; import org.junit.Before; @@ -43,7 +44,9 @@ import org.sonar.api.server.ws.internal.PartImpl; import org.sonar.api.server.ws.internal.ValidatingRequest; import org.sonar.api.utils.DateUtils; +import static com.google.common.base.Strings.repeat; import static com.google.common.collect.Lists.newArrayList; +import static java.lang.String.format; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; import static org.mockito.Mockito.mock; @@ -97,6 +100,28 @@ public class RequestTest { } @Test + public void maximum_length_ok() { + String parameter = "maximum_length_param"; + defineParameterTestAction(newParam -> newParam.setMaximumLength(10), parameter); + String value = repeat("X", 10); + + String param = underTest.setParam(parameter, value).param(parameter); + + assertThat(param).isEqualTo(value); + } + + @Test + public void maximum_length_not_ok() { + String parameter = "maximum_length_param"; + defineParameterTestAction(newParam -> newParam.setMaximumLength(10), parameter); + + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage(format("'%s' length (11) is longer than the maximum authorized (10)", parameter)); + + underTest.setParam(parameter, repeat("X", 11)).param(parameter); + } + + @Test public void required_param_as_strings() { underTest.setParam("a_required_string", "foo,bar"); @@ -580,6 +605,20 @@ public class RequestTest { underTest.mandatoryParamAsPart("required_param"); } + private void defineParameterTestAction(Consumer<WebService.NewParam> newParam, String parameter) { + String controllerPath = "my_controller"; + String actionPath = "my_action"; + WebService.Context context = new WebService.Context(); + WebService.NewController controller = context.createController(controllerPath); + WebService.NewAction action = controller + .createAction(actionPath) + .setHandler(mock(RequestHandler.class)); + WebService.NewParam param = action.createParam(parameter); + newParam.accept(param); + controller.done(); + underTest.setAction(context.controller(controllerPath).action(actionPath)); + } + private static class FakeRequest extends ValidatingRequest { private final ListMultimap<String, String> multiParams = ArrayListMultimap.create(); diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/WebServiceTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/WebServiceTest.java index b73ce7ef5e4..4b674ea392c 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/WebServiceTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/WebServiceTest.java @@ -302,6 +302,20 @@ public class WebServiceTest { } @Test + public void param_with_maximum_length() { + ((WebService) context -> { + NewController newController = context.createController("api/custom_measures"); + NewAction create = newDefaultAction(newController, "create"); + create.createParam("string_value") + .setMaximumLength(24); + newController.done(); + }).define(context); + + WebService.Action action = context.controller("api/custom_measures").action("create"); + assertThat(action.param("string_value").maximumLength()).isEqualTo(24); + } + + @Test public void fail_if_required_param_has_default_value() { expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Default value must not be set on parameter 'api/rule/create?key' as it's marked as required"); |