@@ -100,7 +100,7 @@ public class ListDefinitionsAction implements SettingsWsAction { | |||
propertyDefinitions.getAll().stream() | |||
.filter(definition -> qualifier.map(s -> definition.qualifiers().contains(s)).orElseGet(definition::global)) | |||
.filter(definition -> wsRequest.getBranch() == null || SETTING_ON_BRANCHES.contains(definition.key())) | |||
.filter(settingsWsSupport.isDefinitionVisible(component)) | |||
.filter(definition -> settingsWsSupport.isVisible(definition.key(), definition, component)) | |||
.sorted(comparing(PropertyDefinition::category, String::compareToIgnoreCase) | |||
.thenComparingInt(PropertyDefinition::index) | |||
.thenComparing(PropertyDefinition::name, String::compareToIgnoreCase)) |
@@ -1,98 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2018 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.setting.ws; | |||
import com.google.common.base.Splitter; | |||
import com.google.common.collect.Multimap; | |||
import com.google.common.collect.Ordering; | |||
import com.google.common.collect.TreeMultimap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Objects; | |||
import java.util.Set; | |||
import java.util.stream.Collectors; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.config.PropertyDefinitions; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.property.PropertyDto; | |||
import static org.sonar.api.PropertyType.PROPERTY_SET; | |||
import static org.sonar.server.setting.ws.PropertySetExtractor.extractPropertySetKeys; | |||
public class SettingsFinder { | |||
private static final Splitter DOT_SPLITTER = Splitter.on(".").omitEmptyStrings(); | |||
private final DbClient dbClient; | |||
private final PropertyDefinitions definitions; | |||
public SettingsFinder(DbClient dbClient, PropertyDefinitions definitions) { | |||
this.dbClient = dbClient; | |||
this.definitions = definitions; | |||
} | |||
public List<Setting> loadGlobalSettings(DbSession dbSession, Set<String> keys) { | |||
List<PropertyDto> properties = dbClient.propertiesDao().selectGlobalPropertiesByKeys(dbSession, keys); | |||
List<PropertyDto> propertySets = dbClient.propertiesDao().selectGlobalPropertiesByKeys(dbSession, getPropertySetKeys(properties)); | |||
return properties.stream() | |||
.map(property -> Setting.createFromDto(property, getPropertySets(property.getKey(), propertySets, null), definitions.get(property.getKey()))) | |||
.collect(Collectors.toList()); | |||
} | |||
/** | |||
* Return list of settings by component uuid, sorted from project to lowest module | |||
*/ | |||
public Multimap<String, Setting> loadComponentSettings(DbSession dbSession, Set<String> keys, ComponentDto component) { | |||
List<String> componentUuids = DOT_SPLITTER.splitToList(component.moduleUuidPath()); | |||
List<ComponentDto> componentDtos = dbClient.componentDao().selectByUuids(dbSession, componentUuids); | |||
Set<Long> componentIds = componentDtos.stream().map(ComponentDto::getId).collect(Collectors.toSet()); | |||
Map<Long, String> uuidsById = componentDtos.stream().collect(Collectors.toMap(ComponentDto::getId, ComponentDto::uuid)); | |||
List<PropertyDto> properties = dbClient.propertiesDao().selectPropertiesByKeysAndComponentIds(dbSession, keys, componentIds); | |||
List<PropertyDto> propertySets = dbClient.propertiesDao().selectPropertiesByKeysAndComponentIds(dbSession, getPropertySetKeys(properties), componentIds); | |||
Multimap<String, Setting> settingsByUuid = TreeMultimap.create(Ordering.explicit(componentUuids), Ordering.arbitrary()); | |||
for (PropertyDto propertyDto : properties) { | |||
Long componentId = propertyDto.getResourceId(); | |||
String componentUuid = uuidsById.get(componentId); | |||
String propertyKey = propertyDto.getKey(); | |||
settingsByUuid.put(componentUuid, | |||
Setting.createFromDto(propertyDto, getPropertySets(propertyKey, propertySets, componentId), definitions.get(propertyKey))); | |||
} | |||
return settingsByUuid; | |||
} | |||
private Set<String> getPropertySetKeys(List<PropertyDto> properties) { | |||
return properties.stream() | |||
.filter(propertyDto -> definitions.get(propertyDto.getKey()) != null) | |||
.filter(propertyDto -> definitions.get(propertyDto.getKey()).type().equals(PROPERTY_SET)) | |||
.flatMap(propertyDto -> extractPropertySetKeys(propertyDto, definitions.get(propertyDto.getKey())).stream()) | |||
.collect(Collectors.toSet()); | |||
} | |||
private static List<PropertyDto> getPropertySets(String propertyKey, List<PropertyDto> propertySets, @Nullable Long componentId) { | |||
return propertySets.stream() | |||
.filter(propertyDto -> Objects.equals(propertyDto.getResourceId(), componentId)) | |||
.filter(propertyDto -> propertyDto.getKey().startsWith(propertyKey + ".")) | |||
.collect(Collectors.toList()); | |||
} | |||
} |
@@ -30,7 +30,6 @@ public class SettingsWsModule extends Module { | |||
SettingsWsSupport.class, | |||
ListDefinitionsAction.class, | |||
ValuesAction.class, | |||
SettingsFinder.class, | |||
ResetAction.class, | |||
EncryptAction.class, | |||
GenerateSecretKeyAction.class, |
@@ -20,7 +20,6 @@ | |||
package org.sonar.server.setting.ws; | |||
import java.util.Optional; | |||
import java.util.function.Predicate; | |||
import java.util.stream.Collector; | |||
import java.util.stream.Collectors; | |||
import javax.annotation.Nullable; | |||
@@ -70,14 +69,6 @@ public class SettingsWsSupport { | |||
}); | |||
} | |||
Predicate<Setting> isSettingVisible(Optional<ComponentDto> component) { | |||
return setting -> isVisible(setting.getKey(), setting.getDefinition(), component); | |||
} | |||
Predicate<PropertyDefinition> isDefinitionVisible(Optional<ComponentDto> component) { | |||
return propertyDefinition -> isVisible(propertyDefinition.key(), propertyDefinition, component); | |||
} | |||
boolean isVisible(String key, @Nullable PropertyDefinition definition, Optional<ComponentDto> component) { | |||
return hasPermission(OrganizationPermission.SCAN, SCAN_EXECUTION, component) || (verifySecuredSetting(key, definition, component) && (verifyLicenseSetting(key, definition))); | |||
} |
@@ -21,6 +21,9 @@ package org.sonar.server.setting.ws; | |||
import com.google.common.base.Splitter; | |||
import com.google.common.collect.ImmutableSet; | |||
import com.google.common.collect.Multimap; | |||
import com.google.common.collect.Ordering; | |||
import com.google.common.collect.TreeMultimap; | |||
import java.util.ArrayList; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
@@ -38,10 +41,12 @@ import org.sonar.api.server.ws.Change; | |||
import org.sonar.api.server.ws.Request; | |||
import org.sonar.api.server.ws.Response; | |||
import org.sonar.api.server.ws.WebService; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.permission.OrganizationPermission; | |||
import org.sonar.db.property.PropertyDto; | |||
import org.sonar.server.component.ComponentFinder; | |||
import org.sonar.server.user.UserSession; | |||
import org.sonarqube.ws.Settings; | |||
@@ -55,6 +60,7 @@ import static org.sonar.api.CoreProperties.SERVER_STARTTIME; | |||
import static org.sonar.api.PropertyType.PROPERTY_SET; | |||
import static org.sonar.api.web.UserRole.USER; | |||
import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION; | |||
import static org.sonar.server.setting.ws.PropertySetExtractor.extractPropertySetKeys; | |||
import static org.sonar.server.setting.ws.SettingsWsParameters.PARAM_BRANCH; | |||
import static org.sonar.server.setting.ws.SettingsWsParameters.PARAM_COMPONENT; | |||
import static org.sonar.server.setting.ws.SettingsWsParameters.PARAM_KEYS; | |||
@@ -67,22 +73,21 @@ public class ValuesAction implements SettingsWsAction { | |||
private static final Splitter COMMA_SPLITTER = Splitter.on(","); | |||
private static final String COMMA_ENCODED_VALUE = "%2C"; | |||
private static final Splitter DOT_SPLITTER = Splitter.on(".").omitEmptyStrings(); | |||
private static final Set<String> SERVER_SETTING_KEYS = ImmutableSet.of(SERVER_STARTTIME, SERVER_ID); | |||
private final DbClient dbClient; | |||
private final ComponentFinder componentFinder; | |||
private final UserSession userSession; | |||
private final PropertyDefinitions propertyDefinitions; | |||
private final SettingsFinder settingsFinder; | |||
private final SettingsWsSupport settingsWsSupport; | |||
public ValuesAction(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, PropertyDefinitions propertyDefinitions, SettingsFinder settingsFinder, | |||
public ValuesAction(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, PropertyDefinitions propertyDefinitions, | |||
SettingsWsSupport settingsWsSupport) { | |||
this.dbClient = dbClient; | |||
this.componentFinder = componentFinder; | |||
this.userSession = userSession; | |||
this.propertyDefinitions = propertyDefinitions; | |||
this.settingsFinder = settingsFinder; | |||
this.settingsWsSupport = settingsWsSupport; | |||
} | |||
@@ -94,12 +99,12 @@ public class ValuesAction implements SettingsWsAction { | |||
"The settings from conf/sonar.properties are excluded from results.<br>" + | |||
"Requires 'Browse' or 'Execute Analysis' permission when a component is specified.<br/>" + | |||
"To access licensed settings, authentication is required<br/>" + | |||
"To access secured settings, one of the following permissions is required: " + | |||
"<ul>" + | |||
"<li>'Execute Analysis'</li>" + | |||
"<li>'Administer System'</li>" + | |||
"<li>'Administer' rights on the specified component</li>" + | |||
"</ul>") | |||
"To access secured settings, one of the following permissions is required: " + | |||
"<ul>" + | |||
"<li>'Execute Analysis'</li>" + | |||
"<li>'Administer System'</li>" + | |||
"<li>'Administer' rights on the specified component</li>" + | |||
"</ul>") | |||
.setResponseExample(getClass().getResource("values-example.json")) | |||
.setSince("6.3") | |||
.setChangelog(new Change("7.1", "The settings from conf/sonar.properties are excluded from results.")) | |||
@@ -121,32 +126,26 @@ public class ValuesAction implements SettingsWsAction { | |||
private ValuesWsResponse doHandle(Request request) { | |||
try (DbSession dbSession = dbClient.openSession(true)) { | |||
ValuesRequest valuesRequest = toWsRequest(request); | |||
ValuesRequest valuesRequest = ValuesRequest.from(request); | |||
Optional<ComponentDto> component = loadComponent(dbSession, valuesRequest); | |||
Set<String> keys = loadKeys(valuesRequest); | |||
keys.forEach(SettingsWsSupport::validateKey); | |||
Map<String, String> keysToDisplayMap = getKeysToDisplayMap(keys); | |||
List<Setting> settings = loadSettings(dbSession, component, keysToDisplayMap.keySet()); | |||
return new ValuesResponseBuilder(settings, component, keysToDisplayMap).build(); | |||
} | |||
} | |||
private static ValuesRequest toWsRequest(Request request) { | |||
ValuesRequest result = new ValuesRequest() | |||
.setComponent(request.param(PARAM_COMPONENT)) | |||
.setBranch(request.param(PARAM_BRANCH)) | |||
.setPullRequest(request.param(PARAM_PULL_REQUEST)); | |||
if (request.hasParam(PARAM_KEYS)) { | |||
result.setKeys(request.paramAsStrings(PARAM_KEYS)); | |||
} | |||
return result; | |||
} | |||
private Set<String> loadKeys(ValuesRequest valuesRequest) { | |||
List<String> keys = valuesRequest.getKeys(); | |||
return keys == null || keys.isEmpty() ? concat(propertyDefinitions.getAll().stream().map(PropertyDefinition::key), | |||
SERVER_SETTING_KEYS.stream()).collect(Collectors.toSet()) : ImmutableSet.copyOf(keys); | |||
Set<String> result; | |||
if (keys == null || keys.isEmpty()) { | |||
result = concat(propertyDefinitions.getAll().stream().map(PropertyDefinition::key), SERVER_SETTING_KEYS.stream()).collect(Collectors.toSet()); | |||
} else { | |||
result = ImmutableSet.copyOf(keys); | |||
} | |||
result.forEach(SettingsWsSupport::validateKey); | |||
return result; | |||
} | |||
private Optional<ComponentDto> loadComponent(DbSession dbSession, ValuesRequest valuesRequest) { | |||
@@ -166,19 +165,19 @@ public class ValuesAction implements SettingsWsAction { | |||
private List<Setting> loadSettings(DbSession dbSession, Optional<ComponentDto> component, Set<String> keys) { | |||
// List of settings must be kept in the following orders : default -> global -> component -> branch | |||
List<Setting> settings = new ArrayList<>(); | |||
settings.addAll(loadDefaultSettings(keys)); | |||
settings.addAll(settingsFinder.loadGlobalSettings(dbSession, keys)); | |||
settings.addAll(loadDefaultValues(keys)); | |||
settings.addAll(loadGlobalSettings(dbSession, keys)); | |||
if (component.isPresent() && component.get().getBranch() != null && component.get().getMainBranchProjectUuid() != null) { | |||
ComponentDto project = dbClient.componentDao().selectOrFailByUuid(dbSession, component.get().getMainBranchProjectUuid()); | |||
settings.addAll(settingsFinder.loadComponentSettings(dbSession, keys, project).values()); | |||
settings.addAll(loadComponentSettings(dbSession, keys, project).values()); | |||
} | |||
component.ifPresent(componentDto -> settings.addAll(settingsFinder.loadComponentSettings(dbSession, keys, componentDto).values())); | |||
component.ifPresent(componentDto -> settings.addAll(loadComponentSettings(dbSession, keys, componentDto).values())); | |||
return settings.stream() | |||
.filter(settingsWsSupport.isSettingVisible(component)) | |||
.filter(s -> settingsWsSupport.isVisible(s.getKey(), s.getDefinition(), component)) | |||
.collect(Collectors.toList()); | |||
} | |||
private List<Setting> loadDefaultSettings(Set<String> keys) { | |||
private List<Setting> loadDefaultValues(Set<String> keys) { | |||
return propertyDefinitions.getAll().stream() | |||
.filter(definition -> keys.contains(definition.key())) | |||
.filter(defaultProperty -> !isEmpty(defaultProperty.defaultValue())) | |||
@@ -194,6 +193,51 @@ public class ValuesAction implements SettingsWsAction { | |||
})); | |||
} | |||
private List<Setting> loadGlobalSettings(DbSession dbSession, Set<String> keys) { | |||
List<PropertyDto> properties = dbClient.propertiesDao().selectGlobalPropertiesByKeys(dbSession, keys); | |||
List<PropertyDto> propertySets = dbClient.propertiesDao().selectGlobalPropertiesByKeys(dbSession, getPropertySetKeys(properties)); | |||
return properties.stream() | |||
.map(property -> Setting.createFromDto(property, getPropertySets(property.getKey(), propertySets, null), propertyDefinitions.get(property.getKey()))) | |||
.collect(MoreCollectors.toList(properties.size())); | |||
} | |||
/** | |||
* Return list of settings by component uuid, sorted from project to lowest module | |||
*/ | |||
private Multimap<String, Setting> loadComponentSettings(DbSession dbSession, Set<String> keys, ComponentDto component) { | |||
List<String> componentUuids = DOT_SPLITTER.splitToList(component.moduleUuidPath()); | |||
List<ComponentDto> componentDtos = dbClient.componentDao().selectByUuids(dbSession, componentUuids); | |||
Set<Long> componentIds = componentDtos.stream().map(ComponentDto::getId).collect(Collectors.toSet()); | |||
Map<Long, String> uuidsById = componentDtos.stream().collect(Collectors.toMap(ComponentDto::getId, ComponentDto::uuid)); | |||
List<PropertyDto> properties = dbClient.propertiesDao().selectPropertiesByKeysAndComponentIds(dbSession, keys, componentIds); | |||
List<PropertyDto> propertySets = dbClient.propertiesDao().selectPropertiesByKeysAndComponentIds(dbSession, getPropertySetKeys(properties), componentIds); | |||
Multimap<String, Setting> settingsByUuid = TreeMultimap.create(Ordering.explicit(componentUuids), Ordering.arbitrary()); | |||
for (PropertyDto propertyDto : properties) { | |||
Long componentId = propertyDto.getResourceId(); | |||
String componentUuid = uuidsById.get(componentId); | |||
String propertyKey = propertyDto.getKey(); | |||
settingsByUuid.put(componentUuid, | |||
Setting.createFromDto(propertyDto, getPropertySets(propertyKey, propertySets, componentId), propertyDefinitions.get(propertyKey))); | |||
} | |||
return settingsByUuid; | |||
} | |||
private Set<String> getPropertySetKeys(List<PropertyDto> properties) { | |||
return properties.stream() | |||
.filter(propertyDto -> propertyDefinitions.get(propertyDto.getKey()) != null) | |||
.filter(propertyDto -> propertyDefinitions.get(propertyDto.getKey()).type().equals(PROPERTY_SET)) | |||
.flatMap(propertyDto -> extractPropertySetKeys(propertyDto, propertyDefinitions.get(propertyDto.getKey())).stream()) | |||
.collect(Collectors.toSet()); | |||
} | |||
private static List<PropertyDto> getPropertySets(String propertyKey, List<PropertyDto> propertySets, @Nullable Long componentId) { | |||
return propertySets.stream() | |||
.filter(propertyDto -> Objects.equals(propertyDto.getResourceId(), componentId)) | |||
.filter(propertyDto -> propertyDto.getKey().startsWith(propertyKey + ".")) | |||
.collect(Collectors.toList()); | |||
} | |||
private class ValuesResponseBuilder { | |||
private final List<Setting> settings; | |||
private final Optional<ComponentDto> requestedComponent; | |||
@@ -301,7 +345,6 @@ public class ValuesAction implements SettingsWsAction { | |||
} | |||
private static class ValuesRequest { | |||
private String branch; | |||
private String pullRequest; | |||
private String component; | |||
@@ -346,5 +389,17 @@ public class ValuesAction implements SettingsWsAction { | |||
public List<String> getKeys() { | |||
return keys; | |||
} | |||
private static ValuesRequest from(Request request) { | |||
ValuesRequest result = new ValuesRequest() | |||
.setComponent(request.param(PARAM_COMPONENT)) | |||
.setBranch(request.param(PARAM_BRANCH)) | |||
.setPullRequest(request.param(PARAM_PULL_REQUEST)); | |||
if (request.hasParam(PARAM_KEYS)) { | |||
result.setKeys(request.paramAsStrings(PARAM_KEYS)); | |||
} | |||
return result; | |||
} | |||
} | |||
} |
@@ -1,207 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2018 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.setting.ws; | |||
import com.google.common.collect.ImmutableMap; | |||
import com.google.common.collect.Multimap; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import java.util.Map; | |||
import javax.annotation.Nullable; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.api.config.PropertyDefinition; | |||
import org.sonar.api.config.PropertyDefinitions; | |||
import org.sonar.api.config.PropertyFieldDefinition; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.component.ComponentDbTester; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.component.ComponentTesting; | |||
import org.sonar.db.property.PropertyDto; | |||
import static com.google.common.collect.Sets.newHashSet; | |||
import static java.util.Arrays.asList; | |||
import static java.util.Collections.singletonList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.guava.api.Assertions.assertThat; | |||
import static org.sonar.api.PropertyType.PROPERTY_SET; | |||
import static org.sonar.db.component.ComponentTesting.newModuleDto; | |||
import static org.sonar.db.property.PropertyTesting.newComponentPropertyDto; | |||
import static org.sonar.db.property.PropertyTesting.newGlobalPropertyDto; | |||
public class SettingsFinderTest { | |||
@Rule | |||
public DbTester db = DbTester.create(System2.INSTANCE); | |||
private DbClient dbClient = db.getDbClient(); | |||
private DbSession dbSession = db.getSession(); | |||
private ComponentDbTester componentDb = new ComponentDbTester(db); | |||
private PropertyDefinitions propertyDefinitions = new PropertyDefinitions(); | |||
private SettingsFinder underTest = new SettingsFinder(dbClient, propertyDefinitions); | |||
@Test | |||
public void return_global_settings() { | |||
PropertyDefinition definition = PropertyDefinition.builder("foo").build(); | |||
addDefinitions(definition); | |||
insertProperties(newGlobalPropertyDto().setKey("foo").setValue("one")); | |||
List<Setting> settings = underTest.loadGlobalSettings(dbSession, newHashSet("foo")); | |||
assertThat(settings).hasSize(1); | |||
assertSetting(settings.get(0), "foo", "one", null, true); | |||
assertThat(underTest.loadGlobalSettings(dbSession, newHashSet("unknown"))).isEmpty(); | |||
} | |||
@Test | |||
public void return_global_setting_even_if_no_definition() { | |||
insertProperties(newGlobalPropertyDto().setKey("foo").setValue("one")); | |||
List<Setting> settings = underTest.loadGlobalSettings(dbSession, newHashSet("foo")); | |||
assertThat(settings).hasSize(1); | |||
assertSetting(settings.get(0), "foo", "one", null, false); | |||
} | |||
@Test | |||
public void return_global_settings_with_property_set() { | |||
addDefinitions(PropertyDefinition.builder("set1") | |||
.type(PROPERTY_SET) | |||
.fields(asList( | |||
PropertyFieldDefinition.build("key").name("Key").build(), | |||
PropertyFieldDefinition.build("size.value").name("Size").build())) | |||
.build(), | |||
PropertyDefinition.builder("another") | |||
.type(PROPERTY_SET) | |||
.fields(singletonList(PropertyFieldDefinition.build("key").name("Key").build())) | |||
.build()); | |||
insertProperties( | |||
newGlobalPropertyDto().setKey("set1").setValue("1,2"), | |||
newGlobalPropertyDto().setKey("set1.1.key").setValue("key1"), | |||
newGlobalPropertyDto().setKey("set1.1.size.value").setValue("size1"), | |||
newGlobalPropertyDto().setKey("set1.2.key").setValue("key2"), | |||
newGlobalPropertyDto().setKey("set2").setValue("1"), | |||
newGlobalPropertyDto().setKey("another.1.key").setValue("key1")); | |||
List<Setting> settings = underTest.loadGlobalSettings(dbSession, newHashSet("set1")); | |||
assertThat(settings).hasSize(1); | |||
assertSetting(settings.get(0), "set1", "1,2", null, true, ImmutableMap.of("key", "key1", "size.value", "size1"), ImmutableMap.of("key", "key2")); | |||
} | |||
@Test | |||
public void return_component_settings() { | |||
ComponentDto project = componentDb.insertComponent(ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization())); | |||
addDefinitions(PropertyDefinition.builder("property").defaultValue("default").build()); | |||
insertProperties(newComponentPropertyDto(project).setKey("property").setValue("one")); | |||
Multimap<String, Setting> result = underTest.loadComponentSettings(dbSession, newHashSet("property"), project); | |||
assertThat(result.values()).hasSize(1); | |||
List<Setting> settings = new ArrayList<>(result.get(project.uuid())); | |||
assertThat(settings).hasSize(1); | |||
assertSetting(settings.get(0), "property", "one", project.getId(), true); | |||
assertThat(underTest.loadComponentSettings(dbSession, newHashSet("unknown"), project)).isEmpty(); | |||
} | |||
@Test | |||
public void return_component_setting_even_if_no_definition() { | |||
ComponentDto project = componentDb.insertComponent(ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization())); | |||
insertProperties(newComponentPropertyDto(project).setKey("property").setValue("one")); | |||
Multimap<String, Setting> settings = underTest.loadComponentSettings(dbSession, newHashSet("property"), project); | |||
assertThat(settings.values()).hasSize(1); | |||
assertSetting(settings.get(project.uuid()).iterator().next(), "property", "one", project.getId(), false); | |||
} | |||
@Test | |||
public void return_component_settings_with_property_set() { | |||
ComponentDto project = componentDb.insertComponent(ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization())); | |||
addDefinitions(PropertyDefinition.builder("set1") | |||
.type(PROPERTY_SET) | |||
.fields(asList( | |||
PropertyFieldDefinition.build("key").name("Key").build(), | |||
PropertyFieldDefinition.build("size").name("Size").build())) | |||
.build(), | |||
PropertyDefinition.builder("another") | |||
.type(PROPERTY_SET) | |||
.fields(singletonList(PropertyFieldDefinition.build("key").name("Key").build())) | |||
.build()); | |||
insertProperties( | |||
newComponentPropertyDto(project).setKey("set1").setValue("1,2"), | |||
newComponentPropertyDto(project).setKey("set1.1.key").setValue("key1"), | |||
newComponentPropertyDto(project).setKey("set1.1.size").setValue("size1"), | |||
newComponentPropertyDto(project).setKey("set1.2.key").setValue("key2"), | |||
newComponentPropertyDto(project).setKey("set2").setValue("1"), | |||
newComponentPropertyDto(project).setKey("another.1.key").setValue("key1")); | |||
Multimap<String, Setting> settings = underTest.loadComponentSettings(dbSession, newHashSet("set1"), project); | |||
assertThat(settings).hasSize(1); | |||
assertSetting(settings.get(project.uuid()).iterator().next(), "set1", "1,2", project.getId(), true, ImmutableMap.of("key", "key1", "size", "size1"), ImmutableMap.of("key", "key2")); | |||
} | |||
@Test | |||
public void return_module_settings() { | |||
ComponentDto project = componentDb.insertComponent(ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization())); | |||
ComponentDto module = componentDb.insertComponent(newModuleDto(project)); | |||
ComponentDto subModule = componentDb.insertComponent(newModuleDto(module)); | |||
ComponentDto anotherProject = componentDb.insertComponent(ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization())); | |||
insertProperties( | |||
newComponentPropertyDto(project).setKey("property").setValue("one"), | |||
newComponentPropertyDto(module).setKey("property").setValue("two"), | |||
newComponentPropertyDto(subModule).setKey("property2").setValue("three"), | |||
newComponentPropertyDto(anotherProject).setKey("property").setValue("another one")); | |||
Multimap<String, Setting> result = underTest.loadComponentSettings(dbSession, newHashSet("property", "property2"), subModule); | |||
assertThat(result).hasSize(3); | |||
assertThat(result.keySet()).containsExactly(project.uuid(), module.uuid(), subModule.uuid()); | |||
assertSetting(result.get(subModule.uuid()).iterator().next(), "property2", "three", subModule.getId(), false); | |||
assertSetting(result.get(module.uuid()).iterator().next(), "property", "two", module.getId(), false); | |||
assertSetting(result.get(project.uuid()).iterator().next(), "property", "one", project.getId(), false); | |||
} | |||
private void assertSetting(Setting setting, String expectedKey, String expectedValue, @Nullable Long expectedComponentId, boolean hasPropertyDefinition, | |||
Map<String, String>... propertySets) { | |||
assertThat(setting.getKey()).isEqualTo(expectedKey); | |||
assertThat(setting.getValue()).isEqualTo(expectedValue); | |||
assertThat(setting.getComponentId()).isEqualTo(expectedComponentId); | |||
if (hasPropertyDefinition) { | |||
assertThat(setting.getDefinition()).isEqualTo(propertyDefinitions.get(expectedKey)); | |||
} else { | |||
assertThat(setting.getDefinition()).isNull(); | |||
} | |||
assertThat(setting.getPropertySets()).containsOnly(propertySets); | |||
} | |||
private void insertProperties(PropertyDto... properties) { | |||
for (PropertyDto propertyDto : properties) { | |||
dbClient.propertiesDao().saveProperty(dbSession, propertyDto); | |||
} | |||
dbSession.commit(); | |||
} | |||
private void addDefinitions(PropertyDefinition... definitions) { | |||
propertyDefinitions.addComponents(asList(definitions)); | |||
} | |||
} |
@@ -29,6 +29,6 @@ public class SettingsWsModuleTest { | |||
public void verify_count_of_added_components() { | |||
ComponentContainer container = new ComponentContainer(); | |||
new SettingsWsModule().configure(container); | |||
assertThat(container.size()).isEqualTo(12 + 2); | |||
assertThat(container.size()).isEqualTo(11 + 2); | |||
} | |||
} |
@@ -88,13 +88,12 @@ public class ValuesActionTest { | |||
private PropertyDbTester propertyDb = new PropertyDbTester(db); | |||
private ComponentDbTester componentDb = new ComponentDbTester(db); | |||
private PropertyDefinitions definitions = new PropertyDefinitions(); | |||
private SettingsFinder settingsFinder = new SettingsFinder(dbClient, definitions); | |||
private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db); | |||
private SettingsWsSupport support = new SettingsWsSupport(defaultOrganizationProvider, userSession); | |||
private ComponentDto project; | |||
private WsActionTester ws = new WsActionTester( | |||
new ValuesAction(dbClient, TestComponentFinder.from(db), userSession, definitions, settingsFinder, support)); | |||
new ValuesAction(dbClient, TestComponentFinder.from(db), userSession, definitions, support)); | |||
@Before | |||
public void setUp() throws Exception { | |||
@@ -287,6 +286,17 @@ public class ValuesActionTest { | |||
assertThat(globalPropertyWithoutDefinitionValue.getInherited()).isFalse(); | |||
} | |||
@Test | |||
public void return_values_of_component_even_if_no_property_definition() { | |||
logInAsProjectUser(); | |||
propertyDb.insertProperties( | |||
newComponentPropertyDto(project).setKey("property").setValue("foo")); | |||
ValuesWsResponse response = executeRequestForComponentProperties(project, "property"); | |||
assertThat(response.getSettingsCount()).isEqualTo(1); | |||
assertSetting(response.getSettings(0), "property", "foo", false); | |||
} | |||
@Test | |||
public void return_empty_when_property_def_exists_but_no_value() { | |||
logIn(); | |||
@@ -483,7 +493,7 @@ public class ValuesActionTest { | |||
} | |||
@Test | |||
public void does_not_returned_secured_and_license_settings_when_not_authenticated() { | |||
public void do_not_return_secured_and_license_settings_when_not_authenticated() { | |||
definitions.addComponents(asList( | |||
PropertyDefinition.builder("foo").build(), | |||
PropertyDefinition.builder("secret.secured").build(), | |||
@@ -501,7 +511,7 @@ public class ValuesActionTest { | |||
} | |||
@Test | |||
public void does_not_returned_secured_and_license_settings_in_property_set_when_not_authenticated() { | |||
public void do_not_return_secured_and_license_settings_in_property_set_when_not_authenticated() { | |||
definitions.addComponent(PropertyDefinition | |||
.builder("foo") | |||
.type(PropertyType.PROPERTY_SET) | |||
@@ -958,5 +968,4 @@ public class ValuesActionTest { | |||
} | |||
} | |||
} | |||
} |