From 54be548dbeff18fc8c5ace739f80e99dda5c44eb Mon Sep 17 00:00:00 2001 From: Jacek Date: Thu, 8 Apr 2021 12:50:09 +0200 Subject: [PATCH] SONAR-14661 Disable WS plugin installation for commercial editions --- .../server/plugins/ws/InstallAction.java | 26 ++++-- .../server/plugins/ws/InstallActionTest.java | 93 +++++++++++-------- 2 files changed, 75 insertions(+), 44 deletions(-) diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/plugins/ws/InstallAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/plugins/ws/InstallAction.java index cac53ada5d7..b5778b69f01 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/plugins/ws/InstallAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/plugins/ws/InstallAction.java @@ -19,16 +19,15 @@ */ package org.sonar.server.plugins.ws; -import java.net.HttpURLConnection; import java.util.Objects; import java.util.Optional; - import org.sonar.api.config.Configuration; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; import org.sonar.core.extension.PluginRiskConsent; -import org.sonar.server.exceptions.ServerException; +import org.sonar.core.platform.EditionProvider.Edition; +import org.sonar.core.platform.PlatformEditionProvider; import org.sonar.server.plugins.PluginDownloader; import org.sonar.server.plugins.UpdateCenterMatrixFactory; import org.sonar.server.user.UserSession; @@ -44,19 +43,23 @@ import static org.sonar.server.plugins.edition.EditionBundledPlugins.isEditionBu */ public class InstallAction implements PluginsWsAction { + private static final String BR_HTML_TAG = "
"; private static final String PARAM_KEY = "key"; private final UpdateCenterMatrixFactory updateCenterFactory; private final PluginDownloader pluginDownloader; private final UserSession userSession; private final Configuration configuration; + private final PlatformEditionProvider editionProvider; public InstallAction(UpdateCenterMatrixFactory updateCenterFactory, PluginDownloader pluginDownloader, - UserSession userSession, Configuration configuration) { + UserSession userSession, Configuration configuration, + PlatformEditionProvider editionProvider) { this.updateCenterFactory = updateCenterFactory; this.pluginDownloader = pluginDownloader; this.userSession = userSession; this.configuration = configuration; + this.editionProvider = editionProvider; } @Override @@ -65,9 +68,11 @@ public class InstallAction implements PluginsWsAction { .setPost(true) .setSince("5.2") .setDescription("Installs the latest version of a plugin specified by its key." + - "
" + + BR_HTML_TAG + "Plugin information is retrieved from Update Center." + - "
" + + BR_HTML_TAG + + "Fails if used on commercial editions or plugin risk consent has not been accepted." + + BR_HTML_TAG + "Requires user to be authenticated with Administer System permissions") .setHandler(this); @@ -78,6 +83,8 @@ public class InstallAction implements PluginsWsAction { @Override public void handle(Request request, Response response) throws Exception { userSession.checkIsSystemAdministrator(); + checkEdition(); + if (!hasPluginInstallConsent()) { throw new IllegalArgumentException("Can't install plugin without accepting firstly plugins risk consent"); } @@ -88,6 +95,13 @@ public class InstallAction implements PluginsWsAction { response.noContent(); } + private void checkEdition() { + Edition edition = editionProvider.get().orElse(Edition.COMMUNITY); + if (!Edition.COMMUNITY.equals(edition)) { + throw new IllegalArgumentException("This WS is unsupported in commercial edition. Please install plugin manually."); + } + } + private boolean hasPluginInstallConsent() { Optional pluginRiskConsent = configuration.get(PLUGINS_RISK_CONSENT); return pluginRiskConsent.filter(s -> PluginRiskConsent.valueOf(s) == PluginRiskConsent.ACCEPTED).isPresent(); diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/plugins/ws/InstallActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/plugins/ws/InstallActionTest.java index a3d36b670c3..37a85f9119a 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/plugins/ws/InstallActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/plugins/ws/InstallActionTest.java @@ -23,22 +23,21 @@ import com.google.common.collect.ImmutableList; import com.tngtech.java.junit.dataprovider.DataProvider; import com.tngtech.java.junit.dataprovider.DataProviderRunner; import com.tngtech.java.junit.dataprovider.UseDataProvider; - import java.util.Optional; - import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.sonar.api.config.Configuration; import org.sonar.api.server.ws.WebService; import org.sonar.core.extension.PluginRiskConsent; +import org.sonar.core.platform.EditionProvider.Edition; +import org.sonar.core.platform.PlatformEditionProvider; import org.sonar.server.exceptions.ForbiddenException; -import org.sonar.server.exceptions.ServerException; import org.sonar.server.plugins.PluginDownloader; import org.sonar.server.plugins.UpdateCenterMatrixFactory; 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.sonar.updatecenter.common.Plugin; @@ -63,38 +62,40 @@ public class InstallActionTest { @Rule public UserSessionRule userSessionRule = UserSessionRule.standalone(); - @Rule - public ExpectedException expectedException = ExpectedException.none(); private UpdateCenterMatrixFactory updateCenterFactory = mock(UpdateCenterMatrixFactory.class); private UpdateCenter updateCenter = mock(UpdateCenter.class); private PluginDownloader pluginDownloader = mock(PluginDownloader.class); private Configuration configuration = mock(Configuration.class); - private InstallAction underTest = new InstallAction(updateCenterFactory, pluginDownloader, userSessionRule, configuration); + private PlatformEditionProvider editionProvider = mock(PlatformEditionProvider.class); + private InstallAction underTest = new InstallAction(updateCenterFactory, pluginDownloader, userSessionRule, configuration, + editionProvider); private WsActionTester tester = new WsActionTester(underTest); @Before public void wireMocks() { + when(editionProvider.get()).thenReturn(Optional.of(Edition.COMMUNITY)); when(updateCenterFactory.getUpdateCenter(anyBoolean())).thenReturn(Optional.of(updateCenter)); when(configuration.get(PLUGINS_RISK_CONSENT)).thenReturn(Optional.of(PluginRiskConsent.ACCEPTED.name())); } @Test public void request_fails_with_ForbiddenException_when_user_is_not_logged_in() { - expectedException.expect(ForbiddenException.class); - expectedException.expectMessage("Insufficient privileges"); - - tester.newRequest().execute(); + TestRequest wsRequest = tester.newRequest(); + assertThatThrownBy(wsRequest::execute) + .isInstanceOf(ForbiddenException.class) + .hasMessage("Insufficient privileges"); } @Test public void request_fails_with_ForbiddenException_when_user_is_not_system_administrator() { userSessionRule.logIn().setNonSystemAdministrator(); - expectedException.expect(ForbiddenException.class); - expectedException.expectMessage("Insufficient privileges"); - - tester.newRequest().execute(); + TestRequest request = tester.newRequest(); + assertThatThrownBy(request::execute) + .isInstanceOf(ForbiddenException.class) + .hasMessage("Insufficient privileges"); + ; } @Test @@ -115,20 +116,22 @@ public class InstallActionTest { @Test public void IAE_is_raised_when_key_param_is_not_provided() { logInAsSystemAdministrator(); - expectedException.expect(IllegalArgumentException.class); - tester.newRequest().execute(); + TestRequest request = tester.newRequest(); + assertThatThrownBy(request::execute) + .isInstanceOf(IllegalArgumentException.class); } @Test public void IAE_is_raised_when_there_is_no_available_plugin_for_the_key() { logInAsSystemAdministrator(); - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("No plugin with key 'pluginKey'"); - tester.newRequest() - .setParam(KEY_PARAM, PLUGIN_KEY) - .execute(); + TestRequest request = tester.newRequest() + .setParam(KEY_PARAM, PLUGIN_KEY); + + assertThatThrownBy(request::execute) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("No plugin with key 'pluginKey'"); } @Test @@ -141,34 +144,48 @@ public class InstallActionTest { .setLicense(license) .setOrganization(organization), version), PluginUpdate.Status.COMPATIBLE))); - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("SonarSource commercial plugin with key '" + PLUGIN_KEY + "' can only be installed as part of a SonarSource edition"); - - tester.newRequest() - .setParam(KEY_PARAM, PLUGIN_KEY) - .execute(); + TestRequest request = tester.newRequest() + .setParam(KEY_PARAM, PLUGIN_KEY); + assertThatThrownBy(request::execute) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("SonarSource commercial plugin with key '" + PLUGIN_KEY + "' can only be installed as part of a SonarSource edition"); } @DataProvider public static Object[][] editionBundledOrganizationAndLicense() { - return new Object[][]{ + return new Object[][] { {"SonarSource", "SonarSource"}, {"SonarSource", "Commercial"}, {"sonarsource", "SOnArSOURCE"} }; } + @Test + public void IAE_is_raised_when_WS_used_on_commercial_edition() { + logInAsSystemAdministrator(); + Version version = Version.create("1.0"); + when(updateCenter.findAvailablePlugins()).thenReturn(ImmutableList.of( + PluginUpdate.createWithStatus(new Release(Plugin.factory(PLUGIN_KEY), version), PluginUpdate.Status.COMPATIBLE))); + + when(editionProvider.get()).thenReturn(Optional.of(Edition.DEVELOPER)); + + TestRequest request = tester.newRequest() + .setParam(KEY_PARAM, PLUGIN_KEY); + assertThatThrownBy(request::execute) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("This WS is unsupported in commercial edition. Please install plugin manually."); + } + @Test public void IAE_is_raised_when_update_center_is_unavailable() { logInAsSystemAdministrator(); when(updateCenterFactory.getUpdateCenter(anyBoolean())).thenReturn(Optional.empty()); - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("No plugin with key 'pluginKey'"); - - tester.newRequest() - .setParam(KEY_PARAM, PLUGIN_KEY) - .execute(); + TestRequest request = tester.newRequest() + .setParam(KEY_PARAM, PLUGIN_KEY); + assertThatThrownBy(request::execute) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("No plugin with key 'pluginKey'"); } @Test @@ -192,9 +209,9 @@ public class InstallActionTest { when(configuration.get(PLUGINS_RISK_CONSENT)).thenReturn(Optional.of(PluginRiskConsent.NOT_ACCEPTED.name())); - assertThatThrownBy(() -> tester.newRequest() - .setParam(KEY_PARAM, PLUGIN_KEY) - .execute()) + TestRequest request = tester.newRequest() + .setParam(KEY_PARAM, PLUGIN_KEY); + assertThatThrownBy(request::execute) .isInstanceOf(IllegalArgumentException.class) .hasMessage("Can't install plugin without accepting firstly plugins risk consent"); -- 2.39.5