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.

DeleteAction.java 8.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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.organization.ws;
  21. import java.util.Collection;
  22. import java.util.List;
  23. import java.util.Set;
  24. import org.sonar.api.resources.Qualifiers;
  25. import org.sonar.api.resources.Scopes;
  26. import org.sonar.api.server.ws.Request;
  27. import org.sonar.api.server.ws.Response;
  28. import org.sonar.api.server.ws.WebService;
  29. import org.sonar.core.util.stream.MoreCollectors;
  30. import org.sonar.db.DbClient;
  31. import org.sonar.db.DbSession;
  32. import org.sonar.db.component.ComponentDto;
  33. import org.sonar.db.organization.OrganizationDto;
  34. import org.sonar.db.qualitygate.QualityGateDto;
  35. import org.sonar.db.qualityprofile.QProfileDto;
  36. import org.sonar.db.user.UserDto;
  37. import org.sonar.server.component.ComponentCleanerService;
  38. import org.sonar.server.organization.BillingValidations;
  39. import org.sonar.server.organization.BillingValidationsProxy;
  40. import org.sonar.server.organization.DefaultOrganization;
  41. import org.sonar.server.organization.DefaultOrganizationProvider;
  42. import org.sonar.server.organization.OrganizationFlags;
  43. import org.sonar.server.project.Project;
  44. import org.sonar.server.project.ProjectLifeCycleListeners;
  45. import org.sonar.server.qualityprofile.QProfileFactory;
  46. import org.sonar.server.user.UserSession;
  47. import org.sonar.server.user.index.UserIndexer;
  48. import static com.google.common.base.Preconditions.checkArgument;
  49. import static org.sonar.db.permission.OrganizationPermission.ADMINISTER;
  50. import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_KEY;
  51. import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_ORGANIZATION;
  52. import static org.sonar.server.ws.KeyExamples.KEY_ORG_EXAMPLE_002;
  53. import static org.sonar.server.ws.WsUtils.checkFoundWithOptional;
  54. public class DeleteAction implements OrganizationsWsAction {
  55. private static final String ACTION = "delete";
  56. private final UserSession userSession;
  57. private final DbClient dbClient;
  58. private final DefaultOrganizationProvider defaultOrganizationProvider;
  59. private final ComponentCleanerService componentCleanerService;
  60. private final OrganizationFlags organizationFlags;
  61. private final UserIndexer userIndexer;
  62. private final QProfileFactory qProfileFactory;
  63. private final ProjectLifeCycleListeners projectLifeCycleListeners;
  64. private final BillingValidationsProxy billingValidations;
  65. public DeleteAction(UserSession userSession, DbClient dbClient, DefaultOrganizationProvider defaultOrganizationProvider, ComponentCleanerService componentCleanerService,
  66. OrganizationFlags organizationFlags, UserIndexer userIndexer, QProfileFactory qProfileFactory, ProjectLifeCycleListeners projectLifeCycleListeners,
  67. BillingValidationsProxy billingValidations) {
  68. this.userSession = userSession;
  69. this.dbClient = dbClient;
  70. this.defaultOrganizationProvider = defaultOrganizationProvider;
  71. this.componentCleanerService = componentCleanerService;
  72. this.organizationFlags = organizationFlags;
  73. this.userIndexer = userIndexer;
  74. this.qProfileFactory = qProfileFactory;
  75. this.projectLifeCycleListeners = projectLifeCycleListeners;
  76. this.billingValidations = billingValidations;
  77. }
  78. @Override
  79. public void define(WebService.NewController context) {
  80. WebService.NewAction action = context.createAction(ACTION)
  81. .setPost(true)
  82. .setDescription("Delete an organization.<br/>" +
  83. "Require 'Administer System' permission on the specified organization. Organization support must be enabled.")
  84. .setInternal(true)
  85. .setSince("6.2")
  86. .setHandler(this);
  87. action.createParam(PARAM_ORGANIZATION)
  88. .setRequired(true)
  89. .setDescription("Organization key")
  90. .setDeprecatedKey(PARAM_KEY, "6.4")
  91. .setExampleValue(KEY_ORG_EXAMPLE_002);
  92. }
  93. @Override
  94. public void handle(Request request, Response response) throws Exception {
  95. userSession.checkLoggedIn();
  96. try (DbSession dbSession = dbClient.openSession(false)) {
  97. organizationFlags.checkEnabled(dbSession);
  98. String key = request.mandatoryParam(PARAM_ORGANIZATION);
  99. preventDeletionOfDefaultOrganization(key, defaultOrganizationProvider.get());
  100. OrganizationDto organization = checkFoundWithOptional(dbClient.organizationDao().selectByKey(dbSession, key), "Organization with key '%s' not found", key);
  101. if (organization.isGuarded()) {
  102. userSession.checkIsSystemAdministrator();
  103. } else {
  104. userSession.checkPermission(ADMINISTER, organization);
  105. }
  106. deleteProjects(dbSession, organization);
  107. deletePermissions(dbSession, organization);
  108. deleteGroups(dbSession, organization);
  109. deleteQualityProfiles(dbSession, organization);
  110. deleteQualityGates(dbSession, organization);
  111. deleteOrganizationAlmBinding(dbSession, organization);
  112. deleteOrganization(dbSession, organization);
  113. billingValidations.onDelete(new BillingValidations.Organization(organization.getKey(), organization.getUuid()));
  114. response.noContent();
  115. }
  116. }
  117. private void deleteProjects(DbSession dbSession, OrganizationDto organization) {
  118. List<ComponentDto> roots = dbClient.componentDao().selectProjectsByOrganization(dbSession, organization.getUuid());
  119. try {
  120. componentCleanerService.delete(dbSession, roots);
  121. } finally {
  122. Set<Project> projects = roots.stream()
  123. .filter(DeleteAction::isMainProject)
  124. .map(Project::from)
  125. .collect(MoreCollectors.toSet());
  126. projectLifeCycleListeners.onProjectsDeleted(projects);
  127. }
  128. }
  129. private static boolean isMainProject(ComponentDto p) {
  130. return Scopes.PROJECT.equals(p.scope())
  131. && Qualifiers.PROJECT.equals(p.qualifier())
  132. && p.getMainBranchProjectUuid() == null;
  133. }
  134. private void deletePermissions(DbSession dbSession, OrganizationDto organization) {
  135. dbClient.permissionTemplateDao().deleteByOrganization(dbSession, organization.getUuid());
  136. dbClient.userPermissionDao().deleteByOrganization(dbSession, organization.getUuid());
  137. dbClient.groupPermissionDao().deleteByOrganization(dbSession, organization.getUuid());
  138. }
  139. private void deleteGroups(DbSession dbSession, OrganizationDto organization) {
  140. dbClient.groupDao().deleteByOrganization(dbSession, organization.getUuid());
  141. }
  142. private void deleteQualityProfiles(DbSession dbSession, OrganizationDto organization) {
  143. List<QProfileDto> profiles = dbClient.qualityProfileDao().selectOrderedByOrganizationUuid(dbSession, organization);
  144. qProfileFactory.delete(dbSession, profiles);
  145. }
  146. private void deleteQualityGates(DbSession dbSession, OrganizationDto organization) {
  147. Collection<QualityGateDto> qualityGates = dbClient.qualityGateDao().selectAll(dbSession, organization);
  148. dbClient.qualityGateDao().deleteByUuids(dbSession, qualityGates.stream()
  149. .filter(q -> !q.isBuiltIn())
  150. .map(QualityGateDto::getUuid)
  151. .collect(MoreCollectors.toList()));
  152. dbClient.qualityGateDao().deleteOrgQualityGatesByOrganization(dbSession, organization);
  153. }
  154. private void deleteOrganizationAlmBinding(DbSession dbSession, OrganizationDto organization){
  155. dbClient.organizationAlmBindingDao().deleteByOrganization(dbSession, organization);
  156. }
  157. private void deleteOrganization(DbSession dbSession, OrganizationDto organization) {
  158. Collection<String> uuids = dbClient.organizationMemberDao().selectUserUuidsByOrganizationUuid(dbSession, organization.getUuid());
  159. dbClient.organizationMemberDao().deleteByOrganizationUuid(dbSession, organization.getUuid());
  160. dbClient.organizationDao().deleteByUuid(dbSession, organization.getUuid());
  161. dbClient.userDao().cleanHomepage(dbSession, organization);
  162. dbClient.webhookDao().selectByOrganizationUuid(dbSession, organization.getUuid())
  163. .forEach(wh -> dbClient.webhookDeliveryDao().deleteByWebhook(dbSession, wh));
  164. dbClient.webhookDao().deleteByOrganization(dbSession, organization);
  165. List<UserDto> users = dbClient.userDao().selectByUuids(dbSession, uuids);
  166. userIndexer.commitAndIndex(dbSession, users);
  167. }
  168. private static void preventDeletionOfDefaultOrganization(String key, DefaultOrganization defaultOrganization) {
  169. checkArgument(!defaultOrganization.getKey().equals(key), "Default Organization can't be deleted");
  170. }
  171. }