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;
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;
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) {
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()) {
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()) {
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;
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