--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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.almsettings.ws;
+
+import org.sonar.api.server.ws.Change;
+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.alm.setting.AlmSettingDto;
+import org.sonar.db.alm.setting.ProjectAlmSettingDto;
+import org.sonar.db.project.ProjectDto;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.user.UserSession;
+import org.sonarqube.ws.AlmSettings.GetBindingWsResponse;
+
+import static java.lang.String.format;
+import static java.util.Optional.ofNullable;
+import static org.sonar.api.web.UserRole.ADMIN;
+import static org.sonar.server.almsettings.ws.AlmSettingsSupport.toAlmWs;
+import static org.sonar.server.ws.WsUtils.writeProtobuf;
+
+public class GetBindingAction implements AlmSettingsWsAction {
+
+ private static final String PARAM_PROJECT = "project";
+
+ private final DbClient dbClient;
+ private final UserSession userSession;
+ private final ComponentFinder componentFinder;
+
+ public GetBindingAction(DbClient dbClient, UserSession userSession, ComponentFinder componentFinder) {
+ this.dbClient = dbClient;
+ this.userSession = userSession;
+ this.componentFinder = componentFinder;
+ }
+
+ @Override
+ public void define(WebService.NewController context) {
+ WebService.NewAction action = context.createAction("get_binding")
+ .setDescription("Get ALM binding of a given project.<br/>" +
+ "Requires the 'Administer' permission on the project")
+ .setSince("8.1")
+ .setResponseExample(getClass().getResource("get_binding-example.json"))
+ .setChangelog(new Change("8.6", "Azure binding now contains the project and repository names"))
+ .setChangelog(new Change("8.7", "Azure binding now contains a monorepo flag for monorepo feature in Enterprise Edition and above"))
+ .setHandler(this);
+
+ action
+ .createParam(PARAM_PROJECT)
+ .setDescription("Project key")
+ .setRequired(true);
+ }
+
+ @Override
+ public void handle(Request request, Response response) {
+ GetBindingWsResponse wsResponse = doHandle(request);
+ writeProtobuf(wsResponse, request, response);
+ }
+
+ private GetBindingWsResponse doHandle(Request request) {
+ String projectKey = request.mandatoryParam(PARAM_PROJECT);
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ ProjectDto project = componentFinder.getProjectByKey(dbSession, projectKey);
+ userSession.checkProjectPermission(ADMIN, project);
+ ProjectAlmSettingDto projectAlmSetting = dbClient.projectAlmSettingDao().selectByProject(dbSession, project)
+ .orElseThrow(() -> new NotFoundException(format("Project '%s' is not bound to any ALM", project.getKey())));
+ AlmSettingDto almSetting = dbClient.almSettingDao().selectByUuid(dbSession, projectAlmSetting.getAlmSettingUuid())
+ .orElseThrow(() -> new IllegalStateException(format("ALM setting with uuid '%s' cannot be found", projectAlmSetting.getAlmSettingUuid())));
+
+ GetBindingWsResponse.Builder builder = GetBindingWsResponse.newBuilder()
+ .setAlm(toAlmWs(almSetting.getAlm()))
+ .setKey(almSetting.getKey());
+ ofNullable(projectAlmSetting.getAlmRepo()).ifPresent(builder::setRepository);
+ ofNullable(almSetting.getUrl()).ifPresent(builder::setUrl);
+ ofNullable(projectAlmSetting.getAlmSlug()).ifPresent(builder::setSlug);
+ ofNullable(projectAlmSetting.getSummaryCommentEnabled()).ifPresent(builder::setSummaryCommentEnabled);
+ ofNullable(projectAlmSetting.getMonorepo()).ifPresent(builder::setMonorepo);
+ return builder.build();
+ }
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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.almsettings.ws;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.db.DbTester;
+import org.sonar.db.alm.setting.AlmSettingDto;
+import org.sonar.db.alm.setting.ProjectAlmSettingDto;
+import org.sonar.db.project.ProjectDto;
+import org.sonar.db.user.UserDto;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsActionTester;
+import org.sonarqube.ws.AlmSettings;
+import org.sonarqube.ws.AlmSettings.GetBindingWsResponse;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.groups.Tuple.tuple;
+import static org.sonar.api.web.UserRole.ADMIN;
+import static org.sonar.api.web.UserRole.USER;
+import static org.sonar.test.JsonAssert.assertJson;
+
+public class GetBindingActionTest {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
+ @Rule
+ public DbTester db = DbTester.create();
+
+ private WsActionTester ws = new WsActionTester(new GetBindingAction(db.getDbClient(), userSession, new ComponentFinder(db.getDbClient(), null)));
+
+ private UserDto user;
+ private ProjectDto project;
+
+ @Before
+ public void before() {
+ user = db.users().insertUser();
+ project = db.components().insertPrivateProjectDto();
+ }
+
+ @Test
+ public void get_github_project_binding() {
+ userSession.logIn(user).addProjectPermission(ADMIN, project);
+ AlmSettingDto githubAlmSetting = db.almSettings().insertGitHubAlmSetting();
+ ProjectAlmSettingDto githubProjectAlmSetting = db.almSettings().insertGitHubProjectAlmSetting(githubAlmSetting, project);
+
+ GetBindingWsResponse response = ws.newRequest()
+ .setParam("project", project.getKey())
+ .executeProtobuf(GetBindingWsResponse.class);
+
+ assertThat(response.getAlm()).isEqualTo(AlmSettings.Alm.github);
+ assertThat(response.getKey()).isEqualTo(githubAlmSetting.getKey());
+ assertThat(response.getRepository()).isEqualTo(githubProjectAlmSetting.getAlmRepo());
+ assertThat(response.getUrl()).isEqualTo(githubAlmSetting.getUrl());
+ assertThat(response.getSummaryCommentEnabled()).isTrue();
+ }
+
+ @Test
+ public void get_azure_project_binding() {
+ userSession.logIn(user).addProjectPermission(ADMIN, project);
+ AlmSettingDto almSetting = db.almSettings().insertAzureAlmSetting();
+ ProjectAlmSettingDto projectAlmSettingDto = db.almSettings().insertAzureMonoRepoProjectAlmSetting(almSetting, project);
+
+ GetBindingWsResponse response = ws.newRequest()
+ .setParam("project", project.getKey())
+ .executeProtobuf(GetBindingWsResponse.class);
+
+ assertThat(response.getAlm()).isEqualTo(AlmSettings.Alm.azure);
+ assertThat(response.getKey()).isEqualTo(almSetting.getKey());
+ assertThat(response.getUrl()).isEqualTo(almSetting.getUrl());
+ assertThat(response.getRepository()).isEqualTo(projectAlmSettingDto.getAlmRepo());
+ assertThat(response.getSlug()).isEqualTo(projectAlmSettingDto.getAlmSlug());
+ assertThat(response.hasSummaryCommentEnabled()).isFalse();
+ assertThat(response.getMonorepo()).isTrue();
+ }
+
+ @Test
+ public void get_gitlab_project_binding() {
+ UserDto user = db.users().insertUser();
+ ProjectDto project = db.components().insertPrivateProjectDto();
+ userSession.logIn(user).addProjectPermission(ADMIN, project);
+ AlmSettingDto almSetting = db.almSettings().insertGitlabAlmSetting();
+ db.almSettings().insertGitlabProjectAlmSetting(almSetting, project);
+
+ GetBindingWsResponse response = ws.newRequest()
+ .setParam("project", project.getKey())
+ .executeProtobuf(GetBindingWsResponse.class);
+
+ assertThat(response.getAlm()).isEqualTo(AlmSettings.Alm.gitlab);
+ assertThat(response.getKey()).isEqualTo(almSetting.getKey());
+ assertThat(response.hasRepository()).isFalse();
+ assertThat(response.getUrl()).isEqualTo(almSetting.getUrl());
+ assertThat(response.hasUrl()).isTrue();
+ assertThat(response.hasSummaryCommentEnabled()).isFalse();
+ }
+
+ @Test
+ public void get_bitbucket_project_binding() {
+ userSession.logIn(user).addProjectPermission(ADMIN, project);
+ AlmSettingDto almSetting = db.almSettings().insertBitbucketAlmSetting();
+ ProjectAlmSettingDto projectAlmSettingDto = db.almSettings().insertBitbucketProjectAlmSetting(almSetting, project);
+
+ GetBindingWsResponse response = ws.newRequest()
+ .setParam("project", project.getKey())
+ .executeProtobuf(GetBindingWsResponse.class);
+
+ assertThat(response.getAlm()).isEqualTo(AlmSettings.Alm.bitbucket);
+ assertThat(response.getKey()).isEqualTo(almSetting.getKey());
+ assertThat(response.getRepository()).isEqualTo(projectAlmSettingDto.getAlmRepo());
+ assertThat(response.getUrl()).isEqualTo(almSetting.getUrl());
+ assertThat(response.getSlug()).isEqualTo(projectAlmSettingDto.getAlmSlug());
+ assertThat(response.hasSummaryCommentEnabled()).isFalse();
+ }
+
+ @Test
+ public void fail_when_project_does_not_exist() {
+ userSession.logIn(user).addProjectPermission(ADMIN, project);
+ AlmSettingDto githubAlmSetting = db.almSettings().insertGitHubAlmSetting();
+ db.almSettings().insertGitHubProjectAlmSetting(githubAlmSetting, project);
+
+ expectedException.expect(NotFoundException.class);
+
+ ws.newRequest()
+ .setParam("project", "unknown")
+ .execute();
+ }
+
+ @Test
+ public void fail_when_missing_administer_permission_on_project() {
+ userSession.logIn(user).addProjectPermission(USER, project);
+ AlmSettingDto githubAlmSetting = db.almSettings().insertGitHubAlmSetting();
+ db.almSettings().insertGitHubProjectAlmSetting(githubAlmSetting, project);
+
+ expectedException.expect(ForbiddenException.class);
+
+ ws.newRequest()
+ .setParam("project", project.getKey())
+ .execute();
+ }
+
+ @Test
+ public void json_example() {
+ userSession.logIn(user).addProjectPermission(ADMIN, project);
+ AlmSettingDto githubAlmSetting = db.almSettings().insertGitHubAlmSetting(
+ almSettingDto -> almSettingDto
+ .setKey("GitHub Server - Dev Team")
+ .setUrl("https://github.enterprise.com")
+ .setAppId("12345")
+ .setPrivateKey("54684654"));
+ db.almSettings().insertGitHubProjectAlmSetting(githubAlmSetting, project, projectAlmSetting -> projectAlmSetting.setAlmRepo("team/project"));
+
+ String response = ws.newRequest()
+ .setParam("project", project.getKey())
+ .execute().getInput();
+
+ assertJson(response).isSimilarTo(getClass().getResource("get_binding-example.json"));
+ }
+
+ @Test
+ public void definition() {
+ WebService.Action def = ws.getDef();
+
+ assertThat(def.since()).isEqualTo("8.1");
+ assertThat(def.isPost()).isFalse();
+ assertThat(def.responseExampleAsString()).isNotEmpty();
+ assertThat(def.params())
+ .extracting(WebService.Param::key, WebService.Param::isRequired)
+ .containsExactlyInAnyOrder(tuple("project", true));
+ }
+
+}