]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-16500 Prevent future dates for project bulk delete action
authorKlaudio Sinani <klaudio.sinani@sonarsource.com>
Mon, 20 Jun 2022 18:13:17 +0000 (20:13 +0200)
committersonartech <sonartech@sonarsource.com>
Tue, 21 Jun 2022 20:02:45 +0000 (20:02 +0000)
server/sonar-webserver-webapi/src/main/java/org/sonar/server/project/ws/BulkDeleteAction.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/project/ws/BulkDeleteActionTest.java

index 3a75fb5b14bc6769eadc9f6d8b7042a3bc2188cc..fde1db235c1a257f72c8311db92be33ab4982fe3 100644 (file)
 package org.sonar.server.project.ws;
 
 import com.google.common.base.Strings;
+import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
+import org.apache.commons.lang.StringUtils;
 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;
 import org.sonar.api.server.ws.WebService.Param;
+import org.sonar.api.utils.DateUtils;
 import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
@@ -138,6 +142,7 @@ public class BulkDeleteAction implements ProjectsWsAction {
     try (DbSession dbSession = dbClient.openSession(false)) {
       userSession.checkPermission(GlobalPermission.ADMINISTER);
       checkAtLeastOneParameterIsPresent(searchRequest);
+      checkIfAnalyzedBeforeIsFutureDate(searchRequest);
 
       ComponentQuery query = buildDbQuery(searchRequest);
       Set<ComponentDto> componentDtos = new HashSet<>(dbClient.componentDao().selectByQuery(dbSession, query, 0, Integer.MAX_VALUE));
@@ -159,10 +164,22 @@ public class BulkDeleteAction implements ProjectsWsAction {
     boolean queryPresent = !Strings.isNullOrEmpty(searchRequest.getQuery());
     boolean atLeastOneParameterIsPresent = analyzedBeforePresent || projectsPresent || queryPresent;
 
-    checkArgument(atLeastOneParameterIsPresent, format("At lease one parameter among %s, %s and %s must be provided",
+    checkArgument(atLeastOneParameterIsPresent, format("At least one parameter among %s, %s and %s must be provided",
       PARAM_ANALYZED_BEFORE, PARAM_PROJECTS, Param.TEXT_QUERY));
   }
 
+  private static void checkIfAnalyzedBeforeIsFutureDate(SearchRequest searchRequest) {
+    String analyzedBeforeParam = searchRequest.getAnalyzedBefore();
+
+    Optional.ofNullable(analyzedBeforeParam)
+      .filter(StringUtils::isNotEmpty)
+      .map(DateUtils::parseDateOrDateTime)
+      .ifPresent(analyzedBeforeDate -> {
+        boolean isFutureDate = new Date().compareTo(analyzedBeforeDate) < 0;
+        checkArgument(!isFutureDate, format("Provided value for parameter %s must not be a future date", PARAM_ANALYZED_BEFORE));
+      });
+  }
+
   private static SearchRequest toSearchWsRequest(Request request) {
     return SearchRequest.builder()
       .setQualifiers(request.mandatoryParamAsStrings(PARAM_QUALIFIERS))
index a4cbce31c8a990a6936aa583b9a0884246ed48b9..a831c48045329bb42a6472a62e898fd63291aed1 100644 (file)
@@ -28,6 +28,8 @@ import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 import java.util.stream.Stream;
 import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.math.RandomUtils;
+import org.joda.time.DateTime;
 import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
@@ -120,7 +122,7 @@ public class BulkDeleteActionTest {
       TestRequest request = ws.newRequest();
       assertThatThrownBy(request::execute)
         .isInstanceOf(IllegalArgumentException.class)
-        .hasMessage("At lease one parameter among analyzedBefore, projects and q must be provided");
+        .hasMessage("At least one parameter among analyzedBefore, projects and q must be provided");
     } finally {
       verifyNoDeletions();
       verifyNoMoreInteractions(projectLifeCycleListeners);
@@ -271,6 +273,25 @@ public class BulkDeleteActionTest {
     verifyListenersOnProjectsDeleted(toDelete1, toDelete2);
   }
 
+  @Test
+  public void should_throw_IAE_when_providing_future_date_as_analyzed_before_date() {
+    userSession.logIn().addPermission(ADMINISTER);
+
+    Date now = new Date();
+    Date futureDate = new DateTime(now).plusDays(RandomUtils.nextInt() + 1).toDate();
+    ComponentDto project1 = db.components().insertPublicProject();
+    db.getDbClient().snapshotDao().insert(db.getSession(), newAnalysis(project1).setCreatedAt(now.getTime()));
+    ComponentDto project2 = db.components().insertPublicProject();
+    db.getDbClient().snapshotDao().insert(db.getSession(), newAnalysis(project2).setCreatedAt(now.getTime()));
+    db.commit();
+
+    TestRequest request = ws.newRequest().setParam(PARAM_ANALYZED_BEFORE, formatDate(futureDate));
+
+    assertThatThrownBy(request::execute)
+      .isInstanceOf(IllegalArgumentException.class)
+      .hasMessage("Provided value for parameter analyzedBefore must not be a future date");
+  }
+
   @Test
   public void throw_UnauthorizedException_if_not_logged_in() {
     userSession.anonymous();