Browse Source

SONAR-8050 Validate settings of type LONG

tags/6.1-RC1
Teryk Bellahsene 7 years ago
parent
commit
132d938e7a

+ 2
- 1
server/sonar-server/src/main/java/org/sonar/server/setting/ws/ResetAction.java View File

@@ -40,6 +40,7 @@ import org.sonar.server.setting.ws.SettingValidations.SettingData;
import org.sonar.server.user.UserSession;
import org.sonarqube.ws.client.setting.ResetRequest;

import static java.util.Collections.emptyList;
import static org.sonar.server.setting.ws.SettingsWsComponentParameters.addComponentParameters;
import static org.sonarqube.ws.client.ce.CeWsParameters.PARAM_COMPONENT_KEY;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.ACTION_RESET;
@@ -95,7 +96,7 @@ public class ResetAction implements SettingsWsAction {
Optional<ComponentDto> component = getComponent(dbSession, resetRequest);
checkPermissions(component);
resetRequest.getKeys().forEach(key -> {
SettingData data = new SettingData(key, component.orElse(null));
SettingData data = new SettingData(key, emptyList(), component.orElse(null));
ImmutableList.of(validations.scope(), validations.qualifier())
.forEach(validation -> validation.validate(data));
});

+ 5
- 19
server/sonar-server/src/main/java/org/sonar/server/setting/ws/SetAction.java View File

@@ -29,7 +29,6 @@ import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
@@ -159,7 +158,7 @@ public class SetAction implements SettingsWsAction {

String value;

commonChecks(request, definition, component);
commonChecks(request, component);

if (!request.getFieldValues().isEmpty()) {
value = doHandlePropertySet(dbSession, request, definition, component);
@@ -191,7 +190,7 @@ public class SetAction implements SettingsWsAction {
List<String> fieldValues = request.getFieldValues();
IntStream.of(fieldIds).boxed()
.flatMap(i -> readOneFieldValues(fieldValues.get(i - 1), request.getKey()).entrySet().stream()
.map(entry -> new KeyValue(key + "." + i + "." + entry.getKey(), entry.getValue())))
.map(entry -> new KeyValue(key + "." + i + "." + entry.getKey(), entry.getValue())))
.forEach(keyValue -> dbClient.propertiesDao().saveProperty(dbSession, toFieldProperty(keyValue, componentId)));

return inlinedFieldKeys;
@@ -205,10 +204,10 @@ public class SetAction implements SettingsWsAction {
}
}

private void commonChecks(SetRequest request, @Nullable PropertyDefinition definition, Optional<ComponentDto> component) {
private void commonChecks(SetRequest request, Optional<ComponentDto> component) {
checkValueIsSet(request);
SettingData settingData = new SettingData(request.getKey(), component.orElse(null));
ImmutableList.of(validations.scope(), validations.qualifier()).stream()
SettingData settingData = new SettingData(request.getKey(), valuesFromRequest(request), component.orElse(null));
ImmutableList.of(validations.scope(), validations.qualifier(), validations.valueType())
.forEach(validation -> validation.validate(settingData));
}

@@ -237,7 +236,6 @@ public class SetAction implements SettingsWsAction {
return;
}

checkType(request, definition);
checkSingleOrMultiValue(request, definition);
}

@@ -257,18 +255,6 @@ public class SetAction implements SettingsWsAction {
"Parameter '%s' must be used for single value setting. Parameter '%s' must be used for multi value setting.", PARAM_VALUE, PARAM_VALUES);
}

private void checkType(SetRequest request, PropertyDefinition definition) {
List<String> values = valuesFromRequest(request);
Optional<PropertyDefinition.Result> failingResult = values.stream()
.map(definition::validate)
.filter(result -> !result.isValid())
.findAny();
String errorKey = failingResult.isPresent() ? failingResult.get().getErrorKey() : null;
checkRequest(errorKey == null,
i18n.message(Locale.ENGLISH, "property.error." + errorKey, "Error when validating setting with key '%s' and value '%s'"),
request.getKey(), request.getValue());
}

private static void checkValueIsSet(SetRequest request) {
checkRequest(!isNullOrEmpty(request.getValue())
^ !request.getValues().isEmpty()

+ 31
- 2
server/sonar-server/src/main/java/org/sonar/server/setting/ws/SettingValidations.java View File

@@ -20,14 +20,20 @@

package org.sonar.server.setting.ws;

import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.api.config.PropertyDefinition;
import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.i18n.I18n;
import org.sonar.db.component.ComponentDto;
import org.sonarqube.ws.client.setting.SetRequest;

import static java.util.Objects.requireNonNull;
import static org.sonar.server.ws.WsUtils.checkRequest;

public class SettingValidations {
@@ -56,6 +62,27 @@ public class SettingValidations {
};
}

public SettingValidation valueType() {
return data -> {
PropertyDefinition definition = definitions.get(data.key);
if (definition == null) {
return;
}
Optional<PropertyDefinition.Result> failingResult = data.values.stream()
.map(definition::validate)
.filter(result -> !result.isValid())
.findAny();
String errorKey = failingResult.isPresent() ? failingResult.get().getErrorKey() : null;
checkRequest(errorKey == null,
i18n.message(Locale.ENGLISH, "property.error." + errorKey, "Error when validating setting with key '%s' and value [%s]"),
data.key, data.values.stream().collect(Collectors.joining(", ")));
};
}

private static List<String> valuesFromRequest(SetRequest request) {
return request.getValue() == null ? request.getValues() : Collections.singletonList(request.getValue());
}

private static boolean isGlobal(PropertyDefinition definition) {
return !definition.global() && definition.qualifiers().isEmpty();
}
@@ -67,11 +94,13 @@ public class SettingValidations {

public static class SettingData {
private final String key;
private final List<String> values;
@CheckForNull
private final ComponentDto component;

public SettingData(String key, @Nullable ComponentDto component) {
this.key = key;
public SettingData(String key, List<String> values, @Nullable ComponentDto component) {
this.key = requireNonNull(key);
this.values = requireNonNull(values);
this.component = component;
}


+ 2
- 2
server/sonar-server/src/test/java/org/sonar/server/setting/ws/SetActionTest.java View File

@@ -403,9 +403,9 @@ public class SetActionTest {
.defaultValue("default")
.build());
expectedException.expect(BadRequestException.class);
expectedException.expectMessage("Error when validating setting with key 'my.key' and value 'My Value'");
expectedException.expectMessage("Error when validating setting with key 'my.key' and value [My Value, My Other Value]");

callForGlobalSetting("my.key", "My Value");
callForMultiValueGlobalSetting("my.key", newArrayList("My Value", "My Other Value"));
}

@Test

+ 16
- 8
sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinition.java View File

@@ -38,6 +38,7 @@ import org.sonar.api.server.ServerSide;
import org.sonarsource.api.sonarlint.SonarLintSide;

import static com.google.common.base.Preconditions.checkArgument;
import static org.apache.commons.lang.StringUtils.isBlank;
import static org.sonar.api.PropertyType.PROPERTY_SET;

/**
@@ -150,18 +151,25 @@ public final class PropertyDefinition {
}

public static Result validate(PropertyType type, @Nullable String value, List<String> options) {
if (StringUtils.isNotBlank(value)) {
if (type == PropertyType.BOOLEAN) {
if (isBlank(value)) {
return Result.SUCCESS;
}

switch (type) {
case BOOLEAN:
return validateBoolean(value);
} else if (type == PropertyType.INTEGER) {
case INTEGER:
case LONG:
return validateInteger(value);
} else if (type == PropertyType.FLOAT) {
case FLOAT:
return validateFloat(value);
} else if (type == PropertyType.SINGLE_SELECT_LIST && !options.contains(value)) {
return Result.newError("notInOptions");
}
case SINGLE_SELECT_LIST:
if (!options.contains(value)) {
return Result.newError("notInOptions");
}
default:
return Result.SUCCESS;
}
return Result.SUCCESS;
}

private static Result validateBoolean(String value) {

+ 13
- 0
sonar-plugin-api/src/test/java/org/sonar/api/config/PropertyDefinitionTest.java View File

@@ -226,6 +226,19 @@ public class PropertyDefinitionTest {
assertThat(def.validate("foo").getErrorKey()).isEqualTo("notInteger");
}

@Test
public void should_validate_long() {
PropertyDefinition def = PropertyDefinition.builder("foo").name("foo").type(PropertyType.LONG).build();

assertThat(def.validate(null).isValid()).isTrue();
assertThat(def.validate("").isValid()).isTrue();
assertThat(def.validate(" ").isValid()).isTrue();
assertThat(def.validate("123456").isValid()).isTrue();

assertThat(def.validate("foo").isValid()).isFalse();
assertThat(def.validate("foo").getErrorKey()).isEqualTo("notInteger");
}

@Test
public void should_validate_float() {
PropertyDefinition def = PropertyDefinition.builder("foo").name("foo").type(PropertyType.FLOAT).build();

Loading…
Cancel
Save