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.

UpdateVisibilityActionIT.java 35KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2023 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.project.ws;
  21. import java.util.Arrays;
  22. import java.util.Random;
  23. import java.util.Set;
  24. import java.util.stream.Collectors;
  25. import java.util.stream.IntStream;
  26. import java.util.stream.Stream;
  27. import org.junit.Rule;
  28. import org.junit.Test;
  29. import org.sonar.api.config.Configuration;
  30. import org.sonar.api.resources.Qualifiers;
  31. import org.sonar.api.resources.ResourceTypes;
  32. import org.sonar.api.server.ws.WebService;
  33. import org.sonar.api.utils.System2;
  34. import org.sonar.api.web.UserRole;
  35. import org.sonar.core.util.SequenceUuidFactory;
  36. import org.sonar.core.util.Uuids;
  37. import org.sonar.db.DbClient;
  38. import org.sonar.db.DbSession;
  39. import org.sonar.db.DbTester;
  40. import org.sonar.db.ce.CeQueueDto;
  41. import org.sonar.db.component.BranchDto;
  42. import org.sonar.db.component.BranchType;
  43. import org.sonar.db.component.ComponentDto;
  44. import org.sonar.db.component.ComponentTesting;
  45. import org.sonar.db.component.PortfolioData;
  46. import org.sonar.db.component.ProjectData;
  47. import org.sonar.db.component.ResourceTypesRule;
  48. import org.sonar.db.permission.GlobalPermission;
  49. import org.sonar.db.permission.GroupPermissionDto;
  50. import org.sonar.db.permission.UserPermissionDto;
  51. import org.sonar.db.portfolio.PortfolioDto;
  52. import org.sonar.db.project.ProjectDto;
  53. import org.sonar.db.user.GroupDto;
  54. import org.sonar.db.user.UserDto;
  55. import org.sonar.server.common.management.ManagedInstanceChecker;
  56. import org.sonar.server.es.EsTester;
  57. import org.sonar.server.es.Indexers;
  58. import org.sonar.server.es.TestIndexers;
  59. import org.sonar.server.exceptions.BadRequestException;
  60. import org.sonar.server.exceptions.ForbiddenException;
  61. import org.sonar.server.exceptions.UnauthorizedException;
  62. import org.sonar.server.permission.PermissionService;
  63. import org.sonar.server.permission.PermissionServiceImpl;
  64. import org.sonar.server.permission.index.FooIndexDefinition;
  65. import org.sonar.server.project.Visibility;
  66. import org.sonar.server.project.VisibilityService;
  67. import org.sonar.server.tester.UserSessionRule;
  68. import org.sonar.server.ws.TestRequest;
  69. import org.sonar.server.ws.WsActionTester;
  70. import static java.lang.String.format;
  71. import static java.util.Arrays.stream;
  72. import static java.util.Optional.of;
  73. import static org.assertj.core.api.Assertions.assertThat;
  74. import static org.assertj.core.api.Assertions.assertThatThrownBy;
  75. import static org.assertj.core.api.Assertions.fail;
  76. import static org.mockito.ArgumentMatchers.any;
  77. import static org.mockito.ArgumentMatchers.eq;
  78. import static org.mockito.Mockito.doThrow;
  79. import static org.mockito.Mockito.mock;
  80. import static org.mockito.Mockito.when;
  81. import static org.sonar.api.CoreProperties.CORE_ALLOW_PERMISSION_MANAGEMENT_FOR_PROJECT_ADMINS_PROPERTY;
  82. import static org.sonar.db.component.ComponentTesting.newProjectCopy;
  83. public class UpdateVisibilityActionIT {
  84. private static final String PARAM_VISIBILITY = "visibility";
  85. private static final String PARAM_PROJECT = "project";
  86. private static final String PUBLIC = "public";
  87. private static final String PRIVATE = "private";
  88. private static final String MANAGED_PROJECT_KEY = "managed_project_key";
  89. private static final Set<String> GLOBAL_PERMISSIONS_NAME_SET = stream(GlobalPermission.values()).map(GlobalPermission::getKey)
  90. .collect(Collectors.toSet());
  91. @Rule
  92. public final DbTester dbTester = DbTester.create(System2.INSTANCE);
  93. @Rule
  94. public final EsTester es = EsTester.createCustom(new FooIndexDefinition());
  95. @Rule
  96. public final UserSessionRule userSessionRule = UserSessionRule.standalone().logIn();
  97. private final ResourceTypes resourceTypes = new ResourceTypesRule().setRootQualifiers(Qualifiers.PROJECT);
  98. private final PermissionService permissionService = new PermissionServiceImpl(resourceTypes);
  99. private final Set<String> PROJECT_PERMISSIONS_BUT_USER_AND_CODEVIEWER = permissionService.getAllProjectPermissions().stream()
  100. .filter(perm -> !perm.equals(UserRole.USER) && !perm.equals(UserRole.CODEVIEWER))
  101. .collect(Collectors.toSet());
  102. private final DbClient dbClient = dbTester.getDbClient();
  103. private final DbSession dbSession = dbTester.getSession();
  104. private final TestIndexers projectIndexers = new TestIndexers();
  105. private final Configuration configuration = mock(Configuration.class);
  106. private final ManagedInstanceChecker managedInstanceChecker = mock(ManagedInstanceChecker.class);
  107. private final VisibilityService visibilityService = new VisibilityService(dbClient, projectIndexers, new SequenceUuidFactory());
  108. private final UpdateVisibilityAction underTest = new UpdateVisibilityAction(dbClient, userSessionRule, configuration, visibilityService, managedInstanceChecker);
  109. private final WsActionTester ws = new WsActionTester(underTest);
  110. private final Random random = new Random();
  111. private final String randomVisibility = random.nextBoolean() ? PUBLIC : PRIVATE;
  112. private final TestRequest request = ws.newRequest();
  113. @Test
  114. public void definition() {
  115. WebService.Action definition = ws.getDef();
  116. assertThat(definition.key()).isEqualTo("update_visibility");
  117. assertThat(definition.isPost()).isTrue();
  118. assertThat(definition.since()).isEqualTo("6.4");
  119. assertThat(definition.params()).extracting(WebService.Param::key).containsExactlyInAnyOrder("project", "visibility");
  120. }
  121. @Test
  122. public void execute_fails_if_user_is_not_logged_in() {
  123. userSessionRule.anonymous();
  124. assertThatThrownBy(request::execute)
  125. .isInstanceOf(UnauthorizedException.class)
  126. .hasMessage("Authentication is required");
  127. }
  128. @Test
  129. public void execute_fails_with_IAE_when_project_parameter_is_not_provided() {
  130. assertThatThrownBy(request::execute)
  131. .isInstanceOf(IllegalArgumentException.class)
  132. .hasMessage("The 'project' parameter is missing");
  133. }
  134. @Test
  135. public void execute_fails_with_IAE_when_project_parameter_is_not_empty() {
  136. assertThatThrownBy(request::execute)
  137. .isInstanceOf(IllegalArgumentException.class)
  138. .hasMessage("The 'project' parameter is missing");
  139. }
  140. @Test
  141. public void execute_fails_with_IAE_when_parameter_visibility_is_not_provided() {
  142. request.setParam(PARAM_PROJECT, "foo");
  143. assertThatThrownBy(request::execute)
  144. .isInstanceOf(IllegalArgumentException.class)
  145. .hasMessage("The 'visibility' parameter is missing");
  146. }
  147. @Test
  148. public void execute_fails_with_IAE_when_parameter_visibility_is_empty() {
  149. request.setParam(PARAM_PROJECT, "foo")
  150. .setParam(PARAM_VISIBILITY, "");
  151. assertThatThrownBy(request::execute)
  152. .isInstanceOf(IllegalArgumentException.class)
  153. .hasMessage("Value of parameter '" + PARAM_VISIBILITY + "' () must be one of: [private, public]");
  154. }
  155. @Test
  156. public void execute_fails_with_IAE_when_value_of_parameter_visibility_is_not_lowercase() {
  157. request.setParam(PARAM_PROJECT, "foo");
  158. Stream.of("PUBLIC", "pUBliC", "PRIVATE", "PrIVAtE")
  159. .forEach(visibility -> {
  160. try {
  161. request.setParam(PARAM_VISIBILITY, visibility).execute();
  162. fail("An exception should have been raised");
  163. } catch (IllegalArgumentException e) {
  164. assertThat(e.getMessage()).isEqualTo(format("Value of parameter '%s' (%s) must be one of: [private, public]", PARAM_VISIBILITY, visibility));
  165. }
  166. });
  167. }
  168. @Test
  169. public void execute_fails_with_NotFoundException_when_specified_component_does_not_exist() {
  170. request.setParam(PARAM_PROJECT, "foo")
  171. .setParam(PARAM_VISIBILITY, randomVisibility);
  172. assertThatThrownBy(request::execute)
  173. .isInstanceOf(BadRequestException.class)
  174. .hasMessage("Component must be a project, a portfolio or an application");
  175. }
  176. @Test
  177. public void execute_fails_with_BadRequestException_if_specified_component_is_neither_a_project_a_portfolio_nor_an_application() {
  178. ProjectData project = randomPublicOrPrivateProject();
  179. ComponentDto dir = ComponentTesting.newDirectory(project.getMainBranchComponent(), "path");
  180. ComponentDto file = ComponentTesting.newFileDto(project.getMainBranchComponent());
  181. dbTester.components().insertComponents(dir, file);
  182. ProjectDto application = dbTester.components().insertPublicApplication().getProjectDto();
  183. PortfolioData portfolio = dbTester.components().insertPrivatePortfolioData();
  184. ComponentDto subView = ComponentTesting.newSubPortfolio(portfolio.getRootComponent());
  185. ComponentDto projectCopy = newProjectCopy("foo", project.getMainBranchComponent(), subView);
  186. dbTester.components().insertComponents(subView, projectCopy);
  187. userSessionRule.addProjectPermission(UserRole.ADMIN, project.getProjectDto(), application);
  188. userSessionRule.addPortfolioPermission(UserRole.ADMIN, portfolio.getPortfolioDto());
  189. Stream.of(project.getProjectDto(), portfolio.getPortfolioDto(), application).forEach(c -> request
  190. .setParam(PARAM_PROJECT, c.getKey())
  191. .setParam(PARAM_VISIBILITY, randomVisibility)
  192. .execute());
  193. Stream.of(dir, file, subView, projectCopy)
  194. .forEach(nonRootComponent -> {
  195. request.setParam(PARAM_PROJECT, nonRootComponent.getKey())
  196. .setParam(PARAM_VISIBILITY, randomVisibility);
  197. try {
  198. request.execute();
  199. fail("a BadRequestException should have been raised");
  200. } catch (BadRequestException e) {
  201. assertThat(e.getMessage()).isEqualTo("Component must be a project, a portfolio or an application");
  202. }
  203. });
  204. }
  205. @Test
  206. public void execute_throws_ForbiddenException_if_user_has_no_permission_on_specified_component() {
  207. ComponentDto project = dbTester.components().insertPrivateProject().getMainBranchComponent();
  208. request.setParam(PARAM_PROJECT, project.getKey())
  209. .setParam(PARAM_VISIBILITY, randomVisibility);
  210. assertThatThrownBy(request::execute)
  211. .isInstanceOf(ForbiddenException.class)
  212. .hasMessage("Insufficient privileges");
  213. }
  214. @Test
  215. public void execute_throws_ForbiddenException_if_user_has_all_permissions_but_ADMIN_on_specified_component() {
  216. ProjectData project = dbTester.components().insertPublicProject();
  217. request.setParam(PARAM_PROJECT, project.projectKey())
  218. .setParam(PARAM_VISIBILITY, randomVisibility);
  219. userSessionRule.addProjectPermission(UserRole.ISSUE_ADMIN, project.getProjectDto());
  220. Arrays.stream(GlobalPermission.values())
  221. .forEach(userSessionRule::addPermission);
  222. assertThatThrownBy(request::execute)
  223. .isInstanceOf(ForbiddenException.class)
  224. .hasMessage("Insufficient privileges");
  225. }
  226. @Test
  227. public void execute_throws_ForbiddenException_if_user_has_ADMIN_permission_but_sonar_allowPermissionManagementForProjectAdmins_is_set_to_false() {
  228. when(configuration.getBoolean(CORE_ALLOW_PERMISSION_MANAGEMENT_FOR_PROJECT_ADMINS_PROPERTY)).thenReturn(of(false));
  229. ProjectData project = dbTester.components().insertPublicProject();
  230. request.setParam(PARAM_PROJECT, project.projectKey())
  231. .setParam(PARAM_VISIBILITY, randomVisibility);
  232. userSessionRule.addProjectPermission(UserRole.ADMIN, project.getProjectDto());
  233. assertThatThrownBy(request::execute)
  234. .isInstanceOf(ForbiddenException.class)
  235. .hasMessage("Insufficient privileges");
  236. }
  237. @Test
  238. public void execute_throws_ForbiddenException_if_user_has_global_ADMIN_permission_even_if_sonar_allowPermissionManagementForProjectAdmins_is_set_to_false() {
  239. when(configuration.getBoolean(CORE_ALLOW_PERMISSION_MANAGEMENT_FOR_PROJECT_ADMINS_PROPERTY)).thenReturn(of(false));
  240. ProjectDto project = dbTester.components().insertPublicProject().getProjectDto();
  241. userSessionRule.setSystemAdministrator().addProjectPermission(UserRole.ADMIN, project);
  242. request.setParam(PARAM_PROJECT, project.getKey())
  243. .setParam(PARAM_VISIBILITY, "private");
  244. request.execute();
  245. assertThat(dbClient.projectDao().selectProjectByKey(dbSession, project.getKey()).get().isPrivate()).isTrue();
  246. }
  247. @Test
  248. public void execute_throws_IllegalStateException_if_specified_component_has_pending_tasks() {
  249. ProjectData project = randomPublicOrPrivateProject();
  250. IntStream.range(0, 1 + Math.abs(random.nextInt(5)))
  251. .forEach(i -> insertPendingTask(project.getMainBranchDto()));
  252. request.setParam(PARAM_PROJECT, project.projectKey())
  253. .setParam(PARAM_VISIBILITY, randomVisibility);
  254. userSessionRule.addProjectPermission(UserRole.ADMIN, project.getProjectDto());
  255. assertThatThrownBy(request::execute)
  256. .isInstanceOf(IllegalStateException.class)
  257. .hasMessage("Component visibility can't be changed as long as it has background task(s) pending or in progress");
  258. }
  259. @Test
  260. public void execute_throws_IllegalStateException_if_main_component_of_specified_component_has_in_progress_tasks() {
  261. ProjectData project = randomPublicOrPrivateProject();
  262. IntStream.range(0, 1 + Math.abs(random.nextInt(5)))
  263. .forEach(i -> insertInProgressTask(project.getMainBranchDto()));
  264. request.setParam(PARAM_PROJECT, project.projectKey())
  265. .setParam(PARAM_VISIBILITY, randomVisibility);
  266. userSessionRule.addProjectPermission(UserRole.ADMIN, project.getProjectDto());
  267. assertThatThrownBy(request::execute)
  268. .isInstanceOf(IllegalStateException.class)
  269. .hasMessage("Component visibility can't be changed as long as it has background task(s) pending or in progress");
  270. }
  271. @Test
  272. public void execute_throws_if_project_is_managed() {
  273. ProjectDto project = dbTester.components().insertPublicProject(p -> p.setKey(MANAGED_PROJECT_KEY)).getProjectDto();
  274. request.setParam(PARAM_PROJECT, project.getKey())
  275. .setParam(PARAM_VISIBILITY, Visibility.PUBLIC.getLabel());
  276. userSessionRule.addProjectPermission(UserRole.ADMIN, project);
  277. doThrow(new IllegalStateException("Managed project")).when(managedInstanceChecker).throwIfProjectIsManaged(any(), eq(project.getUuid()));
  278. assertThatThrownBy(request::execute)
  279. .isInstanceOf(IllegalStateException.class)
  280. .hasMessage("Managed project");
  281. }
  282. @Test
  283. public void execute_changes_private_flag_of_specified_project_and_all_children_to_specified_new_visibility() {
  284. ProjectData project = randomPublicOrPrivateProject();
  285. boolean initiallyPrivate = project.getProjectDto().isPrivate();
  286. BranchDto branchDto = ComponentTesting.newBranchDto(project.projectUuid(), BranchType.BRANCH);
  287. dbClient.branchDao().insert(dbSession, branchDto);
  288. ComponentDto branch = ComponentTesting.newBranchComponent(project.getProjectDto(), branchDto);
  289. ComponentDto dir = ComponentTesting.newDirectory(project.getMainBranchComponent(), "path");
  290. ComponentDto file = ComponentTesting.newFileDto(project.getMainBranchComponent());
  291. dbTester.components().insertComponents(branch, dir, file);
  292. userSessionRule.addProjectPermission(UserRole.ADMIN, project.getProjectDto());
  293. request.setParam(PARAM_PROJECT, project.projectKey())
  294. .setParam(PARAM_VISIBILITY, initiallyPrivate ? PUBLIC : PRIVATE)
  295. .execute();
  296. assertThat(dbClient.projectDao().selectProjectByKey(dbSession, project.projectKey()).get().isPrivate()).isEqualTo(!initiallyPrivate);
  297. assertThat(isPrivateInDb(branch)).isEqualTo(!initiallyPrivate);
  298. assertThat(isPrivateInDb(dir)).isEqualTo(!initiallyPrivate);
  299. assertThat(isPrivateInDb(file)).isEqualTo(!initiallyPrivate);
  300. }
  301. @Test
  302. public void execute_has_no_effect_if_specified_project_already_has_specified_visibility() {
  303. ProjectData project = randomPublicOrPrivateProject();
  304. boolean initiallyPrivate = project.getProjectDto().isPrivate();
  305. BranchDto branchDto = ComponentTesting.newBranchDto(project.getMainBranchComponent());
  306. dbClient.branchDao().insert(dbSession, branchDto);
  307. ComponentDto branch = ComponentTesting.newBranchComponent(project.getProjectDto(), branchDto)
  308. .setPrivate(initiallyPrivate);
  309. ComponentDto dir = ComponentTesting.newDirectory(project.getMainBranchComponent(), "path")
  310. // child is inconsistent with root (should not occur) and won't be fixed
  311. .setPrivate(!initiallyPrivate);
  312. ComponentDto file = ComponentTesting.newFileDto(project.getMainBranchComponent())
  313. .setPrivate(initiallyPrivate);
  314. dbTester.components().insertComponents(branch, dir, file);
  315. userSessionRule.addProjectPermission(UserRole.ADMIN, project.getProjectDto());
  316. request.setParam(PARAM_PROJECT, project.projectKey())
  317. .setParam(PARAM_VISIBILITY, initiallyPrivate ? PRIVATE : PUBLIC)
  318. .execute();
  319. assertThat(isPrivateInDb(project.getMainBranchComponent())).isEqualTo(initiallyPrivate);
  320. assertThat(isPrivateInDb(branch)).isEqualTo(initiallyPrivate);
  321. assertThat(isPrivateInDb(dir)).isEqualTo(!initiallyPrivate);
  322. assertThat(isPrivateInDb(file)).isEqualTo(initiallyPrivate);
  323. }
  324. @Test
  325. public void execute_deletes_all_permissions_to_Anyone_on_specified_project_when_new_visibility_is_private() {
  326. ProjectDto project = dbTester.components().insertPublicProject().getProjectDto();
  327. UserDto user = dbTester.users().insertUser();
  328. GroupDto group = dbTester.users().insertGroup();
  329. unsafeGiveAllPermissionsToRootComponent(project, user, group);
  330. userSessionRule.addProjectPermission(UserRole.ADMIN, project);
  331. request.setParam(PARAM_PROJECT, project.getKey())
  332. .setParam(PARAM_VISIBILITY, PRIVATE)
  333. .execute();
  334. verifyHasAllPermissionsButProjectPermissionsToGroupAnyOne(project.getUuid(), user, group);
  335. }
  336. @Test
  337. public void execute_does_not_delete_all_permissions_to_AnyOne_on_specified_project_if_already_private() {
  338. ProjectDto project = dbTester.components().insertPrivateProject().getProjectDto();
  339. UserDto user = dbTester.users().insertUser();
  340. GroupDto group = dbTester.users().insertGroup();
  341. unsafeGiveAllPermissionsToRootComponent(project, user, group);
  342. userSessionRule.addProjectPermission(UserRole.ADMIN, project);
  343. request.setParam(PARAM_PROJECT, project.getKey())
  344. .setParam(PARAM_VISIBILITY, PRIVATE)
  345. .execute();
  346. verifyStillHasAllPermissions(project.getUuid(), user, group);
  347. }
  348. @Test
  349. public void execute_deletes_all_permissions_USER_and_BROWSE_of_specified_project_when_new_visibility_is_public() {
  350. ProjectDto project = dbTester.components().insertPrivateProject().getProjectDto();
  351. UserDto user = dbTester.users().insertUser();
  352. GroupDto group = dbTester.users().insertGroup();
  353. unsafeGiveAllPermissionsToRootComponent(project, user, group);
  354. userSessionRule.addProjectPermission(UserRole.ADMIN, project);
  355. request.setParam(PARAM_PROJECT, project.getKey())
  356. .setParam(PARAM_VISIBILITY, PUBLIC)
  357. .execute();
  358. verifyHasAllPermissionsButProjectPermissionsUserAndBrowse(project.getUuid(), user, group);
  359. }
  360. @Test
  361. public void execute_does_not_delete_permissions_USER_and_BROWSE_of_specified_project_when_new_component_is_already_public() {
  362. ProjectDto project = dbTester.components().insertPublicProject().getProjectDto();
  363. UserDto user = dbTester.users().insertUser();
  364. GroupDto group = dbTester.users().insertGroup();
  365. unsafeGiveAllPermissionsToRootComponent(project, user, group);
  366. userSessionRule.addProjectPermission(UserRole.ADMIN, project);
  367. request.setParam(PARAM_PROJECT, project.getKey())
  368. .setParam(PARAM_VISIBILITY, PUBLIC)
  369. .execute();
  370. verifyStillHasAllPermissions(project.getUuid(), user, group);
  371. }
  372. @Test
  373. public void execute_updates_permission_of_specified_project_in_indexes_when_changing_visibility() {
  374. ProjectData project = randomPublicOrPrivateProject();
  375. boolean initiallyPrivate = project.getProjectDto().isPrivate();
  376. userSessionRule.addProjectPermission(UserRole.ADMIN, project.getProjectDto());
  377. request.setParam(PARAM_PROJECT, project.projectKey())
  378. .setParam(PARAM_VISIBILITY, initiallyPrivate ? PUBLIC : PRIVATE)
  379. .execute();
  380. assertThat(projectIndexers.hasBeenCalledForEntity(project.projectUuid(), Indexers.EntityEvent.PERMISSION_CHANGE)).isTrue();
  381. }
  382. @Test
  383. public void execute_does_not_update_permission_of_specified_project_in_indexes_if_already_has_specified_visibility() {
  384. ProjectData project = randomPublicOrPrivateProject();
  385. boolean initiallyPrivate = project.getProjectDto().isPrivate();
  386. userSessionRule.addProjectPermission(UserRole.ADMIN, project.getProjectDto());
  387. request.setParam(PARAM_PROJECT, project.projectKey())
  388. .setParam(PARAM_VISIBILITY, initiallyPrivate ? PRIVATE : PUBLIC)
  389. .execute();
  390. assertThat(projectIndexers.hasBeenCalledForEntity(project.projectUuid())).isFalse();
  391. }
  392. @Test
  393. public void execute_grants_USER_and_CODEVIEWER_permissions_to_any_user_with_at_least_one_permission_when_making_project_private() {
  394. ProjectDto project = dbTester.components().insertPublicProject().getProjectDto();
  395. UserDto user1 = dbTester.users().insertUser();
  396. UserDto user2 = dbTester.users().insertUser();
  397. UserDto user3 = dbTester.users().insertUser();
  398. dbTester.users().insertProjectPermissionOnUser(user1, "p1", project);
  399. dbTester.users().insertProjectPermissionOnUser(user1, "p2", project);
  400. dbTester.users().insertProjectPermissionOnUser(user2, "p2", project);
  401. userSessionRule.addProjectPermission(UserRole.ADMIN, project);
  402. request.setParam(PARAM_PROJECT, project.getKey())
  403. .setParam(PARAM_VISIBILITY, PRIVATE)
  404. .execute();
  405. assertThat(dbClient.userPermissionDao().selectEntityPermissionsOfUser(dbSession, user1.getUuid(), project.getUuid()))
  406. .containsOnly(UserRole.USER, UserRole.CODEVIEWER, "p1", "p2");
  407. assertThat(dbClient.userPermissionDao().selectEntityPermissionsOfUser(dbSession, user2.getUuid(), project.getUuid()))
  408. .containsOnly(UserRole.USER, UserRole.CODEVIEWER, "p2");
  409. assertThat(dbClient.userPermissionDao().selectEntityPermissionsOfUser(dbSession, user3.getUuid(), project.getUuid()))
  410. .isEmpty();
  411. }
  412. @Test
  413. public void execute_grants_USER_and_CODEVIEWER_permissions_to_any_group_with_at_least_one_permission_when_making_project_private() {
  414. ProjectDto project = dbTester.components().insertPublicProject().getProjectDto();
  415. GroupDto group1 = dbTester.users().insertGroup();
  416. GroupDto group2 = dbTester.users().insertGroup();
  417. GroupDto group3 = dbTester.users().insertGroup();
  418. dbTester.users().insertEntityPermissionOnGroup(group1, "p1", project);
  419. dbTester.users().insertEntityPermissionOnGroup(group1, "p2", project);
  420. dbTester.users().insertEntityPermissionOnGroup(group2, "p2", project);
  421. userSessionRule.addProjectPermission(UserRole.ADMIN, project);
  422. request.setParam(PARAM_PROJECT, project.getKey())
  423. .setParam(PARAM_VISIBILITY, PRIVATE)
  424. .execute();
  425. assertThat(dbClient.groupPermissionDao().selectEntityPermissionsOfGroup(dbSession, group1.getUuid(), project.getUuid()))
  426. .containsOnly(UserRole.USER, UserRole.CODEVIEWER, "p1", "p2");
  427. assertThat(dbClient.groupPermissionDao().selectEntityPermissionsOfGroup(dbSession, group2.getUuid(), project.getUuid()))
  428. .containsOnly(UserRole.USER, UserRole.CODEVIEWER, "p2");
  429. assertThat(dbClient.groupPermissionDao().selectEntityPermissionsOfGroup(dbSession, group3.getUuid(), project.getUuid()))
  430. .isEmpty();
  431. }
  432. @Test
  433. public void update_a_portfolio_to_private() {
  434. PortfolioDto portfolio = dbTester.components().insertPublicPortfolioDto();
  435. GroupDto group = dbTester.users().insertGroup();
  436. dbTester.users().insertEntityPermissionOnGroup(group, UserRole.ISSUE_ADMIN, portfolio);
  437. UserDto user = dbTester.users().insertUser();
  438. dbTester.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, portfolio);
  439. userSessionRule.addPortfolioPermission(UserRole.ADMIN, portfolio);
  440. request.setParam(PARAM_PROJECT, portfolio.getKey())
  441. .setParam(PARAM_VISIBILITY, PRIVATE)
  442. .execute();
  443. assertThat(dbClient.portfolioDao().selectByUuid(dbSession, portfolio.getUuid()).get().isPrivate()).isTrue();
  444. assertThat(dbClient.groupPermissionDao().selectEntityPermissionsOfGroup(dbSession, group.getUuid(), portfolio.getUuid()))
  445. .containsOnly(UserRole.USER, UserRole.CODEVIEWER, UserRole.ISSUE_ADMIN);
  446. assertThat(dbClient.userPermissionDao().selectEntityPermissionsOfUser(dbSession, user.getUuid(), portfolio.getUuid()))
  447. .containsOnly(UserRole.USER, UserRole.CODEVIEWER, UserRole.ADMIN);
  448. }
  449. @Test
  450. public void update_a_portfolio_to_public() {
  451. PortfolioDto portfolio = dbTester.components().insertPrivatePortfolioDto();
  452. userSessionRule.addPortfolioPermission(UserRole.ADMIN, portfolio);
  453. GroupDto group = dbTester.users().insertGroup();
  454. dbTester.users().insertEntityPermissionOnGroup(group, UserRole.ISSUE_ADMIN, portfolio);
  455. dbTester.users().insertEntityPermissionOnGroup(group, UserRole.USER, portfolio);
  456. dbTester.users().insertEntityPermissionOnGroup(group, UserRole.CODEVIEWER, portfolio);
  457. UserDto user = dbTester.users().insertUser();
  458. dbTester.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, portfolio);
  459. dbTester.users().insertProjectPermissionOnUser(user, UserRole.USER, portfolio);
  460. dbTester.users().insertProjectPermissionOnUser(user, UserRole.CODEVIEWER, portfolio);
  461. request.setParam(PARAM_PROJECT, portfolio.getKey())
  462. .setParam(PARAM_VISIBILITY, PUBLIC)
  463. .execute();
  464. assertThat(dbClient.componentDao().selectByUuid(dbSession, portfolio.getUuid()).get().isPrivate()).isFalse();
  465. assertThat(dbClient.groupPermissionDao().selectEntityPermissionsOfGroup(dbSession, group.getUuid(), portfolio.getUuid()))
  466. .containsOnly(UserRole.ISSUE_ADMIN);
  467. assertThat(dbClient.userPermissionDao().selectEntityPermissionsOfUser(dbSession, user.getUuid(), portfolio.getUuid()))
  468. .containsOnly(UserRole.ADMIN);
  469. }
  470. @Test
  471. public void update_an_application_to_private() {
  472. ProjectDto application = dbTester.components().insertPublicApplication().getProjectDto();
  473. GroupDto group = dbTester.users().insertGroup();
  474. dbTester.users().insertEntityPermissionOnGroup(group, UserRole.ISSUE_ADMIN, application);
  475. UserDto user = dbTester.users().insertUser();
  476. dbTester.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, application);
  477. userSessionRule.addProjectPermission(UserRole.ADMIN, application);
  478. request.setParam(PARAM_PROJECT, application.getKey())
  479. .setParam(PARAM_VISIBILITY, PRIVATE)
  480. .execute();
  481. assertThat(dbClient.projectDao().selectByUuid(dbSession, application.getUuid()).get().isPrivate()).isTrue();
  482. assertThat(dbClient.groupPermissionDao().selectEntityPermissionsOfGroup(dbSession, group.getUuid(), application.getUuid()))
  483. .containsOnly(UserRole.USER, UserRole.CODEVIEWER, UserRole.ISSUE_ADMIN);
  484. assertThat(dbClient.userPermissionDao().selectEntityPermissionsOfUser(dbSession, user.getUuid(), application.getUuid()))
  485. .containsOnly(UserRole.USER, UserRole.CODEVIEWER, UserRole.ADMIN);
  486. }
  487. @Test
  488. public void update_an_application_to_public() {
  489. ProjectDto application = dbTester.components().insertPrivateApplication().getProjectDto();
  490. userSessionRule.addProjectPermission(UserRole.ADMIN, application);
  491. GroupDto group = dbTester.users().insertGroup();
  492. dbTester.users().insertEntityPermissionOnGroup(group, UserRole.ISSUE_ADMIN, application);
  493. dbTester.users().insertEntityPermissionOnGroup(group, UserRole.USER, application);
  494. dbTester.users().insertEntityPermissionOnGroup(group, UserRole.CODEVIEWER, application);
  495. UserDto user = dbTester.users().insertUser();
  496. dbTester.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, application);
  497. dbTester.users().insertProjectPermissionOnUser(user, UserRole.USER, application);
  498. dbTester.users().insertProjectPermissionOnUser(user, UserRole.CODEVIEWER, application);
  499. request.setParam(PARAM_PROJECT, application.getKey())
  500. .setParam(PARAM_VISIBILITY, PUBLIC)
  501. .execute();
  502. assertThat(dbClient.projectDao().selectApplicationByKey(dbSession, application.getKey()).get().isPrivate()).isFalse();
  503. assertThat(dbClient.groupPermissionDao().selectEntityPermissionsOfGroup(dbSession, group.getUuid(), application.getUuid()))
  504. .containsOnly(UserRole.ISSUE_ADMIN);
  505. assertThat(dbClient.userPermissionDao().selectEntityPermissionsOfUser(dbSession, user.getUuid(), application.getUuid()))
  506. .containsOnly(UserRole.ADMIN);
  507. }
  508. private void unsafeGiveAllPermissionsToRootComponent(ProjectDto projectDto, UserDto user, GroupDto group) {
  509. Arrays.stream(GlobalPermission.values())
  510. .forEach(globalPermission -> {
  511. dbTester.users().insertPermissionOnAnyone(globalPermission);
  512. dbTester.users().insertPermissionOnGroup(group, globalPermission);
  513. dbTester.users().insertGlobalPermissionOnUser(user, globalPermission);
  514. });
  515. permissionService.getAllProjectPermissions()
  516. .forEach(permission -> {
  517. unsafeInsertProjectPermissionOnAnyone(projectDto, permission);
  518. unsafeInsertProjectPermissionOnGroup(projectDto, group, permission);
  519. unsafeInsertProjectPermissionOnUser(projectDto, user, permission);
  520. });
  521. }
  522. private void unsafeInsertProjectPermissionOnAnyone(ProjectDto projectDto, String permission) {
  523. GroupPermissionDto dto = new GroupPermissionDto()
  524. .setUuid(Uuids.createFast())
  525. .setGroupUuid(null)
  526. .setRole(permission)
  527. .setEntityUuid(projectDto.getUuid())
  528. .setEntityName(projectDto.getName());
  529. dbTester.getDbClient().groupPermissionDao().insert(dbTester.getSession(), dto, projectDto, null);
  530. dbTester.commit();
  531. }
  532. private void unsafeInsertProjectPermissionOnGroup(ProjectDto projectDto, GroupDto group, String permission) {
  533. GroupPermissionDto dto = new GroupPermissionDto()
  534. .setUuid(Uuids.createFast())
  535. .setGroupUuid(group.getUuid())
  536. .setGroupName(group.getName())
  537. .setRole(permission)
  538. .setEntityUuid(projectDto.getUuid())
  539. .setEntityName(projectDto.getName());
  540. dbTester.getDbClient().groupPermissionDao().insert(dbTester.getSession(), dto, projectDto, null);
  541. dbTester.commit();
  542. }
  543. private void unsafeInsertProjectPermissionOnUser(ProjectDto component, UserDto user, String permission) {
  544. UserPermissionDto dto = new UserPermissionDto(Uuids.create(), permission, user.getUuid(), component.getUuid());
  545. dbTester.getDbClient().userPermissionDao().insert(dbTester.getSession(), dto, component, user, null);
  546. dbTester.commit();
  547. }
  548. private void verifyHasAllPermissionsButProjectPermissionsToGroupAnyOne(String projectUuid, UserDto user, GroupDto group) {
  549. assertThat(dbClient.groupPermissionDao().selectGlobalPermissionsOfGroup(dbSession, null))
  550. .containsAll(GLOBAL_PERMISSIONS_NAME_SET);
  551. assertThat(dbClient.groupPermissionDao().selectGlobalPermissionsOfGroup(dbSession, group.getUuid()))
  552. .containsAll(GLOBAL_PERMISSIONS_NAME_SET);
  553. assertThat(dbClient.userPermissionDao().selectGlobalPermissionsOfUser(dbSession, user.getUuid()))
  554. .containsAll(GLOBAL_PERMISSIONS_NAME_SET);
  555. assertThat(dbClient.groupPermissionDao().selectEntityPermissionsOfGroup(dbSession, null, projectUuid))
  556. .isEmpty();
  557. assertThat(dbClient.groupPermissionDao().selectEntityPermissionsOfGroup(dbSession, group.getUuid(), projectUuid))
  558. .containsAll(permissionService.getAllProjectPermissions());
  559. assertThat(dbClient.userPermissionDao().selectEntityPermissionsOfUser(dbSession, user.getUuid(), projectUuid))
  560. .containsAll(permissionService.getAllProjectPermissions());
  561. }
  562. private void verifyHasAllPermissionsButProjectPermissionsUserAndBrowse(String projectUuid, UserDto user, GroupDto group) {
  563. assertThat(dbClient.groupPermissionDao().selectGlobalPermissionsOfGroup(dbSession, null))
  564. .containsAll(GLOBAL_PERMISSIONS_NAME_SET);
  565. assertThat(dbClient.groupPermissionDao().selectGlobalPermissionsOfGroup(dbSession, group.getUuid()))
  566. .containsAll(GLOBAL_PERMISSIONS_NAME_SET);
  567. assertThat(dbClient.userPermissionDao().selectGlobalPermissionsOfUser(dbSession, user.getUuid()))
  568. .containsAll(GLOBAL_PERMISSIONS_NAME_SET);
  569. assertThat(dbClient.groupPermissionDao().selectEntityPermissionsOfGroup(dbSession, null, projectUuid))
  570. .doesNotContain(UserRole.USER)
  571. .doesNotContain(UserRole.CODEVIEWER)
  572. .containsAll(PROJECT_PERMISSIONS_BUT_USER_AND_CODEVIEWER);
  573. assertThat(dbClient.groupPermissionDao().selectEntityPermissionsOfGroup(dbSession, group.getUuid(), projectUuid))
  574. .doesNotContain(UserRole.USER)
  575. .doesNotContain(UserRole.CODEVIEWER)
  576. .containsAll(PROJECT_PERMISSIONS_BUT_USER_AND_CODEVIEWER);
  577. assertThat(dbClient.userPermissionDao().selectEntityPermissionsOfUser(dbSession, user.getUuid(), projectUuid))
  578. .doesNotContain(UserRole.USER)
  579. .doesNotContain(UserRole.CODEVIEWER)
  580. .containsAll(PROJECT_PERMISSIONS_BUT_USER_AND_CODEVIEWER);
  581. }
  582. private void verifyStillHasAllPermissions(String projectUuid, UserDto user, GroupDto group) {
  583. assertThat(dbClient.groupPermissionDao().selectGlobalPermissionsOfGroup(dbSession, null))
  584. .containsAll(GLOBAL_PERMISSIONS_NAME_SET);
  585. assertThat(dbClient.groupPermissionDao().selectGlobalPermissionsOfGroup(dbSession, group.getUuid()))
  586. .containsAll(GLOBAL_PERMISSIONS_NAME_SET);
  587. assertThat(dbClient.userPermissionDao().selectGlobalPermissionsOfUser(dbSession, user.getUuid()))
  588. .containsAll(GLOBAL_PERMISSIONS_NAME_SET);
  589. assertThat(dbClient.groupPermissionDao().selectEntityPermissionsOfGroup(dbSession, null, projectUuid))
  590. .containsAll(permissionService.getAllProjectPermissions());
  591. assertThat(dbClient.groupPermissionDao().selectEntityPermissionsOfGroup(dbSession, group.getUuid(), projectUuid))
  592. .containsAll(permissionService.getAllProjectPermissions());
  593. assertThat(dbClient.userPermissionDao().selectEntityPermissionsOfUser(dbSession, user.getUuid(), projectUuid))
  594. .containsAll(permissionService.getAllProjectPermissions());
  595. }
  596. private void insertPendingTask(BranchDto branch) {
  597. insertCeQueueDto(branch, CeQueueDto.Status.PENDING);
  598. }
  599. private void insertInProgressTask(BranchDto branch) {
  600. insertCeQueueDto(branch, CeQueueDto.Status.IN_PROGRESS);
  601. }
  602. private int counter = 0;
  603. private void insertCeQueueDto(BranchDto branch, CeQueueDto.Status status) {
  604. dbClient.ceQueueDao().insert(dbTester.getSession(), new CeQueueDto()
  605. .setUuid("pending" + counter++)
  606. .setComponentUuid(branch.getUuid())
  607. .setEntityUuid(branch.getProjectUuid())
  608. .setTaskType("foo")
  609. .setStatus(status));
  610. dbTester.commit();
  611. }
  612. private boolean isPrivateInDb(ComponentDto component) {
  613. return dbClient.componentDao().selectByUuid(dbTester.getSession(), component.uuid()).get().isPrivate();
  614. }
  615. private ProjectData randomPublicOrPrivateProject() {
  616. return random.nextBoolean() ? dbTester.components().insertPublicProject() : dbTester.components().insertPrivateProject();
  617. }
  618. }