From d42fce99f8d6dc626fde36bc4a2e872671d545fc Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=A9bastien=20Lesaint?= Date: Thu, 19 Dec 2019 16:24:13 +0100 Subject: [PATCH] SONAR-12723 api/issues/tags and component_tags ignore Hotspots --- .../org/sonar/db/issue/IssueDbTester.java | 3 + .../org/sonar/server/issue/SearchRequest.java | 11 +- .../server/issue/index/IssueQueryFactory.java | 6 + .../server/issue/ws/ComponentTagsAction.java | 6 +- .../org/sonar/server/issue/ws/TagsAction.java | 6 +- .../issue/ws/ComponentTagsActionTest.java | 9 ++ .../issue/ws/SearchActionComponentsTest.java | 17 ++- .../server/issue/ws/SearchActionTest.java | 73 +++++---- .../server/issue/ws/SetTagsActionTest.java | 14 ++ .../sonar/server/issue/ws/TagsActionTest.java | 138 +++++++++++++++--- 10 files changed, 217 insertions(+), 66 deletions(-) diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/issue/IssueDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/issue/IssueDbTester.java index 78686f90848..b548d87b8cd 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/issue/IssueDbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/issue/IssueDbTester.java @@ -33,6 +33,7 @@ import org.sonar.db.organization.OrganizationDto; import org.sonar.db.rule.RuleDefinitionDto; import org.sonar.db.user.UserDto; +import static com.google.common.base.Preconditions.checkArgument; import static java.util.Arrays.stream; import static org.assertj.core.api.Assertions.assertThat; import static org.sonar.api.rules.RuleType.SECURITY_HOTSPOT; @@ -140,6 +141,8 @@ public class IssueDbTester { */ @SafeVarargs public final IssueDto insertHotspot(RuleDefinitionDto rule, ComponentDto project, ComponentDto file, Consumer... populators) { + checkArgument(rule.getType() == RuleType.SECURITY_HOTSPOT.getDbConstant(), "rule must be a hotspot rule"); + IssueDto issue = newIssue(rule, project, file) .setType(SECURITY_HOTSPOT) .setStatus(Issue.STATUS_TO_REVIEW) diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/issue/SearchRequest.java b/server/sonar-server-common/src/main/java/org/sonar/server/issue/SearchRequest.java index 9f0045eb73a..8737403103b 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/issue/SearchRequest.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/issue/SearchRequest.java @@ -19,7 +19,10 @@ */ package org.sonar.server.issue; +import com.google.common.collect.ImmutableSet; +import java.util.Collection; import java.util.List; +import java.util.Set; import javax.annotation.CheckForNull; import javax.annotation.Nullable; @@ -62,7 +65,7 @@ public class SearchRequest { private List severities; private List statuses; private List tags; - private List types; + private Set types; private List owaspTop10; private List sansTop25; private List sonarsourceSecurity; @@ -387,12 +390,12 @@ public class SearchRequest { } @CheckForNull - public List getTypes() { + public Set getTypes() { return types; } - public SearchRequest setTypes(@Nullable List types) { - this.types = types; + public SearchRequest setTypes(@Nullable Collection types) { + this.types = types == null ? null : ImmutableSet.copyOf(types); return this; } diff --git a/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java b/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java index 5142a8ffde0..7dd6221826f 100644 --- a/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java +++ b/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java @@ -43,8 +43,10 @@ import javax.annotation.Nullable; import org.apache.commons.lang.BooleanUtils; import org.sonar.api.resources.Qualifiers; import org.sonar.api.rule.RuleKey; +import org.sonar.api.rules.RuleType; import org.sonar.api.server.ServerSide; import org.sonar.api.web.UserRole; +import org.sonar.core.util.stream.MoreCollectors; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.component.ComponentDto; @@ -88,6 +90,10 @@ public class IssueQueryFactory { .filter(s -> !s.equals(STATUS_TO_REVIEW)) .filter(s -> !s.equals(STATUS_REVIEWED)) .collect(ImmutableList.toImmutableList()); + public static final Set ISSUE_TYPE_NAMES = Arrays.stream(RuleType.values()) + .filter(t -> t != RuleType.SECURITY_HOTSPOT) + .map(Enum::name) + .collect(MoreCollectors.toSet(RuleType.values().length - 1)); private static final ComponentDto UNKNOWN_COMPONENT = new ComponentDto().setUuid(UNKNOWN).setProjectUuid(UNKNOWN); private final DbClient dbClient; diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/ComponentTagsAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/ComponentTagsAction.java index 1324f3127cf..4fb6185a0e4 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/ComponentTagsAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/ComponentTagsAction.java @@ -26,13 +26,14 @@ import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; import org.sonar.api.server.ws.WebService.NewAction; import org.sonar.api.utils.text.JsonWriter; +import org.sonar.server.issue.SearchRequest; +import org.sonar.server.issue.index.IssueIndex; import org.sonar.server.issue.index.IssueQuery; import org.sonar.server.issue.index.IssueQueryFactory; -import org.sonar.server.issue.index.IssueIndex; -import org.sonar.server.issue.SearchRequest; import static java.util.Collections.singletonList; import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE; +import static org.sonar.server.issue.index.IssueQueryFactory.ISSUE_TYPE_NAMES; import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_COMPONENT_TAGS; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_UUID; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CREATED_AFTER; @@ -79,6 +80,7 @@ public class ComponentTagsAction implements IssuesWsAction { public void handle(Request request, Response response) throws Exception { SearchRequest searchRequest = new SearchRequest() .setComponentUuids(singletonList(request.mandatoryParam(PARAM_COMPONENT_UUID))) + .setTypes(ISSUE_TYPE_NAMES) .setResolved(false) .setCreatedAfter(request.param(PARAM_CREATED_AFTER)); diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/TagsAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/TagsAction.java index 8bfd337a3d6..dcd8c9d47c4 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/TagsAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/TagsAction.java @@ -43,8 +43,9 @@ import org.sonarqube.ws.Issues; import static com.google.common.base.Preconditions.checkArgument; import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE; import static org.sonar.api.server.ws.WebService.Param.TEXT_QUERY; -import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; import static org.sonar.server.exceptions.NotFoundException.checkFoundWithOptional; +import static org.sonar.server.issue.index.IssueQueryFactory.ISSUE_TYPE_NAMES; +import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; import static org.sonar.server.ws.WsUtils.writeProtobuf; /** @@ -117,7 +118,8 @@ public class TagsAction implements IssuesWsAction { } private List searchTags(Optional organization, Optional project, Request request) { - IssueQuery.Builder issueQueryBuilder = IssueQuery.builder(); + IssueQuery.Builder issueQueryBuilder = IssueQuery.builder() + .types(ISSUE_TYPE_NAMES); organization.ifPresent(o -> issueQueryBuilder.organizationUuid(o.getUuid())); project.ifPresent(p -> { switch (p.qualifier()) { diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/ComponentTagsActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/ComponentTagsActionTest.java index 7941645b1d7..ee6bdd5650c 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/ComponentTagsActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/ComponentTagsActionTest.java @@ -20,10 +20,12 @@ package org.sonar.server.issue.ws; import com.google.common.collect.ImmutableMap; +import java.util.Arrays; import java.util.Map; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; +import org.sonar.api.rules.RuleType; import org.sonar.api.server.ws.WebService.Action; import org.sonar.api.server.ws.WebService.Param; import org.sonar.server.issue.index.IssueQuery; @@ -38,9 +40,14 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import static org.sonar.api.rules.RuleType.SECURITY_HOTSPOT; import static org.sonar.test.JsonAssert.assertJson; public class ComponentTagsActionTest { + private static String[] ISSUE_RULE_TYPES = Arrays.stream(RuleType.values()) + .filter(t -> t != SECURITY_HOTSPOT) + .map(Enum::name) + .toArray(String[]::new); private IssueIndex service = mock(IssueIndex.class); private IssueQueryFactory issueQueryFactory = mock(IssueQueryFactory.class, Mockito.RETURNS_DEEP_STUBS); @@ -99,6 +106,7 @@ public class ComponentTagsActionTest { .execute(); assertJson(response.getInput()).isSimilarTo(getClass().getResource("ComponentTagsActionTest/component-tags.json")); + assertThat(captor.getValue().getTypes()).containsExactlyInAnyOrder(ISSUE_RULE_TYPES); assertThat(captor.getValue().getComponentUuids()).containsOnly("polop"); assertThat(captor.getValue().getResolved()).isFalse(); assertThat(captor.getValue().getCreatedAfter()).isNull(); @@ -125,6 +133,7 @@ public class ComponentTagsActionTest { .setParam("ps", "5") .execute(); assertJson(response.getInput()).isSimilarTo(getClass().getResource("ComponentTagsActionTest/component-tags.json")); + assertThat(captor.getValue().getTypes()).containsExactlyInAnyOrder(ISSUE_RULE_TYPES); assertThat(captor.getValue().getComponentUuids()).containsOnly(componentUuid); assertThat(captor.getValue().getResolved()).isFalse(); assertThat(captor.getValue().getCreatedAfter()).isEqualTo(createdAfter); diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsTest.java index 3f8c4bd76b2..ddcd67fd5c4 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsTest.java @@ -466,14 +466,15 @@ public class SearchActionComponentsTest { db.components().insertComponents(newProjectCopy(project2, applicationBranch1)); db.components().insertComponents(newProjectCopy(project1Branch2, applicationBranch2)); - RuleDefinitionDto rule = db.rules().insertIssueRule(); - IssueDto issueOnProject1 = db.issues().insertIssue(rule, project1, project1); - IssueDto issueOnProject1Branch1 = db.issues().insertIssue(rule, project1Branch1, project1Branch1); - db.issues().insertHotspot(rule, project1Branch1, project1Branch1); - IssueDto issueOnFileOnProject1Branch1 = db.issues().insertIssue(rule, project1Branch1, fileOnProject1Branch1); - IssueDto issueOnProject1Branch2 = db.issues().insertIssue(rule, project1Branch2, project1Branch2); - IssueDto issueOnProject2 = db.issues().insertIssue(rule, project2, project2); - db.issues().insertHotspot(rule, project2, project2); + RuleDefinitionDto issueRule = db.rules().insertIssueRule(); + RuleDefinitionDto hotspotRule = db.rules().insertHotspotRule(); + IssueDto issueOnProject1 = db.issues().insertIssue(issueRule, project1, project1); + IssueDto issueOnProject1Branch1 = db.issues().insertIssue(issueRule, project1Branch1, project1Branch1); + db.issues().insertHotspot(hotspotRule, project1Branch1, project1Branch1); + IssueDto issueOnFileOnProject1Branch1 = db.issues().insertIssue(issueRule, project1Branch1, fileOnProject1Branch1); + IssueDto issueOnProject1Branch2 = db.issues().insertIssue(issueRule, project1Branch2, project1Branch2); + IssueDto issueOnProject2 = db.issues().insertIssue(issueRule, project2, project2); + db.issues().insertHotspot(hotspotRule, project2, project2); allowAnyoneOnProjects(project1, project2, application); userSession.addProjectPermission(USER, application); indexIssuesAndViews(); diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java index d0f6b112c14..396b09db19b 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java @@ -98,6 +98,7 @@ import static org.sonar.db.component.ComponentTesting.newFileDto; import static org.sonar.db.issue.IssueTesting.newDto; import static org.sonar.server.tester.UserSessionRule.standalone; import static org.sonarqube.ws.Common.RuleType.BUG; +import static org.sonarqube.ws.Common.RuleType.SECURITY_HOTSPOT_VALUE; import static org.sonarqube.ws.Common.RuleType.VULNERABILITY; import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_BRANCH; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ADDITIONAL_FIELDS; @@ -148,7 +149,7 @@ public class SearchActionTest { indexPermissions(); ComponentDto file = db.components().insertComponent(newFileDto(project)); UserDto simon = db.users().insertUser(); - RuleDefinitionDto rule = newRule().getDefinition(); + RuleDefinitionDto rule = newIssueRule().getDefinition(); IssueDto issue = db.issues().insertIssue(rule, project, file, i -> i .setEffort(10L) .setLine(42) @@ -204,7 +205,7 @@ public class SearchActionTest { ComponentDto project = db.components().insertPublicProject(organization); indexPermissions(); ComponentDto file = db.components().insertComponent(newFileDto(project)); - RuleDefinitionDto rule = newRule().getDefinition(); + RuleDefinitionDto rule = newIssueRule().getDefinition(); IssueDto issue = db.issues().insertIssue(rule, project, file, i -> i.setAuthorLogin("John")); indexIssues(); @@ -253,7 +254,7 @@ public class SearchActionTest { .setEndOffset(12) .build()) .build()))); - RuleDefinitionDto rule = newRule().getDefinition(); + RuleDefinitionDto rule = newIssueRule().getDefinition(); db.issues().insertIssue(rule, project, file, i -> i.setLocations(locations.build())); indexIssues(); @@ -274,7 +275,7 @@ public class SearchActionTest { ComponentDto project = db.components().insertPublicProject(); indexPermissions(); ComponentDto file = db.components().insertComponent(newFileDto(project)); - RuleDefinitionDto rule = newRule().getDefinition(); + RuleDefinitionDto rule = newIssueRule().getDefinition(); IssueDto issue = db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")); dbClient.issueChangeDao().insert(session, new IssueChangeDto().setIssueKey(issue.getKey()) @@ -307,7 +308,7 @@ public class SearchActionTest { ComponentDto project = db.components().insertPublicProject(); indexPermissions(); ComponentDto file = db.components().insertComponent(newFileDto(project)); - RuleDefinitionDto rule = newRule().getDefinition(); + RuleDefinitionDto rule = newIssueRule().getDefinition(); IssueDto issue = db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")); dbClient.issueChangeDao().insert(session, new IssueChangeDto().setIssueKey(issue.getKey()) @@ -342,7 +343,7 @@ public class SearchActionTest { ComponentDto project = db.components().insertPublicProject(); indexPermissions(); ComponentDto file = db.components().insertComponent(newFileDto(project)); - RuleDefinitionDto rule = newRule().getDefinition(); + RuleDefinitionDto rule = newIssueRule().getDefinition(); db.issues().insertIssue(rule, project, file, i -> i.setAssigneeUuid(simon.getUuid()).setType(CODE_SMELL)); indexIssues(); userSession.logIn("john"); @@ -362,7 +363,7 @@ public class SearchActionTest { indexPermissions(); ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY").setLanguage("js")); - IssueDto issue = newDto(newRule(), file, project) + IssueDto issue = newDto(newIssueRule(), file, project) .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2") .setAuthorLogin(fabrice.getLogin()) .setAssigneeUuid(simon.getUuid()) @@ -380,7 +381,7 @@ public class SearchActionTest { @Test public void search_by_rule_key() { - RuleDto rule = newRule(); + RuleDto rule = newIssueRule(); OrganizationDto organization = db.organizations().insert(o -> o.setKey("my-org-1")); ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto(organization, "PROJECT_ID").setDbKey("PROJECT_KEY").setLanguage("java")); ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY").setLanguage("java")); @@ -402,7 +403,7 @@ public class SearchActionTest { @Test public void issue_on_removed_file() { - RuleDto rule = newRule(); + RuleDto rule = newIssueRule(); OrganizationDto organization = db.organizations().insert(o -> o.setKey("my-org-2")); ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto(organization, "PROJECT_ID").setDbKey("PROJECT_KEY")); indexPermissions(); @@ -428,7 +429,7 @@ public class SearchActionTest { @Test public void apply_paging_with_one_component() { - RuleDto rule = newRule(); + RuleDto rule = newIssueRule(); OrganizationDto organization = db.organizations().insert(o -> o.setKey("my-org-2")); ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto(organization, "PROJECT_ID").setDbKey("PROJECT_KEY")); indexPermissions(); @@ -451,7 +452,7 @@ public class SearchActionTest { indexPermissions(); ComponentDto module = db.components().insertComponent(ComponentTesting.newModuleDto(project).setDbKey("ModuleHavingFile")); ComponentDto file = db.components().insertComponent(newFileDto(module, null, "BCDE").setDbKey("FileLinkedToModule")); - IssueDto issue = newDto(newRule(), file, project); + IssueDto issue = newDto(newIssueRule(), file, project); dbClient.issueDao().insert(session, issue); session.commit(); indexIssues(); @@ -468,7 +469,7 @@ public class SearchActionTest { ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto(organization, "PROJECT_ID").setDbKey("PROJECT_KEY")); indexPermissions(); ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY")); - RuleDto rule = newRule(); + RuleDto rule = newIssueRule(); IssueDto issue1 = newDto(rule, file, project) .setIssueCreationDate(parseDate("2014-09-04")) .setIssueUpdateDate(parseDate("2017-12-04")) @@ -515,7 +516,7 @@ public class SearchActionTest { ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto(organization, "PROJECT_ID").setDbKey("PROJECT_KEY")); indexPermissions(); ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY")); - RuleDto rule = newRule(); + RuleDto rule = newIssueRule(); IssueDto issue1 = newDto(rule, file, project) .setIssueCreationDate(parseDate("2014-09-04")) .setIssueUpdateDate(parseDate("2017-12-04")) @@ -565,7 +566,7 @@ public class SearchActionTest { ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto(organization, "PROJECT_ID").setDbKey("PROJECT_KEY")); indexPermissions(); ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY")); - RuleDto rule = newRule(); + RuleDto rule = newIssueRule(); IssueDto issue1 = newDto(rule, file, project) .setStatus("OPEN") .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2") @@ -657,7 +658,7 @@ public class SearchActionTest { @Test public void sort_by_updated_at() { - RuleDto rule = newRule(); + RuleDto rule = newIssueRule(); OrganizationDto organization = db.organizations().insert(o -> o.setKey("my-org-2")); ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto(organization, "PROJECT_ID").setDbKey("PROJECT_KEY")); indexPermissions(); @@ -757,12 +758,13 @@ public class SearchActionTest { UserDto user = db.users().insertUser(); ComponentDto project = db.components().insertPublicProject(); ComponentDto file = db.components().insertComponent(newFileDto(project)); - RuleDefinitionDto rule = db.rules().insertIssueRule(); - db.issues().insertHotspot(rule, project, file, issueDto -> issueDto.setAssigneeUuid(user.getUuid())); - IssueDto issueDto1 = db.issues().insertIssue(rule, project, file, issueDto -> issueDto.setAssigneeUuid(user.getUuid())); - IssueDto issueDto2 = db.issues().insertIssue(rule, project, file, issueDto -> issueDto.setAssigneeUuid(user.getUuid())); - IssueDto issueDto3 = db.issues().insertIssue(rule, project, file, issueDto -> issueDto.setAssigneeUuid(user.getUuid())); - IssueDto issueDto4 = db.issues().insertIssue(rule, project, file, issueDto -> issueDto.setAssigneeUuid(user.getUuid())); + RuleDefinitionDto hotspotRule = db.rules().insertHotspotRule(); + db.issues().insertHotspot(hotspotRule, project, file, issueDto -> issueDto.setAssigneeUuid(user.getUuid())); + RuleDefinitionDto issueRule = db.rules().insertIssueRule(); + IssueDto issueDto1 = db.issues().insertIssue(issueRule, project, file, issueDto -> issueDto.setAssigneeUuid(user.getUuid())); + IssueDto issueDto2 = db.issues().insertIssue(issueRule, project, file, issueDto -> issueDto.setAssigneeUuid(user.getUuid())); + IssueDto issueDto3 = db.issues().insertIssue(issueRule, project, file, issueDto -> issueDto.setAssigneeUuid(user.getUuid())); + IssueDto issueDto4 = db.issues().insertIssue(issueRule, project, file, issueDto -> issueDto.setAssigneeUuid(user.getUuid())); indexPermissions(); indexIssues(); @@ -796,7 +798,7 @@ public class SearchActionTest { public void security_hotspots_are_not_returned_by_issues_param_only() { ComponentDto project = db.components().insertPublicProject(); ComponentDto file = db.components().insertComponent(newFileDto(project)); - RuleDefinitionDto rule = db.rules().insertIssueRule(); + RuleDefinitionDto rule = db.rules().insertHotspotRule(); List hotspots = IntStream.range(1, 2 + new Random().nextInt(10)) .mapToObj(value -> db.issues().insertHotspot(rule, project, file)) .collect(Collectors.toList()); @@ -815,11 +817,12 @@ public class SearchActionTest { public void fail_if_trying_to_filter_issues_by_hotspots() { ComponentDto project = db.components().insertPublicProject(); ComponentDto file = db.components().insertComponent(newFileDto(project)); - RuleDefinitionDto rule = newRule().getDefinition(); - db.issues().insertIssue(rule, project, file, i -> i.setType(RuleType.BUG)); - db.issues().insertIssue(rule, project, file, i -> i.setType(RuleType.VULNERABILITY)); - db.issues().insertIssue(rule, project, file, i -> i.setType(CODE_SMELL)); - db.issues().insertHotspot(rule, project, file); + RuleDefinitionDto issueRule = newIssueRule().getDefinition(); + RuleDefinitionDto hotspotRule = newHotspotRule().getDefinition(); + db.issues().insertIssue(issueRule, project, file, i -> i.setType(RuleType.BUG)); + db.issues().insertIssue(issueRule, project, file, i -> i.setType(RuleType.VULNERABILITY)); + db.issues().insertIssue(issueRule, project, file, i -> i.setType(CODE_SMELL)); + db.issues().insertHotspot(hotspotRule, project, file); indexPermissions(); indexIssues(); @@ -878,7 +881,7 @@ public class SearchActionTest { @Test public void paging() { - RuleDto rule = newRule(); + RuleDto rule = newIssueRule(); OrganizationDto organization = db.organizations().insert(o -> o.setKey("my-org-1")); ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto(organization, "PROJECT_ID").setDbKey("PROJECT_KEY")); indexPermissions(); @@ -899,7 +902,7 @@ public class SearchActionTest { @Test public void paging_with_page_size_to_minus_one() { - RuleDto rule = newRule(); + RuleDto rule = newIssueRule(); OrganizationDto organization = db.organizations().insert(o -> o.setKey("my-org-1")); ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto(organization, "PROJECT_ID").setDbKey("PROJECT_KEY")); indexPermissions(); @@ -988,7 +991,7 @@ public class SearchActionTest { "This parameter is mostly used by the Issues page, please prefer usage of the componentKeys parameter. If this parameter is set, projectUuids must not be set."); } - private RuleDto newRule() { + private RuleDto newIssueRule() { RuleDto rule = RuleTesting.newXooX1() .setName("Rule name") .setDescription("Rule desc") @@ -997,6 +1000,16 @@ public class SearchActionTest { return rule; } + private RuleDto newHotspotRule() { + RuleDto rule = RuleTesting.newXooX2() + .setName("Rule name") + .setDescription("Rule desc") + .setStatus(RuleStatus.READY) + .setType(SECURITY_HOTSPOT_VALUE); + db.rules().insert(rule.getDefinition()); + return rule; + } + private void indexPermissions() { permissionIndexer.indexOnStartup(permissionIndexer.getIndexTypes()); } diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SetTagsActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SetTagsActionTest.java index 243d6dc4e3b..b6acfc186ab 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SetTagsActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SetTagsActionTest.java @@ -42,6 +42,7 @@ import org.sonar.db.rule.RuleDefinitionDto; import org.sonar.db.user.UserDto; import org.sonar.server.es.EsTester; import org.sonar.server.exceptions.ForbiddenException; +import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.exceptions.UnauthorizedException; import org.sonar.server.issue.IssueFieldsSetter; import org.sonar.server.issue.IssueFinder; @@ -209,6 +210,19 @@ public class SetTagsActionTest { call(issueDto.getKey(), "bug"); } + @Test + public void fail_when_security_hotspot() { + RuleDefinitionDto rule = db.rules().insertHotspotRule(); + ComponentDto project = db.components().insertMainBranch(newPublicProjectDto(db.getDefaultOrganization())); + ComponentDto file = db.components().insertComponent(newFileDto(project)); + IssueDto issueDto = db.issues().insertHotspot(rule, project, file); + logIn(issueDto); + + expectedException.expect(NotFoundException.class); + + call(issueDto.getKey(), "bug"); + } + @Test public void test_definition() { Action action = ws.getDef(); diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/TagsActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/TagsActionTest.java index 861f2abd7ad..b386900b54b 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/TagsActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/TagsActionTest.java @@ -19,6 +19,8 @@ */ package org.sonar.server.issue.ws; +import com.google.protobuf.ProtocolStringList; +import java.util.function.Consumer; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -28,6 +30,7 @@ import org.sonar.api.utils.System2; import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ResourceTypesRule; +import org.sonar.db.issue.IssueDto; import org.sonar.db.organization.OrganizationDto; import org.sonar.db.rule.RuleDefinitionDto; import org.sonar.server.component.ComponentFinder; @@ -39,6 +42,7 @@ import org.sonar.server.permission.index.PermissionIndexerTester; import org.sonar.server.permission.index.WebAuthorizationTypeSupport; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.view.index.ViewIndexer; +import org.sonar.server.ws.TestRequest; import org.sonar.server.ws.WsActionTester; import org.sonarqube.ws.Issues.TagsResponse; @@ -86,6 +90,21 @@ public class TagsActionTest { assertThat(result.getTagsList()).containsExactly("tag1", "tag2", "tag3", "tag4", "tag5"); } + @Test + public void search_tags_ignores_hotspots() { + ComponentDto project = db.components().insertPrivateProject(); + RuleDefinitionDto issueRule = db.rules().insertIssueRule(); + RuleDefinitionDto hotspotRule = db.rules().insertHotspotRule(); + Consumer setTags = issue -> issue.setTags(asList("tag1", "tag2")); + db.issues().insertIssue(issueRule, project, project, setTags); + db.issues().insertHotspot(hotspotRule, project, project, setTags); + issueIndexer.indexOnStartup(emptySet()); + permissionIndexer.allowOnlyAnyone(project); + TestRequest testRequest = ws.newRequest(); + + assertThat(tagListOf(testRequest)).containsExactly("tag1", "tag2"); + } + @Test public void search_tags_by_query() { RuleDefinitionDto rule = db.rules().insertIssueRule(); @@ -95,11 +114,26 @@ public class TagsActionTest { issueIndexer.indexOnStartup(emptySet()); permissionIndexer.allowOnlyAnyone(project); - TagsResponse result = ws.newRequest() - .setParam("q", "ag1") - .executeProtobuf(TagsResponse.class); + assertThat(tagListOf(ws.newRequest().setParam("q", "ag1"))).containsExactly("tag1", "tag12"); + } - assertThat(result.getTagsList()).containsExactly("tag1", "tag12"); + @Test + public void search_tags_by_query_ignores_hotspots() { + RuleDefinitionDto issueRule = db.rules().insertIssueRule(); + RuleDefinitionDto hotspotRule = db.rules().insertHotspotRule(); + ComponentDto project = db.components().insertPrivateProject(); + db.issues().insertIssue(issueRule, project, project, issue -> issue.setTags(asList("tag1", "tag2"))); + db.issues().insertHotspot(hotspotRule, project, project, issue -> issue.setTags(asList("tag1", "tag12", "tag4", "tag5"))); + issueIndexer.indexOnStartup(emptySet()); + permissionIndexer.allowOnlyAnyone(project); + TestRequest testRequest = ws.newRequest(); + + assertThat(tagListOf(testRequest)).containsExactly("tag1", "tag2"); + assertThat(tagListOf(testRequest.setParam("q", "ag1"))).containsExactly("tag1"); + assertThat(tagListOf(testRequest.setParam("q", "tag1"))).containsExactly("tag1"); + assertThat(tagListOf(testRequest.setParam("q", "tag12"))).isEmpty(); + assertThat(tagListOf(testRequest.setParam("q", "tag2"))).containsOnly("tag2"); + assertThat(tagListOf(testRequest.setParam("q", "ag5"))).isEmpty(); } @Test @@ -116,11 +150,27 @@ public class TagsActionTest { issueIndexer.indexOnStartup(emptySet()); permissionIndexer.allowOnlyAnyone(project1, project2); - TagsResponse result = ws.newRequest() - .setParam("organization", organization1.getKey()) - .executeProtobuf(TagsResponse.class); + assertThat(tagListOf(ws.newRequest().setParam("organization", organization1.getKey()))).containsExactly("tag1", "tag2"); + } - assertThat(result.getTagsList()).containsExactly("tag1", "tag2"); + @Test + public void search_tags_by_organization_ignores_hotspots() { + RuleDefinitionDto issueRule = db.rules().insertIssueRule(); + RuleDefinitionDto hotspotRule = db.rules().insertHotspotRule(); + // Tags on issues of organization 1 + OrganizationDto organization1 = db.organizations().insert(); + ComponentDto project1 = db.components().insertPrivateProject(organization1); + db.issues().insertIssue(issueRule, project1, project1, issue -> issue.setTags(asList("tag1", "tag2"))); + db.issues().insertHotspot(hotspotRule, project1, project1, issue -> issue.setTags(asList("tag3", "tag4"))); + // Tags on issues of organization 2 + OrganizationDto organization2 = db.organizations().insert(); + ComponentDto project2 = db.components().insertPrivateProject(organization2); + db.issues().insertIssue(issueRule, project2, project2, issue -> issue.setTags(singletonList("tag5"))); + db.issues().insertHotspot(hotspotRule, project2, project2, issue -> issue.setTags(singletonList("tag6"))); + issueIndexer.indexOnStartup(emptySet()); + permissionIndexer.allowOnlyAnyone(project1, project2); + + assertThat(tagListOf(ws.newRequest().setParam("organization", organization1.getKey()))).containsExactly("tag1", "tag2"); } @Test @@ -134,12 +184,28 @@ public class TagsActionTest { issueIndexer.indexOnStartup(emptySet()); permissionIndexer.allowOnlyAnyone(project1, project2); - TagsResponse result = ws.newRequest() + assertThat(tagListOf(ws.newRequest() .setParam("organization", organization.getKey()) - .setParam("project", project1.getKey()) - .executeProtobuf(TagsResponse.class); + .setParam("project", project1.getKey()))).containsExactly("tag1"); + } - assertThat(result.getTagsList()).containsExactly("tag1"); + @Test + public void search_tags_by_project_ignores_hotspots() { + RuleDefinitionDto issueRule = db.rules().insertIssueRule(); + RuleDefinitionDto hotspotRule = db.rules().insertHotspotRule(); + OrganizationDto organization = db.organizations().insert(); + ComponentDto project1 = db.components().insertPrivateProject(organization); + ComponentDto project2 = db.components().insertPrivateProject(organization); + db.issues().insertHotspot(hotspotRule, project1, project1, issue -> issue.setTags(singletonList("tag1"))); + db.issues().insertIssue(issueRule, project1, project1, issue -> issue.setTags(singletonList("tag2"))); + db.issues().insertHotspot(hotspotRule, project2, project2, issue -> issue.setTags(singletonList("tag3"))); + db.issues().insertIssue(issueRule, project2, project2, issue -> issue.setTags(singletonList("tag4"))); + issueIndexer.indexOnStartup(emptySet()); + permissionIndexer.allowOnlyAnyone(project1, project2); + + assertThat(tagListOf(ws.newRequest() + .setParam("organization", organization.getKey()) + .setParam("project", project1.getKey()))).containsExactly("tag2"); } @Test @@ -155,11 +221,25 @@ public class TagsActionTest { viewIndexer.indexOnStartup(emptySet()); userSession.logIn().addMembership(organization); - TagsResponse result = ws.newRequest() - .setParam("project", portfolio.getKey()) - .executeProtobuf(TagsResponse.class); + assertThat(tagListOf(ws.newRequest().setParam("project", portfolio.getKey()))).containsExactly("cwe"); + } - assertThat(result.getTagsList()).containsExactly("cwe"); + @Test + public void search_tags_by_portfolio_ignores_hotspots() { + OrganizationDto organization = db.getDefaultOrganization(); + ComponentDto portfolio = db.components().insertPrivatePortfolio(organization); + ComponentDto project = db.components().insertPrivateProject(organization); + db.components().insertComponent(newProjectCopy(project, portfolio)); + permissionIndexer.allowOnlyAnyone(project); + RuleDefinitionDto issueRule = db.rules().insertIssueRule(); + RuleDefinitionDto hotspotRule = db.rules().insertHotspotRule(); + db.issues().insertHotspot(hotspotRule, project, project, issue -> issue.setTags(singletonList("cwe"))); + db.issues().insertIssue(issueRule, project, project, issue -> issue.setTags(singletonList("foo"))); + issueIndexer.indexOnStartup(emptySet()); + viewIndexer.indexOnStartup(emptySet()); + userSession.logIn().addMembership(organization); + + assertThat(tagListOf(ws.newRequest().setParam("project", portfolio.getKey()))).containsExactly("foo"); } @Test @@ -175,11 +255,25 @@ public class TagsActionTest { viewIndexer.indexOnStartup(emptySet()); userSession.logIn().addMembership(organization); - TagsResponse result = ws.newRequest() - .setParam("project", application.getKey()) - .executeProtobuf(TagsResponse.class); + assertThat(tagListOf(ws.newRequest().setParam("project", application.getKey()))).containsExactly("cwe"); + } + + @Test + public void search_tags_by_application_ignores_hotspots() { + OrganizationDto organization = db.getDefaultOrganization(); + ComponentDto application = db.components().insertPrivateApplication(organization); + ComponentDto project = db.components().insertPrivateProject(organization); + db.components().insertComponent(newProjectCopy(project, application)); + permissionIndexer.allowOnlyAnyone(project); + RuleDefinitionDto issueRule = db.rules().insertIssueRule(); + RuleDefinitionDto hotspotRule = db.rules().insertHotspotRule(); + db.issues().insertIssue(issueRule, project, project, issue -> issue.setTags(singletonList("cwe"))); + db.issues().insertHotspot(hotspotRule, project, project, issue -> issue.setTags(singletonList("foo"))); + issueIndexer.indexOnStartup(emptySet()); + viewIndexer.indexOnStartup(emptySet()); + userSession.logIn().addMembership(organization); - assertThat(result.getTagsList()).containsExactly("cwe"); + assertThat(tagListOf(ws.newRequest().setParam("project", application.getKey()))).containsExactly("cwe"); } @Test @@ -305,4 +399,8 @@ public class TagsActionTest { tuple("project", null, "7.4", false, false)); } + private static ProtocolStringList tagListOf(TestRequest testRequest) { + return testRequest.executeProtobuf(TagsResponse.class).getTagsList(); + } + } -- 2.39.5