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.

DeactivateActionTest.java 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  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.user.ws;
  21. import java.util.Optional;
  22. import javax.annotation.Nullable;
  23. import org.junit.Rule;
  24. import org.junit.Test;
  25. import org.junit.rules.ExpectedException;
  26. import org.sonar.api.utils.System2;
  27. import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
  28. import org.sonar.db.DbClient;
  29. import org.sonar.db.DbSession;
  30. import org.sonar.db.DbTester;
  31. import org.sonar.db.component.ComponentDto;
  32. import org.sonar.db.organization.OrganizationDto;
  33. import org.sonar.db.permission.template.PermissionTemplateDto;
  34. import org.sonar.db.permission.template.PermissionTemplateUserDto;
  35. import org.sonar.db.property.PropertyDto;
  36. import org.sonar.db.property.PropertyQuery;
  37. import org.sonar.db.qualityprofile.QProfileDto;
  38. import org.sonar.db.user.GroupDto;
  39. import org.sonar.db.user.UserDto;
  40. import org.sonar.server.es.EsTester;
  41. import org.sonar.server.exceptions.BadRequestException;
  42. import org.sonar.server.exceptions.ForbiddenException;
  43. import org.sonar.server.exceptions.NotFoundException;
  44. import org.sonar.server.exceptions.UnauthorizedException;
  45. import org.sonar.server.organization.DefaultOrganizationProvider;
  46. import org.sonar.server.organization.TestDefaultOrganizationProvider;
  47. import org.sonar.server.tester.UserSessionRule;
  48. import org.sonar.server.user.index.UserIndexDefinition;
  49. import org.sonar.server.user.index.UserIndexer;
  50. import org.sonar.server.ws.TestRequest;
  51. import org.sonar.server.ws.TestResponse;
  52. import org.sonar.server.ws.WsActionTester;
  53. import static java.util.Collections.singletonList;
  54. import static org.assertj.core.api.Assertions.assertThat;
  55. import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
  56. import static org.elasticsearch.index.query.QueryBuilders.termQuery;
  57. import static org.sonar.api.web.UserRole.CODEVIEWER;
  58. import static org.sonar.api.web.UserRole.USER;
  59. import static org.sonar.db.organization.OrganizationTesting.newOrganizationDto;
  60. import static org.sonar.db.permission.OrganizationPermission.ADMINISTER;
  61. import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES;
  62. import static org.sonar.db.permission.OrganizationPermission.SCAN;
  63. import static org.sonar.db.property.PropertyTesting.newUserPropertyDto;
  64. import static org.sonar.server.user.index.UserIndexDefinition.FIELD_ACTIVE;
  65. import static org.sonar.server.user.index.UserIndexDefinition.FIELD_UUID;
  66. import static org.sonar.test.JsonAssert.assertJson;
  67. public class DeactivateActionTest {
  68. private System2 system2 = AlwaysIncreasingSystem2.INSTANCE;
  69. @Rule
  70. public ExpectedException expectedException = ExpectedException.none();
  71. @Rule
  72. public DbTester db = DbTester.create(system2);
  73. @Rule
  74. public EsTester es = EsTester.create();
  75. @Rule
  76. public UserSessionRule userSession = UserSessionRule.standalone();
  77. private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
  78. private DbClient dbClient = db.getDbClient();
  79. private UserIndexer userIndexer = new UserIndexer(dbClient, es.client());
  80. private DbSession dbSession = db.getSession();
  81. private WsActionTester ws = new WsActionTester(new DeactivateAction(
  82. dbClient, userIndexer, userSession, new UserJsonWriter(userSession), defaultOrganizationProvider));
  83. @Test
  84. public void deactivate_user_and_delete_his_related_data() {
  85. UserDto user = db.users().insertUser(u -> u
  86. .setLogin("ada.lovelace")
  87. .setEmail("ada.lovelace@noteg.com")
  88. .setName("Ada Lovelace")
  89. .setScmAccounts(singletonList("al")));
  90. logInAsSystemAdministrator();
  91. deactivate(user.getLogin());
  92. verifyThatUserIsDeactivated(user.getLogin());
  93. assertThat(es.client().prepareSearch(UserIndexDefinition.INDEX_TYPE_USER)
  94. .setQuery(boolQuery()
  95. .must(termQuery(FIELD_UUID, user.getUuid()))
  96. .must(termQuery(FIELD_ACTIVE, "false")))
  97. .get().getHits().getHits()).hasSize(1);
  98. }
  99. @Test
  100. public void deactivate_user_deletes_his_group_membership() {
  101. logInAsSystemAdministrator();
  102. UserDto user = db.users().insertUser();
  103. GroupDto group1 = db.users().insertGroup();
  104. db.users().insertGroup();
  105. db.users().insertMember(group1, user);
  106. deactivate(user.getLogin());
  107. assertThat(db.getDbClient().groupMembershipDao().selectGroupIdsByUserId(dbSession, user.getId())).isEmpty();
  108. }
  109. @Test
  110. public void deactivate_user_deletes_his_tokens() {
  111. logInAsSystemAdministrator();
  112. UserDto user = db.users().insertUser();
  113. db.users().insertToken(user);
  114. db.users().insertToken(user);
  115. db.commit();
  116. deactivate(user.getLogin());
  117. assertThat(db.getDbClient().userTokenDao().selectByUser(dbSession, user)).isEmpty();
  118. }
  119. @Test
  120. public void deactivate_user_deletes_his_properties() {
  121. logInAsSystemAdministrator();
  122. UserDto user = db.users().insertUser();
  123. ComponentDto project = db.components().insertPrivateProject();
  124. db.properties().insertProperty(newUserPropertyDto(user));
  125. db.properties().insertProperty(newUserPropertyDto(user));
  126. db.properties().insertProperty(newUserPropertyDto(user).setResourceId(project.getId()));
  127. deactivate(user.getLogin());
  128. assertThat(db.getDbClient().propertiesDao().selectByQuery(PropertyQuery.builder().setUserId(user.getId()).build(), dbSession)).isEmpty();
  129. assertThat(db.getDbClient().propertiesDao().selectByQuery(PropertyQuery.builder().setUserId(user.getId()).setComponentId(project.getId()).build(), dbSession)).isEmpty();
  130. }
  131. @Test
  132. public void deactivate_user_deletes_his_permissions() {
  133. logInAsSystemAdministrator();
  134. UserDto user = db.users().insertUser();
  135. ComponentDto project = db.components().insertPrivateProject();
  136. db.users().insertPermissionOnUser(user, SCAN);
  137. db.users().insertPermissionOnUser(user, ADMINISTER_QUALITY_PROFILES);
  138. db.users().insertProjectPermissionOnUser(user, USER, project);
  139. db.users().insertProjectPermissionOnUser(user, CODEVIEWER, project);
  140. deactivate(user.getLogin());
  141. assertThat(db.getDbClient().userPermissionDao().selectGlobalPermissionsOfUser(dbSession, user.getId(), db.getDefaultOrganization().getUuid())).isEmpty();
  142. assertThat(db.getDbClient().userPermissionDao().selectProjectPermissionsOfUser(dbSession, user.getId(), project.getId())).isEmpty();
  143. }
  144. @Test
  145. public void deactivate_user_deletes_his_permission_templates() {
  146. logInAsSystemAdministrator();
  147. UserDto user = db.users().insertUser();
  148. PermissionTemplateDto template = db.permissionTemplates().insertTemplate();
  149. PermissionTemplateDto anotherTemplate = db.permissionTemplates().insertTemplate();
  150. db.permissionTemplates().addUserToTemplate(template.getId(), user.getId(), USER);
  151. db.permissionTemplates().addUserToTemplate(anotherTemplate.getId(), user.getId(), CODEVIEWER);
  152. deactivate(user.getLogin());
  153. assertThat(db.getDbClient().permissionTemplateDao().selectUserPermissionsByTemplateId(dbSession, template.getId())).extracting(PermissionTemplateUserDto::getUserId).isEmpty();
  154. assertThat(db.getDbClient().permissionTemplateDao().selectUserPermissionsByTemplateId(dbSession, anotherTemplate.getId())).extracting(PermissionTemplateUserDto::getUserId)
  155. .isEmpty();
  156. }
  157. @Test
  158. public void deactivate_user_deletes_his_qprofiles_permissions() {
  159. logInAsSystemAdministrator();
  160. UserDto user = db.users().insertUser();
  161. QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization());
  162. db.qualityProfiles().addUserPermission(profile, user);
  163. deactivate(user.getLogin());
  164. assertThat(db.getDbClient().qProfileEditUsersDao().exists(dbSession, profile, user)).isFalse();
  165. }
  166. @Test
  167. public void deactivate_user_deletes_his_default_assignee_settings() {
  168. logInAsSystemAdministrator();
  169. UserDto user = db.users().insertUser();
  170. ComponentDto project = db.components().insertPrivateProject();
  171. ComponentDto anotherProject = db.components().insertPrivateProject();
  172. db.properties().insertProperty(new PropertyDto().setKey("sonar.issues.defaultAssigneeLogin").setValue(user.getLogin()).setResourceId(project.getId()));
  173. db.properties().insertProperty(new PropertyDto().setKey("sonar.issues.defaultAssigneeLogin").setValue(user.getLogin()).setResourceId(anotherProject.getId()));
  174. db.properties().insertProperty(new PropertyDto().setKey("other").setValue(user.getLogin()).setResourceId(anotherProject.getId()));
  175. deactivate(user.getLogin());
  176. assertThat(db.getDbClient().propertiesDao().selectByQuery(PropertyQuery.builder().setKey("sonar.issues.defaultAssigneeLogin").build(), db.getSession())).isEmpty();
  177. assertThat(db.getDbClient().propertiesDao().selectByQuery(PropertyQuery.builder().build(), db.getSession())).extracting(PropertyDto::getKey).containsOnly("other");
  178. }
  179. @Test
  180. public void deactivate_user_deletes_his_organization_membership() {
  181. logInAsSystemAdministrator();
  182. UserDto user = db.users().insertUser();
  183. OrganizationDto organization = db.organizations().insert();
  184. db.organizations().addMember(organization, user);
  185. OrganizationDto anotherOrganization = db.organizations().insert();
  186. db.organizations().addMember(anotherOrganization, user);
  187. deactivate(user.getLogin());
  188. assertThat(dbClient.organizationMemberDao().select(db.getSession(), organization.getUuid(), user.getId())).isNotPresent();
  189. assertThat(dbClient.organizationMemberDao().select(db.getSession(), anotherOrganization.getUuid(), user.getId())).isNotPresent();
  190. }
  191. @Test
  192. public void deactivate_user_deletes_his_user_settings() {
  193. logInAsSystemAdministrator();
  194. UserDto user = db.users().insertUser();
  195. db.users().insertUserSetting(user);
  196. db.users().insertUserSetting(user);
  197. UserDto anotherUser = db.users().insertUser();
  198. db.users().insertUserSetting(anotherUser);
  199. deactivate(user.getLogin());
  200. assertThat(db.getDbClient().userPropertiesDao().selectByUser(dbSession, user)).isEmpty();
  201. assertThat(db.getDbClient().userPropertiesDao().selectByUser(dbSession, anotherUser)).hasSize(1);
  202. }
  203. @Test
  204. public void cannot_deactivate_self() {
  205. UserDto user = db.users().insertUser();
  206. userSession.logIn(user.getLogin()).setSystemAdministrator();
  207. expectedException.expect(BadRequestException.class);
  208. expectedException.expectMessage("Self-deactivation is not possible");
  209. deactivate(user.getLogin());
  210. verifyThatUserExists(user.getLogin());
  211. }
  212. @Test
  213. public void deactivation_requires_to_be_logged_in() {
  214. expectedException.expect(UnauthorizedException.class);
  215. expectedException.expectMessage("Authentication is required");
  216. deactivate("someone");
  217. }
  218. @Test
  219. public void deactivation_requires_administrator_permission() {
  220. userSession.logIn();
  221. expectedException.expect(ForbiddenException.class);
  222. expectedException.expectMessage("Insufficient privileges");
  223. deactivate("someone");
  224. }
  225. @Test
  226. public void fail_if_user_does_not_exist() {
  227. logInAsSystemAdministrator();
  228. expectedException.expect(NotFoundException.class);
  229. expectedException.expectMessage("User 'someone' doesn't exist");
  230. deactivate("someone");
  231. }
  232. @Test
  233. public void fail_if_login_is_blank() {
  234. logInAsSystemAdministrator();
  235. expectedException.expect(IllegalArgumentException.class);
  236. expectedException.expectMessage("The 'login' parameter is missing");
  237. deactivate("");
  238. }
  239. @Test
  240. public void fail_if_login_is_missing() {
  241. logInAsSystemAdministrator();
  242. expectedException.expect(IllegalArgumentException.class);
  243. expectedException.expectMessage("The 'login' parameter is missing");
  244. deactivate(null);
  245. }
  246. @Test
  247. public void fail_to_deactivate_last_administrator_of_default_organization() {
  248. UserDto admin = db.users().insertUser();
  249. db.users().insertPermissionOnUser(admin, ADMINISTER);
  250. logInAsSystemAdministrator();
  251. expectedException.expect(BadRequestException.class);
  252. expectedException.expectMessage("User is last administrator, and cannot be deactivated");
  253. deactivate(admin.getLogin());
  254. }
  255. @Test
  256. public void fail_to_deactivate_last_administrator_of_organization() {
  257. // user1 is the unique administrator of org1 and org2.
  258. // user1 and user2 are both administrators of org3
  259. UserDto user1 = db.users().insertUser(u -> u.setLogin("test"));
  260. OrganizationDto org1 = db.organizations().insert(newOrganizationDto().setKey("org1"));
  261. OrganizationDto org2 = db.organizations().insert(newOrganizationDto().setKey("org2"));
  262. OrganizationDto org3 = db.organizations().insert(newOrganizationDto().setKey("org3"));
  263. db.users().insertPermissionOnUser(org1, user1, ADMINISTER);
  264. db.users().insertPermissionOnUser(org2, user1, ADMINISTER);
  265. db.users().insertPermissionOnUser(org3, user1, ADMINISTER);
  266. UserDto user2 = db.users().insertUser();
  267. db.users().insertPermissionOnUser(org3, user2, ADMINISTER);
  268. logInAsSystemAdministrator();
  269. expectedException.expect(BadRequestException.class);
  270. expectedException.expectMessage("User 'test' is last administrator of organizations [org1, org2], and cannot be deactivated");
  271. deactivate(user1.getLogin());
  272. }
  273. @Test
  274. public void administrators_can_be_deactivated_if_there_are_still_other_administrators() {
  275. UserDto admin = db.users().insertUser();
  276. UserDto anotherAdmin = db.users().insertUser();
  277. db.users().insertPermissionOnUser(admin, ADMINISTER);
  278. db.users().insertPermissionOnUser(anotherAdmin, ADMINISTER);
  279. db.commit();
  280. logInAsSystemAdministrator();
  281. deactivate(admin.getLogin());
  282. verifyThatUserIsDeactivated(admin.getLogin());
  283. verifyThatUserExists(anotherAdmin.getLogin());
  284. }
  285. @Test
  286. public void test_definition() {
  287. assertThat(ws.getDef().isPost()).isTrue();
  288. assertThat(ws.getDef().isInternal()).isFalse();
  289. assertThat(ws.getDef().params()).hasSize(1);
  290. }
  291. @Test
  292. public void test_example() {
  293. UserDto user = db.users().insertUser(u -> u
  294. .setLogin("ada.lovelace")
  295. .setEmail("ada.lovelace@noteg.com")
  296. .setName("Ada Lovelace")
  297. .setLocal(true)
  298. .setScmAccounts(singletonList("al")));
  299. logInAsSystemAdministrator();
  300. String json = deactivate(user.getLogin()).getInput();
  301. assertJson(json).isSimilarTo(ws.getDef().responseExampleAsString());
  302. }
  303. private void logInAsSystemAdministrator() {
  304. userSession.logIn().setSystemAdministrator();
  305. }
  306. private TestResponse deactivate(@Nullable String login) {
  307. TestRequest request = ws.newRequest()
  308. .setMethod("POST");
  309. Optional.ofNullable(login).ifPresent(t -> request.setParam("login", login));
  310. return request.execute();
  311. }
  312. private void verifyThatUserExists(String login) {
  313. assertThat(db.users().selectUserByLogin(login)).isPresent();
  314. }
  315. private void verifyThatUserIsDeactivated(String login) {
  316. Optional<UserDto> user = db.users().selectUserByLogin(login);
  317. assertThat(user).isPresent();
  318. assertThat(user.get().isActive()).isFalse();
  319. assertThat(user.get().getEmail()).isNull();
  320. assertThat(user.get().getScmAccountsAsList()).isEmpty();
  321. }
  322. }