From a08329bf170fcfc10aa3620fcb68df29de1537cb Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Fri, 2 Sep 2016 15:01:00 +0200 Subject: [PATCH] SONAR-7985 Create /api/server_id/show WS --- .../UserSessionInitializer.java | 2 +- .../server/platform/ServerIdGenerator.java | 2 + .../platformlevel/PlatformLevel4.java | 4 + .../sonar/server/serverid/ws/ServerIdWs.java | 42 ++++ .../server/serverid/ws/ServerIdWsAction.java | 26 +++ .../server/serverid/ws/ServerIdWsModule.java | 31 +++ .../sonar/server/serverid/ws/ShowAction.java | 125 +++++++++++ .../server/serverid/ws/package-info.java | 23 ++ .../server/serverid/ws/show-example.json | 9 + .../UserSessionInitializerTest.java | 27 ++- .../serverid/ws/ServerIdWsModuleTest.java | 35 +++ .../server/serverid/ws/ShowActionTest.java | 211 ++++++++++++++++++ sonar-ws/src/main/protobuf/ws-serverid.proto | 38 ++++ 13 files changed, 562 insertions(+), 13 deletions(-) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/serverid/ws/ServerIdWs.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/serverid/ws/ServerIdWsAction.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/serverid/ws/ServerIdWsModule.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/serverid/ws/ShowAction.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/serverid/ws/package-info.java create mode 100644 server/sonar-server/src/main/resources/org/sonar/server/serverid/ws/show-example.json create mode 100644 server/sonar-server/src/test/java/org/sonar/server/serverid/ws/ServerIdWsModuleTest.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/serverid/ws/ShowActionTest.java create mode 100644 sonar-ws/src/main/protobuf/ws-serverid.proto diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/UserSessionInitializer.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/UserSessionInitializer.java index f29a0807c74..0be0bfcc9eb 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/authentication/UserSessionInitializer.java +++ b/server/sonar-server/src/main/java/org/sonar/server/authentication/UserSessionInitializer.java @@ -59,7 +59,7 @@ public class UserSessionInitializer { "/setup/*", "/sessions/*", "/api/system/db_migration_status", "/api/system/status", "/api/system/migrate_db", - "/api/server/*", + "/api/server/index", "/api/server/setup", "/api/server/version", AUTH_LOGIN_URL, AUTH_VALIDATE_URL); private static final UrlPattern URL_PATTERN = UrlPattern.builder() diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerIdGenerator.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerIdGenerator.java index 7c9b1299a66..86d03a72efe 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerIdGenerator.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerIdGenerator.java @@ -29,6 +29,7 @@ import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.regex.Pattern; +import javax.annotation.CheckForNull; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang.StringUtils; import org.sonar.api.utils.log.Loggers; @@ -55,6 +56,7 @@ public class ServerIdGenerator { this.acceptPrivateAddress = acceptPrivateAddress; } + @CheckForNull public String generate(String organisationName, String ipAddress) { String id = null; String organisation = organisationName.trim(); 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 4ae90268689..6070b489436 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 @@ -236,6 +236,7 @@ import org.sonar.server.rule.ws.RuleMapper; import org.sonar.server.rule.ws.RuleQueryFactory; import org.sonar.server.rule.ws.RulesWs; import org.sonar.server.rule.ws.TagsAction; +import org.sonar.server.serverid.ws.ServerIdWsModule; import org.sonar.server.setting.ProjectSettingsFactory; import org.sonar.server.setting.ws.SettingsWsModule; import org.sonar.server.source.HtmlSourceDecorator; @@ -615,6 +616,9 @@ public class PlatformLevel4 extends PlatformLevel { ChangeLogLevelAction.class, DbMigrationStatusAction.class, + // Server id + ServerIdWsModule.class, + // Plugins WS PluginWSCommons.class, PluginUpdateAggregator.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/serverid/ws/ServerIdWs.java b/server/sonar-server/src/main/java/org/sonar/server/serverid/ws/ServerIdWs.java new file mode 100644 index 00000000000..0825f9f9dac --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/serverid/ws/ServerIdWs.java @@ -0,0 +1,42 @@ +/* + * 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.serverid.ws; + +import org.sonar.api.server.ws.WebService; + +public class ServerIdWs implements WebService { + + private final ServerIdWsAction[] actions; + + public ServerIdWs(ServerIdWsAction... actions) { + this.actions = actions; + } + + @Override + public void define(Context context) { + NewController controller = context.createController("api/server_id") + .setDescription("Get server id information and generate server id."); + for (ServerIdWsAction action : actions) { + action.define(controller); + } + controller.done(); + } + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/serverid/ws/ServerIdWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/serverid/ws/ServerIdWsAction.java new file mode 100644 index 00000000000..8076f430826 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/serverid/ws/ServerIdWsAction.java @@ -0,0 +1,26 @@ +/* + * 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.serverid.ws; + +import org.sonar.server.ws.WsAction; + +public interface ServerIdWsAction extends WsAction { + // Marker interface +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/serverid/ws/ServerIdWsModule.java b/server/sonar-server/src/main/java/org/sonar/server/serverid/ws/ServerIdWsModule.java new file mode 100644 index 00000000000..2f30d5cbbb6 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/serverid/ws/ServerIdWsModule.java @@ -0,0 +1,31 @@ +/* + * 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.serverid.ws; + +import org.sonar.core.platform.Module; + +public class ServerIdWsModule extends Module { + @Override + protected void configureModule() { + add( + ServerIdWs.class, + ShowAction.class); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/serverid/ws/ShowAction.java b/server/sonar-server/src/main/java/org/sonar/server/serverid/ws/ShowAction.java new file mode 100644 index 00000000000..183f00eacca --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/serverid/ws/ShowAction.java @@ -0,0 +1,125 @@ +/* + * 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.serverid.ws; + +import com.google.common.collect.ImmutableSet; +import java.net.InetAddress; +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.server.ws.Request; +import org.sonar.api.server.ws.Response; +import org.sonar.api.server.ws.WebService; +import org.sonar.core.util.stream.Collectors; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.property.PropertyDto; +import org.sonar.server.platform.ServerIdGenerator; +import org.sonar.server.user.UserSession; + +import static java.util.stream.Collectors.toList; +import static org.sonar.api.CoreProperties.ORGANISATION; +import static org.sonar.api.CoreProperties.PERMANENT_SERVER_ID; +import static org.sonar.api.CoreProperties.SERVER_ID_IP_ADDRESS; +import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN; +import static org.sonar.server.ws.WsUtils.writeProtobuf; +import static org.sonarqube.ws.ServerId.ShowWsResponse; + +public class ShowAction implements ServerIdWsAction { + + private static final Set SETTINGS_KEYS = ImmutableSet.of(PERMANENT_SERVER_ID, ORGANISATION, SERVER_ID_IP_ADDRESS); + + private final UserSession userSession; + private final ServerIdGenerator serverIdGenerator; + private final DbClient dbClient; + + public ShowAction(UserSession userSession, ServerIdGenerator serverIdGenerator, DbClient dbClient) { + this.userSession = userSession; + this.serverIdGenerator = serverIdGenerator; + this.dbClient = dbClient; + } + + @Override + public void define(WebService.NewController controller) { + controller.createAction("show") + .setDescription("Get server id configuration.
" + + "Requires 'System Administer' permissions") + .setSince("6.1") + .setInternal(true) + .setResponseExample(getClass().getResource("show-example.json")) + .setHandler(this); + } + + @Override + public void handle(Request request, Response response) throws Exception { + userSession.checkPermission(SYSTEM_ADMIN); + DbSession dbSession = dbClient.openSession(true); + try { + Map properties = dbClient.propertiesDao().selectGlobalPropertiesByKeys(dbSession, SETTINGS_KEYS).stream() + .collect(Collectors.uniqueIndex(PropertyDto::getKey, Function.identity())); + writeProtobuf(doHandle(properties), request, response); + } finally { + dbClient.closeSession(dbSession); + } + } + + private ShowWsResponse doHandle(Map properties) { + ShowWsResponse.Builder responseBuilder = ShowWsResponse.newBuilder(); + List validIpAdresses = serverIdGenerator.getAvailableAddresses().stream().map(InetAddress::getHostAddress).collect(toList()); + if (!validIpAdresses.isEmpty()) { + responseBuilder.addAllValidIpAdresses(validIpAdresses); + } + + Optional serverId = getSettingValue(properties.get(PERMANENT_SERVER_ID)); + if (serverId.isPresent()) { + responseBuilder.setServerId(serverId.get()); + Optional organisation = getSettingValue(properties.get(ORGANISATION)); + if (organisation.isPresent()) { + responseBuilder.setOrganization(organisation.get()); + } + Optional ip = getSettingValue(properties.get(SERVER_ID_IP_ADDRESS)); + if (ip.isPresent()) { + responseBuilder.setIp(ip.get()); + } + boolean isValidServId = isValidServerId(serverId.get(), organisation, ip); + if (!isValidServId) { + responseBuilder.setInvalidServerId(true); + } + } + return responseBuilder.build(); + } + + private static Optional getSettingValue(@Nullable PropertyDto propertyDto) { + return propertyDto != null ? Optional.of(propertyDto.getValue()) : Optional.empty(); + } + + private boolean isValidServerId(String serverId, Optional organisation, Optional ip) { + if (organisation.isPresent() && ip.isPresent()) { + String generatedServerId = serverIdGenerator.generate(organisation.get(), ip.get()); + return Objects.equals(generatedServerId, serverId); + } + return false; + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/serverid/ws/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/serverid/ws/package-info.java new file mode 100644 index 00000000000..56b2376e9be --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/serverid/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.serverid.ws; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/resources/org/sonar/server/serverid/ws/show-example.json b/server/sonar-server/src/main/resources/org/sonar/server/serverid/ws/show-example.json new file mode 100644 index 00000000000..1f322a4cc57 --- /dev/null +++ b/server/sonar-server/src/main/resources/org/sonar/server/serverid/ws/show-example.json @@ -0,0 +1,9 @@ +{ + "serverId": "server_id", + "organization": "home", + "ip": "127.0.1", + "validIpAdresses": [ + "192.168.1.1", + "127.0.1" + ] +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/UserSessionInitializerTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/UserSessionInitializerTest.java index dba52e8d4dc..5b0a13780fc 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/authentication/UserSessionInitializerTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/authentication/UserSessionInitializerTest.java @@ -20,18 +20,6 @@ package org.sonar.server.authentication; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; -import static org.sonar.db.user.UserTesting.newUserDto; - import java.util.Optional; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -49,6 +37,18 @@ import org.sonar.server.user.ServerUserSession; import org.sonar.server.user.ThreadLocalUserSession; import org.sonar.server.user.UserSession; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; +import static org.sonar.db.user.UserTesting.newUserDto; + public class UserSessionInitializerTest { @Rule @@ -84,6 +84,7 @@ public class UserSessionInitializerTest { public void check_urls() throws Exception { assertPathIsNotIgnored("/"); assertPathIsNotIgnored("/foo"); + assertPathIsNotIgnored("/api/server_id/show"); assertPathIsIgnored("/api/authentication/login"); assertPathIsIgnored("/api/authentication/validate"); @@ -97,6 +98,8 @@ public class UserSessionInitializerTest { assertPathIsIgnored("/api/system/status"); assertPathIsIgnored("/api/system/migrate_db"); assertPathIsIgnored("/api/server/index"); + assertPathIsIgnored("/api/server/setup"); + assertPathIsIgnored("/api/server/version"); // exclude static resources assertPathIsIgnored("/css/style.css"); diff --git a/server/sonar-server/src/test/java/org/sonar/server/serverid/ws/ServerIdWsModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/serverid/ws/ServerIdWsModuleTest.java new file mode 100644 index 00000000000..7c0bf9c26dd --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/serverid/ws/ServerIdWsModuleTest.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.serverid.ws; + +import org.junit.Test; +import org.sonar.core.platform.ComponentContainer; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ServerIdWsModuleTest { + @Test + public void verify_count_of_added_components() { + ComponentContainer container = new ComponentContainer(); + new ServerIdWsModule().configure(container); + assertThat(container.size()).isEqualTo(2 + 2); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/serverid/ws/ShowActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/serverid/ws/ShowActionTest.java new file mode 100644 index 00000000000..2a7dd64321b --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/serverid/ws/ShowActionTest.java @@ -0,0 +1,211 @@ +/* + * 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.serverid.ws; + +import java.io.IOException; +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Nullable; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +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.platform.ServerIdGenerator; +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.MediaTypes; +import org.sonarqube.ws.ServerId.ShowWsResponse; + +import static org.assertj.core.api.Java6Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +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 ShowActionTest { + + @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); + ServerIdGenerator generator = mock(ServerIdGenerator.class); + + WsActionTester ws = new WsActionTester(new ShowAction(userSession, generator, dbClient)); + + @Test + public void return_server_id_info() throws Exception { + setUserAsSystemAdmin(); + when(generator.generate("home", "127.0.1")).thenReturn("server_id"); + setAvailableIpAdresses("192.168.1.1", "127.0.1"); + insertConfiguration("server_id", "home", "127.0.1"); + + ShowWsResponse response = executeRequest(); + + assertThat(response.getServerId()).isEqualTo("server_id"); + assertThat(response.getOrganization()).isEqualTo("home"); + assertThat(response.getIp()).isEqualTo("127.0.1"); + assertThat(response.getValidIpAdressesList()).containsOnly("192.168.1.1", "127.0.1"); + assertThat(response.hasInvalidServerId()).isFalse(); + } + + @Test + public void return_invalid_server_id() throws Exception { + setUserAsSystemAdmin(); + when(generator.generate("home", "127.0.1")).thenReturn("server_id"); + insertConfiguration("invalid", null, null); + + ShowWsResponse response = executeRequest(); + + assertThat(response.hasInvalidServerId()).isTrue(); + assertThat(response.getServerId()).isEqualTo("invalid"); + assertThat(response.hasOrganization()).isFalse(); + assertThat(response.hasIp()).isFalse(); + assertThat(response.getValidIpAdressesList()).isEmpty(); + } + + @Test + public void return_no_server_id_info_when_no_settings_and_no_available_ips() throws Exception { + setUserAsSystemAdmin(); + + ShowWsResponse response = executeRequest(); + + assertThat(response.hasServerId()).isFalse(); + assertThat(response.hasOrganization()).isFalse(); + assertThat(response.hasIp()).isFalse(); + assertThat(response.getValidIpAdressesList()).isEmpty(); + assertThat(response.hasInvalidServerId()).isFalse(); + } + + @Test + public void return_no_server_id_info_when_no_server_id_but_other_settings() throws Exception { + setUserAsSystemAdmin(); + insertConfiguration(null, "home", "127.0.1"); + + ShowWsResponse response = executeRequest(); + + assertThat(response.hasServerId()).isFalse(); + assertThat(response.hasOrganization()).isFalse(); + assertThat(response.hasIp()).isFalse(); + assertThat(response.getValidIpAdressesList()).isEmpty(); + assertThat(response.hasInvalidServerId()).isFalse(); + } + + @Test + public void return_available_ips_even_if_no_settings() throws Exception { + setUserAsSystemAdmin(); + setAvailableIpAdresses("192.168.1.1", "127.0.1"); + + ShowWsResponse response = executeRequest(); + + assertThat(response.hasServerId()).isFalse(); + assertThat(response.hasOrganization()).isFalse(); + assertThat(response.hasIp()).isFalse(); + assertThat(response.getValidIpAdressesList()).containsOnly("192.168.1.1", "127.0.1"); + assertThat(response.hasInvalidServerId()).isFalse(); + } + + @Test + public void fail_when_not_system_admin() throws Exception { + userSession.login("not-admin").setGlobalPermissions(DASHBOARD_SHARING); + + expectedException.expect(ForbiddenException.class); + + executeRequest(); + } + + @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(); + } + + @Test + public void test_example_json_response() { + setUserAsSystemAdmin(); + when(generator.generate("home", "127.0.1")).thenReturn("server_id"); + setAvailableIpAdresses("192.168.1.1", "127.0.1"); + insertConfiguration("server_id", "home", "127.0.1"); + + String result = ws.newRequest() + .setMediaType(JSON) + .execute() + .getInput(); + + JsonAssert.assertJson(ws.getDef().responseExampleAsString()).isSimilarTo(result); + } + + private void insertConfiguration(@Nullable String serverId, @Nullable String organisation, @Nullable String ip) { + if (serverId != null) { + propertyDb.insertProperties(newGlobalPropertyDto().setKey("sonar.server_id").setValue(serverId)); + } + if (organisation != null) { + propertyDb.insertProperties(newGlobalPropertyDto().setKey("sonar.organisation").setValue(organisation)); + } + if (ip != null) { + propertyDb.insertProperties(newGlobalPropertyDto().setKey("sonar.server_id.ip_address").setValue(ip)); + } + } + + private void setAvailableIpAdresses(String... ips) { + List availableAddresses = new ArrayList<>(); + for (String ip : ips) { + InetAddress inetAddress = mock(InetAddress.class); + when(inetAddress.getHostAddress()).thenReturn(ip); + availableAddresses.add(inetAddress); + } + when(generator.getAvailableAddresses()).thenReturn(availableAddresses); + } + + private ShowWsResponse executeRequest() { + TestRequest request = ws.newRequest() + .setMediaType(MediaTypes.PROTOBUF); + try { + return ShowWsResponse.parseFrom(request.execute().getInputStream()); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + private void setUserAsSystemAdmin() { + userSession.login("admin").setGlobalPermissions(SYSTEM_ADMIN); + } +} diff --git a/sonar-ws/src/main/protobuf/ws-serverid.proto b/sonar-ws/src/main/protobuf/ws-serverid.proto new file mode 100644 index 00000000000..18a2a813ef6 --- /dev/null +++ b/sonar-ws/src/main/protobuf/ws-serverid.proto @@ -0,0 +1,38 @@ +// 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.serverid; + +option java_package = "org.sonarqube.ws"; +option java_outer_classname = "ServerId"; +option optimize_for = SPEED; + +// Response of GET api/server_id/show +message ShowWsResponse { + optional string serverId = 1; + optional string organization = 2; + optional string ip = 3; + repeated string validIpAdresses = 4; + optional bool invalidServerId = 5; +} + + + + -- 2.39.5