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