You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BulkApplyTemplateActionTest.java 17KB

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