From: Julien Lancelot Date: Fri, 25 Aug 2017 12:35:39 +0000 (+0200) Subject: SONAR-9616 Handle branch in api/settings/list_definitions X-Git-Tag: 6.6-RC1~380^2~42 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=98d1c53522f3f69e16dfb9bbdb63e0174402ec57;p=sonarqube.git SONAR-9616 Handle branch in api/settings/list_definitions --- diff --git a/server/sonar-server/src/main/java/org/sonar/server/setting/ws/ListDefinitionsAction.java b/server/sonar-server/src/main/java/org/sonar/server/setting/ws/ListDefinitionsAction.java index 1cc3b4a39d7..75293b29194 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/setting/ws/ListDefinitionsAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/setting/ws/ListDefinitionsAction.java @@ -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 loadComponent(ListDefinitionsRequest valuesRequest) { + private Optional 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); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/setting/ws/SetAction.java b/server/sonar-server/src/main/java/org/sonar/server/setting/ws/SetAction.java index 910be41d473..f4386026588 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/setting/ws/SetAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/setting/ws/SetAction.java @@ -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 COMMA_JOINER = Collectors.joining(","); private static final String MSG_NO_EMPTY_VALUE = "A non empty value must be provided"; - public static final Set 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) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/setting/ws/SettingsWs.java b/server/sonar-server/src/main/java/org/sonar/server/setting/ws/SettingsWs.java index 068d1b07209..9a787022b01 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/setting/ws/SettingsWs.java +++ b/server/sonar-server/src/main/java/org/sonar/server/setting/ws/SettingsWs.java @@ -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 SETTING_ON_BRANCHES = ImmutableSet.of(LEAK_PERIOD); + private final SettingsWsAction[] actions; public SettingsWs(SettingsWsAction... actions) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/setting/ws/SettingsWsSupport.java b/server/sonar-server/src/main/java/org/sonar/server/setting/ws/SettingsWsSupport.java index 86bf8bda7db..89541441ed5 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/setting/ws/SettingsWsSupport.java +++ b/server/sonar-server/src/main/java/org/sonar/server/setting/ws/SettingsWsSupport.java @@ -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 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"); + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/setting/ws/ListDefinitionsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/setting/ws/ListDefinitionsActionTest.java index 962811d1bbc..a984bbc78cf 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/setting/ws/ListDefinitionsActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/setting/ws/ListDefinitionsActionTest.java @@ -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 diff --git a/server/sonar-server/src/test/java/org/sonar/server/setting/ws/SetActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/setting/ws/SetActionTest.java index 7f93922865b..1b18dce0a2b 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/setting/ws/SetActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/setting/ws/SetActionTest.java @@ -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 diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/setting/ListDefinitionsRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/setting/ListDefinitionsRequest.java index a5aefe42a9f..0e2ac0ddb19 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/setting/ListDefinitionsRequest.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/setting/ListDefinitionsRequest.java @@ -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); } diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/setting/SettingsService.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/setting/SettingsService.java index 3348fdb48c5..2fddb192e23 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/setting/SettingsService.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/setting/SettingsService.java @@ -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()); } diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/setting/ListDefinitionsRequestTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/setting/ListDefinitionsRequestTest.java index 989fcbc8eae..3a98984c95d 100644 --- a/sonar-ws/src/test/java/org/sonarqube/ws/client/setting/ListDefinitionsRequestTest.java +++ b/sonar-ws/src/test/java/org/sonarqube/ws/client/setting/ListDefinitionsRequestTest.java @@ -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"); } } diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/setting/SettingsServiceTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/setting/SettingsServiceTest.java index 247acd0247f..d3215980f70 100644 --- a/sonar-ws/src/test/java/org/sonarqube/ws/client/setting/SettingsServiceTest.java +++ b/sonar-ws/src/test/java/org/sonarqube/ws/client/setting/SettingsServiceTest.java @@ -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(); }