]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10356 clean message when bulk deleting more than 1000 projects
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Tue, 20 Feb 2018 12:49:17 +0000 (13:49 +0100)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Thu, 22 Feb 2018 08:23:27 +0000 (09:23 +0100)
server/sonar-server/src/main/java/org/sonar/server/project/ws/BulkDeleteAction.java
server/sonar-server/src/test/java/org/sonar/server/project/ws/BulkDeleteActionTest.java

index ec129767b1448bc88ee6475be83433114656a665..785a69f8c622ce68b5e1a0a5681982fdff579a05 100644 (file)
  */
 package org.sonar.server.project.ws;
 
+import java.util.List;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.sonar.api.server.ws.Change;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
@@ -33,6 +37,7 @@ import org.sonar.server.project.Visibility;
 import org.sonar.server.user.UserSession;
 import org.sonarqube.ws.client.project.SearchWsRequest;
 
+import static java.lang.Math.min;
 import static org.sonar.api.resources.Qualifiers.APP;
 import static org.sonar.api.resources.Qualifiers.PROJECT;
 import static org.sonar.api.resources.Qualifiers.VIEW;
@@ -74,7 +79,8 @@ public class BulkDeleteAction implements ProjectsWsAction {
       .setDescription("Delete one or several projects.<br />" +
         "Requires 'Administer System' permission.")
       .setSince("5.2")
-      .setHandler(this);
+      .setHandler(this)
+      .setChangelog(new Change("6.7.2", "Only the 1'000 first items in project filters are taken into account"));
 
     support.addOrganizationParam(action);
 
@@ -86,7 +92,7 @@ public class BulkDeleteAction implements ProjectsWsAction {
 
     action
       .createParam(PARAM_PROJECT_IDS)
-      .setDescription("Comma-separated list of project ids")
+      .setDescription("Comma-separated list of project ids. Only the 1'000 first ids are used. Others are silently ignored.")
       .setDeprecatedKey("ids", "6.4")
       .setDeprecatedSince("6.4")
       .setExampleValue(String.join(",", UUID_EXAMPLE_01, UUID_EXAMPLE_02));
@@ -148,8 +154,16 @@ public class BulkDeleteAction implements ProjectsWsAction {
       .setVisibility(request.param(PARAM_VISIBILITY))
       .setAnalyzedBefore(request.param(PARAM_ANALYZED_BEFORE))
       .setOnProvisionedOnly(request.mandatoryParamAsBoolean(PARAM_ON_PROVISIONED_ONLY))
-      .setProjects(request.paramAsStrings(PARAM_PROJECTS))
-      .setProjectIds(request.paramAsStrings(PARAM_PROJECT_IDS))
+      .setProjects(restrictTo1000Values(request.paramAsStrings(PARAM_PROJECTS)))
+      .setProjectIds(restrictTo1000Values(request.paramAsStrings(PARAM_PROJECT_IDS)))
       .build();
   }
+
+  @CheckForNull
+  private static List<String> restrictTo1000Values(@Nullable List<String> values) {
+    if (values == null) {
+      return null;
+    }
+    return values.subList(0, min(values.size(), 1_000));
+  }
 }
index 79f3806677d36701b2a2673af5aa455cd566d6e5..7f14b392fded8cd89ecf3c3e1a3ced712c838376 100644 (file)
  */
 package org.sonar.server.project.ws;
 
-import java.io.IOException;
 import java.net.HttpURLConnection;
 import java.util.Date;
+import java.util.List;
 import java.util.stream.IntStream;
+import org.apache.commons.lang.StringUtils;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -31,6 +32,7 @@ import org.mockito.ArgumentCaptor;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.server.ws.WebService.Param;
 import org.sonar.api.utils.System2;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
@@ -86,7 +88,7 @@ public class BulkDeleteActionTest {
   }
 
   @Test
-  public void delete_projects_in_default_organization_if_no_org_provided() throws Exception {
+  public void delete_projects_in_default_organization_if_no_org_provided() {
     userSession.logIn().setRoot();
     OrganizationDto defaultOrganization = db.getDefaultOrganization();
     ComponentDto toDeleteInOrg1 = db.components().insertPrivateProject(org1);
@@ -103,7 +105,7 @@ public class BulkDeleteActionTest {
   }
 
   @Test
-  public void delete_projects_by_keys() throws Exception {
+  public void delete_projects_by_keys() {
     userSession.logIn().setRoot();
     ComponentDto toDeleteInOrg1 = db.components().insertPrivateProject(org1);
     ComponentDto toDeleteInOrg2 = db.components().insertPrivateProject(org1);
@@ -118,7 +120,7 @@ public class BulkDeleteActionTest {
   }
 
   @Test
-  public void projects_that_dont_exist_are_ignored_and_dont_break_bulk_deletion() throws Exception {
+  public void projects_that_dont_exist_are_ignored_and_dont_break_bulk_deletion() {
     userSession.logIn().setRoot();
     ComponentDto toDelete1 = db.components().insertPrivateProject(org1);
     ComponentDto toDelete2 = db.components().insertPrivateProject(org1);
@@ -172,7 +174,7 @@ public class BulkDeleteActionTest {
   }
 
   @Test
-  public void projects_and_views() throws IOException {
+  public void projects_and_views() {
     userSession.logIn().addPermission(ADMINISTER, db.getDefaultOrganization());
     ComponentDto project = db.components().insertPrivateProject();
     ComponentDto view = db.components().insertView();
@@ -183,7 +185,7 @@ public class BulkDeleteActionTest {
   }
 
   @Test
-  public void delete_by_key_query_with_partial_match_case_insensitive() throws IOException {
+  public void delete_by_key_query_with_partial_match_case_insensitive() {
     userSession.logIn().addPermission(ADMINISTER, db.getDefaultOrganization());
     ComponentDto matchKeyProject = db.components().insertPrivateProject(p -> p.setDbKey("project-_%-key"));
     ComponentDto matchUppercaseKeyProject = db.components().insertPrivateProject(p -> p.setDbKey("PROJECT-_%-KEY"));
@@ -195,7 +197,7 @@ public class BulkDeleteActionTest {
   }
 
   @Test
-  public void throw_ForbiddenException_if_organization_administrator_does_not_set_organization_parameter() throws Exception {
+  public void throw_ForbiddenException_if_organization_administrator_does_not_set_organization_parameter() {
     userSession.logIn().addPermission(ADMINISTER, org1);
     ComponentDto project = db.components().insertPrivateProject(org1);
 
@@ -209,8 +211,25 @@ public class BulkDeleteActionTest {
     verifyNoDeletions();
   }
 
+  /**
+   * SONAR-10356
+   */
   @Test
-  public void organization_administrator_deletes_projects_by_keys_in_his_organization() throws Exception {
+  public void delete_only_the_1000_first_projects() {
+    userSession.logIn().addPermission(ADMINISTER, org1);
+    List<String> keys = IntStream.range(0, 1_010).mapToObj(i -> "key" + i).collect(MoreCollectors.toArrayList());
+    keys.forEach(key -> db.components().insertPrivateProject(org1, p -> p.setDbKey(key)));
+
+    ws.newRequest()
+      .setParam("organization", org1.getKey())
+      .setParam("projects", StringUtils.join(keys, ","))
+      .execute();
+
+    verify(componentCleanerService, times(1_000)).delete(any(DbSession.class), any(ComponentDto.class));
+  }
+
+  @Test
+  public void organization_administrator_deletes_projects_by_keys_in_his_organization() {
     userSession.logIn().addPermission(ADMINISTER, org1);
     ComponentDto toDelete = db.components().insertPrivateProject(org1);
     ComponentDto cantBeDeleted = db.components().insertPrivateProject(org2);
@@ -224,7 +243,7 @@ public class BulkDeleteActionTest {
   }
 
   @Test
-  public void throw_UnauthorizedException_if_not_logged_in() throws Exception {
+  public void throw_UnauthorizedException_if_not_logged_in() {
     expectedException.expect(UnauthorizedException.class);
     expectedException.expectMessage("Authentication is required");
 
@@ -235,7 +254,7 @@ public class BulkDeleteActionTest {
   }
 
   @Test
-  public void throw_ForbiddenException_if_param_organization_is_not_set_and_not_system_administrator() throws Exception {
+  public void throw_ForbiddenException_if_param_organization_is_not_set_and_not_system_administrator() {
     userSession.logIn().setNonSystemAdministrator();
 
     expectedException.expect(ForbiddenException.class);
@@ -248,7 +267,7 @@ public class BulkDeleteActionTest {
   }
 
   @Test
-  public void throw_ForbiddenException_if_param_organization_is_set_but_not_organization_administrator() throws Exception {
+  public void throw_ForbiddenException_if_param_organization_is_set_but_not_organization_administrator() {
     userSession.logIn();
 
     expectedException.expect(ForbiddenException.class);