import org.junit.ClassRule;
import org.junit.Test;
import org.sonarqube.ws.Settings;
+import org.sonarqube.ws.client.setting.ResetRequest;
import org.sonarqube.ws.client.setting.SetRequest;
import org.sonarqube.ws.client.setting.SettingsService;
import org.sonarqube.ws.client.setting.ValuesRequest;
assertThat(value).isEqualTo("some value");
}
+ @Test
+ public void remove_value() throws Exception {
+ settingsService().set(SetRequest.builder().setKey(PLUGIN_SETTING_KEY).setValue("some value").build());
+ settingsService().reset(ResetRequest.builder().setKey(PLUGIN_SETTING_KEY).build());
+ assertThat(getSetting(PLUGIN_SETTING_KEY).getValue()).isEqualTo("aDefaultValue");
+ }
+
private static SettingsService settingsService() {
return newAdminWsClient(orchestrator).settingsService();
}
--- /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.sonar.server.settings.ws;
+
+import java.util.Optional;
+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.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.client.setting.ResetRequest;
+
+import static org.sonar.server.settings.ws.SettingsWsComponentParameters.addComponentParameters;
+import static org.sonarqube.ws.client.ce.CeWsParameters.PARAM_COMPONENT_KEY;
+import static org.sonarqube.ws.client.setting.SettingsWsParameters.ACTION_RESET;
+import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_COMPONENT_ID;
+import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_KEY;
+
+public class ResetAction implements SettingsWsAction {
+
+ private final DbClient dbClient;
+ private final UserSession userSession;
+ private final ComponentFinder componentFinder;
+ private final PropertyDefinitions definitions;
+
+ public ResetAction(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, PropertyDefinitions definitions) {
+ this.dbClient = dbClient;
+ this.userSession = userSession;
+ this.componentFinder = componentFinder;
+ this.definitions = definitions;
+ }
+
+ @Override
+ public void define(WebService.NewController context) {
+ WebService.NewAction action = context.createAction(ACTION_RESET)
+ .setDescription("Remove a setting value.<br>" +
+ "Either '%s' or '%s' can 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)
+ .setSince("6.1")
+ .setPost(true)
+ .setHandler(this);
+
+ action.createParam(PARAM_KEY)
+ .setDescription("Setting key")
+ .setExampleValue("sonar.links.scm")
+ .setRequired(true);
+ addComponentParameters(action);
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ ResetRequest resetRequest = toWsRequest(request);
+ Optional<ComponentDto> component = getComponent(dbSession, resetRequest);
+ checkPermissions(component);
+
+ PropertyDefinition definition = definitions.get(resetRequest.getKey());
+ String key = definition != null ? definition.key() : resetRequest.getKey();
+ if (component.isPresent()) {
+ dbClient.propertiesDao().deleteProjectProperty(key, component.get().getId(), dbSession);
+ } else {
+ dbClient.propertiesDao().deleteGlobalProperty(key, dbSession);
+ }
+ dbSession.commit();
+ response.noContent();
+ } finally {
+ dbClient.closeSession(dbSession);
+ }
+ }
+
+ private static ResetRequest toWsRequest(Request request) {
+ return ResetRequest.builder()
+ .setKey(request.mandatoryParam(PARAM_KEY))
+ .setComponentId(request.param(PARAM_COMPONENT_ID))
+ .setComponentKey(request.param(PARAM_COMPONENT_KEY))
+ .build();
+ }
+
+ private Optional<ComponentDto> getComponent(DbSession dbSession, ResetRequest request) {
+ if (request.getComponentId() == null && request.getComponentKey() == null) {
+ return Optional.empty();
+ }
+ ComponentDto project = componentFinder.getByUuidOrKey(dbSession, request.getComponentId(), request.getComponentKey(), ComponentFinder.ParamNames.COMPONENT_ID_AND_KEY);
+ return Optional.of(project);
+ }
+
+ private void checkPermissions(Optional<ComponentDto> component) {
+ if (component.isPresent()) {
+ userSession.checkComponentUuidPermission(UserRole.ADMIN, component.get().uuid());
+ } else {
+ userSession.checkPermission(GlobalPermissions.SYSTEM_ADMIN);
+ }
+ }
+}
SettingsWsComponentParameters.class,
ListDefinitionsAction.class,
ValuesAction.class,
- SettingsFinder.class);
+ SettingsFinder.class,
+ ResetAction.class);
}
}
--- /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.sonar.server.settings.ws;
+
+import javax.annotation.Nullable;
+import org.junit.Before;
+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.PropertyDbTester;
+import org.sonar.db.property.PropertyQuery;
+import org.sonar.db.user.UserDto;
+import org.sonar.db.user.UserTesting;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.TestResponse;
+import org.sonar.server.ws.WsActionTester;
+import org.sonarqube.ws.MediaTypes;
+
+import static java.net.HttpURLConnection.HTTP_NO_CONTENT;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.api.web.UserRole.ADMIN;
+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.sonar.db.property.PropertyTesting.newUserPropertyDto;
+
+public class ResetActionTest {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
+
+ @Rule
+ public DbTester db = DbTester.create(System2.INSTANCE);
+
+ PropertyDbTester propertyDb = new PropertyDbTester(db);
+ ComponentDbTester componentDb = new ComponentDbTester(db);
+ DbClient dbClient = db.getDbClient();
+ DbSession dbSession = db.getSession();
+ ComponentFinder componentFinder = new ComponentFinder(dbClient);
+ PropertyDefinitions definitions = new PropertyDefinitions();
+
+ ComponentDto project;
+
+ ResetAction underTest = new ResetAction(dbClient, componentFinder, userSession, definitions);
+ WsActionTester ws = new WsActionTester(underTest);
+
+ @Before
+ public void setUp() throws Exception {
+ project = componentDb.insertComponent(newProjectDto());
+ }
+
+ @Test
+ public void remove_global_setting() throws Exception {
+ setUserAsSystemAdmin();
+ propertyDb.insertProperties(newGlobalPropertyDto().setKey("foo").setValue("one"));
+
+ executeRequestOnGlobalSetting("foo");
+ assertGlobalPropertyDoesNotExist("foo");
+ }
+
+ @Test
+ public void remove_component_setting() throws Exception {
+ setUserAsSystemAdmin();
+ propertyDb.insertProperties(newComponentPropertyDto(project).setKey("foo").setValue("value"));
+
+ executeRequestOnProjectSetting("foo");
+ assertProjectPropertyDoesNotExist("foo");
+ }
+
+ @Test
+ public void ignore_project_setting_when_removing_global_setting() throws Exception {
+ setUserAsSystemAdmin();
+ propertyDb.insertProperties(newGlobalPropertyDto().setKey("foo").setValue("one"));
+ propertyDb.insertProperties(newComponentPropertyDto(project).setKey("foo").setValue("value"));
+
+ executeRequestOnGlobalSetting("foo");
+
+ assertGlobalPropertyDoesNotExist("foo");
+ assertProjectPropertyExists("foo");
+ }
+
+ @Test
+ public void ignore_global_setting_when_removing_project_setting() throws Exception {
+ setUserAsSystemAdmin();
+ propertyDb.insertProperties(newGlobalPropertyDto().setKey("foo").setValue("one"));
+ propertyDb.insertProperties(newComponentPropertyDto(project).setKey("foo").setValue("value"));
+
+ executeRequestOnProjectSetting("foo");
+
+ assertGlobalPropertyExists("foo");
+ assertProjectPropertyDoesNotExist("foo");
+ }
+
+ @Test
+ public void ignore_user_setting_when_removing_global_setting() throws Exception {
+ setUserAsSystemAdmin();
+ UserDto user = dbClient.userDao().insert(dbSession, UserTesting.newUserDto());
+ propertyDb.insertProperties(newUserPropertyDto("foo", "one", user));
+
+ executeRequestOnGlobalSetting("foo");
+ assertUserPropertyExists("foo", user);
+ }
+
+ @Test
+ public void ignore_user_setting_when_removing_project_setting() throws Exception {
+ setUserAsSystemAdmin();
+ UserDto user = dbClient.userDao().insert(dbSession, UserTesting.newUserDto());
+ propertyDb.insertProperties(newUserPropertyDto("foo", "one", user));
+
+ executeRequestOnProjectSetting("foo");
+ assertUserPropertyExists("foo", user);
+ }
+
+ @Test
+ public void ignore_unknown_setting_key() throws Exception {
+ setUserAsSystemAdmin();
+
+ executeRequestOnGlobalSetting("unknown");
+ }
+
+ @Test
+ public void remove_setting_by_deprecated_key() throws Exception {
+ setUserAsSystemAdmin();
+ definitions.addComponent(PropertyDefinition.builder("foo").deprecatedKey("old").build());
+ propertyDb.insertProperties(newGlobalPropertyDto().setKey("foo").setValue("one"));
+
+ executeRequestOnGlobalSetting("old");
+ assertGlobalPropertyDoesNotExist("foo");
+ }
+
+ @Test
+ public void empty_204_response() {
+ setUserAsSystemAdmin();
+ TestResponse result = ws.newRequest()
+ .setParam("key", "my.key")
+ .execute();
+
+ assertThat(result.getStatus()).isEqualTo(HTTP_NO_CONTENT);
+ assertThat(result.getInput()).isEmpty();
+ }
+
+ @Test
+ public void test_ws_definition() {
+ WebService.Action action = ws.getDef();
+ assertThat(action).isNotNull();
+ assertThat(action.isInternal()).isFalse();
+ assertThat(action.isPost()).isTrue();
+ assertThat(action.responseExampleAsString()).isNull();
+ assertThat(action.params()).hasSize(3);
+ }
+
+ private void executeRequestOnGlobalSetting(String key) {
+ executeRequest(key, null, null);
+ }
+
+ private void executeRequestOnProjectSetting(String key) {
+ executeRequest(key, project.uuid(), null);
+ }
+
+ private void executeRequestOnComponentSetting(String key, ComponentDto componentDto) {
+ executeRequest(key, componentDto.uuid(), null);
+ }
+
+ private void executeRequest(String key, @Nullable String componentId, @Nullable String componentKey) {
+ TestRequest request = ws.newRequest()
+ .setMediaType(MediaTypes.PROTOBUF)
+ .setParam("key", key);
+ if (componentId != null) {
+ request.setParam("componentId", componentId);
+ }
+ if (componentKey != null) {
+ request.setParam("componentKey", componentKey);
+ }
+ request.execute();
+ }
+
+ private void setUserAsSystemAdmin() {
+ userSession.login("admin").setGlobalPermissions(SYSTEM_ADMIN);
+ }
+
+ private void setUserAsProjectAdmin() {
+ userSession.login("project-admin").addProjectUuidPermissions(ADMIN, project.uuid());
+ }
+
+ private void assertGlobalPropertyDoesNotExist(String key) {
+ assertThat(dbClient.propertiesDao().selectGlobalProperty(key)).isNull();
+ }
+
+ private void assertGlobalPropertyExists(String key) {
+ assertThat(dbClient.propertiesDao().selectGlobalProperty(key)).isNotNull();
+ }
+
+ private void assertProjectPropertyDoesNotExist(String key) {
+ assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder().setComponentId(project.getId()).setKey(key).build(), dbSession)).isEmpty();
+ }
+
+ private void assertProjectPropertyExists(String key) {
+ assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder().setComponentId(project.getId()).setKey(key).build(), dbSession)).isNotEmpty();
+ }
+
+ private void assertUserPropertyExists(String key, UserDto user) {
+ assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder()
+ .setKey(key)
+ .setUserId(user.getId().intValue())
+ .build(),
+ dbSession)).isNotEmpty();
+ }
+
+}
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new SettingsWsModule().configure(container);
- assertThat(container.size()).isEqualTo(6 + 2);
+ assertThat(container.size()).isEqualTo(7 + 2);
}
}
return property;
}
+
+ public void insertProperties(PropertyDto... properties) {
+ for (PropertyDto propertyDto : properties) {
+ dbClient.propertiesDao().insertProperty(dbSession, propertyDto);
+ }
+ dbSession.commit();
+ }
}
--- /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 javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+public class ResetRequest {
+ private final String key;
+ private final String componentId;
+ private final String componentKey;
+
+ public ResetRequest(Builder builder) {
+ this.key = builder.key;
+ this.componentId = builder.componentId;
+ this.componentKey = builder.componentKey;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ @CheckForNull
+ public String getComponentId() {
+ return componentId;
+ }
+
+ @CheckForNull
+ public String getComponentKey() {
+ return componentKey;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private String key;
+ private String componentId;
+ private String componentKey;
+
+ private Builder() {
+ // enforce factory method use
+ }
+
+ public Builder setKey(String key) {
+ this.key = key;
+ return this;
+ }
+
+ public Builder setComponentId(@Nullable String componentId) {
+ this.componentId = componentId;
+ return this;
+ }
+
+ public Builder setComponentKey(@Nullable String componentKey) {
+ this.componentKey = componentKey;
+ return this;
+ }
+
+ public ResetRequest build() {
+ checkArgument(key != null && !key.isEmpty(), "Setting key is mandatory and must not be empty.");
+ return new ResetRequest(this);
+ }
+ }
+}
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_RESET;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.ACTION_SET;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.ACTION_VALUES;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.CONTROLLER_SETTINGS;
.setParam(PARAM_COMPONENT_KEY, request.getComponentKey()));
}
+ public void reset(ResetRequest request) {
+ call(new PostRequest(path(ACTION_RESET))
+ .setParam(PARAM_KEY, request.getKey())
+ .setParam(PARAM_COMPONENT_ID, request.getComponentId())
+ .setParam(PARAM_COMPONENT_KEY, request.getComponentKey()));
+ }
+
}
public static final String ACTION_LIST_DEFINITIONS = "list_definitions";
public static final String ACTION_VALUES = "values";
public static final String ACTION_SET = "set";
+ public static final String ACTION_RESET = "reset";
public static final String PARAM_COMPONENT_ID = "componentId";
public static final String PARAM_COMPONENT_KEY = "componentKey";
--- /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 org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ResetRequestTest {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ ResetRequest.Builder underTest = ResetRequest.builder();
+
+ @Test
+ public void create_set_request() {
+ ResetRequest result = underTest.setKey("my.key").build();
+
+ assertThat(result.getKey()).isEqualTo("my.key");
+ }
+
+ @Test
+ public void fail_when_empty_key() {
+ expectedException.expect(IllegalArgumentException.class);
+ underTest.setKey("").build();
+ }
+
+}
import org.sonarqube.ws.Settings.ListDefinitionsWsResponse;
import org.sonarqube.ws.Settings.ValuesWsResponse;
import org.sonarqube.ws.client.GetRequest;
-import org.sonarqube.ws.client.PostRequest;
import org.sonarqube.ws.client.ServiceTester;
import org.sonarqube.ws.client.WsConnector;
.setValue("8h")
.setComponentKey("KEY")
.build());
- PostRequest request = serviceTester.getPostRequest();
- serviceTester.assertThat(request)
+ serviceTester.assertThat(serviceTester.getPostRequest())
.hasParam(PARAM_KEY, "sonar.debt")
.hasParam(PARAM_VALUE, "8h")
.hasParam(PARAM_COMPONENT_KEY, "KEY")
.andNoOtherParam();
}
+ @Test
+ public void reset() {
+ underTest.reset(ResetRequest.builder()
+ .setKey("sonar.debt")
+ .setComponentKey("KEY")
+ .build());
+
+ serviceTester.assertThat(serviceTester.getPostRequest())
+ .hasParam(PARAM_KEY, "sonar.debt")
+ .hasParam(PARAM_COMPONENT_KEY, "KEY")
+ .andNoOtherParam();
+ }
+
}