From c8908618870b5a65bba9d61f730b14928f6c1002 Mon Sep 17 00:00:00 2001 From: Jacek Date: Wed, 11 Dec 2019 16:35:02 +0100 Subject: [PATCH] SONAR-12723 remove hotspots from issues API --- .../java/org/sonar/db/issue/IssueTesting.java | 6 +- .../org/sonar/server/issue/IssueFinder.java | 8 + .../sonar/server/issue/ws/SearchAction.java | 84 ++++----- .../issue/ws/EditCommentActionTest.java | 33 +++- .../issue/ws/SearchActionComponentsTest.java | 37 ++-- .../issue/ws/SearchActionFacetsTest.java | 52 ++++-- .../server/issue/ws/SearchActionTest.java | 50 ++---- .../ws/SearchActionTestOnSonarCloud.java | 170 ------------------ .../server/issue/ws/SetTypeActionTest.java | 6 +- 9 files changed, 145 insertions(+), 301 deletions(-) delete mode 100644 server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionTestOnSonarCloud.java diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueTesting.java b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueTesting.java index c700eef4330..2a921520f23 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueTesting.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueTesting.java @@ -19,7 +19,9 @@ */ package org.sonar.db.issue; +import java.util.Arrays; import java.util.Date; +import java.util.Random; import org.apache.commons.lang.math.RandomUtils; import org.sonar.api.issue.Issue; import org.sonar.api.resources.Qualifiers; @@ -40,6 +42,8 @@ import static org.apache.commons.lang.math.RandomUtils.nextInt; import static org.apache.commons.lang.math.RandomUtils.nextLong; public class IssueTesting { + private static final RuleType[] RULE_TYPES_EXCEPT_HOTSPOTS = Arrays.stream(RuleType.values()) + .filter(ruleType -> RuleType.SECURITY_HOTSPOT != ruleType).toArray(RuleType[]::new); private IssueTesting() { // only statics @@ -52,7 +56,7 @@ public class IssueTesting { return new IssueDto() .setKee("uuid_" + randomAlphabetic(5)) .setRule(rule) - .setType(RuleType.values()[nextInt(RuleType.values().length)]) + .setType(RULE_TYPES_EXCEPT_HOTSPOTS[new Random().nextInt(RULE_TYPES_EXCEPT_HOTSPOTS.length)]) .setProject(project) .setComponent(file) .setStatus(Issue.STATUS_OPEN) diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/IssueFinder.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/IssueFinder.java index 2c813e77e1d..063e0359daa 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/IssueFinder.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/IssueFinder.java @@ -19,6 +19,7 @@ */ package org.sonar.server.issue; +import org.sonar.api.rules.RuleType; import org.sonar.api.web.UserRole; import org.sonar.db.DbClient; import org.sonar.db.DbSession; @@ -28,6 +29,7 @@ import org.sonar.server.user.UserSession; import static java.lang.String.format; import static java.util.Objects.requireNonNull; +import static org.sonar.api.rules.RuleType.SECURITY_HOTSPOT; public class IssueFinder { @@ -41,6 +43,12 @@ public class IssueFinder { public IssueDto getByKey(DbSession session, String issueKey) { IssueDto issue = dbClient.issueDao().selectByKey(session, issueKey).orElseThrow(() -> new NotFoundException(format("Issue with key '%s' does not exist", issueKey))); + + RuleType ruleType = RuleType.valueOfNullable(issue.getType()); + if (SECURITY_HOTSPOT.equals(ruleType)) { + throw new NotFoundException(format("Issue with key '%s' does not exist", issueKey)); + } + userSession.checkComponentUuidPermission(UserRole.USER, requireNonNull(issue.getProjectUuid())); return issue; } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchAction.java index e51e384c0e5..9b217558ea1 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchAction.java @@ -19,7 +19,6 @@ */ package org.sonar.server.issue.ws; -import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import java.util.ArrayList; @@ -27,14 +26,11 @@ import java.util.Arrays; import java.util.EnumSet; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import javax.annotation.Nullable; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.search.SearchHit; -import org.sonar.api.Startable; -import org.sonar.api.config.Configuration; import org.sonar.api.rule.Severity; import org.sonar.api.rules.RuleType; import org.sonar.api.server.ws.Change; @@ -47,7 +43,6 @@ 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.organization.OrganizationDto; import org.sonar.db.user.UserDto; import org.sonar.server.es.Facets; import org.sonar.server.es.SearchOptions; @@ -81,7 +76,6 @@ import static org.sonar.api.issue.Issue.STATUS_TO_REVIEW; import static org.sonar.api.server.ws.WebService.Param.FACETS; import static org.sonar.api.utils.Paging.forPageIndex; import static org.sonar.core.util.stream.MoreCollectors.toSet; -import static org.sonar.process.ProcessProperties.Property.SONARCLOUD_ENABLED; import static org.sonar.server.es.SearchOptions.MAX_LIMIT; import static org.sonar.server.issue.index.IssueIndex.FACET_ASSIGNED_TO_ME; import static org.sonar.server.issue.index.IssueIndex.FACET_PROJECTS; @@ -135,9 +129,10 @@ import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_STATUSES; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_TAGS; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_TYPES; -public class SearchAction implements IssuesWsAction, Startable { +public class SearchAction implements IssuesWsAction { private static final String LOGIN_MYSELF = "__me__"; + private static final EnumSet ALL_RULE_TYPES_EXCEPT_SECURITY_HOTSPOTS = EnumSet.complementOf(EnumSet.of(RuleType.SECURITY_HOTSPOT)); static final List SUPPORTED_FACETS = ImmutableList.of( FACET_PROJECTS, @@ -163,26 +158,22 @@ public class SearchAction implements IssuesWsAction, Startable { private static final String INTERNAL_PARAMETER_DISCLAIMER = "This parameter is mostly used by the Issues page, please prefer usage of the componentKeys parameter. "; private static final Set FACETS_REQUIRING_PROJECT_OR_ORGANIZATION = newHashSet(PARAM_MODULE_UUIDS, PARAM_FILE_UUIDS, PARAM_DIRECTORIES); - private static final Joiner COMA_JOINER = Joiner.on(","); private final UserSession userSession; private final IssueIndex issueIndex; private final IssueQueryFactory issueQueryFactory; private final SearchResponseLoader searchResponseLoader; private final SearchResponseFormat searchResponseFormat; - private final Configuration config; private final System2 system2; private final DbClient dbClient; - private boolean isOnSonarCloud; public SearchAction(UserSession userSession, IssueIndex issueIndex, IssueQueryFactory issueQueryFactory, SearchResponseLoader searchResponseLoader, - SearchResponseFormat searchResponseFormat, Configuration config, System2 system2, DbClient dbClient) { + SearchResponseFormat searchResponseFormat, System2 system2, DbClient dbClient) { this.userSession = userSession; this.issueIndex = issueIndex; this.issueQueryFactory = issueQueryFactory; this.searchResponseLoader = searchResponseLoader; this.searchResponseFormat = searchResponseFormat; - this.config = config; this.system2 = system2; this.dbClient = dbClient; } @@ -199,8 +190,10 @@ public class SearchAction implements IssuesWsAction, Startable { PARAM_COMPONENT_KEYS, PARAM_COMPONENT_UUIDS) .setSince("3.6") .setChangelog( - new Change("8.1", "response field 'fromHotspot' has been deprecated and is no more populated"), - new Change("8.1", format("Status %s for Security Hotspots has been deprecated", STATUS_IN_REVIEW)), + new Change("8.2", "'REVIEWED', 'TO_REVIEW' status param values are no longer supported"), + new Change("8.2", "Security hotspots are no longer returned"), + new Change("8.2", "response field 'fromHotspot' has been deprecated and is no more populated"), + new Change("8.2", format("Status %s for Security Hotspots has been deprecated", STATUS_IN_REVIEW)), new Change("7.8", format("added new Security Hotspots statuses : %s, %s and %s", STATUS_TO_REVIEW, STATUS_IN_REVIEW, STATUS_REVIEWED)), new Change("7.8", "Security hotspots are returned by default"), new Change("7.7", format("Value '%s' in parameter '%s' is deprecated, please use '%s' instead", DEPRECATED_PARAM_AUTHORS, FACETS, PARAM_AUTHOR)), @@ -261,7 +254,7 @@ public class SearchAction implements IssuesWsAction, Startable { action.createParam(PARAM_TYPES) .setDescription("Comma-separated list of types.") .setSince("5.5") - .setPossibleValues(RuleType.values()) + .setPossibleValues(ALL_RULE_TYPES_EXCEPT_SECURITY_HOTSPOTS) .setExampleValue(format("%s,%s", RuleType.CODE_SMELL, RuleType.BUG)); action.createParam(PARAM_OWASP_TOP_10) .setDescription("Comma-separated list of OWASP Top 10 lowercase categories.") @@ -391,14 +384,14 @@ public class SearchAction implements IssuesWsAction, Startable { public final void handle(Request request, Response response) { try (DbSession dbSession = dbClient.openSession(false)) { SearchRequest searchRequest = toSearchWsRequest(dbSession, request); - SearchWsResponse searchWsResponse = doHandle(dbSession, searchRequest); + SearchWsResponse searchWsResponse = doHandle(searchRequest); writeProtobuf(searchWsResponse, request, response); } } - private SearchWsResponse doHandle(DbSession dbSession, SearchRequest request) { + private SearchWsResponse doHandle(SearchRequest request) { // prepare the Elasticsearch request - SearchOptions options = createSearchOptionsFromRequest(dbSession, request); + SearchOptions options = createSearchOptionsFromRequest(request); EnumSet additionalFields = SearchAdditionalField.getFromRequest(request); IssueQuery query = issueQueryFactory.create(request); @@ -407,7 +400,7 @@ public class SearchAction implements IssuesWsAction, Startable { .collect(toSet()); checkArgument(facetsRequiringProjectOrOrganizationParameter.isEmpty() || (!query.projectUuids().isEmpty()) || query.organizationUuid() != null, "Facet(s) '%s' require to also filter by project or organization", - COMA_JOINER.join(facetsRequiringProjectOrOrganizationParameter)); + String.join(",", facetsRequiringProjectOrOrganizationParameter)); // execute request SearchResponse result = issueIndex.search(query, options); @@ -436,7 +429,7 @@ public class SearchAction implements IssuesWsAction, Startable { return searchResponseFormat.formatSearch(additionalFields, data, paging, facets); } - private SearchOptions createSearchOptionsFromRequest(DbSession dbSession, SearchRequest request) { + private SearchOptions createSearchOptionsFromRequest(SearchRequest request) { SearchOptions options = new SearchOptions(); options.setPage(request.getPage(), request.getPageSize()); @@ -446,29 +439,13 @@ public class SearchAction implements IssuesWsAction, Startable { return options; } - List requestedFacets = new ArrayList<>(facets); - if (isOnSonarCloud) { - Optional organizationDto = Optional.empty(); - String organizationKey = request.getOrganization(); - if (organizationKey != null) { - organizationDto = dbClient.organizationDao().selectByKey(dbSession, organizationKey); - } - - if (!organizationDto.isPresent() || !userSession.hasMembership(organizationDto.get())) { - // In order to display the authors facet, the organization parameter must be set and the user - // must be member of this organization - requestedFacets.remove(PARAM_AUTHOR); - requestedFacets.remove(DEPRECATED_PARAM_AUTHORS); - } - } - - options.addFacets(requestedFacets); + options.addFacets(facets); return options; } private void completeFacets(Facets facets, SearchRequest request, IssueQuery query) { addMandatoryValuesToFacet(facets, PARAM_SEVERITIES, Severity.ALL); - addMandatoryValuesToFacet(facets, PARAM_STATUSES, STATUSES); + addMandatoryValuesToFacet(facets, PARAM_STATUSES, STATUSES.stream().filter(s -> !STATUS_TO_REVIEW.equals(s)).filter(s -> !STATUS_REVIEWED.equals(s)).collect(toList())); addMandatoryValuesToFacet(facets, PARAM_RESOLUTIONS, concat(singletonList(""), RESOLUTIONS)); addMandatoryValuesToFacet(facets, FACET_PROJECTS, query.projectUuids()); addMandatoryValuesToFacet(facets, PARAM_MODULE_UUIDS, query.moduleUuids()); @@ -486,13 +463,23 @@ public class SearchAction implements IssuesWsAction, Startable { addMandatoryValuesToFacet(facets, PARAM_RULES, query.rules().stream().map(IssueDoc::formatRuleId).collect(toList())); addMandatoryValuesToFacet(facets, PARAM_LANGUAGES, request.getLanguages()); addMandatoryValuesToFacet(facets, PARAM_TAGS, request.getTags()); - addMandatoryValuesToFacet(facets, PARAM_TYPES, RuleType.names()); + + setTypesFacet(facets); + addMandatoryValuesToFacet(facets, PARAM_OWASP_TOP_10, request.getOwaspTop10()); addMandatoryValuesToFacet(facets, PARAM_SANS_TOP_25, request.getSansTop25()); addMandatoryValuesToFacet(facets, PARAM_CWE, request.getCwe()); addMandatoryValuesToFacet(facets, PARAM_SONARSOURCE_SECURITY, request.getSonarsourceSecurity()); } + private void setTypesFacet(Facets facets) { + Map typeFacet = facets.get(PARAM_TYPES); + if (typeFacet != null) { + typeFacet.remove(RuleType.SECURITY_HOTSPOT.name()); + } + addMandatoryValuesToFacet(facets, PARAM_TYPES, ALL_RULE_TYPES_EXCEPT_SECURITY_HOTSPOTS.stream().map(Enum::name).collect(Collectors.toList())); + } + private static void addMandatoryValuesToFacet(Facets facets, String facetName, @Nullable Iterable mandatoryValues) { Map buckets = facets.get(facetName); if (buckets != null && mandatoryValues != null) { @@ -562,13 +549,20 @@ public class SearchAction implements IssuesWsAction, Startable { .setSeverities(request.paramAsStrings(PARAM_SEVERITIES)) .setStatuses(request.paramAsStrings(PARAM_STATUSES)) .setTags(request.paramAsStrings(PARAM_TAGS)) - .setTypes(request.paramAsStrings(PARAM_TYPES)) + .setTypes(allRuleTypesExceptHotspotsIfEmpty(request.paramAsStrings(PARAM_TYPES))) .setOwaspTop10(request.paramAsStrings(PARAM_OWASP_TOP_10)) .setSansTop25(request.paramAsStrings(PARAM_SANS_TOP_25)) .setCwe(request.paramAsStrings(PARAM_CWE)) .setSonarsourceSecurity(request.paramAsStrings(PARAM_SONARSOURCE_SECURITY)); } + private List allRuleTypesExceptHotspotsIfEmpty(@Nullable List types) { + if (types == null || types.isEmpty()) { + return ALL_RULE_TYPES_EXCEPT_SECURITY_HOTSPOTS.stream().map(Enum::name).collect(toList()); + } + return types; + } + private List getLogins(DbSession dbSession, @Nullable List assigneeLogins) { List userLogins = new ArrayList<>(); @@ -592,14 +586,4 @@ public class SearchAction implements IssuesWsAction, Startable { } return assigneeUuid; } - - @Override - public void start() { - this.isOnSonarCloud = config.getBoolean(SONARCLOUD_ENABLED.getKey()).orElse(false); - } - - @Override - public void stop() { - // Nothing to do - } } diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/EditCommentActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/EditCommentActionTest.java index b97344b5c96..80310ccd178 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/EditCommentActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/EditCommentActionTest.java @@ -19,12 +19,15 @@ */ package org.sonar.server.issue.ws; +import java.util.Arrays; +import java.util.Random; import javax.annotation.Nullable; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.ArgumentCaptor; +import org.sonar.api.rules.RuleType; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; @@ -57,6 +60,8 @@ import static org.sonar.api.web.UserRole.USER; public class EditCommentActionTest { private static final long NOW = 10_000_000_000L; + private static final RuleType[] RULE_TYPES_EXCEPT_HOTSPOTS = Arrays.stream(RuleType.values()) + .filter(ruleType -> RuleType.SECURITY_HOTSPOT != ruleType).toArray(RuleType[]::new); @Rule public ExpectedException expectedException = ExpectedException.none(); @@ -81,7 +86,7 @@ public class EditCommentActionTest { @Test public void edit_comment() { - IssueDto issueDto = issueDbTester.insertIssue(); + IssueDto issueDto = newIssue(); UserDto user = dbTester.users().insertUser(); IssueChangeDto commentDto = issueDbTester.insertComment(issueDto, user, "please fix it"); loginWithBrowsePermission(user, USER, issueDto); @@ -98,7 +103,7 @@ public class EditCommentActionTest { @Test public void edit_comment_using_deprecated_key_parameter() { - IssueDto issueDto = issueDbTester.insertIssue(); + IssueDto issueDto = newIssue(); UserDto user = dbTester.users().insertUser(); IssueChangeDto commentDto = issueDbTester.insertComment(issueDto, user, "please fix it"); loginWithBrowsePermission(user, USER, issueDto); @@ -115,7 +120,7 @@ public class EditCommentActionTest { @Test public void fail_when_comment_does_not_belong_to_current_user() { - IssueDto issueDto = issueDbTester.insertIssue(); + IssueDto issueDto = newIssue(); UserDto user = dbTester.users().insertUser(); IssueChangeDto commentDto = issueDbTester.insertComment(issueDto, user, "please fix it"); UserDto another = dbTester.users().insertUser(); @@ -128,7 +133,7 @@ public class EditCommentActionTest { @Test public void fail_when_comment_has_not_user() { - IssueDto issueDto = issueDbTester.insertIssue(); + IssueDto issueDto = newIssue(); UserDto user = dbTester.users().insertUser(); IssueChangeDto commentDto = issueDbTester.insertComment(issueDto, null, "please fix it"); loginWithBrowsePermission(user, USER, issueDto); @@ -164,7 +169,7 @@ public class EditCommentActionTest { @Test public void fail_when_empty_comment_text() { - IssueDto issueDto = issueDbTester.insertIssue(); + IssueDto issueDto = newIssue(); UserDto user = dbTester.users().insertUser(); IssueChangeDto commentDto = issueDbTester.insertComment(issueDto, user, "please fix it"); loginWithBrowsePermission(user, USER, issueDto); @@ -181,7 +186,7 @@ public class EditCommentActionTest { @Test public void fail_when_not_enough_permission() { - IssueDto issueDto = issueDbTester.insertIssue(); + IssueDto issueDto = newIssue(); UserDto user = dbTester.users().insertUser(); IssueChangeDto commentDto = issueDbTester.insertComment(issueDto, user, "please fix it"); loginWithBrowsePermission(user, CODEVIEWER, issueDto); @@ -190,6 +195,18 @@ public class EditCommentActionTest { call(commentDto.getKey(), "please have a look"); } + @Test + public void fail_NFE_if_security_hotspots() { + IssueDto issueDto = issueDbTester.insertIssue(i -> i.setType(RuleType.SECURITY_HOTSPOT)); + UserDto user = dbTester.users().insertUser(); + IssueChangeDto commentDto = issueDbTester.insertComment(issueDto, user, "please fix it"); + loginWithBrowsePermission(user, CODEVIEWER, issueDto); + + expectedException.expect(NotFoundException.class); + expectedException.expectMessage(String.format("Issue with key '%s' does not exist", issueDto.getKey())); + call(commentDto.getKey(), "please have a look"); + } + @Test public void test_definition() { WebService.Action action = tester.getDef(); @@ -207,6 +224,10 @@ public class EditCommentActionTest { return request.execute(); } + private IssueDto newIssue() { + return issueDbTester.insertIssue(i -> i.setType(RULE_TYPES_EXCEPT_HOTSPOTS[new Random().nextInt(RULE_TYPES_EXCEPT_HOTSPOTS.length)])); + } + private void loginWithBrowsePermission(UserDto user, String permission, IssueDto issueDto) { userSession.logIn(user).addProjectPermission(permission, dbClient.componentDao().selectByUuid(dbTester.getSession(), issueDto.getProjectUuid()).get(), 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 418a6f6cebb..ed890d9f9c0 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 @@ -25,7 +25,6 @@ import java.util.Date; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.api.config.internal.MapSettings; import org.sonar.api.resources.Languages; import org.sonar.api.resources.Qualifiers; import org.sonar.api.rule.RuleKey; @@ -110,7 +109,7 @@ public class SearchActionComponentsTest { private PermissionIndexerTester permissionIndexer = new PermissionIndexerTester(es, issueIndexer); private WsActionTester ws = new WsActionTester(new SearchAction(userSession, issueIndex, issueQueryFactory, searchResponseLoader, searchResponseFormat, - new MapSettings().asConfig(), System2.INSTANCE, dbClient)); + System2.INSTANCE, dbClient)); @Test public void search_all_issues_when_no_parameter() { @@ -169,12 +168,12 @@ public class SearchActionComponentsTest { assertThat(ws.newRequest() .setParam(PARAM_COMPONENT_KEYS, module1.getKey()) .executeProtobuf(SearchWsResponse.class).getIssuesList()).extracting(Issue::getKey) - .containsExactlyInAnyOrder(issue1.getKey()); + .containsExactlyInAnyOrder(issue1.getKey()); assertThat(ws.newRequest() .setParam(PARAM_MODULE_UUIDS, module1.uuid()) .executeProtobuf(SearchWsResponse.class).getIssuesList()).extracting(Issue::getKey) - .containsExactlyInAnyOrder(issue1.getKey()); + .containsExactlyInAnyOrder(issue1.getKey()); } @Test @@ -482,11 +481,11 @@ public class SearchActionComponentsTest { .setParam(PARAM_COMPONENT_KEYS, applicationBranch1.getKey()) .setParam(PARAM_BRANCH, applicationBranch1.getBranch()) .executeProtobuf(SearchWsResponse.class).getIssuesList()) - .extracting(Issue::getKey, Issue::getComponent, Issue::getProject, Issue::getBranch, Issue::hasBranch) - .containsExactlyInAnyOrder( - tuple(issueOnProject1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getBranch(), true), - tuple(issueOnFileOnProject1Branch1.getKey(), fileOnProject1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getBranch(), true), - tuple(issueOnProject2.getKey(), project2.getKey(), project2.getKey(), "", false)); + .extracting(Issue::getKey, Issue::getComponent, Issue::getProject, Issue::getBranch, Issue::hasBranch) + .containsExactlyInAnyOrder( + tuple(issueOnProject1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getBranch(), true), + tuple(issueOnFileOnProject1Branch1.getKey(), fileOnProject1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getBranch(), true), + tuple(issueOnProject2.getKey(), project2.getKey(), project2.getKey(), "", false)); // Issues on project1Branch1 assertThat(ws.newRequest() @@ -494,10 +493,10 @@ public class SearchActionComponentsTest { .setParam(PARAM_PROJECTS, project1.getKey()) .setParam(PARAM_BRANCH, applicationBranch1.getBranch()) .executeProtobuf(SearchWsResponse.class).getIssuesList()) - .extracting(Issue::getKey, Issue::getComponent, Issue::getBranch) - .containsExactlyInAnyOrder( - tuple(issueOnProject1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getBranch()), - tuple(issueOnFileOnProject1Branch1.getKey(), fileOnProject1Branch1.getKey(), project1Branch1.getBranch())); + .extracting(Issue::getKey, Issue::getComponent, Issue::getBranch) + .containsExactlyInAnyOrder( + tuple(issueOnProject1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getBranch()), + tuple(issueOnFileOnProject1Branch1.getKey(), fileOnProject1Branch1.getKey(), project1Branch1.getBranch())); } @Test @@ -668,24 +667,24 @@ public class SearchActionComponentsTest { .setParam(PARAM_COMPONENT_KEYS, project.getKey()) .setParam(PARAM_BRANCH, branch.getBranch()) .executeProtobuf(SearchWsResponse.class).getIssuesList()) - .extracting(Issue::getKey, Issue::getComponent, Issue::getBranch) - .containsExactlyInAnyOrder(tuple(branchIssue.getKey(), branchFile.getKey(), branchFile.getBranch())); + .extracting(Issue::getKey, Issue::getComponent, Issue::getBranch) + .containsExactlyInAnyOrder(tuple(branchIssue.getKey(), branchFile.getKey(), branchFile.getBranch())); // On project key + branch assertThat(ws.newRequest() .setParam(PARAM_PROJECT_KEYS, project.getKey()) .setParam(PARAM_BRANCH, branch.getBranch()) .executeProtobuf(SearchWsResponse.class).getIssuesList()) - .extracting(Issue::getKey, Issue::getComponent, Issue::getBranch) - .containsExactlyInAnyOrder(tuple(branchIssue.getKey(), branchFile.getKey(), branchFile.getBranch())); + .extracting(Issue::getKey, Issue::getComponent, Issue::getBranch) + .containsExactlyInAnyOrder(tuple(branchIssue.getKey(), branchFile.getKey(), branchFile.getBranch())); // On file key + branch assertThat(ws.newRequest() .setParam(PARAM_COMPONENT_KEYS, branchFile.getKey()) .setParam(PARAM_BRANCH, branch.getBranch()) .executeProtobuf(SearchWsResponse.class).getIssuesList()) - .extracting(Issue::getKey, Issue::getComponent, Issue::getBranch) - .containsExactlyInAnyOrder(tuple(branchIssue.getKey(), branchFile.getKey(), branchFile.getBranch())); + .extracting(Issue::getKey, Issue::getComponent, Issue::getBranch) + .containsExactlyInAnyOrder(tuple(branchIssue.getKey(), branchFile.getKey(), branchFile.getBranch())); } @Test diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionFacetsTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionFacetsTest.java index f9efa1812a0..0ae6fd93ab3 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionFacetsTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionFacetsTest.java @@ -21,12 +21,14 @@ package org.sonar.server.issue.ws; import com.google.common.collect.ImmutableMap; import java.time.Clock; +import java.util.Arrays; import java.util.Map; +import java.util.Random; import java.util.stream.IntStream; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.api.config.internal.MapSettings; +import org.sonar.api.issue.Issue; import org.sonar.api.resources.Languages; import org.sonar.api.rules.RuleType; import org.sonar.api.server.ws.WebService; @@ -73,6 +75,10 @@ import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PROJECTS; public class SearchActionFacetsTest { + private static final RuleType[] RULE_TYPES_EXCEPT_HOTSPOT = Arrays.stream(RuleType.values()).filter(ruleType -> RuleType.SECURITY_HOTSPOT != ruleType).toArray(RuleType[]::new); + private static final String[] ISSUE_STATUSES = Issue.STATUSES.stream().filter(s -> !Issue.STATUS_TO_REVIEW.equals(s)).filter(s -> !Issue.STATUS_REVIEWED.equals(s)) + .toArray(String[]::new); + @Rule public UserSessionRule userSession = standalone(); @Rule @@ -92,8 +98,7 @@ public class SearchActionFacetsTest { private SearchResponseFormat searchResponseFormat = new SearchResponseFormat(new Durations(), languages, new TextRangeResponseFormatter(), userFormatter); private WsActionTester ws = new WsActionTester( - new SearchAction(userSession, issueIndex, issueQueryFactory, searchResponseLoader, searchResponseFormat, - new MapSettings().asConfig(), System2.INSTANCE, db.getDbClient())); + new SearchAction(userSession, issueIndex, issueQueryFactory, searchResponseLoader, searchResponseFormat, System2.INSTANCE, db.getDbClient())); @Test public void display_all_facets() { @@ -117,7 +122,7 @@ public class SearchActionFacetsTest { .executeProtobuf(SearchWsResponse.class); Map expectedStatuses = ImmutableMap.builder().put("OPEN", 1L).put("CONFIRMED", 0L) - .put("REOPENED", 0L).put("RESOLVED", 0L).put("CLOSED", 0L).put("TO_REVIEW", 0L).put("REVIEWED", 0L).build(); + .put("REOPENED", 0L).put("RESOLVED", 0L).put("CLOSED", 0L).build(); assertThat(response.getFacets().getFacetsList()) .extracting(Common.Facet::getProperty, facet -> facet.getValuesList().stream().collect(toMap(FacetValue::getVal, FacetValue::getCount))) @@ -126,7 +131,7 @@ public class SearchActionFacetsTest { tuple("statuses", expectedStatuses), tuple("resolutions", of("", 1L, "FALSE-POSITIVE", 0L, "FIXED", 0L, "REMOVED", 0L, "WONTFIX", 0L)), tuple("rules", of(rule.getKey().toString(), 1L)), - tuple("types", of("CODE_SMELL", 1L, "BUG", 0L, "VULNERABILITY", 0L, "SECURITY_HOTSPOT", 0L)), + tuple("types", of("CODE_SMELL", 1L, "BUG", 0L, "VULNERABILITY", 0L)), tuple("languages", of(rule.getLanguage(), 1L)), tuple("projects", of(project.getKey(), 1L)), tuple("moduleUuids", of(module.uuid(), 1L)), @@ -155,7 +160,7 @@ public class SearchActionFacetsTest { .executeProtobuf(SearchWsResponse.class); Map expectedStatuses = ImmutableMap.builder().put("OPEN", 10L).put("CONFIRMED", 0L) - .put("REOPENED", 0L).put("RESOLVED", 0L).put("CLOSED", 0L).put("TO_REVIEW", 0L).put("REVIEWED", 0L).build(); + .put("REOPENED", 0L).put("RESOLVED", 0L).put("CLOSED", 0L).build(); assertThat(response.getFacets().getFacetsList()) .extracting(Common.Facet::getProperty, facet -> facet.getValuesList().stream().collect(toMap(FacetValue::getVal, FacetValue::getCount))) @@ -164,7 +169,7 @@ public class SearchActionFacetsTest { tuple("statuses", expectedStatuses), tuple("resolutions", of("", 10L, "FALSE-POSITIVE", 0L, "FIXED", 0L, "REMOVED", 0L, "WONTFIX", 0L)), tuple("rules", of(rule.getKey().toString(), 10L)), - tuple("types", of("CODE_SMELL", 10L, "BUG", 0L, "VULNERABILITY", 0L, "SECURITY_HOTSPOT", 0L)), + tuple("types", of("CODE_SMELL", 10L, "BUG", 0L, "VULNERABILITY", 0L)), tuple("languages", of(rule.getLanguage(), 10L)), tuple("projects", of(project.getKey(), 10L)), tuple("fileUuids", of(file.uuid(), 10L)), @@ -420,17 +425,36 @@ public class SearchActionFacetsTest { } @Test - public void check_facets_max_size() { + public void check_facets_max_size_for_issues() { ComponentDto project = db.components().insertPublicProject(); + Random random = new Random(); IntStream.rangeClosed(1, 110) .forEach(index -> { - RuleDefinitionDto rule = db.rules().insert(); UserDto user = db.users().insertUser(); ComponentDto module = db.components().insertComponent(newModuleDto(project)); ComponentDto directory = db.components().insertComponent(newDirectory(module, "dir" + index)); ComponentDto file = db.components().insertComponent(newFileDto(directory)); - db.issues().insert(rule, project, file, i -> i.setAssigneeUuid(user.getUuid())); + + RuleDefinitionDto rule = db.rules().insert(ruleDefinitionDto -> ruleDefinitionDto.setType(RULE_TYPES_EXCEPT_HOTSPOT[random.nextInt(RULE_TYPES_EXCEPT_HOTSPOT.length)])); + db.issues().insert(rule, project, file, i -> i.setAssigneeUuid(user.getUuid()) + .setStatus(ISSUE_STATUSES[random.nextInt(ISSUE_STATUSES.length)]) + .setType(rule.getType())); }); + + // insert some hotspots which should be filtered by default + IntStream.rangeClosed(1, 30) + .forEach(index -> { + UserDto user = db.users().insertUser(); + ComponentDto module = db.components().insertComponent(newModuleDto(project)); + ComponentDto directory = db.components().insertComponent(newDirectory(module, "dir" + index)); + ComponentDto file = db.components().insertComponent(newFileDto(directory)); + + RuleDefinitionDto rule = db.rules().insert(ruleDefinitionDto -> ruleDefinitionDto.setType(RuleType.SECURITY_HOTSPOT)); + db.issues().insert(rule, project, file, i -> i.setAssigneeUuid(user.getUuid()) + .setStatus(random.nextBoolean() ? Issue.STATUS_TO_REVIEW : Issue.STATUS_REVIEWED) + .setType(rule.getType())); + }); + indexPermissions(); indexIssues(); @@ -450,10 +474,10 @@ public class SearchActionFacetsTest { // Assignees contains one additional element : it's the empty string that will return number of unassigned issues tuple("assignees", 101), // Following facets returned fixed number of elements - tuple("statuses", 7), + tuple("statuses", 5), tuple("resolutions", 5), tuple("severities", 5), - tuple("types", 4)); + tuple("types", 3)); } @Test @@ -509,7 +533,7 @@ public class SearchActionFacetsTest { .executeProtobuf(SearchWsResponse.class); Map expectedStatuses = ImmutableMap.builder().put("OPEN", 1L).put("CONFIRMED", 0L) - .put("REOPENED", 0L).put("RESOLVED", 0L).put("CLOSED", 0L).put("TO_REVIEW", 0L).put("REVIEWED", 0L).build(); + .put("REOPENED", 0L).put("RESOLVED", 0L).put("CLOSED", 0L).build(); assertThat(response.getFacets().getFacetsList()) .extracting(Common.Facet::getProperty, facet -> facet.getValuesList().stream().collect(toMap(FacetValue::getVal, FacetValue::getCount))) @@ -518,7 +542,7 @@ public class SearchActionFacetsTest { tuple("statuses", expectedStatuses), tuple("resolutions", of("", 1L, "FALSE-POSITIVE", 0L, "FIXED", 0L, "REMOVED", 0L, "WONTFIX", 0L)), tuple("rules", of(rule1.getKey().toString(), 1L, rule2.getKey().toString(), 0L)), - tuple("types", of("CODE_SMELL", 1L, "BUG", 0L, "VULNERABILITY", 0L, "SECURITY_HOTSPOT", 0L)), + tuple("types", of("CODE_SMELL", 1L, "BUG", 0L, "VULNERABILITY", 0L)), tuple("languages", of(rule1.getLanguage(), 1L, rule2.getLanguage(), 0L)), tuple("projects", of(project1.getKey(), 1L, project2.getKey(), 0L)), tuple("moduleUuids", of(module1.uuid(), 1L, module2.uuid(), 0L)), 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 dc8b4969586..478092d78ff 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 @@ -28,7 +28,6 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.api.config.internal.MapSettings; import org.sonar.api.resources.Languages; import org.sonar.api.rule.RuleStatus; import org.sonar.api.rules.RuleType; @@ -51,12 +50,12 @@ import org.sonar.db.rule.RuleDefinitionDto; import org.sonar.db.rule.RuleDto; import org.sonar.db.rule.RuleTesting; import org.sonar.db.user.UserDto; -import org.sonar.server.issue.TextRangeResponseFormatter; import org.sonar.server.es.EsTester; import org.sonar.server.es.SearchOptions; import org.sonar.server.es.StartupIndexer; import org.sonar.server.issue.AvatarResolverImpl; import org.sonar.server.issue.IssueFieldsSetter; +import org.sonar.server.issue.TextRangeResponseFormatter; import org.sonar.server.issue.TransitionService; import org.sonar.server.issue.index.IssueIndex; import org.sonar.server.issue.index.IssueIndexer; @@ -92,7 +91,6 @@ 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; 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; @@ -123,8 +121,8 @@ public class SearchActionTest { private Languages languages = new Languages(); private UserResponseFormatter userFormatter = new UserResponseFormatter(new AvatarResolverImpl()); private SearchResponseFormat searchResponseFormat = new SearchResponseFormat(new Durations(), languages, new TextRangeResponseFormatter(), userFormatter); - private WsActionTester ws = new WsActionTester(new SearchAction(userSession, issueIndex, issueQueryFactory, searchResponseLoader, searchResponseFormat, - new MapSettings().asConfig(), System2.INSTANCE, dbClient)); + private WsActionTester ws = new WsActionTester( + new SearchAction(userSession, issueIndex, issueQueryFactory, searchResponseLoader, searchResponseFormat, System2.INSTANCE, dbClient)); private StartupIndexer permissionIndexer = new PermissionIndexer(dbClient, es.client(), issueIndexer); @Before @@ -682,7 +680,7 @@ public class SearchActionTest { } @Test - public void security_hotspots_are_returned_by_default() { + public void security_hotspots_are_not_returned_by_default() { ComponentDto project = db.components().insertPublicProject(); ComponentDto file = db.components().insertComponent(newFileDto(project)); RuleDefinitionDto rule = db.rules().insert(); @@ -697,11 +695,11 @@ public class SearchActionTest { assertThat(result.getIssuesList()) .extracting(Issue::getType) - .containsExactlyInAnyOrder(BUG, VULNERABILITY, Common.RuleType.CODE_SMELL, SECURITY_HOTSPOT); + .containsExactlyInAnyOrder(BUG, VULNERABILITY, Common.RuleType.CODE_SMELL); } @Test - public void security_hotspot_type_included_when_explicitly_selected() { + 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(); @@ -712,17 +710,12 @@ public class SearchActionTest { indexPermissions(); indexIssues(); - assertThat(ws.newRequest() - .setParam("types", RuleType.SECURITY_HOTSPOT.toString()) - .executeProtobuf(SearchWsResponse.class).getIssuesList()) - .extracting(Issue::getType) - .containsExactlyInAnyOrder(SECURITY_HOTSPOT); + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Value of parameter 'types' (SECURITY_HOTSPOT) must be one of: [CODE_SMELL, BUG, VULNERABILITY]"); - assertThat(ws.newRequest() - .setParam("types", String.format("%s,%s", RuleType.BUG, RuleType.SECURITY_HOTSPOT)) - .executeProtobuf(SearchWsResponse.class).getIssuesList()) - .extracting(Issue::getType) - .containsExactlyInAnyOrder(BUG, SECURITY_HOTSPOT); + ws.newRequest() + .setParam("types", RuleType.SECURITY_HOTSPOT.toString()) + .execute(); } @Test @@ -750,27 +743,6 @@ public class SearchActionTest { .containsExactlyInAnyOrder(tuple("MAJOR", 3L), tuple("INFO", 0L), tuple("MINOR", 0L), tuple("CRITICAL", 0L), tuple("BLOCKER", 0L)); } - @Test - public void do_not_return_severity_on_security_hotspots() { - ComponentDto project = db.components().insertPublicProject(); - ComponentDto file = db.components().insertComponent(newFileDto(project)); - RuleDefinitionDto rule = db.rules().insert(); - db.issues().insert(rule, project, file, i -> i.setType(RuleType.BUG).setSeverity(Severity.MAJOR.name())); - db.issues().insert(rule, project, file, i -> i.setType(RuleType.SECURITY_HOTSPOT).setSeverity(Severity.MAJOR.name())); - indexPermissions(); - indexIssues(); - - SearchWsResponse result = ws.newRequest() - .setParam("types", String.format("%s,%s", RuleType.BUG, RuleType.SECURITY_HOTSPOT)) - .executeProtobuf(SearchWsResponse.class); - - assertThat(result.getIssuesList()) - .extracting(Issue::getType, Issue::hasSeverity) - .containsExactlyInAnyOrder( - tuple(BUG, true), - tuple(SECURITY_HOTSPOT, false)); - } - @Test public void return_total_effort() { UserDto john = db.users().insertUser(); diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionTestOnSonarCloud.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionTestOnSonarCloud.java deleted file mode 100644 index 544b1a04bb6..00000000000 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionTestOnSonarCloud.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.issue.ws; - -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import java.time.Clock; -import java.util.Arrays; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.sonar.api.config.internal.MapSettings; -import org.sonar.api.resources.Languages; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.utils.Durations; -import org.sonar.api.utils.System2; -import org.sonar.db.DbClient; -import org.sonar.db.DbTester; -import org.sonar.db.component.ComponentDto; -import org.sonar.db.organization.OrganizationDto; -import org.sonar.db.rule.RuleDefinitionDto; -import org.sonar.db.user.UserDto; -import org.sonar.server.issue.TextRangeResponseFormatter; -import org.sonar.server.es.EsTester; -import org.sonar.server.issue.AvatarResolverImpl; -import org.sonar.server.issue.IssueFieldsSetter; -import org.sonar.server.issue.TransitionService; -import org.sonar.server.issue.index.IssueIndex; -import org.sonar.server.issue.index.IssueIndexer; -import org.sonar.server.issue.index.IssueIteratorFactory; -import org.sonar.server.issue.index.IssueQueryFactory; -import org.sonar.server.issue.workflow.FunctionExecutor; -import org.sonar.server.issue.workflow.IssueWorkflow; -import org.sonar.server.permission.index.PermissionIndexerTester; -import org.sonar.server.permission.index.WebAuthorizationTypeSupport; -import org.sonar.server.tester.UserSessionRule; -import org.sonar.server.ws.WsActionTester; -import org.sonar.test.JsonAssert; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.sonar.api.server.ws.WebService.Param.FACETS; -import static org.sonar.db.component.ComponentTesting.newFileDto; -import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_KEYS; -import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ORGANIZATION; - -public class SearchActionTestOnSonarCloud { - @Rule - public UserSessionRule userSession = UserSessionRule.standalone(); - @Rule - public DbTester db = DbTester.create(); - @Rule - public EsTester es = EsTester.create(); - - private MapSettings mapSettings = new MapSettings().setProperty("sonar.sonarcloud.enabled", true); - - private DbClient dbClient = db.getDbClient(); - private IssueIndex issueIndex = new IssueIndex(es.client(), System2.INSTANCE, userSession, new WebAuthorizationTypeSupport(userSession)); - private IssueIndexer issueIndexer = new IssueIndexer(es.client(), dbClient, new IssueIteratorFactory(dbClient)); - private IssueQueryFactory issueQueryFactory = new IssueQueryFactory(dbClient, Clock.systemUTC(), userSession); - private IssueFieldsSetter issueFieldsSetter = new IssueFieldsSetter(); - private IssueWorkflow issueWorkflow = new IssueWorkflow(new FunctionExecutor(issueFieldsSetter), issueFieldsSetter); - private SearchResponseLoader searchResponseLoader = new SearchResponseLoader(userSession, dbClient, new TransitionService(userSession, issueWorkflow)); - private Languages languages = new Languages(); - private UserResponseFormatter userFormatter = new UserResponseFormatter(new AvatarResolverImpl()); - private SearchResponseFormat searchResponseFormat = new SearchResponseFormat(new Durations(), languages, new TextRangeResponseFormatter(), userFormatter); - private PermissionIndexerTester permissionIndexer = new PermissionIndexerTester(es, issueIndexer); - - private SearchAction underTest = new SearchAction(userSession, issueIndex, issueQueryFactory, searchResponseLoader, searchResponseFormat, - mapSettings.asConfig(), System2.INSTANCE, dbClient); - private WsActionTester ws = new WsActionTester(underTest); - - private OrganizationDto organization; - private UserDto user; - private ComponentDto project; - - @Before - public void setup() { - underTest.start(); - organization = db.organizations().insert(o -> o.setKey("org-1")); - user = db.users().insertUser(); - - project = db.components().insertPublicProject(organization, p -> p.setDbKey("PK1")); - ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1")); - RuleDefinitionDto rule = db.rules().insert(r -> r.setRuleKey(RuleKey.of("xoo", "x1"))); - db.issues().insert(rule, project, file, i -> i.setAuthorLogin("leia").setKee("2bd4eac2-b650-4037-80bc-7b112bd4eac2")); - db.issues().insert(rule, project, file, i -> i.setAuthorLogin("luke@skywalker.name").setKee("82fd47d4-b650-4037-80bc-7b1182fd47d4")); - db.commit(); - allowAnyoneOnProjects(project); - indexIssues(); - } - - @Test - public void authors_facet_is_hidden_if_organization_is_not_set() { - db.organizations().addMember(organization, user); - userSession - .logIn(user) - .addMembership(organization); - - String input = ws.newRequest() - .setParam(PARAM_COMPONENT_KEYS, project.getKey()) - .setParam(FACETS, "authors") - .execute() - .getInput(); - - JsonAssert.assertJson(input).isSimilarTo(this.getClass().getResource(this.getClass().getSimpleName() + "/no_authors_facet.json")); - - JsonElement gson = new JsonParser().parse(input); - assertThat(gson.getAsJsonObject().get("facets").getAsJsonArray()).isEmpty(); - } - - @Test - public void authors_facet_is_hidden_if_user_is_not_a_member_of_the_organization() { - userSession - .logIn(user); - - String input = ws.newRequest() - .setParam(PARAM_COMPONENT_KEYS, project.getKey()) - .setParam(FACETS, "authors") - .execute() - .getInput(); - - JsonAssert.assertJson(input).isSimilarTo(this.getClass().getResource(this.getClass().getSimpleName() + "/no_author_and_no_authors_facet.json")); - - JsonElement gson = new JsonParser().parse(input); - assertThat(gson.getAsJsonObject().get("facets").getAsJsonArray()).isEmpty(); - - } - - @Test - public void authors_facet_is_shown_if_organization_is_set_and_user_is_member_of_the_organization() { - db.organizations().addMember(organization, user); - - userSession - .logIn(user) - .addMembership(organization); - - ws.newRequest() - .setParam(PARAM_COMPONENT_KEYS, project.getKey()) - .setParam(FACETS, "authors") - .setParam(PARAM_ORGANIZATION, organization.getKey()) - .execute() - .assertJson(this.getClass(), "with_authors_facet.json"); - } - - private void indexIssues() { - issueIndexer.indexOnStartup(null); - } - - private void allowAnyoneOnProjects(ComponentDto... projects) { - userSession.registerComponents(projects); - Arrays.stream(projects).forEach(p -> permissionIndexer.allowOnlyAnyone(p)); - } -} diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SetTypeActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SetTypeActionTest.java index 8cc50ad6b5b..87c9ebf0b75 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SetTypeActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SetTypeActionTest.java @@ -48,6 +48,7 @@ import org.sonar.db.rule.RuleDefinitionDto; import org.sonar.db.rule.RuleDto; 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; @@ -189,13 +190,14 @@ public class SetTypeActionTest { @Test @UseDataProvider("allTypesExceptSecurityHotspot") - public void fail_if_trying_to_change_type_of_a_hotspot(RuleType type) { + public void fail_NFE_if_trying_to_change_type_of_a_hotspot(RuleType type) { long now = 1_999_777_234L; when(system2.now()).thenReturn(now); IssueDto issueDto = issueDbTester.insertHotspot(); setUserWithBrowseAndAdministerIssuePermission(issueDto); - expectedException.expect(IllegalArgumentException.class); + expectedException.expect(NotFoundException.class); + expectedException.expectMessage(String.format("Issue with key '%s' does not exist", issueDto.getKey())); call(issueDto.getKey(), type.name()); } -- 2.39.5