Przeglądaj źródła

SONAR-8039 Create /api/licenses/list to return licenses with metadata

tags/6.1-RC1
Julien Lancelot 7 lat temu
rodzic
commit
a9dcddb21d

+ 43
- 0
server/sonar-server/src/main/java/org/sonar/server/license/ws/LicensesWs.java Wyświetl plik

@@ -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();
}
}

+ 32
- 0
server/sonar-server/src/main/java/org/sonar/server/license/ws/LicensesWsModule.java Wyświetl plik

@@ -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);
}
}

+ 189
- 0
server/sonar-server/src/main/java/org/sonar/server/license/ws/ListAction.java Wyświetl plik

@@ -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.<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();
}
}
}

+ 23
- 0
server/sonar-server/src/main/java/org/sonar/server/license/ws/package-info.java Wyświetl plik

@@ -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;

+ 4
- 0
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java Wyświetl plik

@@ -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

+ 28
- 0
server/sonar-server/src/main/resources/org/sonar/server/license/ws/list-example.json Wyświetl plik

@@ -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"
}
}
]
}

+ 35
- 0
server/sonar-server/src/test/java/org/sonar/server/license/ws/LicensesWsModuleTest.java Wyświetl plik

@@ -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);
}
}

+ 317
- 0
server/sonar-server/src/test/java/org/sonar/server/license/ws/ListActionTest.java Wyświetl plik

@@ -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<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());
}

}

+ 29
- 29
server/sonar-server/src/test/java/org/sonar/server/setting/ws/ValuesActionTest.java Wyświetl plik

@@ -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());

+ 41
- 0
sonar-ws/src/main/java/org/sonarqube/ws/client/license/LicensesService.java Wyświetl plik

@@ -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());
}

}

+ 32
- 0
sonar-ws/src/main/java/org/sonarqube/ws/client/license/LicensesWsParameters.java Wyświetl plik

@@ -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
}

}

+ 51
- 0
sonar-ws/src/main/protobuf/ws-licenses.proto Wyświetl plik

@@ -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<string, string> additionalProperties = 1;
}




+ 49
- 0
sonar-ws/src/test/java/org/sonarqube/ws/client/license/LicensesServiceTest.java Wyświetl plik

@@ -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<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();
}

}

Ładowanie…
Anuluj
Zapisz