import static org.sonar.core.component.ComponentKeys.MAX_COMPONENT_KEY_LENGTH;
public class ComponentValidator {
- private static final int MAX_COMPONENT_NAME_LENGTH = 2000;
+ public static final int MAX_COMPONENT_NAME_LENGTH = 2000;
private static final int MAX_COMPONENT_QUALIFIER_LENGTH = 10;
private ComponentValidator() {
import org.sonarqube.ws.client.project.CreateRequest;
import static org.sonar.api.resources.Qualifiers.PROJECT;
+import static org.sonar.core.component.ComponentKeys.MAX_COMPONENT_KEY_LENGTH;
+import static org.sonar.db.component.ComponentValidator.MAX_COMPONENT_NAME_LENGTH;
import static org.sonar.db.permission.OrganizationPermission.PROVISION_PROJECTS;
import static org.sonar.server.component.NewComponent.newComponentBuilder;
import static org.sonar.server.project.ws.ProjectsWsSupport.PARAM_ORGANIZATION;
.setDescription("Key of the project")
.setDeprecatedKey(DEPRECATED_PARAM_KEY, "6.3")
.setRequired(true)
+ .setMaximumLength(MAX_COMPONENT_KEY_LENGTH)
.setExampleValue(KEY_PROJECT_EXAMPLE_001);
action.createParam(PARAM_NAME)
.setDescription("Name of the project")
.setRequired(true)
+ .setMaximumLength(MAX_COMPONENT_NAME_LENGTH)
.setExampleValue("SonarQube");
action.createParam(PARAM_BRANCH)
if (possibleValues != null) {
writer.name("possibleValues").beginArray().values(possibleValues).endArray();
}
+ Integer maximumLength = param.maximumLength();
+ if (maximumLength != null) {
+ writer.prop("maximumLength", maximumLength);
+ }
writer.endObject();
}
},
{
"key": "severity",
+ "maximumLength": 20,
"description": "Severity",
"required": false,
"internal": false,
*/
package org.sonar.server.project.ws;
-import org.assertj.core.api.Assertions;
import org.assertj.core.api.AssertionsForClassTypes;
import org.junit.Rule;
import org.junit.Test;
import org.sonarqube.ws.WsProjects.CreateWsResponse.Project;
import org.sonarqube.ws.client.project.CreateRequest;
-import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
+import static joptsimple.internal.Strings.repeat;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doThrow;
new ProjectsWsSupport(db.getDbClient(), defaultOrganizationProvider, billingValidations),
db.getDbClient(), userSession,
new ComponentUpdater(db.getDbClient(), i18n, system2, mock(PermissionTemplateService.class), new FavoriteUpdater(db.getDbClient()),
- projectIndexers)
- ));
+ projectIndexers)));
@Test
public void create_project() throws Exception {
@Test
public void fail_when_missing_project_parameter() throws Exception {
+ userSession.addPermission(PROVISION_PROJECTS, db.getDefaultOrganization());
+
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("The 'project' parameter is missing");
@Test
public void fail_when_missing_name_parameter() throws Exception {
+ userSession.addPermission(PROVISION_PROJECTS, db.getDefaultOrganization());
+
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("The 'name' parameter is missing");
call(CreateRequest.builder().setKey(DEFAULT_PROJECT_KEY).setName(DEFAULT_PROJECT_NAME).build());
}
+ @Test
+ public void fail_when_project_parameter_is_longer_than_400() {
+ userSession.addPermission(PROVISION_PROJECTS, db.getDefaultOrganization());
+
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("'project' length (401) is longer than the maximum authorized (400)");
+
+ ws.newRequest().setMethod(POST.name())
+ .setParam("project", repeat('a', 401))
+ .setParam("name", DEFAULT_PROJECT_NAME)
+ .execute();
+ }
+
+ @Test
+ public void fail_when_name_parameter_is_longer_than_2000() {
+ userSession.addPermission(PROVISION_PROJECTS, db.getDefaultOrganization());
+
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("'name' length (2001) is longer than the maximum authorized (2000)");
+
+ ws.newRequest().setMethod(POST.name())
+ .setParam("project", "key")
+ .setParam("name", repeat('a', 2001))
+ .execute();
+ }
+
@Test
public void test_example() {
userSession.addPermission(PROVISION_PROJECTS, db.getDefaultOrganization());
public void definition() {
WebService.Action definition = ws.getDef();
- Assertions.assertThat(definition.key()).isEqualTo("create");
- Assertions.assertThat(definition.since()).isEqualTo("4.0");
- Assertions.assertThat(definition.isInternal()).isFalse();
- Assertions.assertThat(definition.responseExampleAsString()).isNotEmpty();
+ assertThat(definition.key()).isEqualTo("create");
+ assertThat(definition.since()).isEqualTo("4.0");
+ assertThat(definition.isInternal()).isFalse();
+ assertThat(definition.responseExampleAsString()).isNotEmpty();
- Assertions.assertThat(definition.params()).extracting(WebService.Param::key).containsExactlyInAnyOrder(
+ assertThat(definition.params()).extracting(WebService.Param::key).containsExactlyInAnyOrder(
PARAM_VISIBILITY,
PARAM_ORGANIZATION,
PARAM_NAME,
PARAM_BRANCH);
WebService.Param organization = definition.param(PARAM_ORGANIZATION);
- Assertions.assertThat(organization.description()).isEqualTo("The key of the organization");
- Assertions.assertThat(organization.isInternal()).isTrue();
- Assertions.assertThat(organization.isRequired()).isFalse();
- Assertions.assertThat(organization.since()).isEqualTo("6.3");
+ assertThat(organization.description()).isEqualTo("The key of the organization");
+ assertThat(organization.isInternal()).isTrue();
+ assertThat(organization.isRequired()).isFalse();
+ assertThat(organization.since()).isEqualTo("6.3");
WebService.Param isPrivate = definition.param(PARAM_VISIBILITY);
- Assertions.assertThat(isPrivate.description()).isNotEmpty();
- Assertions.assertThat(isPrivate.isInternal()).isTrue();
- Assertions.assertThat(isPrivate.isRequired()).isFalse();
- Assertions.assertThat(isPrivate.since()).isEqualTo("6.4");
- Assertions.assertThat(isPrivate.possibleValues()).containsExactlyInAnyOrder("private", "public");
+ assertThat(isPrivate.description()).isNotEmpty();
+ assertThat(isPrivate.isInternal()).isTrue();
+ assertThat(isPrivate.isRequired()).isFalse();
+ assertThat(isPrivate.since()).isEqualTo("6.4");
+ assertThat(isPrivate.possibleValues()).containsExactlyInAnyOrder("private", "public");
+
+ WebService.Param project = definition.param(PARAM_PROJECT);
+ assertThat(project.isRequired()).isTrue();
+ assertThat(project.maximumLength()).isEqualTo(400);
+
+ WebService.Param name = definition.param(PARAM_NAME);
+ assertThat(name.isRequired()).isTrue();
+ assertThat(name.maximumLength()).isEqualTo(2000);
}
private CreateWsResponse call(CreateRequest request) {
// action with a lot of overridden values
NewAction create = newController.createAction("create")
+ .setPost(true)
.setDescription("Create metric")
.setSince("4.1")
.setDeprecatedSince("5.3")
- .setPost(true)
.setResponseExample(Resources.getResource(getClass(), "WebServicesWsTest/metrics_example.json"))
.setChangelog(
new Change("4.5", "Deprecate database ID in response"),
create
.createParam("severity")
+ .setMaximumLength(20)
.setDescription("Severity")
.setSince("4.4")
.setDeprecatedSince("5.2")
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;
return this;
}
+ /**
+ * @since 7.0
+ */
+ public NewParam setMaximumLength(@Nullable Integer maximumLength) {
+ this.maximumLength = maximumLength;
+ return this;
+ }
+
@Override
public String toString() {
return key;
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) {
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);
}
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;
@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
return readPart(key);
}
- @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;
}
}
@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) {
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;
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;
assertThat(underTest.mandatoryParamAsEnum("a_required_enum", RuleStatus.class)).isEqualTo(RuleStatus.BETA);
}
+ @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");
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();
assertThat(action.param("status").possibleValues()).isNull();
}
+ @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);