]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-14361 WS 'hotspot/search' returns no issue if the 'sinceLeakPeriod' filter...
authorDuarte Meneses <duarte.meneses@sonarsource.com>
Tue, 9 Feb 2021 21:53:44 +0000 (15:53 -0600)
committersonartech <sonartech@sonarsource.com>
Wed, 10 Feb 2021 20:07:17 +0000 (20:07 +0000)
server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/SearchAction.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/SearchActionTest.java

index 02a09e068b94a9b7450f50e4f05cac323ae286eb..39237997739e83ef0006d6c0d9594a517014e2a0 100644 (file)
@@ -50,7 +50,9 @@ import org.sonar.api.web.UserRole;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.SnapshotDto;
 import org.sonar.db.issue.IssueDto;
+import org.sonar.db.project.ProjectDto;
 import org.sonar.db.rule.RuleDefinitionDto;
 import org.sonar.server.es.SearchOptions;
 import org.sonar.server.exceptions.NotFoundException;
@@ -79,6 +81,7 @@ import static org.sonar.api.utils.DateUtils.formatDateTime;
 import static org.sonar.api.utils.DateUtils.longToDate;
 import static org.sonar.api.utils.Paging.forPageIndex;
 import static org.sonar.core.util.stream.MoreCollectors.toList;
+import static org.sonar.core.util.stream.MoreCollectors.toSet;
 import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
 import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_INSECURE_INTERACTION;
 import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_POROUS_DEFENSES;
@@ -320,8 +323,15 @@ public class SearchAction implements HotspotsWsAction {
       String projectUuid = firstNonNull(project.getMainBranchProjectUuid(), project.uuid());
       if (Qualifiers.APP.equals(project.qualifier())) {
         builder.viewUuids(singletonList(projectUuid));
+        addCreatedAfterByProjects(builder, dbSession, wsRequest, project);
       } else {
         builder.projectUuids(singletonList(projectUuid));
+        if (wsRequest.isSinceLeakPeriod() && !wsRequest.getPullRequest().isPresent()) {
+          Date sinceDate = dbClient.snapshotDao().selectLastAnalysisByComponentUuid(dbSession, project.uuid())
+            .map(s -> longToDate(s.getPeriodDate()))
+            .orElseGet(() -> new Date(system2.now()));
+          builder.createdAfter(sinceDate, false);
+        }
       }
 
       if (project.getMainBranchProjectUuid() == null) {
@@ -330,13 +340,6 @@ public class SearchAction implements HotspotsWsAction {
         builder.branchUuid(project.uuid());
         builder.mainBranch(false);
       }
-
-      if (wsRequest.isSinceLeakPeriod() && !wsRequest.getPullRequest().isPresent()) {
-        Date sinceDate = dbClient.snapshotDao().selectLastAnalysisByComponentUuid(dbSession, project.uuid())
-          .map(s -> longToDate(s.getPeriodDate()))
-          .orElseGet(() -> new Date(system2.now()));
-        builder.createdAfter(sinceDate, false);
-      }
     }
 
     if (!wsRequest.getHotspotKeys().isEmpty()) {
@@ -366,9 +369,24 @@ public class SearchAction implements HotspotsWsAction {
     return issueIndex.search(query, searchOptions);
   }
 
+  private void addCreatedAfterByProjects(IssueQuery.Builder builder, DbSession dbSession, WsRequest wsRequest, ComponentDto application) {
+    if (!wsRequest.isSinceLeakPeriod() || wsRequest.getPullRequest().isPresent()) {
+      return;
+    }
+
+    Set<String> projectUuids = dbClient.applicationProjectsDao().selectProjects(dbSession, application.uuid()).stream()
+      .map(ProjectDto::getUuid)
+      .collect(Collectors.toSet());
+    long now = system2.now();
+    Map<String, IssueQuery.PeriodStart> leakByProjects = dbClient.snapshotDao().selectLastAnalysesByRootComponentUuids(dbSession, projectUuids).stream()
+      .collect(uniqueIndex(SnapshotDto::getComponentUuid, s ->
+        new IssueQuery.PeriodStart(longToDate(s.getPeriodDate() == null ? now : s.getPeriodDate()), false)));
+
+    builder.createdAfterByProjectUuids(leakByProjects);
+  }
+
   private void loadComponents(DbSession dbSession, SearchResponseData searchResponseData) {
-    Set<String> componentKeys = searchResponseData.getOrderedHotspots()
-      .stream()
+    Set<String> componentKeys = searchResponseData.getOrderedHotspots().stream()
       .flatMap(hotspot -> Stream.of(hotspot.getComponentKey(), hotspot.getProjectKey()))
       .collect(Collectors.toSet());
     if (!componentKeys.isEmpty()) {
index 9c4258ccb43b04e65c60f782fee055c7fdf46b0f..198fdbc078d311ca594deee86e740920bc7be763 100644 (file)
@@ -51,6 +51,7 @@ import org.sonar.db.component.BranchType;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.ComponentTesting;
 import org.sonar.db.issue.IssueDto;
+import org.sonar.db.project.ProjectDto;
 import org.sonar.db.rule.RuleDefinitionDto;
 import org.sonar.db.rule.RuleTesting;
 import org.sonar.server.es.EsTester;
@@ -1499,6 +1500,52 @@ public class SearchActionTest {
     assertThat(responseOnLeak.getHotspotsList()).hasSize(3);
   }
 
+  @Test
+  public void returns_issues_when_sinceLeakPeriod_is_true_and_is_application() {
+    long referenceDate = 800_996_999_332L;
+
+    system2.setNow(referenceDate + 10_000);
+    ComponentDto application = dbTester.components().insertPublicApplication();
+    ComponentDto project = dbTester.components().insertPublicProject();
+    ComponentDto project2 = dbTester.components().insertPublicProject();
+
+    dbTester.components().addApplicationProject(application, project);
+    dbTester.components().addApplicationProject(application, project2);
+
+    dbTester.components().insertComponent(ComponentTesting.newProjectCopy(project, application));
+    dbTester.components().insertComponent(ComponentTesting.newProjectCopy(project2, application));
+
+    indexViews();
+
+    userSessionRule.registerComponents(application, project, project2);
+    indexPermissions();
+    ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
+    dbTester.components().insertSnapshot(project, t -> t.setPeriodDate(referenceDate).setLast(true));
+    RuleDefinitionDto rule = newRule(SECURITY_HOTSPOT);
+    IssueDto afterRef = dbTester.issues().insertHotspot(rule, project, file, t -> t.setIssueCreationTime(referenceDate + 1000));
+    IssueDto atRef = dbTester.issues().insertHotspot(rule, project, file, t -> t.setType(SECURITY_HOTSPOT).setIssueCreationTime(referenceDate));
+    IssueDto beforeRef = dbTester.issues().insertHotspot(rule, project, file, t -> t.setIssueCreationTime(referenceDate - 1000));
+
+    ComponentDto file2 = dbTester.components().insertComponent(newFileDto(project2));
+    IssueDto project2Issue = dbTester.issues().insertHotspot(rule, project2, file2, t -> t.setIssueCreationTime(referenceDate - 1000));
+
+    indexIssues();
+
+    SearchWsResponse responseAll = newRequest(application)
+      .executeProtobuf(SearchWsResponse.class);
+    assertThat(responseAll.getHotspotsList())
+      .extracting(SearchWsResponse.Hotspot::getKey)
+      .containsExactlyInAnyOrder(afterRef.getKey(), atRef.getKey(), beforeRef.getKey(), project2Issue.getKey());
+
+    SearchWsResponse responseOnLeak = newRequest(application,
+      t -> t.setParam("sinceLeakPeriod", "true"))
+      .executeProtobuf(SearchWsResponse.class);
+    assertThat(responseOnLeak.getHotspotsList())
+      .extracting(SearchWsResponse.Hotspot::getKey)
+      .containsExactlyInAnyOrder(afterRef.getKey());
+
+  }
+
   @Test
   public void verify_response_example() {
     ComponentDto project = dbTester.components().insertPublicProject(componentDto -> componentDto