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.gitlab;
22 import java.util.Arrays;
23 import java.util.LinkedList;
24 import org.junit.Rule;
25 import org.junit.Test;
26 import org.sonar.alm.client.gitlab.GitlabApplicationClient;
27 import org.sonar.alm.client.gitlab.Project;
28 import org.sonar.alm.client.gitlab.ProjectList;
29 import org.sonar.api.server.ws.WebService;
30 import org.sonar.db.DbTester;
31 import org.sonar.db.alm.pat.AlmPatDto;
32 import org.sonar.db.alm.setting.AlmSettingDto;
33 import org.sonar.db.project.ProjectDto;
34 import org.sonar.db.user.UserDto;
35 import org.sonar.server.exceptions.ForbiddenException;
36 import org.sonar.server.exceptions.NotFoundException;
37 import org.sonar.server.exceptions.UnauthorizedException;
38 import org.sonar.server.tester.UserSessionRule;
39 import org.sonar.server.ws.TestRequest;
40 import org.sonar.server.ws.WsActionTester;
41 import org.sonarqube.ws.AlmIntegrations;
42 import org.sonarqube.ws.AlmIntegrations.GitlabRepository;
43 import org.sonarqube.ws.AlmIntegrations.SearchGitlabReposWsResponse;
45 import static org.assertj.core.api.Assertions.assertThat;
46 import static org.assertj.core.api.Assertions.assertThatThrownBy;
47 import static org.assertj.core.api.Assertions.tuple;
48 import static org.mockito.ArgumentMatchers.any;
49 import static org.mockito.ArgumentMatchers.anyInt;
50 import static org.mockito.Mockito.mock;
51 import static org.mockito.Mockito.when;
52 import static org.sonar.db.alm.integration.pat.AlmPatsTesting.newAlmPatDto;
53 import static org.sonar.db.permission.GlobalPermission.PROVISION_PROJECTS;
55 public class SearchGitlabReposActionIT {
58 public UserSessionRule userSession = UserSessionRule.standalone();
60 public DbTester db = DbTester.create();
62 private final GitlabApplicationClient gitlabApplicationClient = mock(GitlabApplicationClient.class);
63 private final WsActionTester ws = new WsActionTester(new SearchGitlabReposAction(db.getDbClient(), userSession,
64 gitlabApplicationClient));
67 public void list_gitlab_repos() {
68 Project gitlabProject1 = new Project(1L, "repoName1", "repoNamePath1", "repo-slug-1", "repo-path-slug-1", "url-1");
69 Project gitlabProject2 = new Project(2L, "repoName2", "path1 / repoName2", "repo-slug-2", "path-1/repo-slug-2", "url-2");
70 Project gitlabProject3 = new Project(3L, "repoName3", "repoName3 / repoName3", "repo-slug-3", "repo-slug-3/repo-slug-3", "url-3");
71 Project gitlabProject4 = new Project(4L, "repoName4", "repoName4 / repoName4 / repoName4", "repo-slug-4", "repo-slug-4/repo-slug-4/repo-slug-4", "url-4");
72 when(gitlabApplicationClient.searchProjects(any(), any(), any(), anyInt(), anyInt()))
74 new ProjectList(Arrays.asList(gitlabProject1, gitlabProject2, gitlabProject3, gitlabProject4), 1, 10, 4));
76 UserDto user = db.users().insertUser();
77 userSession.logIn(user).addPermission(PROVISION_PROJECTS);
78 AlmSettingDto almSetting = db.almSettings().insertGitlabAlmSetting();
79 db.almPats().insert(dto -> {
80 dto.setAlmSettingUuid(almSetting.getUuid());
81 dto.setUserUuid(user.getUuid());
82 dto.setPersonalAccessToken("some-pat");
84 ProjectDto projectDto = db.components().insertPrivateProject().getProjectDto();
85 db.almSettings().insertGitlabProjectAlmSetting(almSetting, projectDto);
87 AlmIntegrations.SearchGitlabReposWsResponse response = ws.newRequest()
88 .setParam("almSetting", almSetting.getKey())
89 .executeProtobuf(SearchGitlabReposWsResponse.class);
91 assertThat(response.getRepositoriesCount()).isEqualTo(4);
93 assertThat(response.getRepositoriesList())
94 .extracting(GitlabRepository::getId,
95 GitlabRepository::getName,
96 GitlabRepository::getPathName,
97 GitlabRepository::getSlug,
98 GitlabRepository::getPathSlug,
99 GitlabRepository::getUrl,
100 GitlabRepository::hasSqProjectKey,
101 GitlabRepository::hasSqProjectName)
102 .containsExactlyInAnyOrder(
103 tuple(1L, "repoName1", "repoNamePath1", "repo-slug-1", "repo-path-slug-1", "url-1", false, false),
104 tuple(2L, "repoName2", "path1", "repo-slug-2", "path-1", "url-2", false, false),
105 tuple(3L, "repoName3", "repoName3", "repo-slug-3", "repo-slug-3", "url-3", false, false),
106 tuple(4L, "repoName4", "repoName4 / repoName4", "repo-slug-4", "repo-slug-4/repo-slug-4", "url-4", false, false));
110 public void list_gitlab_repos_some_projects_already_set_up() {
111 Project gitlabProject1 = new Project(1L, "repoName1", "repoNamePath1", "repo-slug-1", "repo-path-slug-1", "url-1");
112 Project gitlabProject2 = new Project(2L, "repoName2", "path1 / repoName2", "repo-slug-2", "path-1/repo-slug-2", "url-2");
113 Project gitlabProject3 = new Project(3L, "repoName3", "repoName3 / repoName3", "repo-slug-3", "repo-slug-3/repo-slug-3", "url-3");
114 Project gitlabProject4 = new Project(4L, "repoName4", "repoName4 / repoName4 / repoName4", "repo-slug-4", "repo-slug-4/repo-slug-4/repo-slug-4", "url-4");
115 when(gitlabApplicationClient.searchProjects(any(), any(), any(), anyInt(), anyInt()))
117 new ProjectList(Arrays.asList(gitlabProject1, gitlabProject2, gitlabProject3, gitlabProject4), 1, 10, 4));
119 UserDto user = db.users().insertUser();
120 userSession.logIn(user).addPermission(PROVISION_PROJECTS);
121 AlmSettingDto almSetting = db.almSettings().insertGitlabAlmSetting();
122 db.almPats().insert(dto -> {
123 dto.setAlmSettingUuid(almSetting.getUuid());
124 dto.setUserUuid(user.getUuid());
125 dto.setPersonalAccessToken("some-pat");
127 ProjectDto projectDto1 = db.components().insertPrivateProject(dto -> dto.setKey("proj_key_1").setName("proj_name_1")).getProjectDto();
128 db.almSettings().insertGitlabProjectAlmSetting(almSetting, projectDto1);
130 ProjectDto projectDto2 = db.components().insertPrivateProject(dto -> dto.setKey("proj_key_2").setName("proj_name_2")).getProjectDto();
131 db.almSettings().insertGitlabProjectAlmSetting(almSetting, projectDto2, projectAlmSettingDto -> projectAlmSettingDto.setAlmRepo("2"));
133 ProjectDto projectDto3 = db.components().insertPrivateProject(dto -> dto.setKey("proj_key_3").setName("proj_name_3")).getProjectDto();
134 db.almSettings().insertGitlabProjectAlmSetting(almSetting, projectDto3, projectAlmSettingDto -> projectAlmSettingDto.setAlmRepo("3"));
136 ProjectDto projectDto4 = db.components().insertPrivateProject(dto -> dto.setKey("proj_key_4").setName("proj_name_4")).getProjectDto();
137 db.almSettings().insertGitlabProjectAlmSetting(almSetting, projectDto4, projectAlmSettingDto -> projectAlmSettingDto.setAlmRepo("3"));
139 AlmIntegrations.SearchGitlabReposWsResponse response = ws.newRequest()
140 .setParam("almSetting", almSetting.getKey())
141 .executeProtobuf(SearchGitlabReposWsResponse.class);
143 assertThat(response.getRepositoriesCount()).isEqualTo(4);
145 assertThat(response.getRepositoriesList())
146 .extracting(GitlabRepository::getId,
147 GitlabRepository::getName,
148 GitlabRepository::getPathName,
149 GitlabRepository::getSlug,
150 GitlabRepository::getPathSlug,
151 GitlabRepository::getUrl,
152 GitlabRepository::getSqProjectKey,
153 GitlabRepository::getSqProjectName)
154 .containsExactlyInAnyOrder(
155 tuple(1L, "repoName1", "repoNamePath1", "repo-slug-1", "repo-path-slug-1", "url-1", "", ""),
156 tuple(2L, "repoName2", "path1", "repo-slug-2", "path-1", "url-2", projectDto2.getKey(), projectDto2.getName()),
157 tuple(3L, "repoName3", "repoName3", "repo-slug-3", "repo-slug-3", "url-3", projectDto3.getKey(), projectDto3.getName()),
158 tuple(4L, "repoName4", "repoName4 / repoName4", "repo-slug-4", "repo-slug-4/repo-slug-4", "url-4", "", ""));
162 public void return_empty_list_when_no_gitlab_projects() {
163 when(gitlabApplicationClient.searchProjects(any(), any(), any(), anyInt(), anyInt())).thenReturn(new ProjectList(new LinkedList<>(), 1, 10, 0));
164 UserDto user = db.users().insertUser();
165 userSession.logIn(user).addPermission(PROVISION_PROJECTS);
166 AlmSettingDto almSetting = db.almSettings().insertBitbucketAlmSetting();
167 db.almPats().insert(dto -> {
168 dto.setAlmSettingUuid(almSetting.getUuid());
169 dto.setUserUuid(user.getUuid());
171 ProjectDto projectDto = db.components().insertPrivateProject().getProjectDto();
172 db.almSettings().insertGitlabProjectAlmSetting(almSetting, projectDto);
174 AlmIntegrations.SearchGitlabReposWsResponse response = ws.newRequest()
175 .setParam("almSetting", almSetting.getKey())
176 .executeProtobuf(SearchGitlabReposWsResponse.class);
178 assertThat(response.getRepositoriesList()).isEmpty();
182 public void check_pat_is_missing() {
183 UserDto user = db.users().insertUser();
184 userSession.logIn(user).addPermission(PROVISION_PROJECTS);
185 AlmSettingDto almSetting = db.almSettings().insertGitlabAlmSetting();
187 TestRequest request = ws.newRequest()
188 .setParam("almSetting", almSetting.getKey());
190 assertThatThrownBy(request::execute)
191 .isInstanceOf(IllegalArgumentException.class)
192 .hasMessage("No personal access token found");
196 public void fail_when_alm_setting_not_found() {
197 UserDto user = db.users().insertUser();
198 userSession.logIn(user).addPermission(PROVISION_PROJECTS);
199 AlmPatDto almPatDto = newAlmPatDto();
200 db.getDbClient().almPatDao().insert(db.getSession(), almPatDto, user.getLogin(), null);
202 TestRequest request = ws.newRequest()
203 .setParam("almSetting", "testKey");
205 assertThatThrownBy(request::execute)
206 .isInstanceOf(NotFoundException.class)
207 .hasMessage("DevOps Platform Setting 'testKey' not found");
211 public void fail_when_not_logged_in() {
212 TestRequest request = ws.newRequest()
213 .setParam("almSetting", "anyvalue");
215 assertThatThrownBy(request::execute)
216 .isInstanceOf(UnauthorizedException.class)
217 .hasMessage("Authentication is required");
221 public void fail_when_no_creation_project_permission() {
222 UserDto user = db.users().insertUser();
223 userSession.logIn(user);
225 TestRequest request = ws.newRequest()
226 .setParam("almSetting", "anyvalue");
228 assertThatThrownBy(request::execute)
229 .isInstanceOf(ForbiddenException.class)
230 .hasMessage("Insufficient privileges");
234 public void verify_response_example() {
235 Project gitlabProject1 = new Project(1L, "Gitlab repo name 1", "Group / Gitlab repo name 1", "gitlab-repo-name-1", "group/gitlab-repo-name-1",
236 "https://example.gitlab.com/group/gitlab-repo-name-1");
237 Project gitlabProject2 = new Project(2L, "Gitlab repo name 2", "Group / Gitlab repo name 2", "gitlab-repo-name-2", "group/gitlab-repo-name-2",
238 "https://example.gitlab.com/group/gitlab-repo-name-2");
239 Project gitlabProject3 = new Project(3L, "Gitlab repo name 3", "Group / Gitlab repo name 3", "gitlab-repo-name-3", "group/gitlab-repo-name-3",
240 "https://example.gitlab.com/group/gitlab-repo-name-3");
241 when(gitlabApplicationClient.searchProjects(any(), any(), any(), anyInt(), anyInt()))
243 new ProjectList(Arrays.asList(gitlabProject1, gitlabProject2, gitlabProject3), 1, 3, 10));
245 UserDto user = db.users().insertUser();
246 userSession.logIn(user).addPermission(PROVISION_PROJECTS);
247 AlmSettingDto almSetting = db.almSettings().insertGitlabAlmSetting();
248 db.almPats().insert(dto -> {
249 dto.setAlmSettingUuid(almSetting.getUuid());
250 dto.setUserUuid(user.getUuid());
251 dto.setPersonalAccessToken("some-pat");
253 ProjectDto projectDto = db.components().insertPrivateProject().getProjectDto();
254 db.almSettings().insertGitlabProjectAlmSetting(almSetting, projectDto);
256 WebService.Action def = ws.getDef();
257 String responseExample = def.responseExampleAsString();
259 assertThat(responseExample).isNotBlank();
262 .setParam("almSetting", almSetting.getKey())
263 .execute().assertJson(
268 public void definition() {
269 WebService.Action def = ws.getDef();
271 assertThat(def.since()).isEqualTo("8.5");
272 assertThat(def.isPost()).isFalse();
273 assertThat(def.params())
274 .extracting(WebService.Param::key, WebService.Param::isRequired)
275 .containsExactlyInAnyOrder(
276 tuple("almSetting", true),
279 tuple("projectName", false));