@@ -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() { |
@@ -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<DopSettingsResource> 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() | |||
); | |||
} | |||
} |
@@ -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(); | |||
} |
@@ -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; |
@@ -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 | |||
) { | |||
} |
@@ -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<DopSettingsResource> dopSettings, PageRestResponse page) { | |||
} |
@@ -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; |
@@ -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); | |||
} | |||
} |
@@ -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<AlmSettingDto> 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; | |||
} | |||
} |
@@ -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; |