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.

RemoveUserActionTest.java 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2020 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;
  21. import org.junit.Before;
  22. import org.junit.Test;
  23. import org.sonar.api.resources.Qualifiers;
  24. import org.sonar.api.resources.ResourceTypes;
  25. import org.sonar.api.web.UserRole;
  26. import org.sonar.db.component.ComponentDto;
  27. import org.sonar.db.component.ResourceTypesRule;
  28. import org.sonar.db.user.UserDto;
  29. import org.sonar.server.exceptions.BadRequestException;
  30. import org.sonar.server.exceptions.ForbiddenException;
  31. import org.sonar.server.exceptions.NotFoundException;
  32. import org.sonar.server.exceptions.ServerException;
  33. import org.sonar.server.permission.PermissionService;
  34. import org.sonar.server.permission.PermissionServiceImpl;
  35. import static java.lang.String.format;
  36. import static org.assertj.core.api.Assertions.assertThat;
  37. import static org.sonar.api.web.UserRole.ADMIN;
  38. import static org.sonar.api.web.UserRole.CODEVIEWER;
  39. import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
  40. import static org.sonar.api.web.UserRole.USER;
  41. import static org.sonar.core.permission.GlobalPermissions.PROVISIONING;
  42. import static org.sonar.core.permission.GlobalPermissions.QUALITY_GATE_ADMIN;
  43. import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
  44. import static org.sonar.db.component.ComponentTesting.newDirectory;
  45. import static org.sonar.db.component.ComponentTesting.newFileDto;
  46. import static org.sonar.db.component.ComponentTesting.newModuleDto;
  47. import static org.sonar.db.component.ComponentTesting.newSubView;
  48. import static org.sonar.db.permission.OrganizationPermission.ADMINISTER;
  49. import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_GATES;
  50. import static org.sonar.db.permission.OrganizationPermission.PROVISION_PROJECTS;
  51. import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PERMISSION;
  52. import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_ID;
  53. import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_KEY;
  54. import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_USER_LOGIN;
  55. public class RemoveUserActionTest extends BasePermissionWsTest<RemoveUserAction> {
  56. private static final String A_PROJECT_UUID = "project-uuid";
  57. private static final String A_PROJECT_KEY = "project-key";
  58. private static final String A_LOGIN = "ray.bradbury";
  59. private UserDto user;
  60. private ResourceTypes resourceTypes = new ResourceTypesRule().setRootQualifiers(Qualifiers.PROJECT);
  61. private PermissionService permissionService = new PermissionServiceImpl(resourceTypes);
  62. private WsParameters wsParameters = new WsParameters(permissionService);
  63. @Before
  64. public void setUp() {
  65. user = db.users().insertUser(A_LOGIN);
  66. }
  67. @Override
  68. protected RemoveUserAction buildWsAction() {
  69. return new RemoveUserAction(db.getDbClient(), userSession, newPermissionUpdater(), newPermissionWsSupport(), wsParameters, permissionService);
  70. }
  71. @Test
  72. public void remove_permission_from_user() {
  73. db.users().insertPermissionOnUser(user, PROVISION_PROJECTS);
  74. db.users().insertPermissionOnUser(user, ADMINISTER_QUALITY_GATES);
  75. loginAsAdmin();
  76. newRequest()
  77. .setParam(PARAM_USER_LOGIN, user.getLogin())
  78. .setParam(PARAM_PERMISSION, QUALITY_GATE_ADMIN)
  79. .execute();
  80. assertThat(db.users().selectPermissionsOfUser(user)).containsOnly(PROVISION_PROJECTS);
  81. }
  82. @Test
  83. public void fail_to_remove_admin_permission_if_last_admin() {
  84. db.users().insertPermissionOnUser(user, ADMINISTER);
  85. loginAsAdmin();
  86. expectedException.expect(BadRequestException.class);
  87. expectedException.expectMessage("Last user with permission 'admin'. Permission cannot be removed.");
  88. newRequest()
  89. .setParam(PARAM_USER_LOGIN, user.getLogin())
  90. .setParam(PARAM_PERMISSION, ADMIN)
  91. .execute();
  92. }
  93. @Test
  94. public void remove_permission_from_project() {
  95. ComponentDto project = db.components().insertPrivateProject();
  96. db.users().insertProjectPermissionOnUser(user, CODEVIEWER, project);
  97. db.users().insertProjectPermissionOnUser(user, ISSUE_ADMIN, project);
  98. loginAsAdmin();
  99. newRequest()
  100. .setParam(PARAM_USER_LOGIN, user.getLogin())
  101. .setParam(PARAM_PROJECT_ID, project.uuid())
  102. .setParam(PARAM_PERMISSION, CODEVIEWER)
  103. .execute();
  104. assertThat(db.users().selectProjectPermissionsOfUser(user, project)).containsOnly(ISSUE_ADMIN);
  105. }
  106. @Test
  107. public void remove_with_project_key() {
  108. ComponentDto project = db.components().insertPrivateProject();
  109. db.users().insertProjectPermissionOnUser(user, ISSUE_ADMIN, project);
  110. db.users().insertProjectPermissionOnUser(user, CODEVIEWER, project);
  111. loginAsAdmin();
  112. newRequest()
  113. .setParam(PARAM_USER_LOGIN, user.getLogin())
  114. .setParam(PARAM_PROJECT_KEY, project.getDbKey())
  115. .setParam(PARAM_PERMISSION, ISSUE_ADMIN)
  116. .execute();
  117. assertThat(db.users().selectProjectPermissionsOfUser(user, project)).containsOnly(CODEVIEWER);
  118. }
  119. @Test
  120. public void remove_with_view_uuid() {
  121. ComponentDto view = db.components().insertView();
  122. db.users().insertProjectPermissionOnUser(user, ISSUE_ADMIN, view);
  123. db.users().insertProjectPermissionOnUser(user, ADMIN, view);
  124. loginAsAdmin();
  125. newRequest()
  126. .setParam(PARAM_USER_LOGIN, user.getLogin())
  127. .setParam(PARAM_PROJECT_KEY, view.getDbKey())
  128. .setParam(PARAM_PERMISSION, ISSUE_ADMIN)
  129. .execute();
  130. assertThat(db.users().selectProjectPermissionsOfUser(user, view)).containsOnly(ADMIN);
  131. }
  132. @Test
  133. public void fail_when_project_does_not_exist() {
  134. loginAsAdmin();
  135. expectedException.expect(NotFoundException.class);
  136. newRequest()
  137. .setParam(PARAM_USER_LOGIN, user.getLogin())
  138. .setParam(PARAM_PROJECT_ID, "unknown-project-uuid")
  139. .setParam(PARAM_PERMISSION, ISSUE_ADMIN)
  140. .execute();
  141. }
  142. @Test
  143. public void fail_when_project_permission_without_permission() {
  144. loginAsAdmin();
  145. expectedException.expect(BadRequestException.class);
  146. newRequest()
  147. .setParam(PARAM_USER_LOGIN, user.getLogin())
  148. .setParam(PARAM_PERMISSION, ISSUE_ADMIN)
  149. .execute();
  150. }
  151. @Test
  152. public void fail_when_component_is_a_module() {
  153. ComponentDto project = db.components().insertPrivateProject();
  154. ComponentDto module = db.components().insertComponent(newModuleDto(project));
  155. failIfComponentIsNotAProjectOrView(module);
  156. }
  157. @Test
  158. public void fail_when_component_is_a_directory() {
  159. ComponentDto project = db.components().insertPrivateProject();
  160. ComponentDto file = db.components().insertComponent(newDirectory(project, "A/B"));
  161. failIfComponentIsNotAProjectOrView(file);
  162. }
  163. @Test
  164. public void fail_when_component_is_a_file() {
  165. ComponentDto project = db.components().insertPrivateProject();
  166. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "file-uuid"));
  167. failIfComponentIsNotAProjectOrView(file);
  168. }
  169. @Test
  170. public void fail_when_component_is_a_subview() {
  171. ComponentDto portfolio = db.components().insertPrivatePortfolio();
  172. ComponentDto file = db.components().insertComponent(newSubView(portfolio));
  173. failIfComponentIsNotAProjectOrView(file);
  174. }
  175. private void failIfComponentIsNotAProjectOrView(ComponentDto file) {
  176. loginAsAdmin();
  177. expectedException.expect(BadRequestException.class);
  178. expectedException.expectMessage("Component '" + file.getDbKey() + "' (id: " + file.uuid() + ") must be a project or a view.");
  179. newRequest()
  180. .setParam(PARAM_USER_LOGIN, user.getLogin())
  181. .setParam(PARAM_PROJECT_ID, file.uuid())
  182. .setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
  183. .execute();
  184. }
  185. @Test
  186. public void fail_when_get_request() {
  187. loginAsAdmin();
  188. expectedException.expect(ServerException.class);
  189. newRequest()
  190. .setMethod("GET")
  191. .setParam(PARAM_USER_LOGIN, "george.orwell")
  192. .setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
  193. .execute();
  194. }
  195. @Test
  196. public void fail_when_user_login_is_missing() {
  197. loginAsAdmin();
  198. expectedException.expect(IllegalArgumentException.class);
  199. newRequest()
  200. .setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
  201. .execute();
  202. }
  203. @Test
  204. public void fail_when_permission_is_missing() {
  205. loginAsAdmin();
  206. expectedException.expect(IllegalArgumentException.class);
  207. newRequest()
  208. .setParam(PARAM_USER_LOGIN, user.getLogin())
  209. .execute();
  210. }
  211. @Test
  212. public void fail_when_project_uuid_and_project_key_are_provided() {
  213. ComponentDto project = db.components().insertPrivateProject();
  214. loginAsAdmin();
  215. expectedException.expect(BadRequestException.class);
  216. expectedException.expectMessage("Project id or project key can be provided, not both.");
  217. newRequest()
  218. .setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
  219. .setParam(PARAM_USER_LOGIN, user.getLogin())
  220. .setParam(PARAM_PROJECT_ID, project.uuid())
  221. .setParam(PARAM_PROJECT_KEY, project.getDbKey())
  222. .execute();
  223. }
  224. @Test
  225. public void removing_global_permission_fails_if_not_system_administrator() {
  226. userSession.logIn();
  227. expectedException.expect(ForbiddenException.class);
  228. newRequest()
  229. .setParam(PARAM_USER_LOGIN, user.getLogin())
  230. .setParam(PARAM_PERMISSION, PROVISIONING)
  231. .execute();
  232. }
  233. @Test
  234. public void removing_project_permission_fails_if_not_administrator_of_project() {
  235. ComponentDto project = db.components().insertPrivateProject();
  236. userSession.logIn();
  237. expectedException.expect(ForbiddenException.class);
  238. newRequest()
  239. .setParam(PARAM_USER_LOGIN, user.getLogin())
  240. .setParam(PARAM_PERMISSION, ISSUE_ADMIN)
  241. .setParam(PARAM_PROJECT_KEY, project.getDbKey())
  242. .execute();
  243. }
  244. /**
  245. * User is project administrator but not system administrator
  246. */
  247. @Test
  248. public void removing_project_permission_is_allowed_to_project_administrators() {
  249. ComponentDto project = db.components().insertPrivateProject();
  250. db.users().insertProjectPermissionOnUser(user, CODEVIEWER, project);
  251. db.users().insertProjectPermissionOnUser(user, ISSUE_ADMIN, project);
  252. userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
  253. newRequest()
  254. .setParam(PARAM_USER_LOGIN, user.getLogin())
  255. .setParam(PARAM_PROJECT_ID, project.uuid())
  256. .setParam(PARAM_PERMISSION, ISSUE_ADMIN)
  257. .execute();
  258. assertThat(db.users().selectProjectPermissionsOfUser(user, project)).containsOnly(CODEVIEWER);
  259. }
  260. @Test
  261. public void fail_when_removing_USER_permission_on_a_public_project() {
  262. ComponentDto project = db.components().insertPublicProject();
  263. userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
  264. expectedException.expect(BadRequestException.class);
  265. expectedException.expectMessage("Permission user can't be removed from a public component");
  266. newRequest()
  267. .setParam(PARAM_USER_LOGIN, user.getLogin())
  268. .setParam(PARAM_PROJECT_ID, project.uuid())
  269. .setParam(PARAM_PERMISSION, USER)
  270. .execute();
  271. }
  272. @Test
  273. public void fail_when_removing_CODEVIEWER_permission_on_a_public_project() {
  274. ComponentDto project = db.components().insertPublicProject();
  275. userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
  276. expectedException.expect(BadRequestException.class);
  277. expectedException.expectMessage("Permission codeviewer can't be removed from a public component");
  278. newRequest()
  279. .setParam(PARAM_USER_LOGIN, user.getLogin())
  280. .setParam(PARAM_PROJECT_ID, project.uuid())
  281. .setParam(PARAM_PERMISSION, CODEVIEWER)
  282. .execute();
  283. }
  284. @Test
  285. public void fail_when_using_branch_db_key() {
  286. ComponentDto project = db.components().insertPublicProject();
  287. userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
  288. ComponentDto branch = db.components().insertProjectBranch(project);
  289. expectedException.expect(NotFoundException.class);
  290. expectedException.expectMessage(format("Project key '%s' not found", branch.getDbKey()));
  291. newRequest()
  292. .setParam(PARAM_PROJECT_KEY, branch.getDbKey())
  293. .setParam(PARAM_USER_LOGIN, user.getLogin())
  294. .setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
  295. .execute();
  296. }
  297. @Test
  298. public void fail_when_using_branch_uuid() {
  299. ComponentDto project = db.components().insertPublicProject();
  300. userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
  301. ComponentDto branch = db.components().insertProjectBranch(project);
  302. expectedException.expect(NotFoundException.class);
  303. expectedException.expectMessage(format("Project id '%s' not found", branch.uuid()));
  304. newRequest()
  305. .setParam(PARAM_PROJECT_ID, branch.uuid())
  306. .setParam(PARAM_USER_LOGIN, user.getLogin())
  307. .setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
  308. .execute();
  309. }
  310. }