@@ -28,34 +28,27 @@ import org.sonar.api.config.PropertyFieldDefinition; | |||
import org.sonar.api.server.ws.Request; | |||
import org.sonar.api.server.ws.Response; | |||
import org.sonar.api.server.ws.WebService; | |||
import org.sonar.api.web.UserRole; | |||
import org.sonar.core.permission.GlobalPermissions; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.server.component.ComponentFinder; | |||
import org.sonar.server.user.UserSession; | |||
import org.sonarqube.ws.Settings; | |||
import org.sonarqube.ws.Settings.ListDefinitionsWsResponse; | |||
import static org.elasticsearch.common.Strings.isNullOrEmpty; | |||
import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01; | |||
import static org.sonar.server.settings.ws.SettingsWsComponentParameters.PARAM_COMPONENT_ID; | |||
import static org.sonar.server.settings.ws.SettingsWsComponentParameters.PARAM_COMPONENT_KEY; | |||
import static org.sonar.server.settings.ws.SettingsWsComponentParameters.addComponentParameters; | |||
import static org.sonar.server.ws.WsUtils.writeProtobuf; | |||
public class ListDefinitionsAction implements SettingsWsAction { | |||
private static final String PARAM_COMPONENT_ID = "componentId"; | |||
private static final String PARAM_COMPONENT_KEY = "componentKey"; | |||
private final DbClient dbClient; | |||
private final ComponentFinder componentFinder; | |||
private final UserSession userSession; | |||
private final SettingsWsComponentParameters settingsWsComponentParameters; | |||
private final PropertyDefinitions propertyDefinitions; | |||
public ListDefinitionsAction(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, PropertyDefinitions propertyDefinitions) { | |||
public ListDefinitionsAction(DbClient dbClient, SettingsWsComponentParameters settingsWsComponentParameters, PropertyDefinitions propertyDefinitions) { | |||
this.dbClient = dbClient; | |||
this.componentFinder = componentFinder; | |||
this.userSession = userSession; | |||
this.settingsWsComponentParameters = settingsWsComponentParameters; | |||
this.propertyDefinitions = propertyDefinitions; | |||
} | |||
@@ -73,13 +66,7 @@ public class ListDefinitionsAction implements SettingsWsAction { | |||
.setSince("6.1") | |||
.setHandler(this); | |||
action.createParam(PARAM_COMPONENT_ID) | |||
.setDescription("Component id") | |||
.setExampleValue(UUID_EXAMPLE_01); | |||
action.createParam(PARAM_COMPONENT_KEY) | |||
.setDescription("Component key") | |||
.setExampleValue("my_component_key"); | |||
addComponentParameters(action); | |||
} | |||
@Override | |||
@@ -150,15 +137,9 @@ public class ListDefinitionsAction implements SettingsWsAction { | |||
private String getQualifier(Request request) { | |||
DbSession dbSession = dbClient.openSession(false); | |||
try { | |||
if (request.hasParam(PARAM_COMPONENT_ID) || request.hasParam(PARAM_COMPONENT_KEY)) { | |||
ComponentDto component = componentFinder.getByUuidOrKey(dbSession, request.param(PARAM_COMPONENT_ID), request.param(PARAM_COMPONENT_KEY), | |||
ComponentFinder.ParamNames.ID_AND_KEY); | |||
userSession.checkComponentUuidPermission(UserRole.ADMIN, component.uuid()); | |||
return component.qualifier(); | |||
} else { | |||
userSession.checkPermission(GlobalPermissions.SYSTEM_ADMIN); | |||
return null; | |||
} | |||
ComponentDto component = settingsWsComponentParameters.getComponent(dbSession, request); | |||
settingsWsComponentParameters.checkAdminPermission(component); | |||
return component == null ? null : component.qualifier(); | |||
} finally { | |||
dbClient.closeSession(dbSession); | |||
} |
@@ -0,0 +1,76 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2016 SonarSource SA | |||
* mailto:contact 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.settings.ws; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.server.ws.Request; | |||
import org.sonar.api.server.ws.WebService; | |||
import org.sonar.api.web.UserRole; | |||
import org.sonar.core.permission.GlobalPermissions; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.server.component.ComponentFinder; | |||
import org.sonar.server.user.UserSession; | |||
import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01; | |||
import static org.sonar.server.component.ComponentFinder.ParamNames.ID_AND_KEY; | |||
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; | |||
public class SettingsWsComponentParameters { | |||
static final String PARAM_COMPONENT_ID = "componentId"; | |||
static final String PARAM_COMPONENT_KEY = "componentKey"; | |||
private final ComponentFinder componentFinder; | |||
private final UserSession userSession; | |||
public SettingsWsComponentParameters(ComponentFinder componentFinder, UserSession userSession) { | |||
this.componentFinder = componentFinder; | |||
this.userSession = userSession; | |||
} | |||
static void addComponentParameters(WebService.NewAction action) { | |||
action.createParam(PARAM_COMPONENT_ID) | |||
.setDescription("Component id") | |||
.setExampleValue(UUID_EXAMPLE_01); | |||
action.createParam(PARAM_COMPONENT_KEY) | |||
.setDescription("Component key") | |||
.setExampleValue(KEY_PROJECT_EXAMPLE_001); | |||
} | |||
@CheckForNull | |||
ComponentDto getComponent(DbSession dbSession, Request request) { | |||
if (request.hasParam(PARAM_COMPONENT_ID) || request.hasParam(PARAM_COMPONENT_KEY)) { | |||
return componentFinder.getByUuidOrKey(dbSession, request.param(PARAM_COMPONENT_ID), request.param(PARAM_COMPONENT_KEY), ID_AND_KEY); | |||
} | |||
return null; | |||
} | |||
void checkAdminPermission(@Nullable ComponentDto component) { | |||
if (component == null) { | |||
userSession.checkPermission(GlobalPermissions.SYSTEM_ADMIN); | |||
} else { | |||
userSession.checkComponentUuidPermission(UserRole.ADMIN, component.uuid()); | |||
} | |||
} | |||
} |
@@ -27,6 +27,8 @@ public class SettingsWsModule extends Module { | |||
add( | |||
SettingsWs.class, | |||
SetAction.class, | |||
ListDefinitionsAction.class); | |||
SettingsWsComponentParameters.class, | |||
ListDefinitionsAction.class, | |||
ValuesAction.class); | |||
} | |||
} |
@@ -0,0 +1,184 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2016 SonarSource SA | |||
* mailto:contact 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.settings.ws; | |||
import com.google.common.base.Splitter; | |||
import java.util.HashMap; | |||
import java.util.HashSet; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Set; | |||
import java.util.function.Function; | |||
import java.util.stream.Collectors; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.config.PropertyDefinition; | |||
import org.sonar.api.config.PropertyDefinitions; | |||
import org.sonar.api.server.ws.Request; | |||
import org.sonar.api.server.ws.Response; | |||
import org.sonar.api.server.ws.WebService; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.property.PropertyDto; | |||
import org.sonarqube.ws.Settings; | |||
import org.sonarqube.ws.Settings.ValuesWsResponse; | |||
import static org.elasticsearch.common.Strings.isNullOrEmpty; | |||
import static org.sonar.server.settings.ws.SettingsWsComponentParameters.PARAM_COMPONENT_ID; | |||
import static org.sonar.server.settings.ws.SettingsWsComponentParameters.PARAM_COMPONENT_KEY; | |||
import static org.sonar.server.settings.ws.SettingsWsComponentParameters.addComponentParameters; | |||
import static org.sonar.server.ws.WsUtils.writeProtobuf; | |||
public class ValuesAction implements SettingsWsAction { | |||
private static final Splitter MULTI_VALUE_SPLITTER = Splitter.on(","); | |||
static final String PARAM_KEYS = "keys"; | |||
private final DbClient dbClient; | |||
private final SettingsWsComponentParameters settingsWsComponentParameters; | |||
private final PropertyDefinitions propertyDefinitions; | |||
public ValuesAction(DbClient dbClient, SettingsWsComponentParameters settingsWsComponentParameters, PropertyDefinitions propertyDefinitions) { | |||
this.dbClient = dbClient; | |||
this.settingsWsComponentParameters = settingsWsComponentParameters; | |||
this.propertyDefinitions = propertyDefinitions; | |||
} | |||
@Override | |||
public void define(WebService.NewController context) { | |||
WebService.NewAction action = context.createAction("values") | |||
.setDescription(String.format("Returns values of given properties.<br>" + | |||
"If no value have been set for a property, then the default value is returned.<br>" + | |||
"Either '%s' or '%s' could be provided, not both.<br> " + | |||
"Requires one of the following permissions: " + | |||
"<ul>" + | |||
"<li>'Administer System'</li>" + | |||
"<li>'Administer' rights on the specified component</li>" + | |||
"</ul>", PARAM_COMPONENT_ID, PARAM_COMPONENT_KEY)) | |||
.setResponseExample(getClass().getResource("values-example.json")) | |||
.setSince("6.1") | |||
.setHandler(this); | |||
addComponentParameters(action); | |||
action.createParam(PARAM_KEYS) | |||
.setDescription("List of property keys") | |||
.setRequired(true) | |||
.setExampleValue("sonar.technicalDebt.hoursInDay,sonar.dbcleaner.cleanDirectory"); | |||
} | |||
@Override | |||
public void handle(Request request, Response response) throws Exception { | |||
writeProtobuf(doHandle(request), request, response); | |||
} | |||
private ValuesWsResponse doHandle(Request request) { | |||
DbSession dbSession = dbClient.openSession(true); | |||
try { | |||
ComponentDto component = settingsWsComponentParameters.getComponent(dbSession, request); | |||
settingsWsComponentParameters.checkAdminPermission(component); | |||
Set<String> keys = new HashSet<>(request.mandatoryParamAsStrings(PARAM_KEYS)); | |||
List<PropertyDefinition> definitions = getDefinitions(keys); | |||
Map<String, PropertyDefinition> definitionsByKey = definitions.stream() | |||
.collect(Collectors.toMap(PropertyDefinition::key, Function.identity())); | |||
ValuesWsResponse.Builder valuesBuilder = ValuesWsResponse.newBuilder(); | |||
new ValuesBuilder(dbSession, valuesBuilder, definitionsByKey, keys, component).build(); | |||
return valuesBuilder.build(); | |||
} finally { | |||
dbClient.closeSession(dbSession); | |||
} | |||
} | |||
private class ValuesBuilder { | |||
private final DbSession dbSession; | |||
private final ValuesWsResponse.Builder valuesWsBuilder; | |||
private final Map<String, PropertyDefinition> definitionsByKey; | |||
private final Set<String> keys; | |||
private final ComponentDto component; | |||
private final Map<String, Settings.Value.Builder> valueBuilderByKey = new HashMap<>(); | |||
ValuesBuilder(DbSession dbSession, ValuesWsResponse.Builder valuesWsBuilder, Map<String, PropertyDefinition> definitionsByKey, | |||
Set<String> keys, @Nullable ComponentDto component) { | |||
this.dbSession = dbSession; | |||
this.valuesWsBuilder = valuesWsBuilder; | |||
this.definitionsByKey = definitionsByKey; | |||
this.keys = keys; | |||
this.component = component; | |||
} | |||
void build() { | |||
processDefinitions(); | |||
processPropertyDtos(dbClient.propertiesDao().selectGlobalPropertiesByKeys(dbSession, keys)); | |||
if (component != null) { | |||
processPropertyDtos(dbClient.propertiesDao().selectComponentPropertiesByKeys(dbSession, keys, component.getId())); | |||
} | |||
valueBuilderByKey.values().forEach(Settings.Value.Builder::build); | |||
} | |||
private void processDefinitions() { | |||
definitionsByKey.values().stream() | |||
.filter(defaultProperty -> !isNullOrEmpty(defaultProperty.defaultValue())) | |||
.forEach(this::processDefaultValue); | |||
} | |||
private void processDefaultValue(PropertyDefinition definition) { | |||
Settings.Value.Builder valueBuilder = valuesWsBuilder.addValuesBuilder() | |||
.setKey(definition.key()) | |||
.setIsDefault(true); | |||
setValue(valueBuilder, definition.defaultValue()); | |||
valueBuilderByKey.put(definition.key(), valueBuilder); | |||
} | |||
private void processPropertyDtos(List<PropertyDto> properties) { | |||
properties.stream() | |||
.filter(propertyDto -> !isNullOrEmpty(propertyDto.getValue())) | |||
.forEach(this::processDtoValue); | |||
} | |||
private void processDtoValue(PropertyDto property) { | |||
Settings.Value.Builder valueBuilder = valueBuilderByKey.get(property.getKey()); | |||
if (valueBuilder == null) { | |||
valueBuilder = valuesWsBuilder.addValuesBuilder().setKey(property.getKey()); | |||
valueBuilderByKey.put(property.getKey(), valueBuilder); | |||
} | |||
valueBuilder.setIsInherited(component != null && property.getResourceId() == null); | |||
valueBuilder.setIsDefault(false); | |||
setValue(valueBuilder, property.getValue()); | |||
} | |||
private void setValue(Settings.Value.Builder valueBuilder, String value) { | |||
PropertyDefinition definition = definitionsByKey.get(valueBuilder.getKey()); | |||
if (definition != null && definition.multiValues()) { | |||
valueBuilder.addAllValues(MULTI_VALUE_SPLITTER.split(value)); | |||
} else { | |||
valueBuilder.setValue(value); | |||
} | |||
} | |||
} | |||
private List<PropertyDefinition> getDefinitions(Set<String> keys) { | |||
return propertyDefinitions.getAll().stream() | |||
.filter(def -> keys.contains(def.key())) | |||
.collect(Collectors.toList()); | |||
} | |||
} |
@@ -0,0 +1,36 @@ | |||
{ | |||
"values": [ | |||
{ | |||
"key": "sonar.test.jira", | |||
"value": "abc", | |||
"isDefault": true | |||
}, | |||
{ | |||
"key": "sonar.autogenerated", | |||
"values": [ | |||
"val1", | |||
"val2", | |||
"val3" | |||
], | |||
"isDefault": false | |||
}, | |||
{ | |||
"key": "sonar.demo", | |||
"setValues": { | |||
"text": { | |||
"values": [ | |||
"foo", | |||
"bar" | |||
] | |||
}, | |||
"boolean": { | |||
"values": [ | |||
"true", | |||
"false" | |||
] | |||
} | |||
}, | |||
"isDefault": false | |||
} | |||
] | |||
} |
@@ -55,6 +55,7 @@ import static org.sonar.api.web.UserRole.USER; | |||
import static org.sonar.core.permission.GlobalPermissions.DASHBOARD_SHARING; | |||
import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN; | |||
import static org.sonar.db.component.ComponentTesting.newProjectDto; | |||
import static org.sonarqube.ws.MediaTypes.JSON; | |||
import static org.sonarqube.ws.Settings.Type.BOOLEAN; | |||
import static org.sonarqube.ws.Settings.Type.PROPERTY_SET; | |||
import static org.sonarqube.ws.Settings.Type.SINGLE_SELECT_LIST; | |||
@@ -78,12 +79,13 @@ public class ListDefinitionsActionTest { | |||
ComponentDto project; | |||
PropertyDefinitions propertyDefinitions = new PropertyDefinitions(); | |||
SettingsWsComponentParameters settingsWsComponentParameters = new SettingsWsComponentParameters(new ComponentFinder(dbClient), userSession); | |||
WsActionTester ws = new WsActionTester(new ListDefinitionsAction(dbClient, new ComponentFinder(dbClient), userSession, propertyDefinitions)); | |||
WsActionTester ws = new WsActionTester(new ListDefinitionsAction(dbClient, settingsWsComponentParameters, propertyDefinitions)); | |||
@Before | |||
public void setUp() throws Exception { | |||
project = insertProject(); | |||
project = componentDb.insertComponent(newProjectDto()); | |||
} | |||
@Test | |||
@@ -369,14 +371,10 @@ public class ListDefinitionsActionTest { | |||
.build()) | |||
.build())); | |||
String result = ws.newRequest().setMediaType(MediaTypes.JSON).execute().getInput(); | |||
String result = ws.newRequest().setMediaType(JSON).execute().getInput(); | |||
JsonAssert.assertJson(ws.getDef().responseExampleAsString()).isSimilarTo(result); | |||
} | |||
private ComponentDto insertProject() { | |||
return componentDb.insertComponent(newProjectDto()); | |||
} | |||
private ListDefinitionsWsResponse newRequest() { | |||
return newRequest(null, null); | |||
} |
@@ -48,8 +48,8 @@ import org.sonar.server.ws.WsActionTester; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.core.groups.Tuple.tuple; | |||
import static org.sonar.db.property.PropertyTesting.newGlobalProperty; | |||
import static org.sonar.db.property.PropertyTesting.newProjectProperty; | |||
import static org.sonar.db.property.PropertyTesting.newComponentPropertyDto; | |||
import static org.sonar.db.property.PropertyTesting.newGlobalPropertyDto; | |||
public class SetActionTest { | |||
@@ -90,7 +90,7 @@ public class SetActionTest { | |||
@Test | |||
public void update_existing_global_property() { | |||
propertyDb.insertProperty(newGlobalProperty("my.key", "my value")); | |||
propertyDb.insertProperty(newGlobalPropertyDto("my.key", "my value")); | |||
assertGlobalProperty("my.key", "my value"); | |||
callForGlobalProperty("my.key", "my new value"); | |||
@@ -100,7 +100,7 @@ public class SetActionTest { | |||
@Test | |||
public void persist_new_project_property() { | |||
propertyDb.insertProperty(newGlobalProperty("my.key", "my global value")); | |||
propertyDb.insertProperty(newGlobalPropertyDto("my.key", "my global value")); | |||
ComponentDto project = componentDb.insertProject(); | |||
callForProjectPropertyByUuid("my.key", "my project value", project.uuid()); | |||
@@ -121,9 +121,9 @@ public class SetActionTest { | |||
@Test | |||
public void update_existing_project_property() { | |||
propertyDb.insertProperty(newGlobalProperty("my.key", "my global value")); | |||
propertyDb.insertProperty(newGlobalPropertyDto("my.key", "my global value")); | |||
ComponentDto project = componentDb.insertProject(); | |||
propertyDb.insertProperty(newProjectProperty("my.key", "my project value", project.getId())); | |||
propertyDb.insertProperty(newComponentPropertyDto("my.key", "my project value", project)); | |||
assertProjectProperty("my.key", "my project value", project.getId()); | |||
callForProjectPropertyByKey("my.key", "my new project value", project.key()); | |||
@@ -133,8 +133,8 @@ public class SetActionTest { | |||
@Test | |||
public void user_property_is_not_updated() { | |||
propertyDb.insertProperty(newGlobalProperty("my.key", "my user value").setUserId(42L)); | |||
propertyDb.insertProperty(newGlobalProperty("my.key", "my global value")); | |||
propertyDb.insertProperty(newGlobalPropertyDto("my.key", "my user value").setUserId(42L)); | |||
propertyDb.insertProperty(newGlobalPropertyDto("my.key", "my global value")); | |||
callForGlobalProperty("my.key", "my new global value"); | |||
@@ -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(3 + 2); | |||
assertThat(container.size()).isEqualTo(5 + 2); | |||
} | |||
} |
@@ -0,0 +1,342 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2016 SonarSource SA | |||
* mailto:contact 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.settings.ws; | |||
import com.google.common.base.Joiner; | |||
import java.io.IOException; | |||
import javax.annotation.Nullable; | |||
import org.junit.Before; | |||
import org.junit.Ignore; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.sonar.api.config.PropertyDefinition; | |||
import org.sonar.api.config.PropertyDefinitions; | |||
import org.sonar.api.server.ws.WebService; | |||
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.property.PropertyDto; | |||
import org.sonar.server.component.ComponentFinder; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.tester.UserSessionRule; | |||
import org.sonar.server.ws.TestRequest; | |||
import org.sonar.server.ws.WsActionTester; | |||
import org.sonar.test.JsonAssert; | |||
import org.sonarqube.ws.MediaTypes; | |||
import org.sonarqube.ws.Settings; | |||
import org.sonarqube.ws.Settings.ValuesWsResponse; | |||
import static org.assertj.core.api.Java6Assertions.assertThat; | |||
import static org.sonar.api.web.UserRole.ADMIN; | |||
import static org.sonar.api.web.UserRole.USER; | |||
import static org.sonar.core.permission.GlobalPermissions.DASHBOARD_SHARING; | |||
import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN; | |||
import static org.sonar.db.component.ComponentTesting.newProjectDto; | |||
import static org.sonar.db.property.PropertyTesting.newComponentPropertyDto; | |||
import static org.sonar.db.property.PropertyTesting.newGlobalPropertyDto; | |||
import static org.sonarqube.ws.MediaTypes.JSON; | |||
public class ValuesActionTest { | |||
static Joiner COMMA_JOINER = Joiner.on(","); | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
@Rule | |||
public UserSessionRule userSession = UserSessionRule.standalone(); | |||
@Rule | |||
public DbTester db = DbTester.create(System2.INSTANCE); | |||
DbClient dbClient = db.getDbClient(); | |||
DbSession dbSession = db.getSession(); | |||
ComponentDbTester componentDb = new ComponentDbTester(db); | |||
SettingsWsComponentParameters settingsWsComponentParameters = new SettingsWsComponentParameters(new ComponentFinder(dbClient), userSession); | |||
PropertyDefinitions propertyDefinitions = new PropertyDefinitions(); | |||
ComponentDto project; | |||
WsActionTester ws = new WsActionTester(new ValuesAction(dbClient, settingsWsComponentParameters, propertyDefinitions)); | |||
@Before | |||
public void setUp() throws Exception { | |||
project = componentDb.insertComponent(newProjectDto()); | |||
} | |||
@Test | |||
public void return_simple_value() throws Exception { | |||
setUserAsSystemAdmin(); | |||
propertyDefinitions.addComponent(PropertyDefinition | |||
.builder("foo") | |||
.build()); | |||
insertProperties(newGlobalPropertyDto().setKey("foo").setValue("one")); | |||
ValuesWsResponse result = newRequestForGlobalProperties("foo"); | |||
assertThat(result.getValuesList()).hasSize(1); | |||
Settings.Value value = result.getValues(0); | |||
assertThat(value.getKey()).isEqualTo("foo"); | |||
assertThat(value.getValue()).isEqualTo("one"); | |||
assertThat(value.getValuesCount()).isZero(); | |||
assertThat(value.getSetValues()).isEmpty(); | |||
assertThat(value.getIsDefault()).isFalse(); | |||
} | |||
@Test | |||
public void return_multi_values() throws Exception { | |||
setUserAsSystemAdmin(); | |||
// Property never defined, default value is returned | |||
propertyDefinitions.addComponent(PropertyDefinition.builder("default") | |||
.multiValues(true) | |||
.defaultValue("one,two") | |||
.build()); | |||
// Property defined at global level | |||
propertyDefinitions.addComponent(PropertyDefinition.builder("global") | |||
.multiValues(true) | |||
.build()); | |||
insertProperties(newGlobalPropertyDto().setKey("global").setValue("three,four")); | |||
ValuesWsResponse result = newRequestForGlobalProperties("default", "global"); | |||
assertThat(result.getValuesList()).hasSize(2); | |||
Settings.Value foo = result.getValues(0); | |||
assertThat(foo.getKey()).isEqualTo("default"); | |||
assertThat(foo.hasValue()).isFalse(); | |||
assertThat(foo.getValuesList()).containsOnly("one", "two"); | |||
assertThat(foo.getSetValues()).isEmpty(); | |||
Settings.Value bar = result.getValues(1); | |||
assertThat(bar.getKey()).isEqualTo("global"); | |||
assertThat(bar.hasValue()).isFalse(); | |||
assertThat(bar.getValuesList()).containsOnly("three", "four"); | |||
assertThat(bar.getSetValues()).isEmpty(); | |||
} | |||
@Test | |||
public void return_default_values() throws Exception { | |||
setUserAsSystemAdmin(); | |||
propertyDefinitions.addComponent(PropertyDefinition | |||
.builder("foo") | |||
.defaultValue("default") | |||
.build()); | |||
ValuesWsResponse result = newRequestForGlobalProperties("foo"); | |||
assertThat(result.getValuesList()).hasSize(1); | |||
Settings.Value value = result.getValues(0); | |||
assertThat(value.getKey()).isEqualTo("foo"); | |||
assertThat(value.getValue()).isEqualTo("default"); | |||
assertThat(value.getIsDefault()).isTrue(); | |||
assertThat(value.getIsInherited()).isFalse(); | |||
} | |||
@Test | |||
public void return_global_values() throws Exception { | |||
setUserAsSystemAdmin(); | |||
propertyDefinitions.addComponent(PropertyDefinition.builder("property").defaultValue("default").build()); | |||
insertProperties( | |||
// The property is overriding default value | |||
newGlobalPropertyDto().setKey("property").setValue("one")); | |||
ValuesWsResponse result = newRequestForGlobalProperties("property"); | |||
assertThat(result.getValuesList()).hasSize(1); | |||
Settings.Value globalPropertyValue = result.getValues(0); | |||
assertThat(globalPropertyValue.getKey()).isEqualTo("property"); | |||
assertThat(globalPropertyValue.getValue()).isEqualTo("one"); | |||
assertThat(globalPropertyValue.getIsDefault()).isFalse(); | |||
assertThat(globalPropertyValue.getIsInherited()).isFalse(); | |||
} | |||
@Test | |||
public void return_component_values() throws Exception { | |||
setUserAsSystemAdmin(); | |||
propertyDefinitions.addComponent(PropertyDefinition.builder("property").defaultValue("default").build()); | |||
insertProperties( | |||
newGlobalPropertyDto().setKey("property").setValue("one"), | |||
// The property is overriding global value | |||
newComponentPropertyDto(project).setKey("property").setValue("two")); | |||
ValuesWsResponse result = newRequestForProjectProperties("property"); | |||
assertThat(result.getValuesList()).hasSize(1); | |||
Settings.Value globalPropertyValue = result.getValues(0); | |||
assertThat(globalPropertyValue.getKey()).isEqualTo("property"); | |||
assertThat(globalPropertyValue.getValue()).isEqualTo("two"); | |||
assertThat(globalPropertyValue.getIsDefault()).isFalse(); | |||
assertThat(globalPropertyValue.getIsInherited()).isFalse(); | |||
} | |||
@Test | |||
public void return_is_inherited_to_true_when_property_is_defined_only_at_global_level() throws Exception { | |||
setUserAsSystemAdmin(); | |||
propertyDefinitions.addComponent(PropertyDefinition.builder("property").defaultValue("default").build()); | |||
// The property is not defined on project | |||
insertProperties(newGlobalPropertyDto().setKey("property").setValue("one")); | |||
ValuesWsResponse result = newRequestForProjectProperties("property"); | |||
assertThat(result.getValuesList()).hasSize(1); | |||
Settings.Value globalPropertyValue = result.getValues(0); | |||
assertThat(globalPropertyValue.getKey()).isEqualTo("property"); | |||
assertThat(globalPropertyValue.getValue()).isEqualTo("one"); | |||
assertThat(globalPropertyValue.getIsDefault()).isFalse(); | |||
assertThat(globalPropertyValue.getIsInherited()).isTrue(); | |||
} | |||
@Test | |||
public void return_values_even_if_no_property_definition() throws Exception { | |||
setUserAsSystemAdmin(); | |||
insertProperties(newGlobalPropertyDto().setKey("globalPropertyWithoutDefinition").setValue("value")); | |||
ValuesWsResponse result = newRequestForGlobalProperties("globalPropertyWithoutDefinition"); | |||
Settings.Value globalPropertyWithoutDefinitionValue = result.getValues(0); | |||
assertThat(globalPropertyWithoutDefinitionValue.getKey()).isEqualTo("globalPropertyWithoutDefinition"); | |||
assertThat(globalPropertyWithoutDefinitionValue.getValue()).isEqualTo("value"); | |||
assertThat(globalPropertyWithoutDefinitionValue.getIsDefault()).isFalse(); | |||
} | |||
@Test | |||
public void return_empty_when_property_def_exists_but_no_value() throws Exception { | |||
setUserAsSystemAdmin(); | |||
propertyDefinitions.addComponent(PropertyDefinition | |||
.builder("foo") | |||
.build()); | |||
insertProperties(newGlobalPropertyDto().setKey("bar").setValue("")); | |||
ValuesWsResponse result = newRequestForGlobalProperties("foo", "bar"); | |||
assertThat(result.getValuesList()).isEmpty(); | |||
} | |||
@Test | |||
public void does_return_nothing_when_unknown_keys() throws Exception { | |||
setUserAsSystemAdmin(); | |||
propertyDefinitions.addComponent(PropertyDefinition | |||
.builder("foo") | |||
.defaultValue("default") | |||
.build()); | |||
insertProperties(newGlobalPropertyDto().setKey("bar").setValue("")); | |||
ValuesWsResponse result = newRequestForGlobalProperties("unknown"); | |||
assertThat(result.getValuesList()).isEmpty(); | |||
} | |||
@Test | |||
@Ignore | |||
public void test_example_json_response() { | |||
setUserAsSystemAdmin(); | |||
propertyDefinitions.addComponent(PropertyDefinition | |||
.builder("sonar.test.jira") | |||
.defaultValue("abc") | |||
.build()); | |||
String result = ws.newRequest() | |||
.setParam("keys", "sonar.test.jira,sonar.autogenerated,sonar.demo") | |||
.setMediaType(JSON) | |||
.execute() | |||
.getInput(); | |||
JsonAssert.assertJson(ws.getDef().responseExampleAsString()).isSimilarTo(result); | |||
} | |||
@Test | |||
public void fail_when_id_and_key_are_set() throws Exception { | |||
setUserAsProjectAdmin(); | |||
expectedException.expect(IllegalArgumentException.class); | |||
newRequest(project.uuid(), project.key()); | |||
} | |||
@Test | |||
public void fail_when_not_system_admin() throws Exception { | |||
userSession.login("not-admin").setGlobalPermissions(DASHBOARD_SHARING); | |||
propertyDefinitions.addComponent(PropertyDefinition.builder("foo").build()); | |||
expectedException.expect(ForbiddenException.class); | |||
newRequestForGlobalProperties(); | |||
} | |||
@Test | |||
public void fail_when_not_project_admin() throws Exception { | |||
userSession.login("project-admin").addProjectUuidPermissions(USER, project.uuid()); | |||
propertyDefinitions.addComponent(PropertyDefinition.builder("foo").build()); | |||
expectedException.expect(ForbiddenException.class); | |||
newRequest(project.uuid(), null); | |||
} | |||
@Test | |||
public void test_ws_definition() { | |||
WebService.Action action = ws.getDef(); | |||
assertThat(action).isNotNull(); | |||
assertThat(action.isInternal()).isFalse(); | |||
assertThat(action.isPost()).isFalse(); | |||
assertThat(action.responseExampleAsString()).isNotEmpty(); | |||
assertThat(action.params()).hasSize(3); | |||
} | |||
private ValuesWsResponse newRequestForProjectProperties(String... keys) { | |||
return newRequest(project.uuid(), null, keys); | |||
} | |||
private ValuesWsResponse newRequestForGlobalProperties(String... keys) { | |||
return newRequest(null, null, keys); | |||
} | |||
private ValuesWsResponse newRequest(@Nullable String id, @Nullable String key, String... keys) { | |||
TestRequest request = ws.newRequest() | |||
.setMediaType(MediaTypes.PROTOBUF) | |||
.setParam("keys", COMMA_JOINER.join(keys)); | |||
if (id != null) { | |||
request.setParam("componentId", id); | |||
} | |||
if (key != null) { | |||
request.setParam("componentKey", key); | |||
} | |||
try { | |||
return ValuesWsResponse.parseFrom(request.execute().getInputStream()); | |||
} catch (IOException e) { | |||
throw new IllegalStateException(e); | |||
} | |||
} | |||
private void setUserAsSystemAdmin() { | |||
userSession.login("admin").setGlobalPermissions(SYSTEM_ADMIN); | |||
} | |||
private void setUserAsProjectAdmin() { | |||
userSession.login("project-admin").addProjectUuidPermissions(ADMIN, project.uuid()); | |||
} | |||
private void insertProperties(PropertyDto... properties) { | |||
for (PropertyDto propertyDto : properties) { | |||
dbClient.propertiesDao().insertProperty(dbSession, propertyDto); | |||
} | |||
dbSession.commit(); | |||
} | |||
} |
@@ -28,6 +28,7 @@ import java.sql.SQLException; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Set; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
import org.apache.commons.dbutils.DbUtils; | |||
@@ -38,6 +39,8 @@ import org.sonar.db.DatabaseUtils; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.MyBatis; | |||
import static org.sonar.db.DatabaseUtils.executeLargeInputs; | |||
public class PropertiesDao implements Dao { | |||
private static final String NOTIFICATION_PREFIX = "notification."; | |||
@@ -161,6 +164,18 @@ public class PropertiesDao implements Dao { | |||
return session.getMapper(PropertiesMapper.class).selectByQuery(query); | |||
} | |||
public List<PropertyDto> selectGlobalPropertiesByKeys(DbSession session, Set<String> keys) { | |||
return selectByKeys(session, keys, null); | |||
} | |||
public List<PropertyDto> selectComponentPropertiesByKeys(DbSession session, Set<String> keys, long componentId) { | |||
return selectByKeys(session, keys, componentId); | |||
} | |||
private List<PropertyDto> selectByKeys(DbSession session, Set<String> keys, @Nullable Long componentId) { | |||
return executeLargeInputs(keys, propertyKeys -> session.getMapper(PropertiesMapper.class).selectByKeys(propertyKeys, componentId)); | |||
} | |||
public void insertProperty(DbSession session, PropertyDto property) { | |||
PropertiesMapper mapper = session.getMapper(PropertiesMapper.class); | |||
PropertyDto persistedProperty = mapper.selectByKey(property); |
@@ -39,6 +39,8 @@ public interface PropertiesMapper { | |||
PropertyDto selectByKey(PropertyDto key); | |||
List<PropertyDto> selectByKeys(@Param("keys") List<String> keys, @Nullable @Param("componentId") Long componentId); | |||
List<PropertyDto> selectByQuery(@Param("query") PropertyQuery query); | |||
List<PropertyDto> selectDescendantModuleProperties(@Param("moduleUuid") String moduleUuid, @Param(value = "scope") String scope, |
@@ -0,0 +1,98 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2016 SonarSource SA | |||
* mailto:contact 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.db.property; | |||
import javax.annotation.Nullable; | |||
import org.apache.commons.lang.math.RandomUtils; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.user.UserDto; | |||
import static com.google.common.base.Preconditions.checkNotNull; | |||
public class PropertyTesting { | |||
private static int cursor = RandomUtils.nextInt(100); | |||
private PropertyTesting() { | |||
// static methods only | |||
} | |||
public static PropertyDto newGlobalPropertyDto(String key, String value) { | |||
return newPropertyDto(key, value, (Long) null, null); | |||
} | |||
public static PropertyDto newGlobalPropertyDto() { | |||
return newPropertyDto((Long) null, null); | |||
} | |||
public static PropertyDto newComponentPropertyDto(String key, String value, ComponentDto component) { | |||
checkNotNull(component.getId()); | |||
return newPropertyDto(key, value, component.getId(), null); | |||
} | |||
public static PropertyDto newComponentPropertyDto(ComponentDto component) { | |||
checkNotNull(component.getId()); | |||
return newPropertyDto(component.getId(), null); | |||
} | |||
public static PropertyDto newUserPropertyDto(String key, String value, UserDto user) { | |||
checkNotNull(user.getId()); | |||
return newPropertyDto(key, value, null, user.getId()); | |||
} | |||
public static PropertyDto newUserPropertyDto(UserDto user) { | |||
checkNotNull(user.getId()); | |||
return newPropertyDto(null, user.getId()); | |||
} | |||
public static PropertyDto newPropertyDto(String key, String value, ComponentDto component, UserDto user) { | |||
checkNotNull(component.getId()); | |||
checkNotNull(user.getId()); | |||
return newPropertyDto(key, value, component.getId(), user.getId()); | |||
} | |||
public static PropertyDto newPropertyDto(ComponentDto component, UserDto user) { | |||
checkNotNull(component.getId()); | |||
checkNotNull(user.getId()); | |||
return newPropertyDto(component.getId(), user.getId()); | |||
} | |||
private static PropertyDto newPropertyDto(@Nullable Long componentId, @Nullable Long userId) { | |||
String key = String.valueOf(cursor); | |||
cursor++; | |||
String value = String.valueOf(cursor); | |||
cursor++; | |||
return newPropertyDto(key, value, componentId, userId); | |||
} | |||
private static PropertyDto newPropertyDto(String key, String value, @Nullable Long componentId, @Nullable Long userId) { | |||
PropertyDto propertyDto = new PropertyDto() | |||
.setKey(key) | |||
.setValue(value); | |||
if (componentId != null) { | |||
propertyDto.setResourceId(componentId); | |||
} | |||
if (userId != null) { | |||
propertyDto.setUserId(userId); | |||
} | |||
return propertyDto; | |||
} | |||
} |
@@ -81,6 +81,24 @@ | |||
</if> | |||
</select> | |||
<select id="selectByKeys" parameterType="map" resultType="Property"> | |||
SELECT p.id as id, p.prop_key as "key", p.text_value as value, p.resource_id as resourceId, p.user_id as userId | |||
FROM properties p | |||
<where> | |||
AND p.prop_key in | |||
<foreach collection="keys" open="(" close=")" item="key" separator=","> | |||
#{key} | |||
</foreach> | |||
<if test="componentId == null"> | |||
AND p.resource_id is null | |||
</if> | |||
<if test="componentId != null"> | |||
AND p.resource_id=#{componentId} | |||
</if> | |||
AND p.user_id is null | |||
</where> | |||
</select> | |||
<select id="selectByQuery" parameterType="map" resultType="Property"> | |||
select p.id as id, p.prop_key as "key", p.text_value as value, p.resource_id as resourceId, p.user_id as userId | |||
from properties p |
@@ -20,18 +20,27 @@ | |||
package org.sonar.db.property; | |||
import com.google.common.collect.ImmutableMap; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
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.ComponentDto; | |||
import org.sonar.db.component.ComponentTesting; | |||
import org.sonar.db.user.UserDto; | |||
import org.sonar.db.user.UserTesting; | |||
import static com.google.common.collect.Sets.newHashSet; | |||
import static java.util.Arrays.asList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.hamcrest.Matchers.is; | |||
import static org.junit.Assert.assertThat; | |||
import static org.sonar.db.property.PropertyTesting.newComponentPropertyDto; | |||
import static org.sonar.db.property.PropertyTesting.newGlobalPropertyDto; | |||
import static org.sonar.db.property.PropertyTesting.newUserPropertyDto; | |||
public class PropertiesDaoTest { | |||
@@ -41,6 +50,9 @@ public class PropertiesDaoTest { | |||
@Rule | |||
public DbTester dbTester = DbTester.create(System2.INSTANCE); | |||
DbClient dbClient = dbTester.getDbClient(); | |||
DbSession session = dbTester.getSession(); | |||
PropertiesDao dao = dbTester.getDbClient().propertiesDao(); | |||
@Test | |||
@@ -98,18 +110,18 @@ public class PropertiesDaoTest { | |||
dbTester.prepareDbUnit(getClass(), "findNotificationSubscribers.xml"); | |||
// Nobody is subscribed | |||
assertThat(dao.hasProjectNotificationSubscribersForDispatchers("PROJECT_A", Arrays.asList("NotSexyDispatcher"))).isFalse(); | |||
assertThat(dao.hasProjectNotificationSubscribersForDispatchers("PROJECT_A", asList("NotSexyDispatcher"))).isFalse(); | |||
// Global subscribers | |||
assertThat(dao.hasProjectNotificationSubscribersForDispatchers("PROJECT_A", Arrays.asList("DispatcherWithGlobalSubscribers"))).isTrue(); | |||
assertThat(dao.hasProjectNotificationSubscribersForDispatchers("PROJECT_A", asList("DispatcherWithGlobalSubscribers"))).isTrue(); | |||
// Project subscribers | |||
assertThat(dao.hasProjectNotificationSubscribersForDispatchers("PROJECT_A", Arrays.asList("DispatcherWithProjectSubscribers"))).isTrue(); | |||
assertThat(dao.hasProjectNotificationSubscribersForDispatchers("PROJECT_B", Arrays.asList("DispatcherWithProjectSubscribers"))).isFalse(); | |||
assertThat(dao.hasProjectNotificationSubscribersForDispatchers("PROJECT_A", asList("DispatcherWithProjectSubscribers"))).isTrue(); | |||
assertThat(dao.hasProjectNotificationSubscribersForDispatchers("PROJECT_B", asList("DispatcherWithProjectSubscribers"))).isFalse(); | |||
// Global + Project subscribers | |||
assertThat(dao.hasProjectNotificationSubscribersForDispatchers("PROJECT_A", Arrays.asList("DispatcherWithGlobalAndProjectSubscribers"))).isTrue(); | |||
assertThat(dao.hasProjectNotificationSubscribersForDispatchers("PROJECT_B", Arrays.asList("DispatcherWithGlobalAndProjectSubscribers"))).isTrue(); | |||
assertThat(dao.hasProjectNotificationSubscribersForDispatchers("PROJECT_A", asList("DispatcherWithGlobalAndProjectSubscribers"))).isTrue(); | |||
assertThat(dao.hasProjectNotificationSubscribersForDispatchers("PROJECT_B", asList("DispatcherWithGlobalAndProjectSubscribers"))).isTrue(); | |||
} | |||
@Test | |||
@@ -193,6 +205,51 @@ public class PropertiesDaoTest { | |||
assertThat(results.get(0).getValue()).isEqualTo("one"); | |||
} | |||
@Test | |||
public void select_global_properties_by_keys() throws Exception { | |||
ComponentDto project = ComponentTesting.newProjectDto(); | |||
dbClient.componentDao().insert(session, project); | |||
UserDto user = UserTesting.newUserDto(); | |||
dbClient.userDao().insert(session, user); | |||
String key = "key"; | |||
String anotherKey = "anotherKey"; | |||
insertProperties( | |||
newGlobalPropertyDto().setKey(key), | |||
newComponentPropertyDto(project).setKey(key), | |||
newUserPropertyDto(user).setKey(key), | |||
newGlobalPropertyDto().setKey(anotherKey)); | |||
assertThat(dao.selectGlobalPropertiesByKeys(session, newHashSet(key))).extracting("key").containsOnly(key); | |||
assertThat(dao.selectGlobalPropertiesByKeys(session, newHashSet(key, anotherKey))).extracting("key").containsOnly(key, anotherKey); | |||
assertThat(dao.selectGlobalPropertiesByKeys(session, newHashSet(key, anotherKey, "unknown"))).extracting("key").containsOnly(key, anotherKey); | |||
assertThat(dao.selectGlobalPropertiesByKeys(session, newHashSet("unknown"))).isEmpty(); | |||
} | |||
@Test | |||
public void select_component_properties_by_keys() throws Exception { | |||
ComponentDto project = ComponentTesting.newProjectDto(); | |||
dbClient.componentDao().insert(session, project); | |||
UserDto user = UserTesting.newUserDto(); | |||
dbClient.userDao().insert(session, user); | |||
String key = "key"; | |||
String anotherKey = "anotherKey"; | |||
insertProperties( | |||
newGlobalPropertyDto().setKey(key), | |||
newComponentPropertyDto(project).setKey(key), | |||
newUserPropertyDto(user).setKey(key), | |||
newComponentPropertyDto(project).setKey(anotherKey)); | |||
assertThat(dao.selectComponentPropertiesByKeys(session, newHashSet(key), project.getId())).extracting("key").containsOnly(key); | |||
assertThat(dao.selectComponentPropertiesByKeys(session, newHashSet(key, anotherKey), project.getId())).extracting("key").containsOnly(key, anotherKey); | |||
assertThat(dao.selectComponentPropertiesByKeys(session, newHashSet(key, anotherKey, "unknown"), project.getId())).extracting("key").containsOnly(key, anotherKey); | |||
assertThat(dao.selectComponentPropertiesByKeys(session, newHashSet("unknown"), project.getId())).isEmpty(); | |||
assertThat(dao.selectComponentPropertiesByKeys(session, newHashSet(key), 123456789L)).isEmpty(); | |||
} | |||
@Test | |||
public void setProperty_update() { | |||
dbTester.prepareDbUnit(getClass(), "update.xml"); | |||
@@ -336,4 +393,11 @@ public class PropertiesDaoTest { | |||
} | |||
return null; | |||
} | |||
private void insertProperties(PropertyDto... properties) { | |||
for (PropertyDto propertyDto : properties) { | |||
dao.insertProperty(session, propertyDto); | |||
} | |||
session.commit(); | |||
} | |||
} |
@@ -1,32 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2016 SonarSource SA | |||
* mailto:contact 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.db.property; | |||
public class PropertyTesting { | |||
public static PropertyDto newGlobalProperty(String key, String value) { | |||
return new PropertyDto().setKey(key).setValue(value); | |||
} | |||
public static PropertyDto newProjectProperty(String key, String value, long componentId) { | |||
return new PropertyDto().setKey(key).setValue(value).setResourceId(componentId); | |||
} | |||
} |
@@ -66,3 +66,21 @@ enum Type { | |||
PROPERTY_SET = 12; | |||
} | |||
// Response of GET api/settings/values | |||
message ValuesWsResponse { | |||
repeated Value values = 1; | |||
} | |||
message Value { | |||
optional string key = 1; | |||
optional string value = 2; | |||
repeated string values = 3; | |||
map<string, SetValue> setValues = 4; | |||
optional bool isDefault = 5; | |||
optional bool isInherited = 6; | |||
} | |||
message SetValue { | |||
repeated string values = 1; | |||
} | |||