]> source.dussan.org Git - sonarqube.git/blob
9c6d73422c6770721c56a838288bb9d5275d40f8
[sonarqube.git] /
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
22 import java.util.Arrays;
23 import java.util.Random;
24 import java.util.Set;
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.core.util.stream.MoreCollectors;
38 import org.sonar.db.DbClient;
39 import org.sonar.db.DbSession;
40 import org.sonar.db.DbTester;
41 import org.sonar.db.ce.CeQueueDto;
42 import org.sonar.db.component.BranchDto;
43 import org.sonar.db.component.ComponentDto;
44 import org.sonar.db.component.ComponentTesting;
45 import org.sonar.db.component.ResourceTypesRule;
46 import org.sonar.db.permission.GlobalPermission;
47 import org.sonar.db.permission.GroupPermissionDto;
48 import org.sonar.db.permission.UserPermissionDto;
49 import org.sonar.db.user.GroupDto;
50 import org.sonar.db.user.UserDto;
51 import org.sonar.server.component.TestComponentFinder;
52 import org.sonar.server.es.EsTester;
53 import org.sonar.server.es.ProjectIndexer;
54 import org.sonar.server.es.TestProjectIndexers;
55 import org.sonar.server.exceptions.BadRequestException;
56 import org.sonar.server.exceptions.ForbiddenException;
57 import org.sonar.server.exceptions.NotFoundException;
58 import org.sonar.server.exceptions.UnauthorizedException;
59 import org.sonar.server.permission.PermissionService;
60 import org.sonar.server.permission.PermissionServiceImpl;
61 import org.sonar.server.permission.index.FooIndexDefinition;
62 import org.sonar.server.tester.UserSessionRule;
63 import org.sonar.server.ws.TestRequest;
64 import org.sonar.server.ws.WsActionTester;
65
66 import static java.lang.String.format;
67 import static java.util.Arrays.stream;
68 import static java.util.Optional.of;
69 import static org.assertj.core.api.Assertions.assertThat;
70 import static org.assertj.core.api.Assertions.assertThatThrownBy;
71 import static org.assertj.core.api.Assertions.fail;
72 import static org.mockito.Mockito.mock;
73 import static org.mockito.Mockito.when;
74 import static org.sonar.api.CoreProperties.CORE_ALLOW_PERMISSION_MANAGEMENT_FOR_PROJECT_ADMINS_PROPERTY;
75 import static org.sonar.db.component.ComponentTesting.newProjectCopy;
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 dir = ComponentTesting.newDirectory(project, "path");
193     ComponentDto file = ComponentTesting.newFileDto(project);
194     dbTester.components().insertComponents(dir, file);
195     ComponentDto application = dbTester.components().insertPublicApplication();
196     ComponentDto portfolio = dbTester.components().insertPrivatePortfolio();
197     ComponentDto subView = ComponentTesting.newSubPortfolio(portfolio);
198     ComponentDto projectCopy = newProjectCopy("foo", project, subView);
199     dbTester.components().insertComponents(subView, projectCopy);
200     userSessionRule.addProjectPermission(UserRole.ADMIN, project, portfolio, application);
201
202     Stream.of(project, portfolio, application).forEach(c -> request
203       .setParam(PARAM_PROJECT, c.getKey())
204       .setParam(PARAM_VISIBILITY, randomVisibility)
205       .execute());
206
207     Stream.of(dir, file, subView, projectCopy)
208       .forEach(nonRootComponent -> {
209         request.setParam(PARAM_PROJECT, nonRootComponent.getKey())
210           .setParam(PARAM_VISIBILITY, randomVisibility);
211
212         try {
213           request.execute();
214           fail("a BadRequestException should have been raised");
215         } catch (BadRequestException e) {
216           assertThat(e.getMessage()).isEqualTo("Component must be a project, a portfolio or an application");
217         }
218       });
219   }
220
221   @Test
222   public void execute_throws_ForbiddenException_if_user_has_no_permission_on_specified_component() {
223     ComponentDto project = dbTester.components().insertPrivateProject();
224     request.setParam(PARAM_PROJECT, project.getKey())
225       .setParam(PARAM_VISIBILITY, randomVisibility);
226
227     assertThatThrownBy(request::execute)
228       .isInstanceOf(ForbiddenException.class)
229       .hasMessage("Insufficient privileges");
230   }
231
232   @Test
233   public void execute_throws_ForbiddenException_if_user_has_all_permissions_but_ADMIN_on_specified_component() {
234     ComponentDto project = dbTester.components().insertPublicProject();
235     request.setParam(PARAM_PROJECT, project.getKey())
236       .setParam(PARAM_VISIBILITY, randomVisibility);
237     userSessionRule.addProjectPermission(UserRole.ISSUE_ADMIN, project);
238     Arrays.stream(GlobalPermission.values())
239       .forEach(userSessionRule::addPermission);
240
241     assertThatThrownBy(request::execute)
242       .isInstanceOf(ForbiddenException.class)
243       .hasMessage("Insufficient privileges");
244   }
245
246   @Test
247   public void execute_throws_ForbiddenException_if_user_has_ADMIN_permission_but_sonar_allowPermissionManagementForProjectAdmins_is_set_to_false() {
248     when(configuration.getBoolean(CORE_ALLOW_PERMISSION_MANAGEMENT_FOR_PROJECT_ADMINS_PROPERTY)).thenReturn(of(false));
249     ComponentDto project = dbTester.components().insertPublicProject();
250     request.setParam(PARAM_PROJECT, project.getKey())
251       .setParam(PARAM_VISIBILITY, randomVisibility);
252     userSessionRule.addProjectPermission(UserRole.ADMIN, project);
253
254     assertThatThrownBy(request::execute)
255       .isInstanceOf(ForbiddenException.class)
256       .hasMessage("Insufficient privileges");
257   }
258
259   @Test
260   public void execute_throws_ForbiddenException_if_user_has_global_ADMIN_permission_even_if_sonar_allowPermissionManagementForProjectAdmins_is_set_to_false() {
261     when(configuration.getBoolean(CORE_ALLOW_PERMISSION_MANAGEMENT_FOR_PROJECT_ADMINS_PROPERTY)).thenReturn(of(false));
262     ComponentDto project = dbTester.components().insertPublicProject();
263     userSessionRule.setSystemAdministrator().addProjectPermission(UserRole.ADMIN, project);
264     request.setParam(PARAM_PROJECT, project.getKey())
265       .setParam(PARAM_VISIBILITY, "private");
266
267     request.execute();
268
269     assertThat(isPrivateInDb(project)).isTrue();
270   }
271
272   @Test
273   public void execute_throws_BadRequestException_if_specified_component_has_pending_tasks() {
274     ComponentDto project = randomPublicOrPrivateProject();
275     IntStream.range(0, 1 + Math.abs(random.nextInt(5)))
276       .forEach(i -> insertPendingTask(project));
277     request.setParam(PARAM_PROJECT, project.getKey())
278       .setParam(PARAM_VISIBILITY, randomVisibility);
279     userSessionRule.addProjectPermission(UserRole.ADMIN, project);
280
281     assertThatThrownBy(request::execute)
282       .isInstanceOf(BadRequestException.class)
283       .hasMessage("Component visibility can't be changed as long as it has background task(s) pending or in progress");
284   }
285
286   @Test
287   public void execute_throws_BadRequestException_if_main_component_of_specified_component_has_in_progress_tasks() {
288     ComponentDto project = randomPublicOrPrivateProject();
289     IntStream.range(0, 1 + Math.abs(random.nextInt(5)))
290       .forEach(i -> insertInProgressTask(project));
291     request.setParam(PARAM_PROJECT, project.getKey())
292       .setParam(PARAM_VISIBILITY, randomVisibility);
293     userSessionRule.addProjectPermission(UserRole.ADMIN, project);
294
295     assertThatThrownBy(request::execute)
296       .isInstanceOf(BadRequestException.class)
297       .hasMessage("Component visibility can't be changed as long as it has background task(s) pending or in progress");
298   }
299
300   @Test
301   public void execute_changes_private_flag_of_specified_project_and_all_children_to_specified_new_visibility() {
302     ComponentDto project = randomPublicOrPrivateProject();
303     boolean initiallyPrivate = project.isPrivate();
304
305     BranchDto branchDto = ComponentTesting.newBranchDto(project);
306     dbClient.branchDao().insert(dbSession, branchDto);
307
308     ComponentDto branch = ComponentTesting.newBranchComponent(project, branchDto);
309     ComponentDto dir = ComponentTesting.newDirectory(project, "path");
310     ComponentDto file = ComponentTesting.newFileDto(project);
311
312     dbTester.components().insertComponents(branch, dir, file);
313     userSessionRule.addProjectPermission(UserRole.ADMIN, project);
314
315     request.setParam(PARAM_PROJECT, project.getKey())
316       .setParam(PARAM_VISIBILITY, initiallyPrivate ? PUBLIC : PRIVATE)
317       .execute();
318
319     assertThat(isPrivateInDb(project)).isEqualTo(!initiallyPrivate);
320     assertThat(isPrivateInDb(branch)).isEqualTo(!initiallyPrivate);
321     assertThat(isPrivateInDb(dir)).isEqualTo(!initiallyPrivate);
322     assertThat(isPrivateInDb(file)).isEqualTo(!initiallyPrivate);
323   }
324
325   @Test
326   public void execute_has_no_effect_if_specified_project_already_has_specified_visibility() {
327     ComponentDto project = randomPublicOrPrivateProject();
328     boolean initiallyPrivate = project.isPrivate();
329
330     BranchDto branchDto = ComponentTesting.newBranchDto(project);
331     dbClient.branchDao().insert(dbSession, branchDto);
332
333     ComponentDto branch = ComponentTesting.newBranchComponent(project, branchDto)
334       .setPrivate(initiallyPrivate);
335     ComponentDto dir = ComponentTesting.newDirectory(project, "path")
336       // child is inconsistent with root (should not occur) and won't be fixed
337       .setPrivate(!initiallyPrivate);
338     ComponentDto file = ComponentTesting.newFileDto(project)
339       .setPrivate(initiallyPrivate);
340     dbTester.components().insertComponents(branch, dir, file);
341     userSessionRule.addProjectPermission(UserRole.ADMIN, project);
342
343     request.setParam(PARAM_PROJECT, project.getKey())
344       .setParam(PARAM_VISIBILITY, initiallyPrivate ? PRIVATE : PUBLIC)
345       .execute();
346
347     assertThat(isPrivateInDb(project)).isEqualTo(initiallyPrivate);
348     assertThat(isPrivateInDb(branch)).isEqualTo(initiallyPrivate);
349     assertThat(isPrivateInDb(dir)).isEqualTo(!initiallyPrivate);
350     assertThat(isPrivateInDb(file)).isEqualTo(initiallyPrivate);
351   }
352
353   @Test
354   public void execute_deletes_all_permissions_to_Anyone_on_specified_project_when_new_visibility_is_private() {
355     ComponentDto project = dbTester.components().insertPublicProject();
356     UserDto user = dbTester.users().insertUser();
357     GroupDto group = dbTester.users().insertGroup();
358     unsafeGiveAllPermissionsToRootComponent(project, user, group);
359     userSessionRule.addProjectPermission(UserRole.ADMIN, project);
360
361     request.setParam(PARAM_PROJECT, project.getKey())
362       .setParam(PARAM_VISIBILITY, PRIVATE)
363       .execute();
364
365     verifyHasAllPermissionsButProjectPermissionsToGroupAnyOne(project, user, group);
366   }
367
368   @Test
369   public void execute_does_not_delete_all_permissions_to_AnyOne_on_specified_project_if_already_private() {
370     ComponentDto project = dbTester.components().insertPrivateProject();
371     UserDto user = dbTester.users().insertUser();
372     GroupDto group = dbTester.users().insertGroup();
373     unsafeGiveAllPermissionsToRootComponent(project, user, group);
374     userSessionRule.addProjectPermission(UserRole.ADMIN, project);
375
376     request.setParam(PARAM_PROJECT, project.getKey())
377       .setParam(PARAM_VISIBILITY, PRIVATE)
378       .execute();
379
380     verifyStillHasAllPermissions(project, user, group);
381   }
382
383   @Test
384   public void execute_deletes_all_permissions_USER_and_BROWSE_of_specified_project_when_new_visibility_is_public() {
385     ComponentDto project = dbTester.components().insertPrivateProject();
386     UserDto user = dbTester.users().insertUser();
387     GroupDto group = dbTester.users().insertGroup();
388     unsafeGiveAllPermissionsToRootComponent(project, user, group);
389     userSessionRule.addProjectPermission(UserRole.ADMIN, project);
390
391     request.setParam(PARAM_PROJECT, project.getKey())
392       .setParam(PARAM_VISIBILITY, PUBLIC)
393       .execute();
394
395     verifyHasAllPermissionsButProjectPermissionsUserAndBrowse(project, user, group);
396   }
397
398   @Test
399   public void execute_does_not_delete_permissions_USER_and_BROWSE_of_specified_project_when_new_component_is_already_public() {
400     ComponentDto project = dbTester.components().insertPublicProject();
401     UserDto user = dbTester.users().insertUser();
402     GroupDto group = dbTester.users().insertGroup();
403     unsafeGiveAllPermissionsToRootComponent(project, user, group);
404     userSessionRule.addProjectPermission(UserRole.ADMIN, project);
405
406     request.setParam(PARAM_PROJECT, project.getKey())
407       .setParam(PARAM_VISIBILITY, PUBLIC)
408       .execute();
409
410     verifyStillHasAllPermissions(project, user, group);
411   }
412
413   @Test
414   public void execute_updates_permission_of_specified_project_in_indexes_when_changing_visibility() {
415     ComponentDto project = randomPublicOrPrivateProject();
416     boolean initiallyPrivate = project.isPrivate();
417     userSessionRule.addProjectPermission(UserRole.ADMIN, project);
418
419     request.setParam(PARAM_PROJECT, project.getKey())
420       .setParam(PARAM_VISIBILITY, initiallyPrivate ? PUBLIC : PRIVATE)
421       .execute();
422
423     assertThat(projectIndexers.hasBeenCalled(project.uuid(), ProjectIndexer.Cause.PERMISSION_CHANGE)).isTrue();
424   }
425
426   @Test
427   public void execute_does_not_update_permission_of_specified_project_in_indexes_if_already_has_specified_visibility() {
428     ComponentDto project = randomPublicOrPrivateProject();
429     boolean initiallyPrivate = project.isPrivate();
430     userSessionRule.addProjectPermission(UserRole.ADMIN, project);
431
432     request.setParam(PARAM_PROJECT, project.getKey())
433       .setParam(PARAM_VISIBILITY, initiallyPrivate ? PRIVATE : PUBLIC)
434       .execute();
435
436     assertThat(projectIndexers.hasBeenCalled(project.uuid())).isFalse();
437   }
438
439   @Test
440   public void execute_grants_USER_and_CODEVIEWER_permissions_to_any_user_with_at_least_one_permission_when_making_project_private() {
441     ComponentDto project = dbTester.components().insertPublicProject();
442     UserDto user1 = dbTester.users().insertUser();
443     UserDto user2 = dbTester.users().insertUser();
444     UserDto user3 = dbTester.users().insertUser();
445     dbTester.users().insertProjectPermissionOnUser(user1, "p1", project);
446     dbTester.users().insertProjectPermissionOnUser(user1, "p2", project);
447     dbTester.users().insertProjectPermissionOnUser(user2, "p2", project);
448     userSessionRule.addProjectPermission(UserRole.ADMIN, project);
449
450     request.setParam(PARAM_PROJECT, project.getKey())
451       .setParam(PARAM_VISIBILITY, PRIVATE)
452       .execute();
453
454     assertThat(dbClient.userPermissionDao().selectProjectPermissionsOfUser(dbSession, user1.getUuid(), project.uuid()))
455       .containsOnly(UserRole.USER, UserRole.CODEVIEWER, "p1", "p2");
456     assertThat(dbClient.userPermissionDao().selectProjectPermissionsOfUser(dbSession, user2.getUuid(), project.uuid()))
457       .containsOnly(UserRole.USER, UserRole.CODEVIEWER, "p2");
458     assertThat(dbClient.userPermissionDao().selectProjectPermissionsOfUser(dbSession, user3.getUuid(), project.uuid()))
459       .isEmpty();
460   }
461
462   @Test
463   public void execute_grants_USER_and_CODEVIEWER_permissions_to_any_group_with_at_least_one_permission_when_making_project_private() {
464     ComponentDto project = dbTester.components().insertPublicProject();
465     GroupDto group1 = dbTester.users().insertGroup();
466     GroupDto group2 = dbTester.users().insertGroup();
467     GroupDto group3 = dbTester.users().insertGroup();
468     dbTester.users().insertProjectPermissionOnGroup(group1, "p1", project);
469     dbTester.users().insertProjectPermissionOnGroup(group1, "p2", project);
470     dbTester.users().insertProjectPermissionOnGroup(group2, "p2", project);
471     userSessionRule.addProjectPermission(UserRole.ADMIN, project);
472
473     request.setParam(PARAM_PROJECT, project.getKey())
474       .setParam(PARAM_VISIBILITY, PRIVATE)
475       .execute();
476
477     assertThat(dbClient.groupPermissionDao().selectProjectPermissionsOfGroup(dbSession, group1.getUuid(), project.uuid()))
478       .containsOnly(UserRole.USER, UserRole.CODEVIEWER, "p1", "p2");
479     assertThat(dbClient.groupPermissionDao().selectProjectPermissionsOfGroup(dbSession, group2.getUuid(), project.uuid()))
480       .containsOnly(UserRole.USER, UserRole.CODEVIEWER, "p2");
481     assertThat(dbClient.groupPermissionDao().selectProjectPermissionsOfGroup(dbSession, group3.getUuid(), project.uuid()))
482       .isEmpty();
483   }
484
485   @Test
486   public void update_a_portfolio_to_private() {
487     ComponentDto portfolio = dbTester.components().insertPublicPortfolio();
488     GroupDto group = dbTester.users().insertGroup();
489     dbTester.users().insertProjectPermissionOnGroup(group, UserRole.ISSUE_ADMIN, portfolio);
490     UserDto user = dbTester.users().insertUser();
491     dbTester.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, portfolio);
492     userSessionRule.addProjectPermission(UserRole.ADMIN, portfolio);
493
494     request.setParam(PARAM_PROJECT, portfolio.getKey())
495       .setParam(PARAM_VISIBILITY, PRIVATE)
496       .execute();
497
498     assertThat(dbClient.componentDao().selectByUuid(dbSession, portfolio.uuid()).get().isPrivate()).isTrue();
499     assertThat(dbClient.groupPermissionDao().selectProjectPermissionsOfGroup(dbSession, group.getUuid(), portfolio.uuid()))
500       .containsOnly(UserRole.USER, UserRole.CODEVIEWER, UserRole.ISSUE_ADMIN);
501     assertThat(dbClient.userPermissionDao().selectProjectPermissionsOfUser(dbSession, user.getUuid(), portfolio.uuid()))
502       .containsOnly(UserRole.USER, UserRole.CODEVIEWER, UserRole.ADMIN);
503   }
504
505   @Test
506   public void update_a_portfolio_to_public() {
507     ComponentDto portfolio = dbTester.components().insertPrivatePortfolio();
508     userSessionRule.addProjectPermission(UserRole.ADMIN, portfolio);
509     GroupDto group = dbTester.users().insertGroup();
510     dbTester.users().insertProjectPermissionOnGroup(group, UserRole.ISSUE_ADMIN, portfolio);
511     dbTester.users().insertProjectPermissionOnGroup(group, UserRole.USER, portfolio);
512     dbTester.users().insertProjectPermissionOnGroup(group, UserRole.CODEVIEWER, portfolio);
513     UserDto user = dbTester.users().insertUser();
514     dbTester.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, portfolio);
515     dbTester.users().insertProjectPermissionOnUser(user, UserRole.USER, portfolio);
516     dbTester.users().insertProjectPermissionOnUser(user, UserRole.CODEVIEWER, portfolio);
517
518     request.setParam(PARAM_PROJECT, portfolio.getKey())
519       .setParam(PARAM_VISIBILITY, PUBLIC)
520       .execute();
521
522     assertThat(dbClient.componentDao().selectByUuid(dbSession, portfolio.uuid()).get().isPrivate()).isFalse();
523     assertThat(dbClient.groupPermissionDao().selectProjectPermissionsOfGroup(dbSession, group.getUuid(), portfolio.uuid()))
524       .containsOnly(UserRole.ISSUE_ADMIN);
525     assertThat(dbClient.userPermissionDao().selectProjectPermissionsOfUser(dbSession, user.getUuid(), portfolio.uuid()))
526       .containsOnly(UserRole.ADMIN);
527   }
528
529   @Test
530   public void update_an_application_to_private() {
531     ComponentDto application = dbTester.components().insertPublicApplication();
532     GroupDto group = dbTester.users().insertGroup();
533     dbTester.users().insertProjectPermissionOnGroup(group, UserRole.ISSUE_ADMIN, application);
534     UserDto user = dbTester.users().insertUser();
535     dbTester.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, application);
536     userSessionRule.addProjectPermission(UserRole.ADMIN, application);
537
538     request.setParam(PARAM_PROJECT, application.getKey())
539       .setParam(PARAM_VISIBILITY, PRIVATE)
540       .execute();
541
542     assertThat(dbClient.componentDao().selectByUuid(dbSession, application.uuid()).get().isPrivate()).isTrue();
543     assertThat(dbClient.groupPermissionDao().selectProjectPermissionsOfGroup(dbSession, group.getUuid(), application.uuid()))
544       .containsOnly(UserRole.USER, UserRole.CODEVIEWER, UserRole.ISSUE_ADMIN);
545     assertThat(dbClient.userPermissionDao().selectProjectPermissionsOfUser(dbSession, user.getUuid(), application.uuid()))
546       .containsOnly(UserRole.USER, UserRole.CODEVIEWER, UserRole.ADMIN);
547   }
548
549   @Test
550   public void update_an_application_to_public() {
551     ComponentDto portfolio = dbTester.components().insertPrivateApplication();
552     userSessionRule.addProjectPermission(UserRole.ADMIN, portfolio);
553     GroupDto group = dbTester.users().insertGroup();
554     dbTester.users().insertProjectPermissionOnGroup(group, UserRole.ISSUE_ADMIN, portfolio);
555     dbTester.users().insertProjectPermissionOnGroup(group, UserRole.USER, portfolio);
556     dbTester.users().insertProjectPermissionOnGroup(group, UserRole.CODEVIEWER, portfolio);
557     UserDto user = dbTester.users().insertUser();
558     dbTester.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, portfolio);
559     dbTester.users().insertProjectPermissionOnUser(user, UserRole.USER, portfolio);
560     dbTester.users().insertProjectPermissionOnUser(user, UserRole.CODEVIEWER, portfolio);
561
562     request.setParam(PARAM_PROJECT, portfolio.getKey())
563       .setParam(PARAM_VISIBILITY, PUBLIC)
564       .execute();
565
566     assertThat(dbClient.componentDao().selectByUuid(dbSession, portfolio.uuid()).get().isPrivate()).isFalse();
567     assertThat(dbClient.groupPermissionDao().selectProjectPermissionsOfGroup(dbSession, group.getUuid(), portfolio.uuid()))
568       .containsOnly(UserRole.ISSUE_ADMIN);
569     assertThat(dbClient.userPermissionDao().selectProjectPermissionsOfUser(dbSession, user.getUuid(), portfolio.uuid()))
570       .containsOnly(UserRole.ADMIN);
571   }
572
573   private void unsafeGiveAllPermissionsToRootComponent(ComponentDto component, UserDto user, GroupDto group) {
574     Arrays.stream(GlobalPermission.values())
575       .forEach(globalPermission -> {
576         dbTester.users().insertPermissionOnAnyone(globalPermission);
577         dbTester.users().insertPermissionOnGroup(group, globalPermission);
578         dbTester.users().insertPermissionOnUser(user, globalPermission);
579       });
580     permissionService.getAllProjectPermissions()
581       .forEach(permission -> {
582         unsafeInsertProjectPermissionOnAnyone(component, permission);
583         unsafeInsertProjectPermissionOnGroup(component, group, permission);
584         unsafeInsertProjectPermissionOnUser(component, user, permission);
585       });
586   }
587
588   private void unsafeInsertProjectPermissionOnAnyone(ComponentDto component, String permission) {
589     GroupPermissionDto dto = new GroupPermissionDto()
590       .setUuid(Uuids.createFast())
591       .setGroupUuid(null)
592       .setRole(permission)
593       .setComponentUuid(component.uuid())
594       .setComponentName(component.name());
595     dbTester.getDbClient().groupPermissionDao().insert(dbTester.getSession(), dto, component, null);
596     dbTester.commit();
597   }
598
599   private void unsafeInsertProjectPermissionOnGroup(ComponentDto component, GroupDto group, String permission) {
600     GroupPermissionDto dto = new GroupPermissionDto()
601       .setUuid(Uuids.createFast())
602       .setGroupUuid(group.getUuid())
603       .setGroupName(group.getName())
604       .setRole(permission)
605       .setComponentUuid(component.uuid())
606       .setComponentName(component.name());
607     dbTester.getDbClient().groupPermissionDao().insert(dbTester.getSession(), dto, component, null);
608     dbTester.commit();
609   }
610
611   private void unsafeInsertProjectPermissionOnUser(ComponentDto component, UserDto user, String permission) {
612     UserPermissionDto dto = new UserPermissionDto(Uuids.create(), permission, user.getUuid(), component.uuid());
613     dbTester.getDbClient().userPermissionDao().insert(dbTester.getSession(), dto, component, user, null);
614     dbTester.commit();
615   }
616
617   private void verifyHasAllPermissionsButProjectPermissionsToGroupAnyOne(ComponentDto component, UserDto user, GroupDto group) {
618     assertThat(dbClient.groupPermissionDao().selectGlobalPermissionsOfGroup(dbSession, null))
619       .containsAll(GLOBAL_PERMISSIONS_NAME_SET);
620     assertThat(dbClient.groupPermissionDao().selectGlobalPermissionsOfGroup(dbSession, group.getUuid()))
621       .containsAll(GLOBAL_PERMISSIONS_NAME_SET);
622     assertThat(dbClient.userPermissionDao().selectGlobalPermissionsOfUser(dbSession, user.getUuid()))
623       .containsAll(GLOBAL_PERMISSIONS_NAME_SET);
624     assertThat(dbClient.groupPermissionDao().selectProjectPermissionsOfGroup(dbSession, null, component.uuid()))
625       .isEmpty();
626     assertThat(dbClient.groupPermissionDao().selectProjectPermissionsOfGroup(dbSession, group.getUuid(), component.uuid()))
627       .containsAll(permissionService.getAllProjectPermissions());
628     assertThat(dbClient.userPermissionDao().selectProjectPermissionsOfUser(dbSession, user.getUuid(), component.uuid()))
629       .containsAll(permissionService.getAllProjectPermissions());
630   }
631
632   private void verifyHasAllPermissionsButProjectPermissionsUserAndBrowse(ComponentDto component, UserDto user, GroupDto group) {
633     assertThat(dbClient.groupPermissionDao().selectGlobalPermissionsOfGroup(dbSession, null))
634       .containsAll(GLOBAL_PERMISSIONS_NAME_SET);
635     assertThat(dbClient.groupPermissionDao().selectGlobalPermissionsOfGroup(dbSession, group.getUuid()))
636       .containsAll(GLOBAL_PERMISSIONS_NAME_SET);
637     assertThat(dbClient.userPermissionDao().selectGlobalPermissionsOfUser(dbSession, user.getUuid()))
638       .containsAll(GLOBAL_PERMISSIONS_NAME_SET);
639     assertThat(dbClient.groupPermissionDao().selectProjectPermissionsOfGroup(dbSession, null, component.uuid()))
640       .doesNotContain(UserRole.USER)
641       .doesNotContain(UserRole.CODEVIEWER)
642       .containsAll(PROJECT_PERMISSIONS_BUT_USER_AND_CODEVIEWER);
643     assertThat(dbClient.groupPermissionDao().selectProjectPermissionsOfGroup(dbSession, group.getUuid(), component.uuid()))
644       .doesNotContain(UserRole.USER)
645       .doesNotContain(UserRole.CODEVIEWER)
646       .containsAll(PROJECT_PERMISSIONS_BUT_USER_AND_CODEVIEWER);
647     assertThat(dbClient.userPermissionDao().selectProjectPermissionsOfUser(dbSession, user.getUuid(), component.uuid()))
648       .doesNotContain(UserRole.USER)
649       .doesNotContain(UserRole.CODEVIEWER)
650       .containsAll(PROJECT_PERMISSIONS_BUT_USER_AND_CODEVIEWER);
651   }
652
653   private void verifyStillHasAllPermissions(ComponentDto component, UserDto user, GroupDto group) {
654     assertThat(dbClient.groupPermissionDao().selectGlobalPermissionsOfGroup(dbSession, null))
655       .containsAll(GLOBAL_PERMISSIONS_NAME_SET);
656     assertThat(dbClient.groupPermissionDao().selectGlobalPermissionsOfGroup(dbSession, group.getUuid()))
657       .containsAll(GLOBAL_PERMISSIONS_NAME_SET);
658     assertThat(dbClient.userPermissionDao().selectGlobalPermissionsOfUser(dbSession, user.getUuid()))
659       .containsAll(GLOBAL_PERMISSIONS_NAME_SET);
660     assertThat(dbClient.groupPermissionDao().selectProjectPermissionsOfGroup(dbSession, null, component.uuid()))
661       .containsAll(permissionService.getAllProjectPermissions());
662     assertThat(dbClient.groupPermissionDao().selectProjectPermissionsOfGroup(dbSession, group.getUuid(), component.uuid()))
663       .containsAll(permissionService.getAllProjectPermissions());
664     assertThat(dbClient.userPermissionDao().selectProjectPermissionsOfUser(dbSession, user.getUuid(), component.uuid()))
665       .containsAll(permissionService.getAllProjectPermissions());
666   }
667
668   private void insertPendingTask(ComponentDto project) {
669     insertCeQueueDto(project, CeQueueDto.Status.PENDING);
670   }
671
672   private void insertInProgressTask(ComponentDto project) {
673     insertCeQueueDto(project, CeQueueDto.Status.IN_PROGRESS);
674   }
675
676   private int counter = 0;
677
678   private void insertCeQueueDto(ComponentDto project, CeQueueDto.Status status) {
679     dbClient.ceQueueDao().insert(dbTester.getSession(), new CeQueueDto()
680       .setUuid("pending" + counter++)
681       .setComponent(project)
682       .setTaskType("foo")
683       .setStatus(status));
684     dbTester.commit();
685   }
686
687   private boolean isPrivateInDb(ComponentDto project) {
688     return dbClient.componentDao().selectByUuid(dbTester.getSession(), project.uuid()).get().isPrivate();
689   }
690
691   private ComponentDto randomPublicOrPrivateProject() {
692     return random.nextBoolean() ? dbTester.components().insertPublicProject() : dbTester.components().insertPrivateProject();
693   }
694 }