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