3 * Copyright (C) 2009-2021 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 org.junit.Before;
23 import org.junit.BeforeClass;
24 import org.junit.Rule;
25 import org.junit.Test;
26 import org.junit.rules.ExpectedException;
27 import org.sonar.alm.client.bitbucketserver.BitbucketServerRestClient;
28 import org.sonar.alm.client.bitbucketserver.Branch;
29 import org.sonar.alm.client.bitbucketserver.BranchesList;
30 import org.sonar.alm.client.bitbucketserver.Project;
31 import org.sonar.alm.client.bitbucketserver.Repository;
32 import org.sonar.api.server.ws.WebService;
33 import org.sonar.api.utils.System2;
34 import org.sonar.core.i18n.I18n;
35 import org.sonar.core.util.SequenceUuidFactory;
36 import org.sonar.db.DbTester;
37 import org.sonar.db.alm.pat.AlmPatDto;
38 import org.sonar.db.alm.setting.AlmSettingDto;
39 import org.sonar.db.component.BranchDto;
40 import org.sonar.db.project.ProjectDto;
41 import org.sonar.db.user.UserDto;
42 import org.sonar.server.almintegration.ws.ImportHelper;
43 import org.sonar.server.component.ComponentUpdater;
44 import org.sonar.server.es.TestProjectIndexers;
45 import org.sonar.server.exceptions.BadRequestException;
46 import org.sonar.server.exceptions.ForbiddenException;
47 import org.sonar.server.exceptions.NotFoundException;
48 import org.sonar.server.exceptions.UnauthorizedException;
49 import org.sonar.server.favorite.FavoriteUpdater;
50 import org.sonar.server.permission.PermissionTemplateService;
51 import org.sonar.server.project.ProjectDefaultVisibility;
52 import org.sonar.server.project.Visibility;
53 import org.sonar.server.tester.UserSessionRule;
54 import org.sonar.server.ws.WsActionTester;
55 import org.sonarqube.ws.Projects;
57 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
58 import static org.apache.commons.lang.math.JVMRandom.nextLong;
59 import static org.assertj.core.api.Assertions.assertThat;
60 import static org.assertj.core.api.Assertions.tuple;
61 import static org.mockito.ArgumentMatchers.any;
62 import static org.mockito.Mockito.mock;
63 import static org.mockito.Mockito.when;
64 import static org.sonar.db.alm.integration.pat.AlmPatsTesting.newAlmPatDto;
65 import static org.sonar.db.permission.GlobalPermission.PROVISION_PROJECTS;
66 import static org.sonar.db.permission.GlobalPermission.SCAN;
67 import java.util.Collection;
68 import java.util.Collections;
69 import java.util.List;
70 import java.util.Optional;
71 import java.util.stream.Collectors;
73 public class ImportBitbucketServerProjectActionTest {
76 public ExpectedException expectedException = ExpectedException.none();
78 public UserSessionRule userSession = UserSessionRule.standalone();
80 public DbTester db = DbTester.create();
82 private final ProjectDefaultVisibility projectDefaultVisibility = mock(ProjectDefaultVisibility.class);
83 private final BitbucketServerRestClient bitbucketServerRestClient = mock(BitbucketServerRestClient.class);
85 private final ComponentUpdater componentUpdater = new ComponentUpdater(db.getDbClient(), mock(I18n.class), System2.INSTANCE,
86 mock(PermissionTemplateService.class), new FavoriteUpdater(db.getDbClient()), new TestProjectIndexers(), new SequenceUuidFactory());
88 private final ImportHelper importHelper = new ImportHelper(db.getDbClient(), userSession);
89 private final WsActionTester ws = new WsActionTester(new ImportBitbucketServerProjectAction(db.getDbClient(), userSession,
90 bitbucketServerRestClient, projectDefaultVisibility, componentUpdater, importHelper));
92 private static BranchesList defaultBranchesList;
95 public static void beforeAll() {
96 Branch defaultBranch = new Branch("default", true);
97 defaultBranchesList = new BranchesList(Collections.singletonList(defaultBranch));
101 public void before() {
102 when(projectDefaultVisibility.get(any())).thenReturn(Visibility.PRIVATE);
106 public void import_project() {
107 UserDto user = db.users().insertUser();
108 userSession.logIn(user).addPermission(PROVISION_PROJECTS);
109 AlmSettingDto almSetting = db.almSettings().insertGitHubAlmSetting();
110 db.almPats().insert(dto -> {
111 dto.setAlmSettingUuid(almSetting.getUuid());
112 dto.setUserUuid(user.getUuid());
114 Project project = getGsonBBSProject();
115 Repository repo = getGsonBBSRepo(project);
116 when(bitbucketServerRestClient.getRepo(any(), any(), any(), any())).thenReturn(repo);
117 when(bitbucketServerRestClient.getBranches(any(), any(), any(), any())).thenReturn(defaultBranchesList);
119 Projects.CreateWsResponse response = ws.newRequest()
120 .setParam("almSetting", almSetting.getKey())
121 .setParam("projectKey", "projectKey")
122 .setParam("repositorySlug", "repo-slug")
123 .executeProtobuf(Projects.CreateWsResponse.class);
125 Projects.CreateWsResponse.Project result = response.getProject();
126 assertThat(result.getKey()).isEqualTo(project.getKey() + "_" + repo.getSlug());
127 assertThat(result.getName()).isEqualTo(repo.getName());
129 Optional<ProjectDto> projectDto = db.getDbClient().projectDao().selectProjectByKey(db.getSession(), result.getKey());
130 assertThat(projectDto).isPresent();
131 assertThat(db.getDbClient().projectAlmSettingDao().selectByProject(db.getSession(), projectDto.get())).isPresent();
135 public void fail_project_already_exist() {
136 UserDto user = db.users().insertUser();
137 userSession.logIn(user).addPermission(PROVISION_PROJECTS);
138 AlmSettingDto almSetting = db.almSettings().insertGitHubAlmSetting();
139 db.almPats().insert(dto -> {
140 dto.setAlmSettingUuid(almSetting.getUuid());
141 dto.setUserUuid(user.getUuid());
143 Project project = getGsonBBSProject();
144 Repository repo = getGsonBBSRepo(project);
145 String projectKey = project.getKey() + "_" + repo.getSlug();
146 db.components().insertPublicProject(p -> p.setDbKey(projectKey));
148 expectedException.expect(BadRequestException.class);
149 expectedException.expectMessage("Could not create null, key already exists: " + projectKey);
151 when(bitbucketServerRestClient.getRepo(any(), any(), any(), any())).thenReturn(repo);
152 when(bitbucketServerRestClient.getBranches(any(), any(), any(), any())).thenReturn(defaultBranchesList);
155 .setParam("almSetting", almSetting.getKey())
156 .setParam("projectKey", "projectKey")
157 .setParam("repositorySlug", "repo-slug")
162 public void fail_when_not_logged_in() {
163 expectedException.expect(UnauthorizedException.class);
166 .setParam("almSetting", "sdgfdshfjztutz")
167 .setParam("projectKey", "projectKey")
168 .setParam("repositorySlug", "repo-slug")
173 public void fail_when_missing_project_creator_permission() {
174 UserDto user = db.users().insertUser();
175 userSession.logIn(user).addPermission(SCAN);
177 expectedException.expect(ForbiddenException.class);
178 expectedException.expectMessage("Insufficient privileges");
181 .setParam("almSetting", "sdgfdshfjztutz")
182 .setParam("projectKey", "projectKey")
183 .setParam("repositorySlug", "repo-slug")
188 public void check_pat_is_missing() {
189 UserDto user = db.users().insertUser();
190 userSession.logIn(user).addPermission(PROVISION_PROJECTS);
191 AlmSettingDto almSetting = db.almSettings().insertGitHubAlmSetting();
193 expectedException.expect(IllegalArgumentException.class);
194 expectedException.expectMessage("personal access token for '" + almSetting.getKey() + "' is missing");
197 .setParam("almSetting", almSetting.getKey())
202 public void fail_check_alm_setting_not_found() {
203 UserDto user = db.users().insertUser();
204 userSession.logIn(user).addPermission(PROVISION_PROJECTS);
205 AlmPatDto almPatDto = newAlmPatDto();
206 db.getDbClient().almPatDao().insert(db.getSession(), almPatDto, user.getLogin(), null);
208 expectedException.expect(NotFoundException.class);
209 expectedException.expectMessage("ALM Setting 'testKey' not found");
212 .setParam("almSetting", "testKey")
217 public void fail_when_no_creation_project_permission() {
218 UserDto user = db.users().insertUser();
219 userSession.logIn(user);
221 expectedException.expect(ForbiddenException.class);
222 expectedException.expectMessage("Insufficient privileges");
225 .setParam("almSetting", "anyvalue")
230 public void handle_givenNoDefaultBranchFound_doNotUpdateDefaultBranchName() {
231 BranchesList branchesList = new BranchesList();
232 Branch branch = new Branch("not_a_master", false);
233 branchesList.addBranch(branch);
235 UserDto user = db.users().insertUser();
236 userSession.logIn(user).addPermission(PROVISION_PROJECTS);
237 AlmSettingDto almSetting = db.almSettings().insertGitHubAlmSetting();
238 db.almPats().insert(dto -> {
239 dto.setAlmSettingUuid(almSetting.getUuid());
240 dto.setUserUuid(user.getUuid());
242 Project project = getGsonBBSProject();
243 Repository repo = getGsonBBSRepo(project);
244 when(bitbucketServerRestClient.getRepo(any(), any(), any(), any())).thenReturn(repo);
245 when(bitbucketServerRestClient.getBranches(any(), any(), any(), any())).thenReturn(branchesList);
247 Projects.CreateWsResponse response = ws.newRequest()
248 .setParam("almSetting", almSetting.getKey())
249 .setParam("projectKey", "projectKey")
250 .setParam("repositorySlug", "repo-slug")
251 .executeProtobuf(Projects.CreateWsResponse.class);
253 Projects.CreateWsResponse.Project result = response.getProject();
255 Optional<ProjectDto> projectDto = db.getDbClient().projectDao().selectProjectByKey(db.getSession(), result.getKey());
257 Collection<BranchDto> branchDtos = db.getDbClient().branchDao().selectByProject(db.getSession(), projectDto.get());
258 List<BranchDto> collect = branchDtos.stream().filter(BranchDto::isMain).collect(Collectors.toList());
259 String mainBranchName = collect.iterator().next().getKey();
260 assertThat(mainBranchName).isEqualTo("master");
264 public void handle_givenDefaultBranchNamedDefault_updateDefaultBranchNameToDefault() {
265 BranchesList branchesList = new BranchesList();
266 Branch branch = new Branch("default", true);
267 branchesList.addBranch(branch);
269 UserDto user = db.users().insertUser();
270 userSession.logIn(user).addPermission(PROVISION_PROJECTS);
271 AlmSettingDto almSetting = db.almSettings().insertGitHubAlmSetting();
272 db.almPats().insert(dto -> {
273 dto.setAlmSettingUuid(almSetting.getUuid());
274 dto.setUserUuid(user.getUuid());
276 Project project = getGsonBBSProject();
277 Repository repo = getGsonBBSRepo(project);
278 when(bitbucketServerRestClient.getRepo(any(), any(), any(), any())).thenReturn(repo);
279 when(bitbucketServerRestClient.getBranches(any(), any(), any(), any())).thenReturn(branchesList);
281 Projects.CreateWsResponse response = ws.newRequest()
282 .setParam("almSetting", almSetting.getKey())
283 .setParam("projectKey", "projectKey")
284 .setParam("repositorySlug", "repo-slug")
285 .executeProtobuf(Projects.CreateWsResponse.class);
287 Projects.CreateWsResponse.Project result = response.getProject();
289 Optional<ProjectDto> projectDto = db.getDbClient().projectDao().selectProjectByKey(db.getSession(), result.getKey());
291 Collection<BranchDto> branchDtos = db.getDbClient().branchDao().selectByProject(db.getSession(), projectDto.get());
292 List<BranchDto> collect = branchDtos.stream().filter(BranchDto::isMain).collect(Collectors.toList());
293 String mainBranchName = collect.iterator().next().getKey();
294 assertThat(mainBranchName).isEqualTo("default");
298 public void definition() {
299 WebService.Action def = ws.getDef();
301 assertThat(def.since()).isEqualTo("8.2");
302 assertThat(def.isPost()).isTrue();
303 assertThat(def.params())
304 .extracting(WebService.Param::key, WebService.Param::isRequired)
305 .containsExactlyInAnyOrder(
306 tuple("almSetting", true),
307 tuple("repositorySlug", true),
308 tuple("projectKey", true));
311 private Repository getGsonBBSRepo(Project project) {
312 Repository bbsResult = new Repository();
313 bbsResult.setProject(project);
314 bbsResult.setSlug(randomAlphanumeric(5));
315 bbsResult.setName(randomAlphanumeric(5));
316 bbsResult.setId(nextLong(100));
320 private Project getGsonBBSProject() {
322 .setKey(randomAlphanumeric(5))
323 .setId(nextLong(100))
324 .setName(randomAlphanumeric(5));