]> source.dussan.org Git - sonarqube.git/blob
edb7f92ed1c953abdc440cd8476eb4f1438e4ad3
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2019 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.ws.template;
21
22 import java.util.Collections;
23 import java.util.List;
24 import org.apache.commons.lang.StringUtils;
25 import org.junit.Before;
26 import org.junit.Test;
27 import org.sonar.api.resources.Qualifiers;
28 import org.sonar.api.server.ws.WebService.Param;
29 import org.sonar.api.web.UserRole;
30 import org.sonar.db.component.ComponentDto;
31 import org.sonar.db.component.ComponentTesting;
32 import org.sonar.db.organization.OrganizationDto;
33 import org.sonar.db.permission.PermissionQuery;
34 import org.sonar.db.permission.template.PermissionTemplateDto;
35 import org.sonar.db.user.GroupDto;
36 import org.sonar.db.user.UserDto;
37 import org.sonar.server.es.ProjectIndexers;
38 import org.sonar.server.es.TestProjectIndexers;
39 import org.sonar.server.exceptions.BadRequestException;
40 import org.sonar.server.exceptions.NotFoundException;
41 import org.sonar.server.l18n.I18nRule;
42 import org.sonar.server.permission.DefaultTemplatesResolverRule;
43 import org.sonar.server.permission.PermissionTemplateService;
44 import org.sonar.server.permission.ws.BasePermissionWsTest;
45
46 import static org.assertj.core.api.Assertions.assertThat;
47 import static org.sonar.api.utils.DateUtils.parseDate;
48 import static org.sonar.db.component.ComponentTesting.newApplication;
49 import static org.sonar.db.component.ComponentTesting.newView;
50 import static org.sonar.db.component.SnapshotTesting.newAnalysis;
51 import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_ORGANIZATION;
52 import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_ID;
53 import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_NAME;
54 import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_ANALYZED_BEFORE;
55 import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_ON_PROVISIONED_ONLY;
56 import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_PROJECTS;
57 import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_QUALIFIERS;
58 import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_VISIBILITY;
59
60 public class BulkApplyTemplateActionTest extends BasePermissionWsTest<BulkApplyTemplateAction> {
61
62   @org.junit.Rule
63   public DefaultTemplatesResolverRule defaultTemplatesResolver = DefaultTemplatesResolverRule.withoutGovernance();
64
65   private UserDto user1;
66   private UserDto user2;
67   private GroupDto group1;
68   private GroupDto group2;
69   private OrganizationDto organization;
70   private PermissionTemplateDto template1;
71   private PermissionTemplateDto template2;
72   private ProjectIndexers projectIndexers = new TestProjectIndexers();
73
74   @Override
75   protected BulkApplyTemplateAction buildWsAction() {
76     PermissionTemplateService permissionTemplateService = new PermissionTemplateService(db.getDbClient(),
77       projectIndexers, userSession, defaultTemplatesResolver);
78     return new BulkApplyTemplateAction(db.getDbClient(), userSession, permissionTemplateService, newPermissionWsSupport(), new I18nRule(), newRootResourceTypes());
79   }
80
81   @Before
82   public void setUp() {
83     organization = db.organizations().insert();
84
85     user1 = db.users().insertUser();
86     user2 = db.users().insertUser();
87     group1 = db.users().insertGroup(organization);
88     group2 = db.users().insertGroup(organization);
89
90     db.organizations().addMember(organization, user1);
91     db.organizations().addMember(organization, user2);
92
93     // template 1 for org 1
94     template1 = db.permissionTemplates().insertTemplate(organization);
95     addUserToTemplate(user1, template1, UserRole.CODEVIEWER);
96     addUserToTemplate(user2, template1, UserRole.ISSUE_ADMIN);
97     addGroupToTemplate(group1, template1, UserRole.ADMIN);
98     addGroupToTemplate(group2, template1, UserRole.USER);
99     // template 2
100     template2 = db.permissionTemplates().insertTemplate(organization);
101     addUserToTemplate(user1, template2, UserRole.USER);
102     addUserToTemplate(user2, template2, UserRole.USER);
103     addGroupToTemplate(group1, template2, UserRole.USER);
104     addGroupToTemplate(group2, template2, UserRole.USER);
105   }
106
107   @Test
108   public void bulk_apply_template_by_template_uuid() {
109     // this project should not be applied the template
110     OrganizationDto otherOrganization = db.organizations().insert();
111     db.components().insertPrivateProject(otherOrganization);
112
113     ComponentDto privateProject = db.components().insertPrivateProject(organization);
114     ComponentDto publicProject = db.components().insertPublicProject(organization);
115     loginAsAdmin(organization);
116
117     newRequest()
118       .setParam(PARAM_TEMPLATE_ID, template1.getUuid())
119       .execute();
120
121     assertTemplate1AppliedToPrivateProject(privateProject);
122     assertTemplate1AppliedToPublicProject(publicProject);
123   }
124
125   @Test
126   public void request_throws_NotFoundException_if_template_with_specified_name_does_not_exist_in_specified_organization() {
127     OrganizationDto otherOrganization = db.organizations().insert();
128     loginAsAdmin(otherOrganization);
129
130     expectedException.expect(NotFoundException.class);
131     expectedException.expectMessage("Permission template with name '" + template1.getName()
132       + "' is not found (case insensitive) in organization with key '" + otherOrganization.getKey() + "'");
133
134     newRequest()
135       .setParam(PARAM_ORGANIZATION, otherOrganization.getKey())
136       .setParam(PARAM_TEMPLATE_NAME, template1.getName())
137       .execute();
138   }
139
140   @Test
141   public void request_throws_IAE_if_more_than_1000_projects() {
142     expectedException.expect(IllegalArgumentException.class);
143     expectedException.expectMessage("'projects' can contains only 1000 values, got 1001");
144
145     newRequest()
146       .setParam(PARAM_ORGANIZATION, organization.getKey())
147       .setParam(PARAM_TEMPLATE_NAME, template1.getName())
148       .setParam(PARAM_PROJECTS, StringUtils.join(Collections.nCopies(1_001, "foo"), ","))
149       .execute();
150   }
151
152   @Test
153   public void bulk_apply_template_by_template_name() {
154     ComponentDto privateProject = db.components().insertPrivateProject(organization);
155     ComponentDto publicProject = db.components().insertPublicProject(organization);
156     loginAsAdmin(organization);
157
158     newRequest()
159       .setParam(PARAM_ORGANIZATION, organization.getKey())
160       .setParam(PARAM_TEMPLATE_NAME, template1.getName())
161       .execute();
162
163     assertTemplate1AppliedToPrivateProject(privateProject);
164     assertTemplate1AppliedToPublicProject(publicProject);
165   }
166
167   @Test
168   public void apply_template_by_qualifiers() {
169     ComponentDto publicProject = db.components().insertPublicProject(organization);
170     ComponentDto privateProject = db.components().insertPrivateProject(organization);
171     ComponentDto view = db.components().insertComponent(newView(organization));
172     ComponentDto application = db.components().insertComponent(newApplication(organization));
173     loginAsAdmin(organization);
174
175     newRequest()
176       .setParam(PARAM_TEMPLATE_ID, template1.getUuid())
177       .setParam(PARAM_QUALIFIERS, String.join(",", Qualifiers.PROJECT, Qualifiers.APP))
178       .execute();
179
180     assertTemplate1AppliedToPrivateProject(privateProject);
181     assertTemplate1AppliedToPublicProject(publicProject);
182     assertTemplate1AppliedToPublicProject(application);
183     assertNoPermissionOnProject(view);
184   }
185
186   @Test
187   public void apply_template_by_query_on_name_and_key_public_project() {
188     ComponentDto publicProjectFoundByKey = ComponentTesting.newPublicProjectDto(organization).setDbKey("sonar");
189     db.components().insertProjectAndSnapshot(publicProjectFoundByKey);
190     ComponentDto publicProjectFoundByName = ComponentTesting.newPublicProjectDto(organization).setName("name-sonar-name");
191     db.components().insertProjectAndSnapshot(publicProjectFoundByName);
192     ComponentDto projectUntouched = ComponentTesting.newPublicProjectDto(organization).setDbKey("new-sona").setName("project-name");
193     db.components().insertProjectAndSnapshot(projectUntouched);
194     loginAsAdmin(organization);
195
196     newRequest()
197       .setParam(PARAM_TEMPLATE_ID, template1.getUuid())
198       .setParam(Param.TEXT_QUERY, "SONAR")
199       .execute();
200
201     assertTemplate1AppliedToPublicProject(publicProjectFoundByKey);
202     assertTemplate1AppliedToPublicProject(publicProjectFoundByName);
203     assertNoPermissionOnProject(projectUntouched);
204   }
205
206   @Test
207   public void apply_template_by_query_on_name_and_key() {
208     // partial match on key
209     ComponentDto privateProjectFoundByKey = ComponentTesting.newPrivateProjectDto(organization).setDbKey("sonarqube");
210     db.components().insertProjectAndSnapshot(privateProjectFoundByKey);
211     ComponentDto privateProjectFoundByName = ComponentTesting.newPrivateProjectDto(organization).setName("name-sonar-name");
212     db.components().insertProjectAndSnapshot(privateProjectFoundByName);
213     ComponentDto projectUntouched = ComponentTesting.newPublicProjectDto(organization).setDbKey("new-sona").setName("project-name");
214     db.components().insertProjectAndSnapshot(projectUntouched);
215     loginAsAdmin(organization);
216
217     newRequest()
218       .setParam(PARAM_TEMPLATE_ID, template1.getUuid())
219       .setParam(Param.TEXT_QUERY, "SONAR")
220       .execute();
221
222     assertTemplate1AppliedToPrivateProject(privateProjectFoundByKey);
223     assertTemplate1AppliedToPrivateProject(privateProjectFoundByName);
224     assertNoPermissionOnProject(projectUntouched);
225   }
226
227   @Test
228   public void apply_template_by_project_keys() {
229     ComponentDto project1 = db.components().insertPrivateProject(organization);
230     ComponentDto project2 = db.components().insertPrivateProject(organization);
231     ComponentDto untouchedProject = db.components().insertPrivateProject(organization);
232     loginAsAdmin(organization);
233
234     newRequest()
235       .setParam(PARAM_TEMPLATE_ID, template1.getUuid())
236       .setParam(PARAM_PROJECTS, String.join(",", project1.getKey(), project2.getKey()))
237       .execute();
238
239     assertTemplate1AppliedToPrivateProject(project1);
240     assertTemplate1AppliedToPrivateProject(project2);
241     assertNoPermissionOnProject(untouchedProject);
242   }
243
244   @Test
245   public void apply_template_by_provisioned_only() {
246     ComponentDto provisionedProject1 = db.components().insertPrivateProject(organization);
247     ComponentDto provisionedProject2 = db.components().insertPrivateProject(organization);
248     ComponentDto analyzedProject = db.components().insertPrivateProject(organization);
249     db.components().insertSnapshot(newAnalysis(analyzedProject));
250     loginAsAdmin(organization);
251
252     newRequest()
253       .setParam(PARAM_TEMPLATE_ID, template1.getUuid())
254       .setParam(PARAM_ON_PROVISIONED_ONLY, "true")
255       .execute();
256
257     assertTemplate1AppliedToPrivateProject(provisionedProject1);
258     assertTemplate1AppliedToPrivateProject(provisionedProject2);
259     assertNoPermissionOnProject(analyzedProject);
260   }
261
262   @Test
263   public void apply_template_by_analyzed_before() {
264     ComponentDto oldProject1 = db.components().insertPrivateProject(organization);
265     ComponentDto oldProject2 = db.components().insertPrivateProject(organization);
266     ComponentDto recentProject = db.components().insertPrivateProject(organization);
267     db.components().insertSnapshot(oldProject1, a -> a.setCreatedAt(parseDate("2015-02-03").getTime()));
268     db.components().insertSnapshot(oldProject2, a -> a.setCreatedAt(parseDate("2016-12-11").getTime()));
269     db.components().insertSnapshot(recentProject, a -> a.setCreatedAt(System.currentTimeMillis()));
270     loginAsAdmin(organization);
271
272     newRequest()
273       .setParam(PARAM_TEMPLATE_ID, template1.getUuid())
274       .setParam(PARAM_ANALYZED_BEFORE, "2017-09-07")
275       .execute();
276
277     assertTemplate1AppliedToPrivateProject(oldProject1);
278     assertTemplate1AppliedToPrivateProject(oldProject2);
279     assertNoPermissionOnProject(recentProject);
280   }
281
282   @Test
283   public void apply_template_by_visibility() {
284     ComponentDto privateProject1 = db.components().insertPrivateProject(organization);
285     ComponentDto privateProject2 = db.components().insertPrivateProject(organization);
286     ComponentDto publicProject = db.components().insertPublicProject(organization);
287     loginAsAdmin(organization);
288
289     newRequest()
290       .setParam(PARAM_TEMPLATE_ID, template1.getUuid())
291       .setParam(PARAM_VISIBILITY, "private")
292       .execute();
293
294     assertTemplate1AppliedToPrivateProject(privateProject1);
295     assertTemplate1AppliedToPrivateProject(privateProject2);
296     assertNoPermissionOnProject(publicProject);
297   }
298
299   @Test
300   public void fail_if_no_template_parameter() {
301     loginAsAdmin(db.getDefaultOrganization());
302
303     expectedException.expect(BadRequestException.class);
304     expectedException.expectMessage("Template name or template id must be provided, not both.");
305
306     newRequest().execute();
307   }
308
309   @Test
310   public void fail_if_template_name_is_incorrect() {
311     loginAsAdmin(db.getDefaultOrganization());
312
313     expectedException.expect(NotFoundException.class);
314     expectedException.expectMessage("Permission template with id 'unknown-template-uuid' is not found");
315
316     newRequest().setParam(PARAM_TEMPLATE_ID, "unknown-template-uuid").execute();
317   }
318
319   private void assertTemplate1AppliedToPublicProject(ComponentDto project) {
320     assertThat(selectProjectPermissionGroups(project, UserRole.ADMIN)).containsExactly(group1.getName());
321     assertThat(selectProjectPermissionGroups(project, UserRole.USER)).isEmpty();
322     assertThat(selectProjectPermissionUsers(project, UserRole.ADMIN)).isEmpty();
323     assertThat(selectProjectPermissionUsers(project, UserRole.CODEVIEWER)).isEmpty();
324     assertThat(selectProjectPermissionUsers(project, UserRole.ISSUE_ADMIN)).containsExactly(user2.getId());
325   }
326
327   private void assertTemplate1AppliedToPrivateProject(ComponentDto project) {
328     assertThat(selectProjectPermissionGroups(project, UserRole.ADMIN)).containsExactly(group1.getName());
329     assertThat(selectProjectPermissionGroups(project, UserRole.USER)).containsExactly(group2.getName());
330     assertThat(selectProjectPermissionUsers(project, UserRole.ADMIN)).isEmpty();
331     assertThat(selectProjectPermissionUsers(project, UserRole.CODEVIEWER)).containsExactly(user1.getId());
332     assertThat(selectProjectPermissionUsers(project, UserRole.ISSUE_ADMIN)).containsExactly(user2.getId());
333   }
334
335   private void assertNoPermissionOnProject(ComponentDto project) {
336     assertThat(selectProjectPermissionGroups(project, UserRole.ADMIN)).isEmpty();
337     assertThat(selectProjectPermissionGroups(project, UserRole.CODEVIEWER)).isEmpty();
338     assertThat(selectProjectPermissionGroups(project, UserRole.ISSUE_ADMIN)).isEmpty();
339     assertThat(selectProjectPermissionGroups(project, UserRole.USER)).isEmpty();
340     assertThat(selectProjectPermissionUsers(project, UserRole.ADMIN)).isEmpty();
341     assertThat(selectProjectPermissionUsers(project, UserRole.CODEVIEWER)).isEmpty();
342     assertThat(selectProjectPermissionUsers(project, UserRole.ISSUE_ADMIN)).isEmpty();
343     assertThat(selectProjectPermissionUsers(project, UserRole.USER)).isEmpty();
344   }
345
346   private void addUserToTemplate(UserDto user, PermissionTemplateDto permissionTemplate, String permission) {
347     db.getDbClient().permissionTemplateDao().insertUserPermission(db.getSession(), permissionTemplate.getId(), user.getId(), permission);
348     db.commit();
349   }
350
351   private void addGroupToTemplate(GroupDto group, PermissionTemplateDto permissionTemplate, String permission) {
352     db.getDbClient().permissionTemplateDao().insertGroupPermission(db.getSession(), permissionTemplate.getId(), group.getId(), permission);
353     db.commit();
354   }
355
356   private List<String> selectProjectPermissionGroups(ComponentDto project, String permission) {
357     PermissionQuery query = PermissionQuery.builder().setOrganizationUuid(project.getOrganizationUuid()).setPermission(permission).setComponentUuid(project.uuid()).build();
358     return db.getDbClient().groupPermissionDao().selectGroupNamesByQuery(db.getSession(), query);
359   }
360
361   private List<Integer> selectProjectPermissionUsers(ComponentDto project, String permission) {
362     PermissionQuery query = PermissionQuery.builder().setOrganizationUuid(project.getOrganizationUuid()).setPermission(permission).setComponentUuid(project.uuid()).build();
363     return db.getDbClient().userPermissionDao().selectUserIdsByQuery(db.getSession(), query);
364   }
365 }