From 0873f296b037c2f55c5707911e0de50b3d78c639 Mon Sep 17 00:00:00 2001 From: Antoine Vigneau Date: Fri, 22 Mar 2024 11:55:23 +0100 Subject: [PATCH] SONAR-21819 Add api/v2 endpoint to get all DOP Settings --- .../org/sonar/server/v2/WebApiEndpoints.java | 2 + .../DefaultDopSettingsController.java | 67 +++++++++++ .../dop/controller/DopSettingsController.java | 39 +++++++ .../v2/api/dop/controller/package-info.java | 23 ++++ .../api/dop/response/DopSettingsResource.java | 36 ++++++ .../dop/response/DopSettingsRestResponse.java | 26 +++++ .../v2/api/dop/response/package-info.java | 23 ++++ .../v2/config/PlatformLevel4WebConfig.java | 12 +- .../DefaultDopSettingsControllerTest.java | 110 ++++++++++++++++++ .../controller/DefaultUserControllerTest.java | 2 +- 10 files changed, 336 insertions(+), 4 deletions(-) create mode 100644 server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/controller/DefaultDopSettingsController.java create mode 100644 server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/controller/DopSettingsController.java create mode 100644 server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/controller/package-info.java create mode 100644 server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/response/DopSettingsResource.java create mode 100644 server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/response/DopSettingsRestResponse.java create mode 100644 server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/response/package-info.java create mode 100644 server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/dop/controller/DefaultDopSettingsControllerTest.java diff --git a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/WebApiEndpoints.java b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/WebApiEndpoints.java index 201c625b04a..c906493f7e1 100644 --- a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/WebApiEndpoints.java +++ b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/WebApiEndpoints.java @@ -40,6 +40,8 @@ public class WebApiEndpoints { public static final String BOUND_PROJECTS_ENDPOINT = DOP_TRANSLATION_DOMAIN + "/bound-projects"; + public static final String DOP_SETTINGS_ENDPOINT = DOP_TRANSLATION_DOMAIN + "/dop-settings"; + public static final String INTERNAL = "internal"; private WebApiEndpoints() { diff --git a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/controller/DefaultDopSettingsController.java b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/controller/DefaultDopSettingsController.java new file mode 100644 index 00000000000..49d4f1b697a --- /dev/null +++ b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/controller/DefaultDopSettingsController.java @@ -0,0 +1,67 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 SonarSource SA + * mailto:info 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.v2.api.dop.controller; + +import java.util.List; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.alm.setting.AlmSettingDto; +import org.sonar.server.user.UserSession; +import org.sonar.server.v2.api.dop.response.DopSettingsResource; +import org.sonar.server.v2.api.dop.response.DopSettingsRestResponse; +import org.sonar.server.v2.api.response.PageRestResponse; + +import static org.sonar.db.permission.GlobalPermission.PROVISION_PROJECTS; + +public class DefaultDopSettingsController implements DopSettingsController { + + private final UserSession userSession; + private final DbClient dbClient; + + public DefaultDopSettingsController(UserSession userSession, DbClient dbClient) { + this.userSession = userSession; + this.dbClient = dbClient; + } + + @Override + public DopSettingsRestResponse fetchAllDopSettings() { + userSession.checkLoggedIn().checkPermission(PROVISION_PROJECTS); + try (DbSession dbSession = dbClient.openSession(false)) { + List dopSettingsResources = dbClient.almSettingDao().selectAll(dbSession) + .stream() + .map(DefaultDopSettingsController::toDopSettingsResource) + .toList(); + + PageRestResponse pageRestResponse = new PageRestResponse(1, dopSettingsResources.size(), dopSettingsResources.size()); + return new DopSettingsRestResponse(dopSettingsResources, pageRestResponse); + } + } + + private static DopSettingsResource toDopSettingsResource(AlmSettingDto almSettingDto) { + return new DopSettingsResource( + almSettingDto.getUuid(), + almSettingDto.getRawAlm(), + almSettingDto.getKey(), + almSettingDto.getUrl(), + almSettingDto.getAppId() + ); + } + +} diff --git a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/controller/DopSettingsController.java b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/controller/DopSettingsController.java new file mode 100644 index 00000000000..50aaa0cfbf2 --- /dev/null +++ b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/controller/DopSettingsController.java @@ -0,0 +1,39 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 SonarSource SA + * mailto:info 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.v2.api.dop.controller; + +import io.swagger.v3.oas.annotations.Operation; +import org.sonar.server.v2.api.dop.response.DopSettingsRestResponse; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import static org.sonar.server.v2.WebApiEndpoints.DOP_SETTINGS_ENDPOINT; + +@RequestMapping(DOP_SETTINGS_ENDPOINT) +@RestController +public interface DopSettingsController { + + @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "List all DevOps Platform Integration settings", description = "Requires the 'Create Projects' permission ") + DopSettingsRestResponse fetchAllDopSettings(); + +} diff --git a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/controller/package-info.java b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/controller/package-info.java new file mode 100644 index 00000000000..732a99af6cf --- /dev/null +++ b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/controller/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 SonarSource SA + * mailto:info 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.v2.api.dop.controller; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/response/DopSettingsResource.java b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/response/DopSettingsResource.java new file mode 100644 index 00000000000..830723f4e09 --- /dev/null +++ b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/response/DopSettingsResource.java @@ -0,0 +1,36 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 SonarSource SA + * mailto:info 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.v2.api.dop.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import javax.annotation.Nullable; + +public record DopSettingsResource( + @Schema(accessMode = Schema.AccessMode.READ_ONLY) + String id, + @Schema(description = "Supported DevOps Platform are: github, gitlab, azure_devops, bitbucket_cloud, bitbucket_server") + String type, + String key, + @Nullable + String url, + @Nullable + String appId +) { +} diff --git a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/response/DopSettingsRestResponse.java b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/response/DopSettingsRestResponse.java new file mode 100644 index 00000000000..8acf4db2407 --- /dev/null +++ b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/response/DopSettingsRestResponse.java @@ -0,0 +1,26 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 SonarSource SA + * mailto:info 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.v2.api.dop.response; + +import java.util.List; +import org.sonar.server.v2.api.response.PageRestResponse; + +public record DopSettingsRestResponse(List dopSettings, PageRestResponse page) { +} diff --git a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/response/package-info.java b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/response/package-info.java new file mode 100644 index 00000000000..06335f50565 --- /dev/null +++ b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/dop/response/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 SonarSource SA + * mailto:info 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.v2.api.dop.response; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/config/PlatformLevel4WebConfig.java b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/config/PlatformLevel4WebConfig.java index af59c51d9ed..c48cf412bc6 100644 --- a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/config/PlatformLevel4WebConfig.java +++ b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/config/PlatformLevel4WebConfig.java @@ -41,14 +41,16 @@ import org.sonar.server.platform.NodeInformation; import org.sonar.server.rule.RuleDescriptionFormatter; import org.sonar.server.user.SystemPasscode; import org.sonar.server.user.UserSession; +import org.sonar.server.v2.api.dop.controller.DefaultDopSettingsController; +import org.sonar.server.v2.api.dop.controller.DopSettingsController; import org.sonar.server.v2.api.gitlab.config.controller.DefaultGitlabConfigurationController; import org.sonar.server.v2.api.gitlab.config.controller.GitlabConfigurationController; import org.sonar.server.v2.api.group.controller.DefaultGroupController; import org.sonar.server.v2.api.group.controller.GroupController; import org.sonar.server.v2.api.membership.controller.DefaultGroupMembershipController; import org.sonar.server.v2.api.membership.controller.GroupMembershipController; -import org.sonar.server.v2.api.projects.controller.DefaultBoundProjectsController; import org.sonar.server.v2.api.projects.controller.BoundProjectsController; +import org.sonar.server.v2.api.projects.controller.DefaultBoundProjectsController; import org.sonar.server.v2.api.rule.controller.DefaultRuleController; import org.sonar.server.v2.api.rule.controller.RuleController; import org.sonar.server.v2.api.rule.converter.RuleRestResponseGenerator; @@ -133,8 +135,12 @@ public class PlatformLevel4WebConfig { @Bean public BoundProjectsController importedProjectsController(UserSession userSession, ImportProjectService importProjectService) { - return new DefaultBoundProjectsController( - userSession, importProjectService); + return new DefaultBoundProjectsController(userSession, importProjectService); + } + + @Bean + public DopSettingsController dopSettingsController(UserSession userSession, DbClient dbClient) { + return new DefaultDopSettingsController(userSession, dbClient); } } diff --git a/server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/dop/controller/DefaultDopSettingsControllerTest.java b/server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/dop/controller/DefaultDopSettingsControllerTest.java new file mode 100644 index 00000000000..70f6c72d509 --- /dev/null +++ b/server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/dop/controller/DefaultDopSettingsControllerTest.java @@ -0,0 +1,110 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 SonarSource SA + * mailto:info 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.v2.api.dop.controller; + +import com.google.gson.Gson; +import java.util.List; +import org.junit.Rule; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.alm.setting.AlmSettingDto; +import org.sonar.server.tester.UserSessionRule; +import org.sonar.server.v2.api.ControllerTester; +import org.sonar.server.v2.api.dop.response.DopSettingsResource; +import org.sonar.server.v2.api.dop.response.DopSettingsRestResponse; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.sonar.db.permission.GlobalPermission.PROVISION_PROJECTS; +import static org.sonar.server.v2.WebApiEndpoints.DOP_SETTINGS_ENDPOINT; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +class DefaultDopSettingsControllerTest { + + @Rule + public UserSessionRule userSession = UserSessionRule.standalone(); + private final DbClient dbClient = mock(DbClient.class, RETURNS_DEEP_STUBS); + private final DbSession dbSession = mock(); + + private final MockMvc mockMvc = ControllerTester.getMockMvc( + new DefaultDopSettingsController(userSession, dbClient)); + + private static final Gson gson = new Gson(); + + @BeforeEach + void setup() { + when(dbClient.openSession(false)).thenReturn(dbSession); + } + + @Test + void fetchAllDopSettings_whenUserDoesntHaveCreateProjectPermission_returnsForbidden() throws Exception { + userSession.logIn(); + mockMvc + .perform(get(DOP_SETTINGS_ENDPOINT)) + .andExpect(status().isForbidden()); + } + + @Test + void fetchAllDopSettings_whenDbClientReturnsData_returnsResponse() throws Exception { + List dopSettings = List.of( + generateAlmSettingsDto("github"), + generateAlmSettingsDto("azure"), + generateAlmSettingsDto("bitbucket_cloud") + ); + when(dbClient.almSettingDao().selectAll(dbSession)).thenReturn(dopSettings); + + userSession.logIn().addPermission(PROVISION_PROJECTS);; + MvcResult mvcResult = mockMvc + .perform(get(DOP_SETTINGS_ENDPOINT)) + .andExpect(status().isOk()) + .andReturn(); + DopSettingsRestResponse response = gson.fromJson(mvcResult.getResponse().getContentAsString(), DopSettingsRestResponse.class); + assertThat(response.dopSettings()) + .containsExactlyInAnyOrderElementsOf(dopSettings.stream().map(DefaultDopSettingsControllerTest::toDopSettingsResource).toList()); + } + + private static DopSettingsResource toDopSettingsResource(AlmSettingDto almSettingDto) { + return new DopSettingsResource( + almSettingDto.getUuid(), + almSettingDto.getRawAlm(), + almSettingDto.getKey(), + almSettingDto.getUrl(), + almSettingDto.getAppId() + ); + } + + private AlmSettingDto generateAlmSettingsDto(String dopType) { + AlmSettingDto dto = mock(); + when(dto.getUuid()).thenReturn("uuid_" + dopType); + when(dto.getRawAlm()).thenReturn(dopType); + when(dto.getKey()).thenReturn("key_" + dopType); + when(dto.getUrl()).thenReturn("url_" + dopType); + when(dto.getAppId()).thenReturn("appId_" + dopType); + return dto; + } + +} diff --git a/server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/user/controller/DefaultUserControllerTest.java b/server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/user/controller/DefaultUserControllerTest.java index d3d4b4a675f..50d8264e4ce 100644 --- a/server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/user/controller/DefaultUserControllerTest.java +++ b/server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/user/controller/DefaultUserControllerTest.java @@ -44,9 +44,9 @@ import org.sonar.server.v2.api.ControllerTester; import org.sonar.server.v2.api.model.RestError; import org.sonar.server.v2.api.response.PageRestResponse; import org.sonar.server.v2.api.user.converter.UsersSearchRestResponseGenerator; +import org.sonar.server.v2.api.user.request.UserCreateRestRequest; import org.sonar.server.v2.api.user.response.UserRestResponse; import org.sonar.server.v2.api.user.response.UserRestResponseForAdmins; -import org.sonar.server.v2.api.user.request.UserCreateRestRequest; import org.sonar.server.v2.api.user.response.UsersSearchRestResponse; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; -- 2.39.5