--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.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();
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.license.ws;
+
+import org.sonar.core.platform.Module;
+
+public class LicensesWsModule extends Module {
+ @Override
+ protected void configureModule() {
+ add(
+ LicensesWs.class,
+ ListAction.class);
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.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.<br>" +
+ "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<String> licenseSettingsKeys = definitions.getAll().stream()
+ .filter(definition -> LICENSE.equals(definition.type()))
+ .map(PropertyDefinition::key)
+ .collect(toSet());
+ Set<String> settingsKeys = newHashSet(licenseSettingsKeys);
+ settingsKeys.add(PERMANENT_SERVER_ID);
+ List<PropertyDto> properties = dbClient.propertiesDao().selectGlobalPropertiesByKeys(dbSession, settingsKeys);
+ return new ListResponseBuilder(licenseSettingsKeys, properties).build();
+ }
+
+ private static class ListResponseBuilder {
+ private final Optional<String> serverId;
+ private final Map<String, PropertyDto> licenseSettingsByKey;
+ private final Set<String> licenseSettingsKeys;
+
+ ListResponseBuilder(Set<String> licenseSettingsKeys, List<PropertyDto> 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<String, String> additionalProperties = license.additionalProperties();
+ if (!additionalProperties.isEmpty()) {
+ licenseBuilder.getAdditionalPropertiesBuilder().putAllAdditionalProperties(additionalProperties).build();
+ }
+ }
+
+ private static Optional<String> getServerId(List<PropertyDto> propertyDtos) {
+ Optional<PropertyDto> propertyDto = propertyDtos.stream().filter(setting -> setting.getKey().equals(PERMANENT_SERVER_ID)).findFirst();
+ return propertyDto.isPresent() ? Optional.of(propertyDto.get().getValue()) : Optional.empty();
+ }
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.server.license.ws;
+
+import javax.annotation.ParametersAreNonnullByDefault;
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;
PropertiesWs.class,
SettingsWsModule.class,
+ // Licences
+ LicensesWsModule.class,
+
TypeValidationModule.class,
// Project Links
--- /dev/null
+{
+ "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"
+ }
+ }
+ ]
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.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);
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.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<String, String> 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<String, String> entry : additionalProperties.entrySet()) {
+ data.append(entry.getKey()).append(": ").append(entry.getValue()).append(" \n");
+ }
+ return toBase64(data.toString());
+ }
+
+}
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 {
@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"));
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"));
@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");
@Test
public void return_property_set() throws Exception {
setUserAsSystemAdmin();
- propertyDefinitions.addComponent(PropertyDefinition
+ definitions.addComponent(PropertyDefinition
.builder("foo")
.type(PropertyType.PROPERTY_SET)
.fields(asList(
@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(
@Test
public void return_default_values() throws Exception {
setUserAsSystemAdmin();
- propertyDefinitions.addComponent(PropertyDefinition
+ definitions.addComponent(PropertyDefinition
.builder("foo")
.defaultValue("default")
.build());
@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"));
@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
@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"));
@Test
public void return_empty_when_property_def_exists_but_no_value() throws Exception {
setUserAsSystemAdmin();
- propertyDefinitions.addComponent(PropertyDefinition
+ definitions.addComponent(PropertyDefinition
.builder("foo")
.build());
@Test
public void return_nothing_when_unknown_keys() throws Exception {
setUserAsSystemAdmin();
- propertyDefinitions.addComponent(PropertyDefinition
+ definitions.addComponent(PropertyDefinition
.builder("foo")
.defaultValue("default")
.build());
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
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(),
@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(
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"),
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"),
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(
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")
@Test
public void return_value_of_deprecated_key() throws Exception {
setUserAsSystemAdmin();
- propertyDefinitions.addComponent(PropertyDefinition
+ definitions.addComponent(PropertyDefinition
.builder("foo")
.deprecatedKey("deprecated")
.build());
@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(),
@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);
@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);
@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());
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonarqube.ws.client.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());
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonarqube.ws.client.license;
+
+public class LicensesWsParameters {
+ public static final String CONTROLLER_SETTINGS = "api/licenses";
+
+ public static final String ACTION_LIST = "list";
+
+ private LicensesWsParameters() {
+ // Only static stuff
+ }
+
+}
--- /dev/null
+// 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<string, string> additionalProperties = 1;
+}
+
+
+
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonarqube.ws.client.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<LicensesService> 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();
+ }
+
+}