You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ReportSubmitterIT.java 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2024 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  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.
  10. *
  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.
  15. *
  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.
  19. */
  20. package org.sonar.server.ce.queue;
  21. import java.io.InputStream;
  22. import java.util.Map;
  23. import java.util.Optional;
  24. import java.util.Set;
  25. import org.apache.commons.io.IOUtils;
  26. import org.junit.Before;
  27. import org.junit.Rule;
  28. import org.junit.Test;
  29. import org.sonar.alm.client.github.GithubGlobalSettingsValidator;
  30. import org.sonar.api.utils.System2;
  31. import org.sonar.auth.github.GitHubSettings;
  32. import org.sonar.auth.github.client.GithubApplicationClient;
  33. import org.sonar.ce.queue.CeQueue;
  34. import org.sonar.ce.queue.CeQueueImpl;
  35. import org.sonar.ce.queue.CeTaskSubmit;
  36. import org.sonar.core.i18n.I18n;
  37. import org.sonar.core.util.SequenceUuidFactory;
  38. import org.sonar.db.DbSession;
  39. import org.sonar.db.DbTester;
  40. import org.sonar.db.alm.setting.ALM;
  41. import org.sonar.db.alm.setting.AlmSettingDto;
  42. import org.sonar.db.ce.CeTaskTypes;
  43. import org.sonar.db.component.BranchDto;
  44. import org.sonar.db.component.ComponentDto;
  45. import org.sonar.db.component.ProjectData;
  46. import org.sonar.db.permission.GlobalPermission;
  47. import org.sonar.db.project.CreationMethod;
  48. import org.sonar.db.project.ProjectDto;
  49. import org.sonar.db.user.UserDto;
  50. import org.sonar.server.common.almintegration.ProjectKeyGenerator;
  51. import org.sonar.server.common.almsettings.DelegatingDevOpsProjectCreatorFactory;
  52. import org.sonar.server.common.almsettings.DevOpsProjectCreator;
  53. import org.sonar.server.common.almsettings.DevOpsProjectCreatorFactory;
  54. import org.sonar.server.common.almsettings.DevOpsProjectDescriptor;
  55. import org.sonar.server.common.almsettings.github.GithubProjectCreationParameters;
  56. import org.sonar.server.common.almsettings.github.GithubProjectCreator;
  57. import org.sonar.server.common.almsettings.github.GithubProjectCreatorFactory;
  58. import org.sonar.server.common.component.ComponentUpdater;
  59. import org.sonar.server.common.permission.PermissionTemplateService;
  60. import org.sonar.server.common.permission.PermissionUpdater;
  61. import org.sonar.server.common.permission.UserPermissionChange;
  62. import org.sonar.server.common.project.ProjectCreator;
  63. import org.sonar.server.es.TestIndexers;
  64. import org.sonar.server.exceptions.BadRequestException;
  65. import org.sonar.server.exceptions.ForbiddenException;
  66. import org.sonar.server.favorite.FavoriteUpdater;
  67. import org.sonar.server.management.ManagedInstanceService;
  68. import org.sonar.server.management.ManagedProjectService;
  69. import org.sonar.server.permission.PermissionService;
  70. import org.sonar.server.permission.PermissionServiceImpl;
  71. import org.sonar.server.project.DefaultBranchNameResolver;
  72. import org.sonar.server.project.ProjectDefaultVisibility;
  73. import org.sonar.server.project.Visibility;
  74. import org.sonar.server.tester.UserSessionRule;
  75. import static java.lang.String.format;
  76. import static java.nio.charset.StandardCharsets.UTF_8;
  77. import static java.util.Collections.emptyMap;
  78. import static java.util.stream.IntStream.rangeClosed;
  79. import static org.assertj.core.api.Assertions.assertThat;
  80. import static org.assertj.core.api.Assertions.assertThatThrownBy;
  81. import static org.mockito.ArgumentMatchers.any;
  82. import static org.mockito.ArgumentMatchers.anyString;
  83. import static org.mockito.ArgumentMatchers.argThat;
  84. import static org.mockito.ArgumentMatchers.eq;
  85. import static org.mockito.Mockito.doReturn;
  86. import static org.mockito.Mockito.mock;
  87. import static org.mockito.Mockito.never;
  88. import static org.mockito.Mockito.spy;
  89. import static org.mockito.Mockito.verify;
  90. import static org.mockito.Mockito.verifyNoInteractions;
  91. import static org.mockito.Mockito.when;
  92. import static org.sonar.core.ce.CeTaskCharacteristics.BRANCH;
  93. import static org.sonar.db.component.BranchDto.DEFAULT_MAIN_BRANCH_NAME;
  94. import static org.sonar.db.component.ComponentTesting.newDirectory;
  95. import static org.sonar.db.permission.GlobalPermission.PROVISION_PROJECTS;
  96. import static org.sonar.db.permission.GlobalPermission.SCAN;
  97. public class ReportSubmitterIT {
  98. private static final String PROJECT_KEY = "MY_PROJECT";
  99. private static final String PROJECT_UUID = "P1";
  100. private static final String PROJECT_NAME = "My Project";
  101. private static final String TASK_UUID = "TASK_1";
  102. private static final Map<String, String> CHARACTERISTICS = Map.of("random", "data");
  103. @Rule
  104. public final UserSessionRule userSession = UserSessionRule.standalone();
  105. @Rule
  106. public final DbTester db = DbTester.create();
  107. private final ProjectDefaultVisibility projectDefaultVisibility = mock(ProjectDefaultVisibility.class);
  108. private final DefaultBranchNameResolver defaultBranchNameResolver = mock(DefaultBranchNameResolver.class);
  109. private final CeQueue queue = mock(CeQueueImpl.class);
  110. private final TestIndexers projectIndexers = new TestIndexers();
  111. private final PermissionTemplateService permissionTemplateService = mock(PermissionTemplateService.class);
  112. private final BranchSupport ossEditionBranchSupport = new BranchSupport(null);
  113. private final GithubApplicationClient githubApplicationClient = mock();
  114. private final GithubGlobalSettingsValidator githubGlobalSettingsValidator = mock();
  115. private final GitHubSettings gitHubSettings = mock();
  116. private final ProjectKeyGenerator projectKeyGenerator = mock();
  117. private final PermissionUpdater<UserPermissionChange> permissionUpdater = mock();
  118. private final PermissionService permissionService = new PermissionServiceImpl(mock());
  119. private final ComponentUpdater componentUpdater = new ComponentUpdater(db.getDbClient(), mock(I18n.class), mock(System2.class), permissionTemplateService,
  120. new FavoriteUpdater(db.getDbClient()), projectIndexers, new SequenceUuidFactory(), defaultBranchNameResolver, mock(PermissionUpdater.class), permissionService);
  121. private final ManagedProjectService managedProjectService = mock();
  122. private final ManagedInstanceService managedInstanceService = mock();
  123. private final ProjectCreator projectCreator = new ProjectCreator(userSession, projectDefaultVisibility, componentUpdater);
  124. private final GithubProjectCreatorFactory githubProjectCreatorFactory = new GithubProjectCreatorFactory(db.getDbClient(), githubGlobalSettingsValidator,
  125. githubApplicationClient, projectKeyGenerator, userSession, projectCreator, gitHubSettings, null, permissionUpdater, permissionService,
  126. managedProjectService);
  127. private final DevOpsProjectCreatorFactory devOpsProjectCreatorFactory = new DelegatingDevOpsProjectCreatorFactory(Set.of(githubProjectCreatorFactory));
  128. private final DevOpsProjectCreatorFactory devOpsProjectCreatorFactorySpy = spy(devOpsProjectCreatorFactory);
  129. private final ReportSubmitter underTest = new ReportSubmitter(queue, userSession, projectCreator, componentUpdater, permissionTemplateService, db.getDbClient(),
  130. ossEditionBranchSupport, devOpsProjectCreatorFactorySpy, managedInstanceService);
  131. @Before
  132. public void before() {
  133. when(projectDefaultVisibility.get(any())).thenReturn(Visibility.PUBLIC);
  134. when(defaultBranchNameResolver.getEffectiveMainBranchName()).thenReturn(DEFAULT_MAIN_BRANCH_NAME);
  135. userSession.logIn("login");
  136. }
  137. @Test
  138. public void submit_with_characteristics_fails_with_ISE_when_no_branch_support_delegate() {
  139. userSession
  140. .addPermission(GlobalPermission.SCAN)
  141. .addPermission(PROVISION_PROJECTS);
  142. mockSuccessfulPrepareSubmitCall();
  143. when(permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(), any(), eq(PROJECT_KEY)))
  144. .thenReturn(true);
  145. Map<String, String> nonEmptyCharacteristics = Map.of(BRANCH, "branch1");
  146. InputStream reportInput = IOUtils.toInputStream("{binary}", UTF_8);
  147. assertThatThrownBy(() -> underTest.submit(PROJECT_KEY, PROJECT_NAME, nonEmptyCharacteristics, reportInput))
  148. .isInstanceOf(IllegalStateException.class)
  149. .hasMessage("Current edition does not support branch feature");
  150. }
  151. @Test
  152. public void submit_stores_report() {
  153. userSession
  154. .addPermission(GlobalPermission.SCAN)
  155. .addPermission(PROVISION_PROJECTS);
  156. mockSuccessfulPrepareSubmitCall();
  157. when(permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(), any(), eq(PROJECT_KEY)))
  158. .thenReturn(true);
  159. underTest.submit(PROJECT_KEY, PROJECT_NAME, emptyMap(), IOUtils.toInputStream("{binary}", UTF_8));
  160. verifyReportIsPersisted(TASK_UUID);
  161. }
  162. @Test
  163. public void submit_a_report_on_existing_project() {
  164. ProjectData project = db.components().insertPrivateProject();
  165. UserDto user = db.users().insertUser();
  166. userSession.logIn(user).addProjectPermission(SCAN.getKey(), project.getProjectDto())
  167. .addProjectBranchMapping(project.projectUuid(), project.getMainBranchComponent());
  168. mockSuccessfulPrepareSubmitCall();
  169. underTest.submit(project.projectKey(), project.getProjectDto().getName(), emptyMap(), IOUtils.toInputStream("{binary}", UTF_8));
  170. verifyReportIsPersisted(TASK_UUID);
  171. verifyNoInteractions(permissionTemplateService);
  172. verify(queue).submit(argThat(submit -> submit.getType().equals(CeTaskTypes.REPORT)
  173. && submit.getComponent()
  174. .filter(cpt -> cpt.getUuid().equals(project.getMainBranchComponent().uuid()) && cpt.getEntityUuid().equals(project.projectUuid()))
  175. .isPresent()
  176. && submit.getSubmitterUuid().equals(user.getUuid())
  177. && submit.getUuid().equals(TASK_UUID)));
  178. }
  179. @Test
  180. public void provision_project_if_does_not_exist() {
  181. userSession
  182. .addPermission(GlobalPermission.SCAN)
  183. .addPermission(PROVISION_PROJECTS);
  184. mockSuccessfulPrepareSubmitCall();
  185. when(permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(DbSession.class), any(), eq(PROJECT_KEY))).thenReturn(true);
  186. when(permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(any(DbSession.class), any(ProjectDto.class))).thenReturn(true);
  187. underTest.submit(PROJECT_KEY, PROJECT_NAME, emptyMap(), IOUtils.toInputStream("{binary}", UTF_8));
  188. ComponentDto createdProject = db.getDbClient().componentDao().selectByKey(db.getSession(), PROJECT_KEY).get();
  189. ProjectDto projectDto = db.getDbClient().projectDao().selectProjectByKey(db.getSession(), PROJECT_KEY).orElseThrow();
  190. verifyReportIsPersisted(TASK_UUID);
  191. verify(queue).submit(argThat(submit -> submit.getType().equals(CeTaskTypes.REPORT)
  192. && submit.getComponent().filter(cpt -> cpt.getUuid().equals(createdProject.uuid()) && cpt.getEntityUuid().equals(projectDto.getUuid()))
  193. .isPresent()
  194. && submit.getUuid().equals(TASK_UUID)));
  195. assertThat(projectDto.getCreationMethod()).isEqualTo(CreationMethod.SCANNER_API);
  196. }
  197. @Test
  198. public void add_project_as_favorite_when_project_creator_permission_on_permission_template() {
  199. UserDto user = db.users().insertUser();
  200. userSession
  201. .logIn(user)
  202. .addPermission(GlobalPermission.SCAN)
  203. .addPermission(PROVISION_PROJECTS);
  204. mockSuccessfulPrepareSubmitCall();
  205. when(permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(DbSession.class), any(), eq(PROJECT_KEY))).thenReturn(true);
  206. when(permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(any(DbSession.class), any(ProjectDto.class))).thenReturn(true);
  207. underTest.submit(PROJECT_KEY, PROJECT_NAME, emptyMap(), IOUtils.toInputStream("{binary}", UTF_8));
  208. ProjectDto createdProject = db.getDbClient().projectDao().selectProjectByKey(db.getSession(), PROJECT_KEY).get();
  209. assertThat(db.favorites().hasFavorite(createdProject, user.getUuid())).isTrue();
  210. }
  211. @Test
  212. public void do_no_add_favorite_when_no_project_creator_permission_on_permission_template() {
  213. userSession
  214. .addPermission(GlobalPermission.SCAN)
  215. .addPermission(PROVISION_PROJECTS);
  216. when(permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(DbSession.class), any(), eq(PROJECT_KEY)))
  217. .thenReturn(true);
  218. when(permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(any(DbSession.class), any(ProjectDto.class))).thenReturn(false);
  219. mockSuccessfulPrepareSubmitCall();
  220. underTest.submit(PROJECT_KEY, PROJECT_NAME, emptyMap(), IOUtils.toInputStream("{binary}"));
  221. ProjectDto createdProject = db.getDbClient().projectDao().selectProjectByKey(db.getSession(), PROJECT_KEY).get();
  222. assertThat(db.favorites().hasNoFavorite(createdProject)).isTrue();
  223. }
  224. @Test
  225. public void do_no_add_favorite_when_already_100_favorite_projects_and_no_project_creator_permission_on_permission_template() {
  226. UserDto user = db.users().insertUser();
  227. rangeClosed(1, 100).forEach(i -> db.favorites().add(db.components().insertPrivateProject().getProjectDto(), user.getUuid(), user.getLogin()));
  228. userSession
  229. .logIn(user)
  230. .addPermission(GlobalPermission.SCAN)
  231. .addPermission(PROVISION_PROJECTS);
  232. mockSuccessfulPrepareSubmitCall();
  233. when(permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(DbSession.class), any(), eq(PROJECT_KEY))).thenReturn(true);
  234. when(permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(any(DbSession.class), any(ProjectDto.class))).thenReturn(true);
  235. underTest.submit(PROJECT_KEY, PROJECT_NAME, emptyMap(), IOUtils.toInputStream("{binary}", UTF_8));
  236. ProjectDto createdProject = db.getDbClient().projectDao().selectProjectByKey(db.getSession(), PROJECT_KEY).get();
  237. assertThat(db.favorites().hasNoFavorite(createdProject)).isTrue();
  238. }
  239. @Test
  240. public void submit_whenReportIsForANewProjectWithoutDevOpsMetadata_createsLocalProject() {
  241. userSession.addPermission(PROVISION_PROJECTS).addPermission(SCAN);
  242. mockSuccessfulPrepareSubmitCall();
  243. when(permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(), anyString(), anyString())).thenReturn(true);
  244. underTest.submit(PROJECT_KEY, PROJECT_NAME, emptyMap(), IOUtils.toInputStream("{binary}", UTF_8));
  245. ProjectDto projectDto = assertLocalProjectWasCreated();
  246. verify(permissionTemplateService).applyDefaultToNewComponent(any(DbSession.class), eq(projectDto), eq(userSession.getUuid()));
  247. }
  248. @Test
  249. public void submit_whenReportIsForANewProjectWithValidAlmSettingsAutoProvisioningOnAndPermOnGh_createsProjectWithBinding() {
  250. UserDto user = db.users().insertUser();
  251. userSession.logIn(user).addPermission(PROVISION_PROJECTS).addPermission(SCAN);
  252. when(gitHubSettings.isProvisioningEnabled()).thenReturn(true);
  253. mockSuccessfulPrepareSubmitCall();
  254. DevOpsProjectCreator devOpsProjectCreator = mockAlmSettingDtoAndDevOpsProjectCreator(CHARACTERISTICS, false);
  255. doReturn(true).when(devOpsProjectCreator).isScanAllowedUsingPermissionsFromDevopsPlatform();
  256. underTest.submit(PROJECT_KEY, PROJECT_NAME, CHARACTERISTICS, IOUtils.toInputStream("{binary}", UTF_8));
  257. assertProjectWasCreatedWithBinding(true);
  258. verify(permissionTemplateService, never()).applyDefaultToNewComponent(any(), any(), any());
  259. }
  260. @Test
  261. public void submit_whenReportIsForANewProjectWithValidAlmSettingsAutoProvisioningOnAndProjectVisibilitySyncAndPermOnGh_createsProjectWithBinding() {
  262. UserDto user = db.users().insertUser();
  263. userSession.logIn(user).addPermission(PROVISION_PROJECTS).addPermission(SCAN);
  264. when(gitHubSettings.isProvisioningEnabled()).thenReturn(true);
  265. when(gitHubSettings.isProjectVisibilitySynchronizationActivated()).thenReturn(true);
  266. mockSuccessfulPrepareSubmitCall();
  267. DevOpsProjectCreator devOpsProjectCreator = mockAlmSettingDtoAndDevOpsProjectCreator(CHARACTERISTICS, false);
  268. doReturn(true).when(devOpsProjectCreator).isScanAllowedUsingPermissionsFromDevopsPlatform();
  269. underTest.submit(PROJECT_KEY, PROJECT_NAME, CHARACTERISTICS, IOUtils.toInputStream("{binary}", UTF_8));
  270. assertProjectWasCreatedWithBinding(false);
  271. verify(permissionTemplateService, never()).applyDefaultToNewComponent(any(), any(), any());
  272. }
  273. @Test
  274. public void submit_whenReportIsForANewProjectWithValidAlmSettingsAutoProvisioningOnNoPermOnGhAndGlobalScanPerm_createsProjectWithBinding() {
  275. UserDto user = db.users().insertUser();
  276. userSession.logIn(user).addPermission(GlobalPermission.SCAN).addPermission(PROVISION_PROJECTS);
  277. when(gitHubSettings.isProvisioningEnabled()).thenReturn(true);
  278. mockSuccessfulPrepareSubmitCall();
  279. DevOpsProjectCreator devOpsProjectCreator = mockAlmSettingDtoAndDevOpsProjectCreator(CHARACTERISTICS, false);
  280. doReturn(true).when(devOpsProjectCreator).isScanAllowedUsingPermissionsFromDevopsPlatform();
  281. underTest.submit(PROJECT_KEY, PROJECT_NAME, CHARACTERISTICS, IOUtils.toInputStream("{binary}", UTF_8));
  282. assertProjectWasCreatedWithBinding(true);
  283. verify(permissionTemplateService, never()).applyDefaultToNewComponent(any(), any(), any());
  284. }
  285. @Test
  286. public void submit_whenReportIsForANewProjectWithoutDevOpsMetadataAndAutoProvisioningOn_shouldCreateLocalProject() {
  287. UserDto user = db.users().insertUser();
  288. userSession.logIn(user).addPermission(GlobalPermission.SCAN).addPermission(PROVISION_PROJECTS);
  289. when(managedInstanceService.isInstanceExternallyManaged()).thenReturn(true);
  290. when(permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(DbSession.class), any(), eq(PROJECT_KEY))).thenReturn(true);
  291. mockSuccessfulPrepareSubmitCall();
  292. underTest.submit(PROJECT_KEY, PROJECT_NAME, CHARACTERISTICS, IOUtils.toInputStream("{binary}", UTF_8));
  293. ProjectDto projectDto = assertLocalProjectWasCreated();
  294. verify(permissionTemplateService).applyDefaultToNewComponent(any(DbSession.class), eq(projectDto), eq(userSession.getUuid()));
  295. }
  296. private ProjectDto assertLocalProjectWasCreated() {
  297. ProjectDto projectDto = db.getDbClient().projectDao().selectProjectByKey(db.getSession(), PROJECT_KEY).orElseThrow();
  298. assertThat(projectDto.getCreationMethod()).isEqualTo(CreationMethod.SCANNER_API);
  299. assertThat(projectDto.getName()).isEqualTo(PROJECT_NAME);
  300. BranchDto branchDto = db.getDbClient().branchDao().selectByBranchKey(db.getSession(), projectDto.getUuid(), "main").orElseThrow();
  301. assertThat(branchDto.isMain()).isTrue();
  302. assertThat(db.getDbClient().projectAlmSettingDao().selectByProject(db.getSession(), projectDto.getUuid())).isEmpty();
  303. return projectDto;
  304. }
  305. @Test
  306. public void submit_whenReportIsForANewProjectWithValidAlmSettings_createsProjectWithDevOpsBinding() {
  307. userSession.addPermission(GlobalPermission.SCAN).addPermission(PROVISION_PROJECTS);
  308. mockSuccessfulPrepareSubmitCall();
  309. mockAlmSettingDtoAndDevOpsProjectCreator(CHARACTERISTICS, true);
  310. when(permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(DbSession.class), any(), eq(PROJECT_KEY))).thenReturn(true);
  311. underTest.submit(PROJECT_KEY, PROJECT_NAME, CHARACTERISTICS, IOUtils.toInputStream("{binary}", UTF_8));
  312. assertProjectWasCreatedWithBinding(false);
  313. }
  314. private void assertProjectWasCreatedWithBinding(boolean isPrivate) {
  315. ProjectDto projectDto = db.getDbClient().projectDao().selectProjectByKey(db.getSession(), PROJECT_KEY).orElseThrow();
  316. assertThat(projectDto.getCreationMethod()).isEqualTo(CreationMethod.SCANNER_API_DEVOPS_AUTO_CONFIG);
  317. assertThat(projectDto.getName()).isEqualTo(PROJECT_NAME);
  318. assertThat(projectDto.isPrivate()).isEqualTo(isPrivate);
  319. BranchDto branchDto = db.getDbClient().branchDao().selectByBranchKey(db.getSession(), projectDto.getUuid(), "defaultBranch").orElseThrow();
  320. assertThat(branchDto.isMain()).isTrue();
  321. assertThat(db.getDbClient().projectAlmSettingDao().selectByProject(db.getSession(), projectDto.getUuid())).isPresent();
  322. }
  323. private DevOpsProjectCreator mockAlmSettingDtoAndDevOpsProjectCreator(Map<String, String> characteristics, boolean isPrivate) {
  324. AlmSettingDto almSettingDto = mock(AlmSettingDto.class);
  325. when(almSettingDto.getAlm()).thenReturn(ALM.GITHUB);
  326. when(almSettingDto.getUrl()).thenReturn("https://www.toto.com");
  327. when(almSettingDto.getUuid()).thenReturn("uuid_gh_1");
  328. mockGithubRepository(isPrivate);
  329. DevOpsProjectDescriptor projectDescriptor = new DevOpsProjectDescriptor(ALM.GITHUB, "apiUrl", "orga/repo", null);
  330. GithubProjectCreationParameters githubProjectCreationParameters = new GithubProjectCreationParameters(projectDescriptor, almSettingDto, userSession, mock(), null);
  331. DevOpsProjectCreator devOpsProjectCreator = spy(new GithubProjectCreator(db.getDbClient(), githubApplicationClient, null, projectKeyGenerator,
  332. permissionUpdater, permissionService, managedProjectService, projectCreator, githubProjectCreationParameters, gitHubSettings));
  333. doReturn(Optional.of(devOpsProjectCreator)).when(devOpsProjectCreatorFactorySpy).getDevOpsProjectCreator(any(), eq(characteristics));
  334. return devOpsProjectCreator;
  335. }
  336. private void mockGithubRepository(boolean isPrivate) {
  337. GithubApplicationClient.Repository repository = mock(GithubApplicationClient.Repository.class);
  338. when(repository.getDefaultBranch()).thenReturn("defaultBranch");
  339. when(repository.getFullName()).thenReturn("orga/repoName");
  340. when(repository.getName()).thenReturn("repoName");
  341. when(repository.isPrivate()).thenReturn(isPrivate);
  342. when(githubApplicationClient.getRepository(any(), any(), any())).thenReturn(Optional.of(repository));
  343. }
  344. @Test
  345. public void user_with_scan_permission_is_allowed_to_submit_a_report_on_existing_project() {
  346. ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
  347. userSession.addPermission(SCAN);
  348. mockSuccessfulPrepareSubmitCall();
  349. underTest.submit(project.getKey(), project.name(), emptyMap(), IOUtils.toInputStream("{binary}", UTF_8));
  350. verify(queue).submit(any(CeTaskSubmit.class));
  351. }
  352. @Test
  353. public void submit_a_report_on_existing_project_with_project_scan_permission() {
  354. ProjectData projectData = db.components().insertPrivateProject();
  355. ProjectDto project = projectData.getProjectDto();
  356. userSession.addProjectPermission(SCAN.getKey(), project)
  357. .addProjectBranchMapping(project.getUuid(), projectData.getMainBranchComponent());
  358. mockSuccessfulPrepareSubmitCall();
  359. underTest.submit(project.getKey(), project.getName(), emptyMap(), IOUtils.toInputStream("{binary}", UTF_8));
  360. verify(queue).submit(any(CeTaskSubmit.class));
  361. }
  362. @Test
  363. public void fail_if_component_is_not_a_project() {
  364. ComponentDto component = db.components().insertPublicPortfolio();
  365. userSession.logIn().addPortfolioPermission(SCAN.getKey(), component);
  366. mockSuccessfulPrepareSubmitCall();
  367. String dbKey = component.getKey();
  368. String name = component.name();
  369. Map<String, String> emptyMap = emptyMap();
  370. InputStream stream = IOUtils.toInputStream("{binary}", UTF_8);
  371. assertThatThrownBy(() -> underTest.submit(dbKey, name, emptyMap, stream))
  372. .isInstanceOf(BadRequestException.class)
  373. .hasMessage(format("Component '%s' is not a project", component.getKey()));
  374. }
  375. @Test
  376. public void fail_if_project_key_already_exists_as_other_component() {
  377. ProjectData projectData = db.components().insertPrivateProject();
  378. ProjectDto project = projectData.getProjectDto();
  379. ComponentDto dir = db.components().insertComponent(newDirectory(projectData.getMainBranchComponent(), "path"));
  380. userSession.logIn().addProjectPermission(SCAN.getKey(), project);
  381. mockSuccessfulPrepareSubmitCall();
  382. String dirDbKey = dir.getKey();
  383. String name = dir.name();
  384. Map<String, String> emptyMap = emptyMap();
  385. InputStream inputStream = IOUtils.toInputStream("{binary}", UTF_8);
  386. assertThatThrownBy(() -> underTest.submit(dirDbKey, name, emptyMap, inputStream))
  387. .isInstanceOf(BadRequestException.class)
  388. .extracting(throwable -> ((BadRequestException) throwable).errors())
  389. .asList()
  390. .contains(format("The project '%s' is already defined in SonarQube but as a module of project '%s'. " +
  391. "If you really want to stop directly analysing project '%s', please first delete it from SonarQube and then relaunch the analysis of project '%s'.",
  392. dir.getKey(), project.getKey(), project.getKey(), dir.getKey()));
  393. }
  394. @Test
  395. public void fail_with_forbidden_exception_when_no_scan_permission() {
  396. Map<String, String> emptyMap = emptyMap();
  397. InputStream inputStream = IOUtils.toInputStream("{binary}", UTF_8);
  398. assertThatThrownBy(() -> underTest.submit(PROJECT_KEY, PROJECT_NAME, emptyMap, inputStream))
  399. .isInstanceOf(ForbiddenException.class);
  400. }
  401. @Test
  402. public void fail_with_forbidden_exception_on_new_project_when_only_project_scan_permission() {
  403. ProjectDto project = db.components().insertPrivateProject(PROJECT_UUID).getProjectDto();
  404. userSession.addProjectPermission(SCAN.getKey(), project);
  405. mockSuccessfulPrepareSubmitCall();
  406. Map<String, String> emptyMap = emptyMap();
  407. InputStream inputStream = IOUtils.toInputStream("{binary}", UTF_8);
  408. assertThatThrownBy(() -> underTest.submit(PROJECT_KEY, PROJECT_NAME, emptyMap, inputStream))
  409. .isInstanceOf(ForbiddenException.class);
  410. }
  411. private void verifyReportIsPersisted(String taskUuid) {
  412. assertThat(db.selectFirst("select task_uuid from ce_task_input where task_uuid='" + taskUuid + "'")).isNotNull();
  413. }
  414. private void mockSuccessfulPrepareSubmitCall() {
  415. when(queue.prepareSubmit()).thenReturn(new CeTaskSubmit.Builder(TASK_UUID));
  416. }
  417. }