]> source.dussan.org Git - sonarqube.git/blob
69df458665eb27fe0faa77234840068e3b217c85
[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.permission;
21
22 import org.apache.commons.lang.StringUtils;
23 import org.junit.Before;
24 import org.junit.Rule;
25 import org.junit.Test;
26 import org.sonar.api.resources.Qualifiers;
27 import org.sonar.api.resources.ResourceTypes;
28 import org.sonar.api.utils.System2;
29 import org.sonar.core.util.SequenceUuidFactory;
30 import org.sonar.db.DbTester;
31 import org.sonar.db.component.ComponentDto;
32 import org.sonar.db.component.ResourceTypesRule;
33 import org.sonar.db.permission.GlobalPermission;
34 import org.sonar.db.user.GroupDto;
35 import org.sonar.db.user.UserDto;
36 import org.sonar.db.user.UserIdDto;
37 import org.sonar.server.exceptions.BadRequestException;
38
39 import static org.assertj.core.api.Assertions.assertThat;
40 import static org.assertj.core.api.Assertions.assertThatThrownBy;
41 import static org.sonar.api.web.UserRole.ADMIN;
42 import static org.sonar.api.web.UserRole.CODEVIEWER;
43 import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
44 import static org.sonar.api.web.UserRole.USER;
45 import static org.sonar.core.permission.GlobalPermissions.QUALITY_GATE_ADMIN;
46 import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION;
47 import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
48 import static org.sonar.db.permission.GlobalPermission.ADMINISTER;
49 import static org.sonar.db.permission.GlobalPermission.ADMINISTER_QUALITY_GATES;
50 import static org.sonar.db.permission.GlobalPermission.SCAN;
51 import static org.sonar.server.permission.PermissionChange.Operation.ADD;
52 import static org.sonar.server.permission.PermissionChange.Operation.REMOVE;
53
54 public class UserPermissionChangerTest {
55   @Rule
56   public DbTester db = DbTester.create(System2.INSTANCE);
57
58
59   private final ResourceTypes resourceTypes = new ResourceTypesRule().setRootQualifiers(Qualifiers.PROJECT);
60   private final PermissionService permissionService = new PermissionServiceImpl(resourceTypes);
61   private final UserPermissionChanger underTest = new UserPermissionChanger(db.getDbClient(), new SequenceUuidFactory());
62   private UserDto user1;
63   private UserDto user2;
64   private ComponentDto privateProject;
65   private ComponentDto publicProject;
66
67   @Before
68   public void setUp() {
69     user1 = db.users().insertUser();
70     user2 = db.users().insertUser();
71     privateProject = db.components().insertPrivateProject();
72     publicProject = db.components().insertPublicProject();
73   }
74
75   @Test
76   public void apply_adds_any_global_permission_to_user() {
77     permissionService.getGlobalPermissions()
78       .forEach(perm -> {
79         UserPermissionChange change = new UserPermissionChange(ADD, perm.getKey(), null, UserIdDto.from(user1), permissionService);
80
81         apply(change);
82
83         assertThat(db.users().selectPermissionsOfUser(user1)).contains(perm);
84       });
85   }
86
87   @Test
88   public void apply_removes_any_global_permission_to_user() {
89     // give ADMIN perm to user2 so that user1 is not the only one with this permission and it can be removed from user1
90     db.users().insertPermissionOnUser(user2, GlobalPermission.ADMINISTER);
91     permissionService.getGlobalPermissions()
92       .forEach(perm -> db.users().insertPermissionOnUser(user1, perm));
93     assertThat(db.users().selectPermissionsOfUser(user1))
94       .containsOnly(permissionService.getGlobalPermissions().toArray(new GlobalPermission[0]));
95
96     permissionService.getGlobalPermissions()
97       .forEach(perm -> {
98         UserPermissionChange change = new UserPermissionChange(REMOVE, perm.getKey(), null, UserIdDto.from(user1), permissionService);
99
100         apply(change);
101
102         assertThat(db.users().selectPermissionsOfUser(user1)).doesNotContain(perm);
103       });
104   }
105
106   @Test
107   public void apply_has_no_effect_when_adding_permission_USER_on_a_public_project() {
108     UserPermissionChange change = new UserPermissionChange(ADD, USER, publicProject, UserIdDto.from(user1), permissionService);
109
110     apply(change);
111
112     assertThat(db.users().selectProjectPermissionsOfUser(user1, publicProject)).doesNotContain(USER);
113   }
114
115   @Test
116   public void apply_has_no_effect_when_adding_permission_CODEVIEWER_on_a_public_project() {
117     UserPermissionChange change = new UserPermissionChange(ADD, CODEVIEWER, publicProject, UserIdDto.from(user1), permissionService);
118
119     apply(change);
120
121     assertThat(db.users().selectProjectPermissionsOfUser(user1, publicProject)).doesNotContain(CODEVIEWER);
122   }
123
124   @Test
125   public void apply_adds_permission_ADMIN_on_a_public_project() {
126     applyAddsPermissionOnAPublicProject(ADMIN);
127   }
128
129   @Test
130   public void apply_adds_permission_ISSUE_ADMIN_on_a_public_project() {
131     applyAddsPermissionOnAPublicProject(ISSUE_ADMIN);
132   }
133
134   @Test
135   public void apply_adds_permission_SCAN_EXECUTION_on_a_public_project() {
136     applyAddsPermissionOnAPublicProject(SCAN_EXECUTION);
137   }
138
139   private void applyAddsPermissionOnAPublicProject(String permission) {
140     UserPermissionChange change = new UserPermissionChange(ADD, permission, publicProject, UserIdDto.from(user1), permissionService);
141
142     apply(change);
143
144     assertThat(db.users().selectProjectPermissionsOfUser(user1, publicProject)).containsOnly(permission);
145   }
146
147   @Test
148   public void apply_fails_with_BadRequestException_when_removing_permission_USER_from_a_public_project() {
149     UserPermissionChange change = new UserPermissionChange(REMOVE, USER, publicProject, UserIdDto.from(user1), permissionService);
150
151     assertThatThrownBy(() -> apply(change))
152       .isInstanceOf(BadRequestException.class)
153       .hasMessage("Permission user can't be removed from a public component");
154   }
155
156   @Test
157   public void apply_fails_with_BadRequestException_when_removing_permission_CODEVIEWER_from_a_public_project() {
158     UserPermissionChange change = new UserPermissionChange(REMOVE, CODEVIEWER, publicProject, UserIdDto.from(user1), permissionService);
159
160     assertThatThrownBy(() -> apply(change))
161       .isInstanceOf(BadRequestException.class)
162       .hasMessage("Permission codeviewer can't be removed from a public component");
163   }
164
165   @Test
166   public void apply_removes_permission_ADMIN_from_a_public_project() {
167     applyRemovesPermissionFromPublicProject(ADMIN);
168   }
169
170   @Test
171   public void apply_removes_permission_ISSUE_ADMIN_from_a_public_project() {
172     applyRemovesPermissionFromPublicProject(ISSUE_ADMIN);
173   }
174
175   @Test
176   public void apply_removes_permission_SCAN_EXECUTION_from_a_public_project() {
177     applyRemovesPermissionFromPublicProject(SCAN_EXECUTION);
178   }
179
180   private void applyRemovesPermissionFromPublicProject(String permission) {
181     db.users().insertProjectPermissionOnUser(user1, permission, publicProject);
182     UserPermissionChange change = new UserPermissionChange(REMOVE, permission, publicProject, UserIdDto.from(user1), permissionService);
183
184     apply(change);
185
186     assertThat(db.users().selectProjectPermissionsOfUser(user1, publicProject)).isEmpty();
187   }
188
189   @Test
190   public void apply_adds_any_permission_to_a_private_project() {
191     permissionService.getAllProjectPermissions()
192       .forEach(permission -> {
193         UserPermissionChange change = new UserPermissionChange(ADD, permission, privateProject, UserIdDto.from(user1), permissionService);
194
195         apply(change);
196
197         assertThat(db.users().selectProjectPermissionsOfUser(user1, privateProject)).contains(permission);
198       });
199   }
200
201   @Test
202   public void apply_removes_any_permission_from_a_private_project() {
203     permissionService.getAllProjectPermissions()
204       .forEach(permission -> db.users().insertProjectPermissionOnUser(user1, permission, privateProject));
205
206     permissionService.getAllProjectPermissions()
207       .forEach(permission -> {
208         UserPermissionChange change = new UserPermissionChange(REMOVE, permission, privateProject, UserIdDto.from(user1), permissionService);
209
210         apply(change);
211
212         assertThat(db.users().selectProjectPermissionsOfUser(user1, privateProject)).doesNotContain(permission);
213       });
214   }
215
216   @Test
217   public void add_global_permission_to_user() {
218     UserPermissionChange change = new UserPermissionChange(ADD, SCAN_EXECUTION, null, UserIdDto.from(user1), permissionService);
219
220     apply(change);
221
222     assertThat(db.users().selectPermissionsOfUser(user1)).containsOnly(SCAN);
223     assertThat(db.users().selectProjectPermissionsOfUser(user1, privateProject)).isEmpty();
224     assertThat(db.users().selectPermissionsOfUser(user2)).isEmpty();
225     assertThat(db.users().selectProjectPermissionsOfUser(user2, privateProject)).isEmpty();
226   }
227
228   @Test
229   public void add_project_permission_to_user() {
230     UserPermissionChange change = new UserPermissionChange(ADD, ISSUE_ADMIN, privateProject, UserIdDto.from(user1), permissionService);
231     apply(change);
232
233     assertThat(db.users().selectPermissionsOfUser(user1)).isEmpty();
234     assertThat(db.users().selectProjectPermissionsOfUser(user1, privateProject)).contains(ISSUE_ADMIN);
235     assertThat(db.users().selectPermissionsOfUser(user2)).isEmpty();
236     assertThat(db.users().selectProjectPermissionsOfUser(user2, privateProject)).isEmpty();
237   }
238
239   @Test
240   public void do_nothing_when_adding_global_permission_that_already_exists() {
241     db.users().insertPermissionOnUser(user1, ADMINISTER_QUALITY_GATES);
242
243     UserPermissionChange change = new UserPermissionChange(ADD, QUALITY_GATE_ADMIN, null, UserIdDto.from(user1), permissionService);
244     apply(change);
245
246     assertThat(db.users().selectPermissionsOfUser(user1)).containsOnly(ADMINISTER_QUALITY_GATES);
247   }
248
249   @Test
250   public void fail_to_add_global_permission_on_project() {
251     assertThatThrownBy(() -> {
252       UserPermissionChange change = new UserPermissionChange(ADD, QUALITY_GATE_ADMIN, privateProject, UserIdDto.from(user1), permissionService);
253       apply(change);
254     })
255       .isInstanceOf(BadRequestException.class)
256       .hasMessage("Invalid project permission 'gateadmin'. Valid values are [" + StringUtils.join(permissionService.getAllProjectPermissions(), ", ") + "]");
257   }
258
259   @Test
260   public void fail_to_add_project_permission() {
261     assertThatThrownBy(() -> {
262       UserPermissionChange change = new UserPermissionChange(ADD, ISSUE_ADMIN, null, UserIdDto.from(user1), permissionService);
263       apply(change);
264     })
265       .isInstanceOf(BadRequestException.class)
266       .hasMessage("Invalid global permission 'issueadmin'. Valid values are [admin, gateadmin, profileadmin, provisioning, scan]");
267   }
268
269   @Test
270   public void remove_global_permission_from_user() {
271     db.users().insertPermissionOnUser(user1, QUALITY_GATE_ADMIN);
272     db.users().insertPermissionOnUser(user1, SCAN_EXECUTION);
273     db.users().insertPermissionOnUser(user2, QUALITY_GATE_ADMIN);
274     db.users().insertProjectPermissionOnUser(user1, ISSUE_ADMIN, privateProject);
275
276     UserPermissionChange change = new UserPermissionChange(REMOVE, QUALITY_GATE_ADMIN, null, UserIdDto.from(user1), permissionService);
277     apply(change);
278
279     assertThat(db.users().selectPermissionsOfUser(user1)).containsOnly(SCAN);
280     assertThat(db.users().selectPermissionsOfUser(user2)).containsOnly(ADMINISTER_QUALITY_GATES);
281     assertThat(db.users().selectProjectPermissionsOfUser(user1, privateProject)).containsOnly(ISSUE_ADMIN);
282   }
283
284   @Test
285   public void remove_project_permission_from_user() {
286     ComponentDto project2 = db.components().insertPrivateProject();
287     db.users().insertPermissionOnUser(user1, ADMINISTER_QUALITY_GATES);
288     db.users().insertProjectPermissionOnUser(user1, ISSUE_ADMIN, privateProject);
289     db.users().insertProjectPermissionOnUser(user1, USER, privateProject);
290     db.users().insertProjectPermissionOnUser(user2, ISSUE_ADMIN, privateProject);
291     db.users().insertProjectPermissionOnUser(user1, ISSUE_ADMIN, project2);
292
293     UserPermissionChange change = new UserPermissionChange(REMOVE, ISSUE_ADMIN, privateProject, UserIdDto.from(user1), permissionService);
294     apply(change);
295
296     assertThat(db.users().selectProjectPermissionsOfUser(user1, privateProject)).containsOnly(USER);
297     assertThat(db.users().selectProjectPermissionsOfUser(user2, privateProject)).containsOnly(ISSUE_ADMIN);
298     assertThat(db.users().selectProjectPermissionsOfUser(user1, project2)).containsOnly(ISSUE_ADMIN);
299   }
300
301   @Test
302   public void do_not_fail_if_removing_a_global_permission_that_does_not_exist() {
303     UserPermissionChange change = new UserPermissionChange(REMOVE, QUALITY_GATE_ADMIN, null, UserIdDto.from(user1), permissionService);
304     apply(change);
305
306     assertThat(db.users().selectPermissionsOfUser(user1)).isEmpty();
307   }
308
309   @Test
310   public void do_not_fail_if_removing_a_project_permission_that_does_not_exist() {
311     UserPermissionChange change = new UserPermissionChange(REMOVE, ISSUE_ADMIN, privateProject, UserIdDto.from(user1), permissionService);
312     apply(change);
313
314     assertThat(db.users().selectProjectPermissionsOfUser(user1, privateProject)).isEmpty();
315   }
316
317   @Test
318   public void fail_to_remove_admin_global_permission_if_no_more_admins() {
319     db.users().insertPermissionOnUser(user1, SYSTEM_ADMIN);
320
321     assertThatThrownBy(() -> {
322       UserPermissionChange change = new UserPermissionChange(REMOVE, SYSTEM_ADMIN, null, UserIdDto.from(user1), permissionService);
323       underTest.apply(db.getSession(), change);
324     })
325       .isInstanceOf(BadRequestException.class)
326       .hasMessage("Last user with permission 'admin'. Permission cannot be removed.");
327   }
328
329   @Test
330   public void remove_admin_user_if_still_other_admins() {
331     db.users().insertPermissionOnUser(user1, ADMINISTER);
332     GroupDto admins = db.users().insertGroup("admins");
333     db.users().insertMember(admins, user2);
334     db.users().insertPermissionOnGroup(admins, ADMINISTER);
335
336     UserPermissionChange change = new UserPermissionChange(REMOVE, ADMINISTER.getKey(), null, UserIdDto.from(user1), permissionService);
337     underTest.apply(db.getSession(), change);
338
339     assertThat(db.users().selectPermissionsOfUser(user1)).isEmpty();
340   }
341
342   private void apply(UserPermissionChange change) {
343     underTest.apply(db.getSession(), change);
344     db.commit();
345   }
346 }