Browse Source

SONAR-9616 Handle branch in api/settings/list_definitions

tags/6.6-RC1
Julien Lancelot 6 years ago
parent
commit
98d1c53522

+ 8
- 3
server/sonar-server/src/main/java/org/sonar/server/setting/ws/ListDefinitionsAction.java View File

@@ -39,9 +39,11 @@ import org.sonarqube.ws.client.setting.ListDefinitionsRequest;
import static com.google.common.base.Strings.emptyToNull;
import static org.sonar.api.web.UserRole.USER;
import static org.sonar.core.util.Protobuf.setNullable;
import static org.sonar.server.setting.ws.SettingsWs.SETTING_ON_BRANCHES;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.ACTION_LIST_DEFINITIONS;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_BRANCH;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_COMPONENT;

public class ListDefinitionsAction implements SettingsWsAction {
@@ -79,6 +81,7 @@ public class ListDefinitionsAction implements SettingsWsAction {
action.createParam(PARAM_COMPONENT)
.setDescription("Component key")
.setExampleValue(KEY_PROJECT_EXAMPLE_001);
settingsWsSupport.addBranchParam(action);
}

@Override
@@ -93,6 +96,7 @@ public class ListDefinitionsAction implements SettingsWsAction {
ListDefinitionsWsResponse.Builder wsResponse = ListDefinitionsWsResponse.newBuilder();
propertyDefinitions.getAll().stream()
.filter(definition -> qualifier.isPresent() ? definition.qualifiers().contains(qualifier.get()) : definition.global())
.filter(definition -> wsRequest.getBranch() == null || SETTING_ON_BRANCHES.contains(definition.key()))
.filter(settingsWsSupport.isDefinitionVisible(component))
.forEach(definition -> addDefinition(definition, wsResponse));
return wsResponse.build();
@@ -101,6 +105,7 @@ public class ListDefinitionsAction implements SettingsWsAction {
private static ListDefinitionsRequest toWsRequest(Request request) {
return ListDefinitionsRequest.builder()
.setComponent(request.param(PARAM_COMPONENT))
.setBranch(request.param(PARAM_BRANCH))
.build();
}

@@ -108,13 +113,13 @@ public class ListDefinitionsAction implements SettingsWsAction {
return component.isPresent() ? Optional.of(component.get().qualifier()) : Optional.empty();
}

private Optional<ComponentDto> loadComponent(ListDefinitionsRequest valuesRequest) {
private Optional<ComponentDto> loadComponent(ListDefinitionsRequest request) {
try (DbSession dbSession = dbClient.openSession(false)) {
String componentKey = valuesRequest.getComponent();
String componentKey = request.getComponent();
if (componentKey == null) {
return Optional.empty();
}
ComponentDto component = componentFinder.getByKey(dbSession, componentKey);
ComponentDto component = componentFinder.getByKeyAndOptionalBranch(dbSession, componentKey, request.getBranch());
userSession.checkComponentPermission(USER, component);
return Optional.of(component);
}

+ 6
- 12
server/sonar-server/src/main/java/org/sonar/server/setting/ws/SetAction.java View File

@@ -21,7 +21,6 @@ package org.sonar.server.setting.ws;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ListMultimap;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
@@ -59,8 +58,6 @@ import org.sonarqube.ws.client.setting.SetRequest;

import static com.google.common.base.Preconditions.checkArgument;
import static java.lang.String.format;
import static org.sonar.core.config.CorePropertyDefinitions.LEAK_PERIOD;
import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
import static org.sonar.server.ws.WsUtils.checkRequest;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.ACTION_SET;
@@ -74,7 +71,6 @@ import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_VALUES;
public class SetAction implements SettingsWsAction {
private static final Collector<CharSequence, ?, String> COMMA_JOINER = Collectors.joining(",");
private static final String MSG_NO_EMPTY_VALUE = "A non empty value must be provided";
public static final Set<String> SETTING_ON_BRANCHES = ImmutableSet.of(LEAK_PERIOD);

private final PropertyDefinitions propertyDefinitions;
private final DbClient dbClient;
@@ -83,9 +79,10 @@ public class SetAction implements SettingsWsAction {
private final SettingsUpdater settingsUpdater;
private final SettingsChangeNotifier settingsChangeNotifier;
private final SettingValidations validations;
private final SettingsWsSupport settingsWsSupport;

public SetAction(PropertyDefinitions propertyDefinitions, DbClient dbClient, ComponentFinder componentFinder, UserSession userSession,
SettingsUpdater settingsUpdater, SettingsChangeNotifier settingsChangeNotifier, SettingValidations validations) {
SettingsUpdater settingsUpdater, SettingsChangeNotifier settingsChangeNotifier, SettingValidations validations, SettingsWsSupport settingsWsSupport) {
this.propertyDefinitions = propertyDefinitions;
this.dbClient = dbClient;
this.componentFinder = componentFinder;
@@ -93,6 +90,7 @@ public class SetAction implements SettingsWsAction {
this.settingsUpdater = settingsUpdater;
this.settingsChangeNotifier = settingsChangeNotifier;
this.validations = validations;
this.settingsWsSupport = settingsWsSupport;
}

@Override
@@ -131,12 +129,7 @@ public class SetAction implements SettingsWsAction {
.setDescription("Component key")
.setDeprecatedKey("componentKey", "6.3")
.setExampleValue(KEY_PROJECT_EXAMPLE_001);

action.createParam(PARAM_BRANCH)
.setDescription("Branch key. Only available on following settings : %s", SETTING_ON_BRANCHES.stream().collect(COMMA_JOINER))
.setExampleValue(KEY_BRANCH_EXAMPLE_001)
.setInternal(true)
.setSince("6.6");
settingsWsSupport.addBranchParam(action);
}

@Override
@@ -207,7 +200,8 @@ public class SetAction implements SettingsWsAction {
SettingData settingData = new SettingData(settingKey, valuesFromRequest(request), component.orElse(null));
ImmutableList.of(validations.scope(), validations.qualifier(), validations.valueType())
.forEach(validation -> validation.accept(settingData));
component.map(ComponentDto::getBranch).ifPresent(b -> checkArgument(SETTING_ON_BRANCHES.contains(settingKey), format("Setting '%s' cannot be set on a branch", settingKey)));
component.map(ComponentDto::getBranch)
.ifPresent(b -> checkArgument(SettingsWs.SETTING_ON_BRANCHES.contains(settingKey), format("Setting '%s' cannot be set on a branch", settingKey)));
}

private static void validatePropertySet(SetRequest request, @Nullable PropertyDefinition definition) {

+ 5
- 0
server/sonar-server/src/main/java/org/sonar/server/setting/ws/SettingsWs.java View File

@@ -19,12 +19,17 @@
*/
package org.sonar.server.setting.ws;

import com.google.common.collect.ImmutableSet;
import java.util.Set;
import org.sonar.api.server.ws.WebService;

import static org.sonar.core.config.CorePropertyDefinitions.LEAK_PERIOD;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.CONTROLLER_SETTINGS;

public class SettingsWs implements WebService {

public static final Set<String> SETTING_ON_BRANCHES = ImmutableSet.of(LEAK_PERIOD);

private final SettingsWsAction[] actions;

public SettingsWs(SettingsWsAction... actions) {

+ 16
- 1
server/sonar-server/src/main/java/org/sonar/server/setting/ws/SettingsWsSupport.java View File

@@ -21,21 +21,28 @@ 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;
import org.sonar.api.config.PropertyDefinition;
import org.sonar.api.server.ServerSide;
import org.sonar.api.server.ws.WebService;
import org.sonar.db.component.ComponentDto;
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.db.permission.OrganizationPermission;
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.user.UserSession;

import static org.sonar.api.PropertyType.LICENSE;
import static org.sonar.api.web.UserRole.ADMIN;
import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION;
import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001;
import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_BRANCH;

@ServerSide
public class SettingsWsSupport {

private static final Collector<CharSequence, ?, String> COMMA_JOINER = Collectors.joining(",");

public static final String DOT_SECURED = ".secured";
public static final String DOT_LICENSE = ".license";
private static final String LICENSE_SUFFIX = DOT_LICENSE + DOT_SECURED;
@@ -81,4 +88,12 @@ public class SettingsWsSupport {
.map(c -> userSession.hasComponentPermission(projectPermission, c))
.orElse(false);
}

WebService.NewParam addBranchParam(WebService.NewAction action){
return action.createParam(PARAM_BRANCH)
.setDescription("Branch key. Only available on following settings : %s", SettingsWs.SETTING_ON_BRANCHES.stream().collect(COMMA_JOINER))
.setExampleValue(KEY_BRANCH_EXAMPLE_001)
.setInternal(true)
.setSince("6.6");
}
}

+ 46
- 1
server/sonar-server/src/test/java/org/sonar/server/setting/ws/ListDefinitionsActionTest.java View File

@@ -29,6 +29,7 @@ import org.sonar.api.config.PropertyDefinition;
import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.config.PropertyFieldDefinition;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.server.ws.WebService.Param;
import org.sonar.api.utils.System2;
import org.sonar.db.DbClient;
import org.sonar.db.DbTester;
@@ -38,6 +39,7 @@ import org.sonar.db.component.ComponentTesting;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.server.component.TestComponentFinder;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.organization.TestDefaultOrganizationProvider;
import org.sonar.server.tester.UserSessionRule;
@@ -47,6 +49,7 @@ import org.sonar.test.JsonAssert;
import org.sonarqube.ws.Settings;
import org.sonarqube.ws.Settings.ListDefinitionsWsResponse;

import static java.lang.String.format;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.groups.Tuple.tuple;
@@ -379,6 +382,23 @@ public class ListDefinitionsActionTest {
assertThat(result.getDefinitionsList()).extracting(Settings.Definition::getKey).containsOnly("foo", "secret.secured", "plugin.license.secured");
}

@Test
public void definitions_on_branch() throws Exception {
ComponentDto project = db.components().insertMainBranch();
userSession.logIn().addProjectPermission(USER, project);
ComponentDto branch = db.components().insertProjectBranch(project);
propertyDefinitions.addComponents(asList(
PropertyDefinition.builder("sonar.leak.period").onQualifiers(PROJECT).build(),
PropertyDefinition.builder("other").onQualifiers(PROJECT).build()));

ListDefinitionsWsResponse result = ws.newRequest()
.setParam("component", branch.getKey())
.setParam("branch", branch.getBranch())
.executeProtobuf(Settings.ListDefinitionsWsResponse.class);

assertThat(result.getDefinitionsList()).extracting(Settings.Definition::getKey).containsExactlyInAnyOrder("sonar.leak.period");
}

@Test
public void fail_when_user_has_not_project_browse_permission() throws Exception {
userSession.logIn("project-admin").addProjectPermission(CODEVIEWER, project);
@@ -389,6 +409,31 @@ public class ListDefinitionsActionTest {
executeRequest(project.getDbKey());
}

@Test
public void fail_when_component_not_found() {
expectedException.expect(NotFoundException.class);
expectedException.expectMessage("Component key 'unknown' not found");

ws.newRequest()
.setParam("component", "unknown")
.execute();
}

@Test
public void fail_when_branch_not_found() {
ComponentDto project = db.components().insertMainBranch();
ComponentDto branch = db.components().insertProjectBranch(project);
userSession.logIn().addProjectPermission(USER, project);

expectedException.expect(NotFoundException.class);
expectedException.expectMessage(format("Component '%s' on branch 'unknown' not found", branch.getKey()));

ws.newRequest()
.setParam("component", branch.getKey())
.setParam("branch", "unknown")
.execute();
}

@Test
public void test_ws_definition() {
WebService.Action action = ws.getDef();
@@ -396,7 +441,7 @@ public class ListDefinitionsActionTest {
assertThat(action.isInternal()).isFalse();
assertThat(action.isPost()).isFalse();
assertThat(action.responseExampleAsString()).isNotEmpty();
assertThat(action.params()).hasSize(1);
assertThat(action.params()).extracting(Param::key).containsExactlyInAnyOrder("component", "branch");
}

@Test

+ 13
- 9
server/sonar-server/src/test/java/org/sonar/server/setting/ws/SetActionTest.java View File

@@ -54,6 +54,8 @@ import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.i18n.I18nRule;
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.organization.TestDefaultOrganizationProvider;
import org.sonar.server.platform.SettingsChangeNotifier;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest;
@@ -92,7 +94,9 @@ public class SetActionTest {
private FakeSettingsNotifier settingsChangeNotifier = new FakeSettingsNotifier(dbClient);
private SettingsUpdater settingsUpdater = new SettingsUpdater(dbClient, definitions);
private SettingValidations validations = new SettingValidations(definitions, dbClient, i18n);
private SetAction underTest = new SetAction(definitions, dbClient, componentFinder, userSession, settingsUpdater, settingsChangeNotifier, validations);
private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
private SetAction underTest = new SetAction(definitions, dbClient, componentFinder, userSession, settingsUpdater, settingsChangeNotifier, validations,
new SettingsWsSupport(defaultOrganizationProvider, userSession));

private WsActionTester ws = new WsActionTester(underTest);

@@ -939,14 +943,14 @@ public class SetActionTest {

@Test
public void fail_when_component_not_found() {
expectedException.expect(NotFoundException.class);
expectedException.expectMessage("Component key 'unknown' not found");
ws.newRequest()
.setParam("key", "foo")
.setParam("value", "2")
.setParam("component", "unknown")
.execute();
expectedException.expect(NotFoundException.class);
expectedException.expectMessage("Component key 'unknown' not found");
ws.newRequest()
.setParam("key", "foo")
.setParam("value", "2")
.setParam("component", "unknown")
.execute();
}

@Test

+ 13
- 0
sonar-ws/src/main/java/org/sonarqube/ws/client/setting/ListDefinitionsRequest.java View File

@@ -27,9 +27,11 @@ import javax.annotation.concurrent.Immutable;
public class ListDefinitionsRequest {

private final String component;
private final String branch;

private ListDefinitionsRequest(Builder builder) {
this.component = builder.component;
this.branch = builder.branch;
}

@CheckForNull
@@ -37,12 +39,18 @@ public class ListDefinitionsRequest {
return component;
}

@CheckForNull
public String getBranch() {
return branch;
}

public static Builder builder() {
return new Builder();
}

public static class Builder {
private String component;
private String branch;

private Builder() {
// enforce factory method use
@@ -53,6 +61,11 @@ public class ListDefinitionsRequest {
return this;
}

public Builder setBranch(@Nullable String branch) {
this.branch = branch;
return this;
}

public ListDefinitionsRequest build() {
return new ListDefinitionsRequest(this);
}

+ 2
- 1
sonar-ws/src/main/java/org/sonarqube/ws/client/setting/SettingsService.java View File

@@ -46,7 +46,8 @@ public class SettingsService extends BaseService {

public ListDefinitionsWsResponse listDefinitions(ListDefinitionsRequest request) {
GetRequest getRequest = new GetRequest(path(ACTION_LIST_DEFINITIONS))
.setParam(PARAM_COMPONENT, request.getComponent());
.setParam(PARAM_COMPONENT, request.getComponent())
.setParam(PARAM_BRANCH, request.getBranch());
return call(getRequest, ListDefinitionsWsResponse.parser());
}


+ 12
- 2
sonar-ws/src/test/java/org/sonarqube/ws/client/setting/ListDefinitionsRequestTest.java View File

@@ -33,17 +33,27 @@ public class ListDefinitionsRequestTest {
ListDefinitionsRequest.Builder underTest = ListDefinitionsRequest.builder();

@Test
public void create_request_with_no_component() {
public void create_request_with_nothing() {
ListDefinitionsRequest result = underTest.build();

assertThat(result.getComponent()).isNull();
assertThat(result.getBranch()).isNull();
}

@Test
public void create_request_with_component_key() {
public void create_request_with_component() {
ListDefinitionsRequest result = underTest.setComponent("projectKey").build();

assertThat(result.getComponent()).isEqualTo("projectKey");
assertThat(result.getBranch()).isNull();
}

@Test
public void create_request_with_component_and_branch() {
ListDefinitionsRequest result = underTest.setComponent("projectKey").setBranch("branch").build();

assertThat(result.getComponent()).isEqualTo("projectKey");
assertThat(result.getBranch()).isEqualTo("branch");
}

}

+ 2
- 0
sonar-ws/src/test/java/org/sonarqube/ws/client/setting/SettingsServiceTest.java View File

@@ -49,12 +49,14 @@ public class SettingsServiceTest {
public void list_definitions() {
underTest.listDefinitions(ListDefinitionsRequest.builder()
.setComponent("KEY")
.setBranch("BRANCH")
.build());
GetRequest getRequest = serviceTester.getGetRequest();

assertThat(serviceTester.getGetParser()).isSameAs(ListDefinitionsWsResponse.parser());
serviceTester.assertThat(getRequest)
.hasParam(PARAM_COMPONENT, "KEY")
.hasParam(PARAM_BRANCH, "BRANCH")
.andNoOtherParam();
}


Loading…
Cancel
Save