From 1bb7566e9774cf0a0d262fc7f07c347181e0d240 Mon Sep 17 00:00:00 2001 From: Teryk Bellahsene Date: Fri, 9 Sep 2016 17:11:51 +0200 Subject: SONAR-8046 Validate settings of type METRIC --- .../server/setting/ws/SettingValidations.java | 67 +++++++++++++++------- .../sonar/server/setting/ws/ResetActionTest.java | 2 +- .../org/sonar/server/setting/ws/SetActionTest.java | 45 ++++++++++++++- 3 files changed, 90 insertions(+), 24 deletions(-) (limited to 'server') diff --git a/server/sonar-server/src/main/java/org/sonar/server/setting/ws/SettingValidations.java b/server/sonar-server/src/main/java/org/sonar/server/setting/ws/SettingValidations.java index 0f70613f543..6281ee259a0 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/setting/ws/SettingValidations.java +++ b/server/sonar-server/src/main/java/org/sonar/server/setting/ws/SettingValidations.java @@ -20,28 +20,33 @@ 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.PropertyType; import org.sonar.api.config.PropertyDefinition; import org.sonar.api.config.PropertyDefinitions; import org.sonar.api.i18n.I18n; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; import org.sonar.db.component.ComponentDto; -import org.sonarqube.ws.client.setting.SetRequest; +import org.sonar.db.metric.MetricDto; +import org.sonar.server.exceptions.BadRequestException; +import static java.lang.String.format; import static java.util.Objects.requireNonNull; import static org.sonar.server.ws.WsUtils.checkRequest; public class SettingValidations { private final PropertyDefinitions definitions; + private final DbClient dbClient; private final I18n i18n; - public SettingValidations(PropertyDefinitions definitions, I18n i18n) { + public SettingValidations(PropertyDefinitions definitions, DbClient dbClient, I18n i18n) { this.definitions = definitions; + this.dbClient = dbClient; this.i18n = i18n; } @@ -63,24 +68,7 @@ public class SettingValidations { } public SettingValidation valueType() { - return data -> { - PropertyDefinition definition = definitions.get(data.key); - if (definition == null) { - return; - } - Optional 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 valuesFromRequest(SetRequest request) { - return request.getValue() == null ? request.getValues() : Collections.singletonList(request.getValue()); + return new ValueTypeValidation(); } private static boolean isGlobal(PropertyDefinition definition) { @@ -103,6 +91,41 @@ public class SettingValidations { this.values = requireNonNull(values); this.component = component; } + } + + private class ValueTypeValidation implements SettingValidation { + + @Override + public void validate(SettingData data) { + PropertyDefinition definition = definitions.get(data.key); + if (definition == null) { + return; + } + + if (definition.type() == PropertyType.METRIC) { + metric(data); + } else { + otherTypes(data, definition); + } + } + private void otherTypes(SettingData data, PropertyDefinition definition) { + data.values.stream() + .map(definition::validate) + .filter(result -> !result.isValid()) + .findAny() + .ifPresent(result -> { + throw new BadRequestException(i18n.message(Locale.ENGLISH, "property.error." + result.getErrorKey(), + format("Error when validating setting with key '%s' and value [%s]", data.key, data.values.stream().collect(Collectors.joining(", "))))); + }); + } + + private void metric(SettingData data) { + try (DbSession dbSession = dbClient.openSession(false)) { + List metrics = dbClient.metricDao().selectByKeys(dbSession, data.values); + checkRequest(data.values.size() == metrics.size(), "Error when validating metric setting with key '%s' and values [%s]. A value is not a valid metric key.", + data.key, data.values.stream().collect(Collectors.joining(", "))); + } + } } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/setting/ws/ResetActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/setting/ws/ResetActionTest.java index 7808d583615..d3c0722bf55 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/setting/ws/ResetActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/setting/ws/ResetActionTest.java @@ -81,7 +81,7 @@ public class ResetActionTest { ComponentFinder componentFinder = new ComponentFinder(dbClient); PropertyDefinitions definitions = new PropertyDefinitions(); SettingsUpdater settingsUpdater = new SettingsUpdater(dbClient, definitions); - SettingValidations settingValidations = new SettingValidations(definitions, i18n); + SettingValidations settingValidations = new SettingValidations(definitions, dbClient, i18n); ComponentDto project; diff --git a/server/sonar-server/src/test/java/org/sonar/server/setting/ws/SetActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/setting/ws/SetActionTest.java index f808060d76b..ec4206d1796 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/setting/ws/SetActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/setting/ws/SetActionTest.java @@ -62,6 +62,7 @@ import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.groups.Tuple.tuple; import static org.sonar.db.component.ComponentTesting.newView; +import static org.sonar.db.metric.MetricTesting.newMetricDto; import static org.sonar.db.property.PropertyTesting.newComponentPropertyDto; import static org.sonar.db.property.PropertyTesting.newGlobalPropertyDto; @@ -86,7 +87,7 @@ public class SetActionTest { PropertyDefinitions definitions = new PropertyDefinitions(); FakeSettingsNotifier settingsChangeNotifier = new FakeSettingsNotifier(dbClient); SettingsUpdater settingsUpdater = new SettingsUpdater(dbClient, definitions); - SettingValidations validations = new SettingValidations(definitions, i18n); + SettingValidations validations = new SettingValidations(definitions, dbClient, i18n); SetAction underTest = new SetAction(definitions, i18n, dbClient, componentFinder, userSession, settingsUpdater, settingsChangeNotifier, validations); @@ -305,6 +306,27 @@ public class SetActionTest { assertThat(settingsChangeNotifier.wasCalled).isFalse(); } + @Test + public void persist_multi_value_with_type_metric() { + definitions.addComponent(PropertyDefinition + .builder("my.key") + .name("foo") + .description("desc") + .category("cat") + .subCategory("subCat") + .type(PropertyType.METRIC) + .defaultValue("default") + .multiValues(true) + .build()); + dbClient.metricDao().insert(dbSession, newMetricDto().setKey("metric.key.1")); + dbClient.metricDao().insert(dbSession, newMetricDto().setKey("metric.key.2")); + dbSession.commit(); + + callForMultiValueGlobalSetting("my.key", newArrayList("metric.key.1", "metric.key.2")); + + assertGlobalSetting("my.key", "metric.key.1,metric.key.2"); + } + @Test public void user_setting_is_not_updated() { propertyDb.insertProperty(newGlobalPropertyDto("my.key", "my user value").setUserId(42L)); @@ -391,6 +413,27 @@ public class SetActionTest { callForGlobalSetting("my.key", "My Value"); } + @Test + public void fail_when_data_and_metric_type_with_invalid_key() { + definitions.addComponent(PropertyDefinition + .builder("my.key") + .name("foo") + .description("desc") + .category("cat") + .subCategory("subCat") + .type(PropertyType.METRIC) + .defaultValue("default") + .multiValues(true) + .build()); + dbClient.metricDao().insert(dbSession, newMetricDto().setKey("metric.key")); + dbSession.commit(); + + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("Error when validating metric setting with key 'my.key' and values [metric.key, My Value]. A value is not a valid metric key."); + + callForMultiValueGlobalSetting("my.key", newArrayList("metric.key", "My Value")); + } + @Test public void fail_when_data_and_type_do_not_match_with_unknown_error_key() { definitions.addComponent(PropertyDefinition -- cgit v1.2.3