From a9dcddb21deaa014255d8bff601515bbdbdf20ff Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Tue, 30 Aug 2016 15:50:56 +0200 Subject: [PATCH] SONAR-8039 Create /api/licenses/list to return licenses with metadata --- .../sonar/server/license/ws/LicensesWs.java | 43 +++ .../server/license/ws/LicensesWsModule.java | 32 ++ .../sonar/server/license/ws/ListAction.java | 189 +++++++++++ .../sonar/server/license/ws/package-info.java | 23 ++ .../platformlevel/PlatformLevel4.java | 4 + .../sonar/server/license/ws/list-example.json | 28 ++ .../license/ws/LicensesWsModuleTest.java | 35 ++ .../server/license/ws/ListActionTest.java | 317 ++++++++++++++++++ .../server/setting/ws/ValuesActionTest.java | 58 ++-- .../ws/client/license/LicensesService.java | 41 +++ .../client/license/LicensesWsParameters.java | 32 ++ sonar-ws/src/main/protobuf/ws-licenses.proto | 51 +++ .../client/license/LicensesServiceTest.java | 49 +++ 13 files changed, 873 insertions(+), 29 deletions(-) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/license/ws/LicensesWs.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/license/ws/LicensesWsModule.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/license/ws/ListAction.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/license/ws/package-info.java create mode 100644 server/sonar-server/src/main/resources/org/sonar/server/license/ws/list-example.json create mode 100644 server/sonar-server/src/test/java/org/sonar/server/license/ws/LicensesWsModuleTest.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/license/ws/ListActionTest.java create mode 100644 sonar-ws/src/main/java/org/sonarqube/ws/client/license/LicensesService.java create mode 100644 sonar-ws/src/main/java/org/sonarqube/ws/client/license/LicensesWsParameters.java create mode 100644 sonar-ws/src/main/protobuf/ws-licenses.proto create mode 100644 sonar-ws/src/test/java/org/sonarqube/ws/client/license/LicensesServiceTest.java diff --git a/server/sonar-server/src/main/java/org/sonar/server/license/ws/LicensesWs.java b/server/sonar-server/src/main/java/org/sonar/server/license/ws/LicensesWs.java new file mode 100644 index 00000000000..06dc877ddcb --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/license/ws/LicensesWs.java @@ -0,0 +1,43 @@ +/* + * 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.license.ws; + +import org.sonar.api.server.ws.WebService; + +import static org.sonarqube.ws.client.license.LicensesWsParameters.CONTROLLER_SETTINGS; + +public class LicensesWs implements WebService { + + private final ListAction listAction; + + public LicensesWs(ListAction listAction) { + this.listAction = listAction; + } + + @Override + public void define(Context context) { + NewController controller = context.createController(CONTROLLER_SETTINGS) + .setDescription("Manage licenses") + .setSince("6.1"); + listAction.define(controller); + controller.done(); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/license/ws/LicensesWsModule.java b/server/sonar-server/src/main/java/org/sonar/server/license/ws/LicensesWsModule.java new file mode 100644 index 00000000000..656dcc175a4 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/license/ws/LicensesWsModule.java @@ -0,0 +1,32 @@ +/* + * 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.license.ws; + +import org.sonar.core.platform.Module; + +public class LicensesWsModule extends Module { + @Override + protected void configureModule() { + add( + LicensesWs.class, + ListAction.class); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/license/ws/ListAction.java b/server/sonar-server/src/main/java/org/sonar/server/license/ws/ListAction.java new file mode 100644 index 00000000000..6ff20b00d23 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/license/ws/ListAction.java @@ -0,0 +1,189 @@ +/* + * 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.license.ws; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; +import javax.annotation.Nullable; +import org.sonar.api.config.License; +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.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.property.PropertyDto; +import org.sonar.server.user.UserSession; +import org.sonar.server.ws.WsAction; +import org.sonarqube.ws.Licenses; +import org.sonarqube.ws.Licenses.ListWsResponse; + +import static com.google.common.collect.Sets.newHashSet; +import static org.sonar.api.CoreProperties.PERMANENT_SERVER_ID; +import static org.sonar.api.PropertyType.LICENSE; +import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN; +import static org.sonar.core.util.stream.Collectors.toSet; +import static org.sonar.core.util.stream.Collectors.uniqueIndex; +import static org.sonar.server.ws.WsUtils.writeProtobuf; +import static org.sonarqube.ws.client.license.LicensesWsParameters.ACTION_LIST; + +public class ListAction implements WsAction { + + private static final String ALL_SERVERS_VALUE = "*"; + + private final UserSession userSession; + private final PropertyDefinitions definitions; + private final DbClient dbClient; + + public ListAction(UserSession userSession, PropertyDefinitions definitions, DbClient dbClient) { + this.userSession = userSession; + this.definitions = definitions; + this.dbClient = dbClient; + } + + @Override + public void define(WebService.NewController context) { + context.createAction(ACTION_LIST) + .setDescription("List licenses settings.
" + + "Requires 'Administer System' permission") + .setResponseExample(getClass().getResource("list-example.json")) + .setSince("6.1") + .setInternal(true) + .setHandler(this); + } + + @Override + public void handle(Request request, Response response) throws Exception { + userSession.checkPermission(SYSTEM_ADMIN); + + DbSession dbSession = dbClient.openSession(true); + try { + writeProtobuf(doHandle(dbSession), request, response); + } finally { + dbClient.closeSession(dbSession); + } + } + + private ListWsResponse doHandle(DbSession dbSession) { + Set licenseSettingsKeys = definitions.getAll().stream() + .filter(definition -> LICENSE.equals(definition.type())) + .map(PropertyDefinition::key) + .collect(toSet()); + Set settingsKeys = newHashSet(licenseSettingsKeys); + settingsKeys.add(PERMANENT_SERVER_ID); + List properties = dbClient.propertiesDao().selectGlobalPropertiesByKeys(dbSession, settingsKeys); + return new ListResponseBuilder(licenseSettingsKeys, properties).build(); + } + + private static class ListResponseBuilder { + private final Optional serverId; + private final Map licenseSettingsByKey; + private final Set licenseSettingsKeys; + + ListResponseBuilder(Set licenseSettingsKeys, List properties) { + this.serverId = getServerId(properties); + this.licenseSettingsKeys = licenseSettingsKeys; + this.licenseSettingsByKey = properties.stream().collect(uniqueIndex(PropertyDto::getKey, Function.identity())); + } + + ListWsResponse build() { + ListWsResponse.Builder wsResponse = ListWsResponse.newBuilder(); + licenseSettingsKeys.forEach(key -> wsResponse.addLicenses(buildLicense(key, licenseSettingsByKey.get(key)))); + return wsResponse.build(); + } + + private Licenses.License buildLicense(String key, @Nullable PropertyDto setting) { + Licenses.License.Builder licenseBuilder = Licenses.License.newBuilder().setKey(key); + if (setting != null) { + License license = License.readBase64(setting.getValue()); + licenseBuilder.setValue(setting.getValue()); + setProduct(licenseBuilder, license, setting); + setOrganization(licenseBuilder, license); + setExpiration(licenseBuilder, license); + setServerId(licenseBuilder, license); + setType(licenseBuilder, license); + setAdditionalProperties(licenseBuilder, license); + } + return licenseBuilder.build(); + } + + private static void setProduct(Licenses.License.Builder licenseBuilder, License license, PropertyDto setting) { + String product = license.getProduct(); + if (product != null) { + licenseBuilder.setProduct(product); + } + if (product == null || !setting.getKey().contains(product)) { + licenseBuilder.setInvalidProduct(true); + } + } + + private static void setOrganization(Licenses.License.Builder licenseBuilder, License license) { + String licenseOrganization = license.getOrganization(); + if (licenseOrganization != null) { + licenseBuilder.setOrganization(licenseOrganization); + } + } + + private void setServerId(Licenses.License.Builder licenseBuilder, License license) { + String licenseServerId = license.getServer(); + if (licenseServerId != null) { + licenseBuilder.setServerId(licenseServerId); + } + if (!Objects.equals(ALL_SERVERS_VALUE, licenseServerId) && serverId.isPresent() && !serverId.get().equals(licenseServerId)) { + licenseBuilder.setInvalidServerId(true); + } + } + + private static void setExpiration(Licenses.License.Builder licenseBuilder, License license) { + String expiration = license.getExpirationDateAsString(); + if (expiration != null) { + licenseBuilder.setExpiration(expiration); + } + if (license.isExpired()) { + licenseBuilder.setInvalidExpiration(true); + } + } + + private static void setType(Licenses.License.Builder licenseBuilder, License license) { + String type = license.getType(); + if (type != null) { + licenseBuilder.setType(type); + } + } + + private static void setAdditionalProperties(Licenses.License.Builder licenseBuilder, License license) { + Map additionalProperties = license.additionalProperties(); + if (!additionalProperties.isEmpty()) { + licenseBuilder.getAdditionalPropertiesBuilder().putAllAdditionalProperties(additionalProperties).build(); + } + } + + private static Optional getServerId(List propertyDtos) { + Optional propertyDto = propertyDtos.stream().filter(setting -> setting.getKey().equals(PERMANENT_SERVER_ID)).findFirst(); + return propertyDto.isPresent() ? Optional.of(propertyDto.get().getValue()) : Optional.empty(); + } + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/license/ws/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/license/ws/package-info.java new file mode 100644 index 00000000000..c31656ea2fe --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/license/ws/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ +@ParametersAreNonnullByDefault +package org.sonar.server.license.ws; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java index fa0fcc45238..b2a65af5969 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java @@ -119,6 +119,7 @@ import org.sonar.server.issue.workflow.FunctionExecutor; import org.sonar.server.issue.workflow.IssueWorkflow; import org.sonar.server.issue.ws.IssueWsModule; import org.sonar.server.language.ws.LanguageWs; +import org.sonar.server.license.ws.LicensesWsModule; import org.sonar.server.measure.MeasureFilterEngine; import org.sonar.server.measure.MeasureFilterExecutor; import org.sonar.server.measure.MeasureFilterFactory; @@ -584,6 +585,9 @@ public class PlatformLevel4 extends PlatformLevel { PropertiesWs.class, SettingsWsModule.class, + // Licences + LicensesWsModule.class, + TypeValidationModule.class, // Project Links diff --git a/server/sonar-server/src/main/resources/org/sonar/server/license/ws/list-example.json b/server/sonar-server/src/main/resources/org/sonar/server/license/ws/list-example.json new file mode 100644 index 00000000000..3ec21fa9f71 --- /dev/null +++ b/server/sonar-server/src/main/resources/org/sonar/server/license/ws/list-example.json @@ -0,0 +1,28 @@ +{ + "licenses": [ + { + "key": "sonar.devcockpit.license.secured", + "value": "T3JnYW5pc2F0aW9uOiBVbmtub3duIApTZXJ2ZXI6IDU0MzIxIApQcm9kdWN0OiBvdGhlciAKRXhwaXJhdGlvbjogMjAxMC0wMS0wMSAKVHlwZTogRVZBTFVBVElPTiAK", + "product": "other", + "organization": "Unknown", + "expiration": "2010-01-01", + "serverId": "54321", + "type": "EVALUATION", + "invalidProduct": true, + "invalidExpiration": true, + "invalidServerId": true + }, + { + "key": "sonar.governance.license.secured", + "value": "T3JnYW5pc2F0aW9uOiBTb25hclNvdXJjZSAKU2VydmVyOiAxMjM0NSAKUHJvZHVjdDogZ292ZXJuYW5jZSAKRXhwaXJhdGlvbjogMjA5OS0wMS0wMSAKVHlwZTogUFJPRFVDVElPTiAKb3RoZXI6IHZhbHVlIAo\u003d", + "product": "governance", + "organization": "SonarSource", + "expiration": "2099-01-01", + "serverId": "12345", + "type": "PRODUCTION", + "additionalProperties": { + "other": "value" + } + } + ] +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/license/ws/LicensesWsModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/license/ws/LicensesWsModuleTest.java new file mode 100644 index 00000000000..dc1c9ff24c9 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/license/ws/LicensesWsModuleTest.java @@ -0,0 +1,35 @@ +/* + * 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.license.ws; + +import org.junit.Test; +import org.sonar.core.platform.ComponentContainer; + +import static org.assertj.core.api.Assertions.assertThat; + +public class LicensesWsModuleTest { + @Test + public void verify_count_of_added_components() { + ComponentContainer container = new ComponentContainer(); + new LicensesWsModule().configure(container); + assertThat(container.size()).isEqualTo(2 + 2); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/license/ws/ListActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/license/ws/ListActionTest.java new file mode 100644 index 00000000000..15edb494b36 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/license/ws/ListActionTest.java @@ -0,0 +1,317 @@ +/* + * 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.license.ws; + +import com.google.common.collect.ImmutableMap; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.Map; +import javax.annotation.Nullable; +import org.apache.commons.codec.binary.Base64; +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.DbTester; +import org.sonar.db.property.PropertyDbTester; +import org.sonar.server.exceptions.ForbiddenException; +import org.sonar.server.tester.UserSessionRule; +import org.sonar.server.ws.TestRequest; +import org.sonar.server.ws.WsActionTester; +import org.sonar.test.JsonAssert; +import org.sonarqube.ws.Licenses; +import org.sonarqube.ws.Licenses.ListWsResponse; +import org.sonarqube.ws.MediaTypes; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Java6Assertions.entry; +import static org.sonar.api.CoreProperties.PERMANENT_SERVER_ID; +import static org.sonar.api.PropertyType.LICENSE; +import static org.sonar.core.permission.GlobalPermissions.DASHBOARD_SHARING; +import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN; +import static org.sonar.db.property.PropertyTesting.newGlobalPropertyDto; +import static org.sonarqube.ws.MediaTypes.JSON; + +public class ListActionTest { + + private static final String LICENSE_KEY_SAMPLE = "sonar.governance.license.secured"; + private static final String ORGANISATION_SAMPLE = "SonarSource"; + private static final String SERVER_ID_SAMPLE = "12345"; + private static final String PRODUCT_SAMPLE = "governance"; + private static final String TYPE_SAMPLE = "PRODUCTION"; + private static final String EXPIRATION_SAMPLE = "2099-01-01"; + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Rule + public UserSessionRule userSession = UserSessionRule.standalone(); + + @Rule + public DbTester db = DbTester.create(System2.INSTANCE); + + DbClient dbClient = db.getDbClient(); + PropertyDbTester propertyDb = new PropertyDbTester(db); + PropertyDefinitions definitions = new PropertyDefinitions(); + + WsActionTester ws = new WsActionTester(new ListAction(userSession, definitions, dbClient)); + + @Test + public void return_licenses() throws Exception { + setUserAsSystemAdmin(); + addServerIdSettings("12345"); + String data = createBase64License("SonarSource", "governance", "12345", "2099-01-01", "PRODUCTION", ImmutableMap.of("other", "value")); + addLicenseSetting("sonar.governance.license.secured", data); + + ListWsResponse result = executeRequest(); + + assertThat(result.getLicensesList()).hasSize(1); + Licenses.License license = result.getLicenses(0); + assertThat(license.getKey()).isEqualTo("sonar.governance.license.secured"); + assertThat(license.getValue()).isEqualTo(data); + assertThat(license.getProduct()).isEqualTo("governance"); + assertThat(license.getOrganization()).isEqualTo("SonarSource"); + assertThat(license.getExpiration()).isEqualTo("2099-01-01"); + assertThat(license.getType()).isEqualTo("PRODUCTION"); + assertThat(license.getServerId()).isEqualTo("12345"); + assertThat(license.getAdditionalProperties().getAdditionalProperties()).containsOnly(entry("other", "value")); + + assertThat(license.hasInvalidProduct()).isFalse(); + assertThat(license.hasInvalidExpiration()).isFalse(); + assertThat(license.hasInvalidServerId()).isFalse(); + } + + @Test + public void return_licenses_even_if_no_value_set_in_database() throws Exception { + setUserAsSystemAdmin(); + addServerIdSettings("12345"); + definitions.addComponent(PropertyDefinition.builder("sonar.governance.license.secured").type(LICENSE).build()); + + ListWsResponse result = executeRequest(); + + assertThat(result.getLicensesList()).hasSize(1); + Licenses.License license = result.getLicenses(0); + assertThat(license.getKey()).isEqualTo("sonar.governance.license.secured"); + assertThat(license.hasValue()).isFalse(); + assertThat(license.hasProduct()).isFalse(); + assertThat(license.hasOrganization()).isFalse(); + assertThat(license.hasExpiration()).isFalse(); + assertThat(license.hasType()).isFalse(); + assertThat(license.hasServerId()).isFalse(); + assertThat(license.hasAdditionalProperties()).isFalse(); + + assertThat(license.hasInvalidProduct()).isFalse(); + assertThat(license.hasInvalidExpiration()).isFalse(); + assertThat(license.hasInvalidServerId()).isFalse(); + } + + @Test + public void return_license_with_minimal_info() throws Exception { + setUserAsSystemAdmin(); + addServerIdSettings(SERVER_ID_SAMPLE); + addLicenseSetting(LICENSE_KEY_SAMPLE, toBase64("")); + + ListWsResponse result = executeRequest(); + + assertThat(result.getLicensesList()).hasSize(1); + Licenses.License license = result.getLicenses(0); + assertThat(license.getKey()).isEqualTo(LICENSE_KEY_SAMPLE); + assertThat(license.getValue()).isEmpty(); + assertThat(license.hasProduct()).isFalse(); + assertThat(license.hasOrganization()).isFalse(); + assertThat(license.hasExpiration()).isFalse(); + assertThat(license.hasType()).isFalse(); + assertThat(license.hasServerId()).isFalse(); + assertThat(license.hasAdditionalProperties()).isFalse(); + + assertThat(license.hasInvalidProduct()).isTrue(); + assertThat(license.hasInvalidExpiration()).isFalse(); + assertThat(license.hasInvalidServerId()).isTrue(); + } + + @Test + public void return_license_with_bad_product() throws Exception { + setUserAsSystemAdmin(); + addServerIdSettings(SERVER_ID_SAMPLE); + addLicenseSetting(LICENSE_KEY_SAMPLE, createBase64License(ORGANISATION_SAMPLE, "Other", SERVER_ID_SAMPLE, EXPIRATION_SAMPLE, TYPE_SAMPLE, Collections.emptyMap())); + + ListWsResponse result = executeRequest(); + + assertThat(result.getLicensesList()).hasSize(1); + Licenses.License license = result.getLicenses(0); + assertThat(license.getProduct()).isEqualTo("Other"); + assertThat(license.getInvalidProduct()).isTrue(); + assertThat(license.hasInvalidExpiration()).isFalse(); + assertThat(license.hasInvalidServerId()).isFalse(); + } + + @Test + public void return_license_with_bad_server_id() throws Exception { + setUserAsSystemAdmin(); + addServerIdSettings(SERVER_ID_SAMPLE); + addLicenseSetting(LICENSE_KEY_SAMPLE, createBase64License(ORGANISATION_SAMPLE, PRODUCT_SAMPLE, "Other", EXPIRATION_SAMPLE, TYPE_SAMPLE, Collections.emptyMap())); + + ListWsResponse result = executeRequest(); + + assertThat(result.getLicensesList()).hasSize(1); + Licenses.License license = result.getLicenses(0); + assertThat(license.getServerId()).isEqualTo("Other"); + assertThat(license.getInvalidServerId()).isTrue(); + assertThat(license.hasInvalidProduct()).isFalse(); + assertThat(license.hasInvalidExpiration()).isFalse(); + } + + @Test + public void does_not_return_invalid_server_id_when_all_servers_accepted_and_no_server_id_setting() throws Exception { + setUserAsSystemAdmin(); + addLicenseSetting(LICENSE_KEY_SAMPLE, createBase64License(ORGANISATION_SAMPLE, PRODUCT_SAMPLE, "*", EXPIRATION_SAMPLE, TYPE_SAMPLE, Collections.emptyMap())); + + ListWsResponse result = executeRequest(); + + assertThat(result.getLicensesList()).hasSize(1); + Licenses.License license = result.getLicenses(0); + assertThat(license.getServerId()).isEqualTo("*"); + assertThat(license.hasInvalidServerId()).isFalse(); + } + + @Test + public void return_license_when_all_servers_are_accepted() throws Exception { + setUserAsSystemAdmin(); + addServerIdSettings(SERVER_ID_SAMPLE); + addLicenseSetting(LICENSE_KEY_SAMPLE, createBase64License(ORGANISATION_SAMPLE, PRODUCT_SAMPLE, "*", EXPIRATION_SAMPLE, TYPE_SAMPLE, Collections.emptyMap())); + + ListWsResponse result = executeRequest(); + + assertThat(result.getLicensesList()).hasSize(1); + Licenses.License license = result.getLicenses(0); + assertThat(license.getServerId()).isEqualTo("*"); + assertThat(license.hasInvalidServerId()).isFalse(); + } + + @Test + public void return_license_when_expired() throws Exception { + setUserAsSystemAdmin(); + addServerIdSettings(SERVER_ID_SAMPLE); + addLicenseSetting(LICENSE_KEY_SAMPLE, + createBase64License(ORGANISATION_SAMPLE, PRODUCT_SAMPLE, SERVER_ID_SAMPLE, "2010-01-01", TYPE_SAMPLE, Collections.emptyMap())); + + ListWsResponse result = executeRequest(); + + assertThat(result.getLicensesList()).hasSize(1); + Licenses.License license = result.getLicenses(0); + assertThat(license.getExpiration()).isEqualTo("2010-01-01"); + assertThat(license.getInvalidExpiration()).isTrue(); + assertThat(license.hasInvalidProduct()).isFalse(); + assertThat(license.hasInvalidServerId()).isFalse(); + } + + @Test + public void none_license_type_settings_are_not_returned() throws Exception { + setUserAsSystemAdmin(); + definitions.addComponent(PropertyDefinition.builder("foo").build()); + propertyDb.insertProperties(newGlobalPropertyDto().setKey("foo").setValue("value")); + + ListWsResponse result = executeRequest(); + + assertThat(result.getLicensesList()).isEmpty(); + } + + @Test + public void fail_when_not_system_admin() throws Exception { + userSession.login("not-admin").setGlobalPermissions(DASHBOARD_SHARING); + definitions.addComponent(PropertyDefinition.builder("foo").build()); + + expectedException.expect(ForbiddenException.class); + + executeRequest(); + } + + @Test + public void test_example_json_response() { + setUserAsSystemAdmin(); + addServerIdSettings("12345"); + addLicenseSetting("sonar.governance.license.secured", createBase64License("SonarSource", "governance", "12345", "2099-01-01", "PRODUCTION", ImmutableMap.of("other", "value"))); + addLicenseSetting("sonar.devcockpit.license.secured", createBase64License("Unknown", "other", "54321", "2010-01-01", "EVALUATION", Collections.emptyMap())); + + String result = ws.newRequest() + .setMediaType(JSON) + .execute() + .getInput(); + + JsonAssert.assertJson(ws.getDef().responseExampleAsString()).isSimilarTo(result); + } + + @Test + public void test_ws_definition() { + WebService.Action action = ws.getDef(); + assertThat(action).isNotNull(); + assertThat(action.isInternal()).isTrue(); + assertThat(action.isPost()).isFalse(); + assertThat(action.responseExampleAsString()).isNotEmpty(); + assertThat(action.params()).isEmpty(); + } + + private ListWsResponse executeRequest() { + TestRequest request = ws.newRequest() + .setMediaType(MediaTypes.PROTOBUF); + try { + return ListWsResponse.parseFrom(request.execute().getInputStream()); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + private void setUserAsSystemAdmin() { + userSession.login("admin").setGlobalPermissions(SYSTEM_ADMIN); + } + + private void addLicenseSetting(String key, String value) { + definitions.addComponent(PropertyDefinition.builder(key).type(LICENSE).build()); + propertyDb.insertProperties(newGlobalPropertyDto().setKey(key).setValue(value)); + } + + private void addServerIdSettings(String serverId) { + propertyDb.insertProperties(newGlobalPropertyDto().setKey(PERMANENT_SERVER_ID).setValue(serverId)); + } + + private static String toBase64(String data) { + return Base64.encodeBase64String((data.getBytes(StandardCharsets.UTF_8))); + } + + private static String createBase64License(@Nullable String organisation, @Nullable String product, @Nullable String serverId, @Nullable String expirationDate, + @Nullable String type, Map additionalProperties) { + StringBuilder data = new StringBuilder(); + data.append("Organisation: ").append(organisation).append(" \n"); + data.append("Server: ").append(serverId).append(" \n"); + data.append("Product: ").append(product).append(" \n"); + data.append("Expiration: ").append(expirationDate).append(" \n"); + data.append("Type: ").append(type).append(" \n"); + for (Map.Entry entry : additionalProperties.entrySet()) { + data.append(entry.getKey()).append(": ").append(entry.getValue()).append(" \n"); + } + return toBase64(data.toString()); + } + +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/setting/ws/ValuesActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/setting/ws/ValuesActionTest.java index 59ec14cf1d0..f32885cca81 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/setting/ws/ValuesActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/setting/ws/ValuesActionTest.java @@ -78,12 +78,12 @@ public class ValuesActionTest { DbClient dbClient = db.getDbClient(); PropertyDbTester propertyDb = new PropertyDbTester(db); ComponentDbTester componentDb = new ComponentDbTester(db); - PropertyDefinitions propertyDefinitions = new PropertyDefinitions(); - SettingsFinder settingsFinder = new SettingsFinder(dbClient, propertyDefinitions); + PropertyDefinitions definitions = new PropertyDefinitions(); + SettingsFinder settingsFinder = new SettingsFinder(dbClient, definitions); ComponentDto project; - WsActionTester ws = new WsActionTester(new ValuesAction(dbClient, new ComponentFinder(dbClient), userSession, propertyDefinitions, settingsFinder)); + WsActionTester ws = new WsActionTester(new ValuesAction(dbClient, new ComponentFinder(dbClient), userSession, definitions, settingsFinder)); @Before public void setUp() throws Exception { @@ -93,7 +93,7 @@ public class ValuesActionTest { @Test public void return_simple_value() throws Exception { setUserAsSystemAdmin(); - propertyDefinitions.addComponent(PropertyDefinition + definitions.addComponent(PropertyDefinition .builder("foo") .build()); propertyDb.insertProperties(newGlobalPropertyDto().setKey("foo").setValue("one")); @@ -114,13 +114,13 @@ public class ValuesActionTest { setUserAsSystemAdmin(); // Property never defined, default value is returned - propertyDefinitions.addComponent(PropertyDefinition.builder("default") + definitions.addComponent(PropertyDefinition.builder("default") .multiValues(true) .defaultValue("one,two") .build()); // Property defined at global level - propertyDefinitions.addComponent(PropertyDefinition.builder("global") + definitions.addComponent(PropertyDefinition.builder("global") .multiValues(true) .build()); propertyDb.insertProperties(newGlobalPropertyDto().setKey("global").setValue("three,four")); @@ -144,7 +144,7 @@ public class ValuesActionTest { @Test public void return_multi_value_with_coma() throws Exception { setUserAsSystemAdmin(); - propertyDefinitions.addComponent(PropertyDefinition.builder("global").multiValues(true).build()); + definitions.addComponent(PropertyDefinition.builder("global").multiValues(true).build()); propertyDb.insertProperties(newGlobalPropertyDto().setKey("global").setValue("three,four%2Cfive")); ValuesWsResponse result = executeRequestForGlobalProperties("global"); @@ -158,7 +158,7 @@ public class ValuesActionTest { @Test public void return_property_set() throws Exception { setUserAsSystemAdmin(); - propertyDefinitions.addComponent(PropertyDefinition + definitions.addComponent(PropertyDefinition .builder("foo") .type(PropertyType.PROPERTY_SET) .fields(asList( @@ -180,7 +180,7 @@ public class ValuesActionTest { @Test public void return_property_set_for_component() throws Exception { setUserAsSystemAdmin(); - propertyDefinitions.addComponent(PropertyDefinition + definitions.addComponent(PropertyDefinition .builder("foo") .type(PropertyType.PROPERTY_SET) .fields(asList( @@ -202,7 +202,7 @@ public class ValuesActionTest { @Test public void return_default_values() throws Exception { setUserAsSystemAdmin(); - propertyDefinitions.addComponent(PropertyDefinition + definitions.addComponent(PropertyDefinition .builder("foo") .defaultValue("default") .build()); @@ -216,7 +216,7 @@ public class ValuesActionTest { @Test public void return_global_values() throws Exception { setUserAsSystemAdmin(); - propertyDefinitions.addComponent(PropertyDefinition.builder("property").defaultValue("default").build()); + definitions.addComponent(PropertyDefinition.builder("property").defaultValue("default").build()); propertyDb.insertProperties( // The property is overriding default value newGlobalPropertyDto().setKey("property").setValue("one")); @@ -230,7 +230,7 @@ public class ValuesActionTest { @Test public void return_project_values() throws Exception { setUserAsSystemAdmin(); - propertyDefinitions.addComponent(PropertyDefinition.builder("property").defaultValue("default").build()); + definitions.addComponent(PropertyDefinition.builder("property").defaultValue("default").build()); propertyDb.insertProperties( newGlobalPropertyDto().setKey("property").setValue("one"), // The property is overriding global value @@ -245,7 +245,7 @@ public class ValuesActionTest { @Test public void return_is_inherited_to_true_when_property_is_defined_only_at_global_level() throws Exception { setUserAsSystemAdmin(); - propertyDefinitions.addComponent(PropertyDefinition.builder("property").defaultValue("default").build()); + definitions.addComponent(PropertyDefinition.builder("property").defaultValue("default").build()); // The property is not defined on project propertyDb.insertProperties(newGlobalPropertyDto().setKey("property").setValue("one")); @@ -271,7 +271,7 @@ public class ValuesActionTest { @Test public void return_empty_when_property_def_exists_but_no_value() throws Exception { setUserAsSystemAdmin(); - propertyDefinitions.addComponent(PropertyDefinition + definitions.addComponent(PropertyDefinition .builder("foo") .build()); @@ -283,7 +283,7 @@ public class ValuesActionTest { @Test public void return_nothing_when_unknown_keys() throws Exception { setUserAsSystemAdmin(); - propertyDefinitions.addComponent(PropertyDefinition + definitions.addComponent(PropertyDefinition .builder("foo") .defaultValue("default") .build()); @@ -298,7 +298,7 @@ public class ValuesActionTest { public void return_module_values() throws Exception { setUserAsSystemAdmin(); ComponentDto module = componentDb.insertComponent(newModuleDto(project)); - propertyDefinitions.addComponent(PropertyDefinition.builder("property").defaultValue("default").build()); + definitions.addComponent(PropertyDefinition.builder("property").defaultValue("default").build()); propertyDb.insertProperties( newGlobalPropertyDto().setKey("property").setValue("one"), // The property is overriding global value @@ -314,7 +314,7 @@ public class ValuesActionTest { public void return_inherited_values_on_module() throws Exception { setUserAsSystemAdmin(); ComponentDto module = componentDb.insertComponent(newModuleDto(project)); - propertyDefinitions.addComponents(asList( + definitions.addComponents(asList( PropertyDefinition.builder("defaultProperty").defaultValue("default").build(), PropertyDefinition.builder("globalProperty").build(), PropertyDefinition.builder("projectProperty").build(), @@ -336,7 +336,7 @@ public class ValuesActionTest { @Test public void return_inherited_values_on_global_setting() throws Exception { setUserAsSystemAdmin(); - propertyDefinitions.addComponents(asList( + definitions.addComponents(asList( PropertyDefinition.builder("defaultProperty").defaultValue("default").build(), PropertyDefinition.builder("globalProperty").build())); propertyDb.insertProperties( @@ -354,7 +354,7 @@ public class ValuesActionTest { setUserAsSystemAdmin(); ComponentDto module = componentDb.insertComponent(newModuleDto(project)); ComponentDto subModule = componentDb.insertComponent(newModuleDto(module)); - propertyDefinitions.addComponents(asList( + definitions.addComponents(asList( PropertyDefinition.builder("foo").defaultValue("default").build())); propertyDb.insertProperties( newGlobalPropertyDto().setKey("foo").setValue("global"), @@ -372,7 +372,7 @@ public class ValuesActionTest { setUserAsSystemAdmin(); ComponentDto module = componentDb.insertComponent(newModuleDto(project)); ComponentDto subModule = componentDb.insertComponent(newModuleDto(module)); - propertyDefinitions.addComponents(asList( + definitions.addComponents(asList( PropertyDefinition.builder("foo").defaultValue("default1,default2").multiValues(true).build())); propertyDb.insertProperties( newGlobalPropertyDto().setKey("foo").setValue("global1,global2"), @@ -390,7 +390,7 @@ public class ValuesActionTest { setUserAsSystemAdmin(); ComponentDto module = componentDb.insertComponent(newModuleDto(project)); ComponentDto subModule = componentDb.insertComponent(newModuleDto(module)); - propertyDefinitions.addComponent(PropertyDefinition + definitions.addComponent(PropertyDefinition .builder("foo") .type(PropertyType.PROPERTY_SET) .fields(asList( @@ -412,7 +412,7 @@ public class ValuesActionTest { setUserAsSystemAdmin(); ComponentDto module = componentDb.insertComponent(newModuleDto(project)); ComponentDto subModule = componentDb.insertComponent(newModuleDto(module)); - propertyDefinitions.addComponents(asList( + definitions.addComponents(asList( PropertyDefinition.builder("simple").build(), PropertyDefinition.builder("multi").multiValues(true).build(), PropertyDefinition.builder("set") @@ -447,7 +447,7 @@ public class ValuesActionTest { @Test public void return_value_of_deprecated_key() throws Exception { setUserAsSystemAdmin(); - propertyDefinitions.addComponent(PropertyDefinition + definitions.addComponent(PropertyDefinition .builder("foo") .deprecatedKey("deprecated") .build()); @@ -464,16 +464,16 @@ public class ValuesActionTest { @Test public void test_example_json_response() { setUserAsSystemAdmin(); - propertyDefinitions.addComponent(PropertyDefinition + definitions.addComponent(PropertyDefinition .builder("sonar.test.jira") .defaultValue("abc") .build()); - propertyDefinitions.addComponent(PropertyDefinition + definitions.addComponent(PropertyDefinition .builder("sonar.autogenerated") .multiValues(true) .build()); propertyDb.insertProperties(newGlobalPropertyDto().setKey("sonar.autogenerated").setValue("val1,val2,val3")); - propertyDefinitions.addComponent(PropertyDefinition + definitions.addComponent(PropertyDefinition .builder("sonar.demo") .type(PropertyType.PROPERTY_SET) .fields(PropertyFieldDefinition.build("text").name("Text").build(), @@ -502,7 +502,7 @@ public class ValuesActionTest { @Test public void fail_when_not_system_admin() throws Exception { userSession.login("not-admin").setGlobalPermissions(DASHBOARD_SHARING); - propertyDefinitions.addComponent(PropertyDefinition.builder("foo").build()); + definitions.addComponent(PropertyDefinition.builder("foo").build()); expectedException.expect(ForbiddenException.class); @@ -512,7 +512,7 @@ public class ValuesActionTest { @Test public void fail_when_not_project_admin() throws Exception { userSession.login("project-admin").addProjectUuidPermissions(USER, project.uuid()); - propertyDefinitions.addComponent(PropertyDefinition.builder("foo").build()); + definitions.addComponent(PropertyDefinition.builder("foo").build()); expectedException.expect(ForbiddenException.class); @@ -522,7 +522,7 @@ public class ValuesActionTest { @Test public void fail_when_deprecated_key_and_new_key_are_used() throws Exception { setUserAsSystemAdmin(); - propertyDefinitions.addComponent(PropertyDefinition + definitions.addComponent(PropertyDefinition .builder("foo") .deprecatedKey("deprecated") .build()); diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/license/LicensesService.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/license/LicensesService.java new file mode 100644 index 00000000000..93fb452ac0d --- /dev/null +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/license/LicensesService.java @@ -0,0 +1,41 @@ +/* + * 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.license; + +import org.sonarqube.ws.Licenses.ListWsResponse; +import org.sonarqube.ws.client.BaseService; +import org.sonarqube.ws.client.GetRequest; +import org.sonarqube.ws.client.WsConnector; + +import static org.sonarqube.ws.client.license.LicensesWsParameters.ACTION_LIST; +import static org.sonarqube.ws.client.license.LicensesWsParameters.CONTROLLER_SETTINGS; + +public class LicensesService extends BaseService { + + public LicensesService(WsConnector wsConnector) { + super(wsConnector, CONTROLLER_SETTINGS); + } + + public ListWsResponse list() { + GetRequest getRequest = new GetRequest(path(ACTION_LIST)); + return call(getRequest, ListWsResponse.parser()); + } + +} diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/license/LicensesWsParameters.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/license/LicensesWsParameters.java new file mode 100644 index 00000000000..a035f684519 --- /dev/null +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/license/LicensesWsParameters.java @@ -0,0 +1,32 @@ +/* + * 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.license; + +public class LicensesWsParameters { + public static final String CONTROLLER_SETTINGS = "api/licenses"; + + public static final String ACTION_LIST = "list"; + + private LicensesWsParameters() { + // Only static stuff + } + +} diff --git a/sonar-ws/src/main/protobuf/ws-licenses.proto b/sonar-ws/src/main/protobuf/ws-licenses.proto new file mode 100644 index 00000000000..77f1002ffba --- /dev/null +++ b/sonar-ws/src/main/protobuf/ws-licenses.proto @@ -0,0 +1,51 @@ +// SonarQube, open source software quality management tool. +// Copyright (C) 2008-2015 SonarSource +// mailto:contact AT sonarsource DOT com +// +// SonarQube 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. +// +// SonarQube 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. + +syntax = "proto2"; + +package sonarqube.ws.licenses; + +option java_package = "org.sonarqube.ws"; +option java_outer_classname = "Licenses"; +option optimize_for = SPEED; + +// Response of GET api/licenses/list +message ListWsResponse { + repeated License licenses = 1; +} + +message License { + optional string key = 1; + optional string value = 2; + optional string product = 3; + optional string organization = 4; + optional string expiration = 5; + optional string serverId = 6; + optional string type = 7; + optional AdditionalProperties additionalProperties = 8; + optional bool invalidProduct = 9; + optional bool invalidExpiration = 10; + optional bool invalidServerId = 11; +} + +message AdditionalProperties { + map additionalProperties = 1; +} + + + diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/license/LicensesServiceTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/license/LicensesServiceTest.java new file mode 100644 index 00000000000..8b305df0514 --- /dev/null +++ b/sonar-ws/src/test/java/org/sonarqube/ws/client/license/LicensesServiceTest.java @@ -0,0 +1,49 @@ +/* + * 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.license; + +import org.junit.Rule; +import org.junit.Test; +import org.sonarqube.ws.Licenses.ListWsResponse; +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; + +public class LicensesServiceTest { + + @Rule + public ServiceTester serviceTester = new ServiceTester<>(new LicensesService(mock(WsConnector.class))); + + private LicensesService underTest = serviceTester.getInstanceUnderTest(); + + @Test + public void list_definitions() { + underTest.list(); + GetRequest getRequest = serviceTester.getGetRequest(); + + assertThat(serviceTester.getGetParser()).isSameAs(ListWsResponse.parser()); + serviceTester.assertThat(getRequest).andNoOtherParam(); + } + +} -- 2.39.5