3 * Copyright (C) 2009-2024 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.server.almintegration.ws.bitbucketserver;
22 import java.util.ArrayList;
23 import java.util.List;
24 import org.junit.Before;
25 import org.junit.Rule;
26 import org.junit.Test;
27 import org.sonar.alm.client.bitbucketserver.BitbucketServerRestClient;
28 import org.sonar.alm.client.bitbucketserver.Project;
29 import org.sonar.alm.client.bitbucketserver.Repository;
30 import org.sonar.alm.client.bitbucketserver.RepositoryList;
31 import org.sonar.api.server.ws.WebService;
32 import org.sonar.db.DbTester;
33 import org.sonar.db.alm.pat.AlmPatDto;
34 import org.sonar.db.alm.setting.AlmSettingDto;
35 import org.sonar.db.alm.setting.ProjectAlmSettingDao;
36 import org.sonar.db.project.ProjectDao;
37 import org.sonar.db.project.ProjectDto;
38 import org.sonar.db.user.UserDto;
39 import org.sonar.server.exceptions.ForbiddenException;
40 import org.sonar.server.exceptions.NotFoundException;
41 import org.sonar.server.exceptions.UnauthorizedException;
42 import org.sonar.server.tester.UserSessionRule;
43 import org.sonar.server.ws.WsActionTester;
44 import org.sonarqube.ws.AlmIntegrations;
45 import org.sonarqube.ws.AlmIntegrations.SearchBitbucketserverReposWsResponse;
47 import static org.assertj.core.api.Assertions.assertThat;
48 import static org.assertj.core.api.Assertions.assertThatThrownBy;
49 import static org.assertj.core.api.Assertions.tuple;
50 import static org.mockito.ArgumentMatchers.any;
51 import static org.mockito.Mockito.mock;
52 import static org.mockito.Mockito.when;
53 import static org.sonar.db.alm.integration.pat.AlmPatsTesting.newAlmPatDto;
54 import static org.sonar.db.permission.GlobalPermission.PROVISION_PROJECTS;
56 public class SearchBitbucketServerReposActionIT {
59 public UserSessionRule userSession = UserSessionRule.standalone();
61 public DbTester db = DbTester.create();
63 private final BitbucketServerRestClient bitbucketServerRestClient = mock(BitbucketServerRestClient.class);
64 private final ProjectAlmSettingDao projectAlmSettingDao = db.getDbClient().projectAlmSettingDao();
65 private final ProjectDao projectDao = db.getDbClient().projectDao();
66 private final WsActionTester ws = new WsActionTester(
67 new SearchBitbucketServerReposAction(db.getDbClient(), userSession, bitbucketServerRestClient, projectAlmSettingDao, projectDao));
70 public void before() {
71 RepositoryList gsonBBSRepoList = new RepositoryList();
72 gsonBBSRepoList.setLastPage(true);
73 List<Repository> values = new ArrayList<>();
74 values.add(getGsonBBSRepo1());
75 values.add(getGsonBBSRepo2());
76 gsonBBSRepoList.setValues(values);
77 when(bitbucketServerRestClient.getRepos(any(), any(), any(), any())).thenReturn(gsonBBSRepoList);
81 public void list_repos() {
82 UserDto user = db.users().insertUser();
83 userSession.logIn(user).addPermission(PROVISION_PROJECTS);
84 AlmSettingDto almSetting = db.almSettings().insertBitbucketAlmSetting();
85 db.almPats().insert(dto -> {
86 dto.setAlmSettingUuid(almSetting.getUuid());
87 dto.setUserUuid(user.getUuid());
89 ProjectDto projectDto = db.components().insertPrivateProject().getProjectDto();
90 db.almSettings().insertBitbucketProjectAlmSetting(almSetting, projectDto, s -> s.setAlmRepo("projectKey2"), s -> s.setAlmSlug("repo-slug-2"));
92 AlmIntegrations.SearchBitbucketserverReposWsResponse response = ws.newRequest()
93 .setParam("almSetting", almSetting.getKey())
94 .executeProtobuf(SearchBitbucketserverReposWsResponse.class);
96 assertThat(response.getIsLastPage()).isTrue();
97 assertThat(response.getRepositoriesList())
98 .extracting(AlmIntegrations.BBSRepo::getId, AlmIntegrations.BBSRepo::getName, AlmIntegrations.BBSRepo::getSlug, AlmIntegrations.BBSRepo::hasSqProjectKey,
99 AlmIntegrations.BBSRepo::getSqProjectKey, AlmIntegrations.BBSRepo::getProjectKey)
100 .containsExactlyInAnyOrder(
101 tuple(1L, "repoName1", "repo-slug-1", false, "", "projectKey1"),
102 tuple(3L, "repoName2", "repo-slug-2", true, projectDto.getKey(), "projectKey2"));
106 public void return_empty_list_when_no_bbs_repo() {
107 RepositoryList gsonBBSRepoList = new RepositoryList();
108 gsonBBSRepoList.setLastPage(true);
109 gsonBBSRepoList.setValues(new ArrayList<>());
110 when(bitbucketServerRestClient.getRepos(any(), any(), any(), any())).thenReturn(gsonBBSRepoList);
111 UserDto user = db.users().insertUser();
112 userSession.logIn(user).addPermission(PROVISION_PROJECTS);
113 AlmSettingDto almSetting = db.almSettings().insertBitbucketAlmSetting();
114 db.almPats().insert(dto -> {
115 dto.setAlmSettingUuid(almSetting.getUuid());
116 dto.setUserUuid(user.getUuid());
118 ProjectDto projectDto = db.components().insertPrivateProject().getProjectDto();
119 db.almSettings().insertBitbucketProjectAlmSetting(almSetting, projectDto, s -> s.setAlmRepo("projectKey2"), s -> s.setAlmSlug("repo-slug-2"));
121 AlmIntegrations.SearchBitbucketserverReposWsResponse response = ws.newRequest()
122 .setParam("almSetting", almSetting.getKey())
123 .executeProtobuf(SearchBitbucketserverReposWsResponse.class);
125 assertThat(response.getIsLastPage()).isTrue();
126 assertThat(response.getRepositoriesList()).isEmpty();
130 public void already_imported_detection_does_not_get_confused_by_same_slug_in_different_projects() {
131 UserDto user = db.users().insertUser();
132 userSession.logIn(user).addPermission(PROVISION_PROJECTS);
133 AlmSettingDto almSetting = db.almSettings().insertBitbucketAlmSetting();
134 db.almPats().insert(dto -> {
135 dto.setAlmSettingUuid(almSetting.getUuid());
136 dto.setUserUuid(user.getUuid());
138 ProjectDto projectDto = db.components().insertPrivateProject().getProjectDto();
139 db.almSettings().insertBitbucketProjectAlmSetting(almSetting, projectDto, s -> s.setAlmRepo("projectKey2"), s -> s.setAlmSlug("repo-slug-2"));
140 db.almSettings().insertBitbucketProjectAlmSetting(almSetting, db.components().insertPrivateProject().getProjectDto(), s -> s.setAlmRepo("projectKey2"), s -> s.setAlmSlug("repo-slug-2"));
142 AlmIntegrations.SearchBitbucketserverReposWsResponse response = ws.newRequest()
143 .setParam("almSetting", almSetting.getKey())
144 .executeProtobuf(SearchBitbucketserverReposWsResponse.class);
146 assertThat(response.getIsLastPage()).isTrue();
147 assertThat(response.getRepositoriesList())
148 .extracting(AlmIntegrations.BBSRepo::getId, AlmIntegrations.BBSRepo::getName, AlmIntegrations.BBSRepo::getSlug, AlmIntegrations.BBSRepo::getSqProjectKey,
149 AlmIntegrations.BBSRepo::getProjectKey)
150 .containsExactlyInAnyOrder(
151 tuple(1L, "repoName1", "repo-slug-1", "", "projectKey1"),
152 tuple(3L, "repoName2", "repo-slug-2", projectDto.getKey(), "projectKey2"));
156 public void use_projectKey_to_disambiguate_when_multiple_projects_are_binded_on_one_bitbucketserver_repo() {
157 UserDto user = db.users().insertUser();
158 userSession.logIn(user).addPermission(PROVISION_PROJECTS);
159 AlmSettingDto almSetting = db.almSettings().insertBitbucketAlmSetting();
160 db.almPats().insert(dto -> {
161 dto.setAlmSettingUuid(almSetting.getUuid());
162 dto.setUserUuid(user.getUuid());
164 ProjectDto project1 = db.components().insertPrivateProject(p -> p.setKey("B")).getProjectDto();
165 ProjectDto project2 = db.components().insertPrivateProject(p -> p.setKey("A")).getProjectDto();
166 db.almSettings().insertBitbucketProjectAlmSetting(almSetting, project1, s -> s.setAlmRepo("projectKey2"), s -> s.setAlmSlug("repo-slug-2"));
167 db.almSettings().insertBitbucketProjectAlmSetting(almSetting, project2, s -> s.setAlmRepo("projectKey2"), s -> s.setAlmSlug("repo-slug-2"));
169 AlmIntegrations.SearchBitbucketserverReposWsResponse response = ws.newRequest()
170 .setParam("almSetting", almSetting.getKey())
171 .executeProtobuf(SearchBitbucketserverReposWsResponse.class);
173 assertThat(response.getIsLastPage()).isTrue();
174 assertThat(response.getRepositoriesList())
175 .extracting(AlmIntegrations.BBSRepo::getId, AlmIntegrations.BBSRepo::getName, AlmIntegrations.BBSRepo::getSlug, AlmIntegrations.BBSRepo::getSqProjectKey,
176 AlmIntegrations.BBSRepo::getProjectKey)
177 .containsExactlyInAnyOrder(
178 tuple(1L, "repoName1", "repo-slug-1", "", "projectKey1"),
179 tuple(3L, "repoName2", "repo-slug-2", "A", "projectKey2"));
183 public void check_pat_is_missing() {
184 UserDto user = db.users().insertUser();
185 userSession.logIn(user).addPermission(PROVISION_PROJECTS);
186 AlmSettingDto almSetting = db.almSettings().insertGitHubAlmSetting();
188 assertThatThrownBy(() -> {
190 .setParam("almSetting", almSetting.getKey())
193 .isInstanceOf(IllegalArgumentException.class)
194 .hasMessage("No personal access token found");
198 public void fail_check_pat_alm_setting_not_found() {
199 UserDto user = db.users().insertUser();
200 userSession.logIn(user).addPermission(PROVISION_PROJECTS);
201 AlmPatDto almPatDto = newAlmPatDto();
202 db.getDbClient().almPatDao().insert(db.getSession(), almPatDto, user.getLogin(), null);
204 assertThatThrownBy(() -> {
206 .setParam("almSetting", "testKey")
209 .isInstanceOf(NotFoundException.class)
210 .hasMessage("DevOps Platform Setting 'testKey' not found");
214 public void fail_when_not_logged_in() {
215 assertThatThrownBy(() -> {
217 .setParam("almSetting", "anyvalue")
220 .isInstanceOf(UnauthorizedException.class);
224 public void fail_when_no_creation_project_permission() {
225 UserDto user = db.users().insertUser();
226 userSession.logIn(user);
228 assertThatThrownBy(() -> {
230 .setParam("almSetting", "anyvalue")
233 .isInstanceOf(ForbiddenException.class)
234 .hasMessage("Insufficient privileges");
238 public void definition() {
239 WebService.Action def = ws.getDef();
241 assertThat(def.since()).isEqualTo("8.2");
242 assertThat(def.isPost()).isFalse();
243 assertThat(def.responseExampleFormat()).isEqualTo("json");
244 assertThat(def.params())
245 .extracting(WebService.Param::key, WebService.Param::isRequired)
246 .containsExactlyInAnyOrder(
247 tuple("almSetting", true),
248 tuple("projectName", false),
249 tuple("repositoryName", false));
252 private Repository getGsonBBSRepo1() {
253 Repository gsonBBSRepo1 = new Repository();
254 gsonBBSRepo1.setId(1L);
255 gsonBBSRepo1.setName("repoName1");
256 Project project1 = new Project();
257 project1.setName("projectName1");
258 project1.setKey("projectKey1");
260 gsonBBSRepo1.setProject(project1);
261 gsonBBSRepo1.setSlug("repo-slug-1");
265 private Repository getGsonBBSRepo2() {
266 Repository gsonBBSRepo = new Repository();
267 gsonBBSRepo.setId(3L);
268 gsonBBSRepo.setName("repoName2");
269 Project project = new Project();
270 project.setName("projectName2");
271 project.setKey("projectKey2");
273 gsonBBSRepo.setProject(project);
274 gsonBBSRepo.setSlug("repo-slug-2");