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.core.util.stream.Collectors;
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.ValuesWsResponse;
+import org.sonarqube.ws.client.setting.ValuesRequest;
import static org.elasticsearch.common.Strings.isNullOrEmpty;
import static org.sonar.api.PropertyType.PROPERTY_SET;
+import static org.sonar.server.component.ComponentFinder.ParamNames.ID_AND_KEY;
import static org.sonar.server.settings.ws.SettingsWsComponentParameters.addComponentParameters;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
+import static org.sonarqube.ws.client.setting.SettingsWsParameters.ACTION_VALUES;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_COMPONENT_ID;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_COMPONENT_KEY;
+import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_KEYS;
public class ValuesAction implements SettingsWsAction {
private static final Splitter COMMA_SPLITTER = Splitter.on(",");
- private static final String PARAM_KEYS = "keys";
-
private final DbClient dbClient;
- private final SettingsWsComponentParameters settingsWsComponentParameters;
+ private final ComponentFinder componentFinder;
+ private final UserSession userSession;
private final PropertyDefinitions propertyDefinitions;
private final SettingsFinder settingsFinder;
- public ValuesAction(DbClient dbClient, SettingsWsComponentParameters settingsWsComponentParameters, PropertyDefinitions propertyDefinitions, SettingsFinder settingsFinder) {
+ public ValuesAction(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, PropertyDefinitions propertyDefinitions, SettingsFinder settingsFinder) {
this.dbClient = dbClient;
- this.settingsWsComponentParameters = settingsWsComponentParameters;
+ this.componentFinder = componentFinder;
+ this.userSession = userSession;
this.propertyDefinitions = propertyDefinitions;
this.settingsFinder = settingsFinder;
}
@Override
public void define(WebService.NewController context) {
- WebService.NewAction action = context.createAction("values")
+ WebService.NewAction action = context.createAction(ACTION_VALUES)
.setDescription("List settings values.<br>" +
"If no value has been set for a setting, then the default value is returned.<br>" +
"Either '%s' or '%s' can be provided, not both.<br> " +
.setHandler(this);
addComponentParameters(action);
action.createParam(PARAM_KEYS)
- .setDescription("List of property keys")
+ .setDescription("List of setting keys")
.setRequired(true)
.setExampleValue("sonar.technicalDebt.hoursInDay,sonar.dbcleaner.cleanDirectory");
}
private ValuesWsResponse doHandle(Request request) {
DbSession dbSession = dbClient.openSession(true);
try {
- ComponentDto componentDto = settingsWsComponentParameters.getComponent(dbSession, request);
- settingsWsComponentParameters.checkAdminPermission(componentDto);
- Set<String> keys = new HashSet<>(request.mandatoryParamAsStrings(PARAM_KEYS));
- Optional<ComponentDto> component = Optional.ofNullable(componentDto);
+ ValuesRequest valuesRequest = toWsRequest(request);
+ Optional<ComponentDto> component = getComponent(dbSession, valuesRequest);
+ checkAdminPermission(component);
+ Set<String> keys = new HashSet<>(valuesRequest.getKeys());
return new ValuesResponseBuilder(loadSettings(dbSession, component, keys), component).build();
} finally {
dbClient.closeSession(dbSession);
}
}
+ private static ValuesRequest toWsRequest(Request request) {
+ return ValuesRequest.builder()
+ .setKeys(request.mandatoryParamAsStrings(PARAM_KEYS))
+ .setComponentId(request.param(PARAM_COMPONENT_ID))
+ .setComponentKey(request.param(PARAM_COMPONENT_KEY))
+ .build();
+ }
+
+ private Optional<ComponentDto> getComponent(DbSession dbSession, ValuesRequest valuesRequest) {
+ String componentId = valuesRequest.getComponentId();
+ String componentKey = valuesRequest.getComponentKey();
+ if (componentId != null || componentKey != null) {
+ return Optional.of(componentFinder.getByUuidOrKey(dbSession, componentId, componentKey, ID_AND_KEY));
+ }
+ return Optional.empty();
+ }
+
+ private void checkAdminPermission(Optional<ComponentDto> component) {
+ if (component.isPresent()) {
+ userSession.checkComponentUuidPermission(UserRole.ADMIN, component.get().uuid());
+ } else {
+ userSession.checkPermission(GlobalPermissions.SYSTEM_ADMIN);
+ }
+ }
+
private List<Setting> loadSettings(DbSession dbSession, Optional<ComponentDto> component, Set<String> keys) {
if (keys.isEmpty()) {
return Collections.emptyList();
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();
SettingsFinder settingsFinder = new SettingsFinder(dbClient, propertyDefinitions);
ComponentDto project;
- WsActionTester ws = new WsActionTester(new ValuesAction(dbClient, settingsWsComponentParameters, propertyDefinitions, settingsFinder));
+ WsActionTester ws = new WsActionTester(new ValuesAction(dbClient, new ComponentFinder(dbClient), userSession, propertyDefinitions, settingsFinder));
@Before
public void setUp() throws Exception {
propertyDefinitions.addComponent(PropertyDefinition.builder("foo").build());
expectedException.expect(ForbiddenException.class);
- newRequestForGlobalProperties();
+ newRequestForGlobalProperties("foo");
}
@Test
propertyDefinitions.addComponent(PropertyDefinition.builder("foo").build());
expectedException.expect(ForbiddenException.class);
- newRequest(project.uuid(), null);
+ newRequest(project.uuid(), null, "foo");
}
@Test
package org.sonarqube.ws.client.setting;
import org.sonarqube.ws.Settings.ListDefinitionsWsResponse;
+import org.sonarqube.ws.Settings.ValuesWsResponse;
import org.sonarqube.ws.client.BaseService;
import org.sonarqube.ws.client.GetRequest;
import org.sonarqube.ws.client.WsConnector;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_COMPONENT_ID;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_COMPONENT_KEY;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.ACTION_LIST_DEFINITIONS;
+import static org.sonarqube.ws.client.setting.SettingsWsParameters.ACTION_VALUES;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.CONTROLLER_SETTINGS;
+import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_KEYS;
public class SettingsService extends BaseService {
public SettingsService(WsConnector wsConnector) {
return call(getRequest, ListDefinitionsWsResponse.parser());
}
+ public ValuesWsResponse values(ValuesRequest request) {
+ GetRequest getRequest = new GetRequest(path(ACTION_VALUES))
+ .setParam(PARAM_KEYS, inlineMultipleParamValue(request.getKeys()))
+ .setParam(PARAM_COMPONENT_ID, request.getComponentId())
+ .setParam(PARAM_COMPONENT_KEY, request.getComponentKey());
+ return call(getRequest, ValuesWsResponse.parser());
+ }
+
}
public static final String CONTROLLER_SETTINGS = "api/settings";
public static final String ACTION_LIST_DEFINITIONS = "list_definitions";
+ public static final String ACTION_VALUES = "values";
public static final String PARAM_COMPONENT_ID = "componentId";
public static final String PARAM_COMPONENT_KEY = "componentKey";
+ public static final String PARAM_KEYS = "keys";
+
+ private SettingsWsParameters() {
+ // Only static stuff
+ }
}
--- /dev/null
+/*
+ * 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.sonarqube.ws.client.setting;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Arrays.asList;
+import static java.util.Objects.requireNonNull;
+import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_KEYS;
+
+public class ValuesRequest {
+
+ private final String componentId;
+ private final String componentKey;
+ private final List<String> keys;
+
+ public ValuesRequest(Builder builder) {
+ this.componentId = builder.componentId;
+ this.componentKey = builder.componentKey;
+ this.keys = builder.keys;
+ }
+
+ @CheckForNull
+ public String getComponentId() {
+ return componentId;
+ }
+
+ @CheckForNull
+ public String getComponentKey() {
+ return componentKey;
+ }
+
+ public List<String> getKeys() {
+ return keys;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private String componentId;
+ private String componentKey;
+ private List<String> keys = new ArrayList<>();
+
+ private Builder() {
+ // enforce factory method use
+ }
+
+ public Builder setComponentId(@Nullable String componentId) {
+ this.componentId = componentId;
+ return this;
+ }
+
+ public Builder setComponentKey(@Nullable String componentKey) {
+ this.componentKey = componentKey;
+ return this;
+ }
+
+ public Builder setKeys(List<String> keys) {
+ this.keys = requireNonNull(keys);
+ return this;
+ }
+
+ public Builder setKeys(String... keys) {
+ return setKeys(asList(keys));
+ }
+
+ public ValuesRequest build() {
+ checkArgument(!keys.isEmpty(), "'%s' cannot be empty", PARAM_KEYS);
+ return new ValuesRequest(this);
+ }
+ }
+
+}
import org.junit.Rule;
import org.junit.Test;
-import org.sonarqube.ws.Settings;
+import org.sonarqube.ws.Settings.ListDefinitionsWsResponse;
+import org.sonarqube.ws.Settings.ValuesWsResponse;
import org.sonarqube.ws.client.GetRequest;
import org.sonarqube.ws.client.ServiceTester;
import org.sonarqube.ws.client.WsConnector;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_COMPONENT_KEY;
+import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_KEYS;
public class SettingsServiceTest {
@Test
public void list_definitions() {
- ListDefinitionsRequest request = ListDefinitionsRequest.builder()
+ underTest.listDefinitions(ListDefinitionsRequest.builder()
.setComponentKey("KEY")
- .build();
+ .build());
+ GetRequest getRequest = serviceTester.getGetRequest();
+
+ assertThat(serviceTester.getGetParser()).isSameAs(ListDefinitionsWsResponse.parser());
+ serviceTester.assertThat(getRequest)
+ .hasParam(PARAM_COMPONENT_KEY, "KEY")
+ .andNoOtherParam();
+ }
- underTest.listDefinitions(request);
+ @Test
+ public void values() {
+ underTest.values(ValuesRequest.builder()
+ .setKeys("sonar.debt,sonar.issue")
+ .setComponentKey("KEY")
+ .build());
GetRequest getRequest = serviceTester.getGetRequest();
- assertThat(serviceTester.getGetParser()).isSameAs(Settings.ListDefinitionsWsResponse.parser());
+ assertThat(serviceTester.getGetParser()).isSameAs(ValuesWsResponse.parser());
serviceTester.assertThat(getRequest)
+ .hasParam(PARAM_KEYS, "sonar.debt,sonar.issue")
.hasParam(PARAM_COMPONENT_KEY, "KEY")
.andNoOtherParam();
}
--- /dev/null
+/*
+ * 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.sonarqube.ws.client.setting;
+
+import java.util.List;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ValuesRequestTest {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ ValuesRequest.Builder underTest = ValuesRequest.builder();
+
+ @Test
+ public void create_request_with_no_component() {
+ ValuesRequest result = underTest.setKeys("sonar.debt").build();
+
+ assertThat(result.getComponentId()).isNull();
+ assertThat(result.getComponentKey()).isNull();
+ assertThat(result.getKeys()).containsOnly("sonar.debt");
+ }
+
+ @Test
+ public void create_request_with_component_id() {
+ ValuesRequest result = underTest.setKeys("sonar.debt").setComponentId("projectId").build();
+
+ assertThat(result.getComponentId()).isEqualTo("projectId");
+ assertThat(result.getComponentKey()).isNull();
+ assertThat(result.getKeys()).containsOnly("sonar.debt");
+ }
+
+ @Test
+ public void create_request_with_component_key() {
+ ValuesRequest result = underTest.setKeys("sonar.debt").setComponentKey("projectKey").build();
+
+ assertThat(result.getComponentId()).isNull();
+ assertThat(result.getComponentKey()).isEqualTo("projectKey");
+ assertThat(result.getKeys()).containsOnly("sonar.debt");
+ }
+
+ @Test
+ public void fail_when_keys_is_null() throws Exception {
+ expectedException.expect(NullPointerException.class);
+ underTest
+ .setKeys((List<String>) null)
+ .setComponentId("projectId")
+ .build();
+ }
+
+ @Test
+ public void fail_when_keys_is_empty() throws Exception {
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("'keys' cannot be empty");
+
+ underTest.setComponentId("projectId").build();
+ }
+
+}