aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2017-10-19 17:50:42 +0200
committerJulien Lancelot <julien.lancelot@sonarsource.com>2017-10-20 13:09:23 +0200
commitdef87ea26a53c40af92b225d1c2e03d1a28016da (patch)
treebde483a48b4486531853a86e6f66f39d5a42f307
parent7de0fd0dc2ed69a76bcaf795eaf11764d766a9e5 (diff)
downloadsonarqube-def87ea26a53c40af92b225d1c2e03d1a28016da.tar.gz
sonarqube-def87ea26a53c40af92b225d1c2e03d1a28016da.zip
SONAR-9262 Prevent using files/dirs/modules facets when no proj/org
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java11
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsTest.java137
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java4
3 files changed, 147 insertions, 5 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java
index 7e99634b893..e9fac5edb66 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java
@@ -19,6 +19,7 @@
*/
package org.sonar.server.issue.ws;
+import com.google.common.base.Joiner;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import java.util.Arrays;
@@ -51,6 +52,7 @@ import org.sonar.server.user.UserSession;
import org.sonarqube.ws.Issues.SearchWsResponse;
import org.sonarqube.ws.client.issue.SearchWsRequest;
+import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Sets.newHashSet;
import static java.lang.String.format;
@@ -107,6 +109,8 @@ public class SearchAction implements IssuesWsAction {
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<String> IGNORED_FACETS = newHashSet(PARAM_PLANNED, DEPRECATED_PARAM_ACTION_PLANS, PARAM_REPORTERS);
+ private static final Set<String> FACETS_REQUIRING_PROJECT_OR_ORGANIZATION = newHashSet(PARAM_FILE_UUIDS, PARAM_DIRECTORIES, PARAM_MODULE_UUIDS);
+ private static final Joiner COMA_JOINER = Joiner.on(",");
private final UserSession userSession;
private final IssueIndex issueIndex;
@@ -333,6 +337,13 @@ public class SearchAction implements IssuesWsAction {
// This is a constraint from webapp UX.
completeFacets(facets, request, wsRequest);
collectFacets(collector, facets);
+
+ Set<String> facetsRequiringProjectOrOrganizationParameter = facets.getNames().stream()
+ .filter(FACETS_REQUIRING_PROJECT_OR_ORGANIZATION::contains)
+ .collect(MoreCollectors.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));
}
SearchResponseData data = searchResponseLoader.load(collector, facets);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsTest.java
index b00028310b7..ca0539ed339 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsTest.java
@@ -25,6 +25,7 @@ import java.util.Arrays;
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;
@@ -83,6 +84,8 @@ import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SINCE_LEAK_
public class SearchActionComponentsTest {
@Rule
+ public ExpectedException expectedException = ExpectedException.none();
+ @Rule
public UserSessionRule userSession = UserSessionRule.standalone();
@Rule
public DbTester db = DbTester.create();
@@ -322,8 +325,9 @@ public class SearchActionComponentsTest {
}
@Test
- public void display_file_facet() throws Exception {
- ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
+ public void display_file_facet_with_project() throws Exception {
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto project = db.components().insertPublicProject(organization, p -> p.setDbKey("PK1"));
ComponentDto file1 = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1"));
ComponentDto file2 = db.components().insertComponent(newFileDto(project, null, "F2").setDbKey("FK2"));
ComponentDto file3 = db.components().insertComponent(newFileDto(project, null, "F3").setDbKey("FK3"));
@@ -334,7 +338,28 @@ public class SearchActionComponentsTest {
indexIssues();
ws.newRequest()
- .setParam(IssuesWsParameters.PARAM_COMPONENT_UUIDS, project.uuid())
+ .setParam(IssuesWsParameters.PARAM_COMPONENT_KEYS, project.getKey())
+ .setParam(IssuesWsParameters.PARAM_FILE_UUIDS, file1.uuid() + "," + file3.uuid())
+ .setParam(WebService.Param.FACETS, "fileUuids")
+ .execute()
+ .assertJson(this.getClass(), "display_file_facet.json");
+ }
+
+ @Test
+ public void display_file_facet_with_organization() throws Exception {
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto project = db.components().insertPublicProject(organization, p -> p.setDbKey("PK1"));
+ ComponentDto file1 = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1"));
+ ComponentDto file2 = db.components().insertComponent(newFileDto(project, null, "F2").setDbKey("FK2"));
+ ComponentDto file3 = db.components().insertComponent(newFileDto(project, null, "F3").setDbKey("FK3"));
+ RuleDefinitionDto rule = db.rules().insert(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
+ db.issues().insert(rule, project, file1, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
+ db.issues().insert(rule, project, file2, i -> i.setKee("2bd4eac2-b650-4037-80bc-7b1182fd47d4"));
+ allowAnyoneOnProjects(project);
+ indexIssues();
+
+ ws.newRequest()
+ .setParam(IssuesWsParameters.PARAM_ORGANIZATION, organization.getKey())
.setParam(IssuesWsParameters.PARAM_FILE_UUIDS, file1.uuid() + "," + file3.uuid())
.setParam(WebService.Param.FACETS, "fileUuids")
.execute()
@@ -342,6 +367,24 @@ public class SearchActionComponentsTest {
}
@Test
+ public void fail_to_display_file_facet_when_no_organization_or_project_is_set() {
+ ComponentDto project = db.components().insertPublicProject();
+ ComponentDto file = db.components().insertComponent(newFileDto(project));
+ RuleDefinitionDto rule = db.rules().insert();
+ db.issues().insert(rule, project, file);
+ allowAnyoneOnProjects(project);
+ indexIssues();
+
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("Facet(s) 'fileUuids' require to also filter by project or organization");
+
+ ws.newRequest()
+ .setParam(IssuesWsParameters.PARAM_FILE_UUIDS, file.uuid())
+ .setParam(WebService.Param.FACETS, "fileUuids")
+ .execute();
+ }
+
+ @Test
public void search_by_directory_path() throws Exception {
ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
ComponentDto directory = db.components().insertComponent(newDirectory(project, "D1", "src/main/java/dir"));
@@ -420,7 +463,7 @@ public class SearchActionComponentsTest {
}
@Test
- public void display_module_facet() throws Exception {
+ public void display_module_facet_using_project() throws Exception {
ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
ComponentDto module = db.components().insertComponent(newModuleDto("M1", project).setDbKey("MK1"));
ComponentDto subModule1 = db.components().insertComponent(newModuleDto("SUBM1", module).setDbKey("SUBMK1"));
@@ -435,6 +478,32 @@ public class SearchActionComponentsTest {
indexIssues();
ws.newRequest()
+ .setParam(IssuesWsParameters.PARAM_PROJECTS, project.getKey())
+ .setParam(IssuesWsParameters.PARAM_COMPONENT_UUIDS, module.uuid())
+ .setParam(IssuesWsParameters.PARAM_MODULE_UUIDS, subModule1.uuid() + "," + subModule3.uuid())
+ .setParam(WebService.Param.FACETS, "moduleUuids")
+ .execute()
+ .assertJson(this.getClass(), "display_module_facet.json");
+ }
+
+ @Test
+ public void display_module_facet_using_organization() throws Exception {
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto project = db.components().insertPublicProject(organization, p -> p.setDbKey("PK1"));
+ ComponentDto module = db.components().insertComponent(newModuleDto("M1", project).setDbKey("MK1"));
+ ComponentDto subModule1 = db.components().insertComponent(newModuleDto("SUBM1", module).setDbKey("SUBMK1"));
+ ComponentDto subModule2 = db.components().insertComponent(newModuleDto("SUBM2", module).setDbKey("SUBMK2"));
+ ComponentDto subModule3 = db.components().insertComponent(newModuleDto("SUBM3", module).setDbKey("SUBMK3"));
+ ComponentDto file1 = db.components().insertComponent(newFileDto(subModule1, null, "F1").setDbKey("FK1"));
+ ComponentDto file2 = db.components().insertComponent(newFileDto(subModule2, null, "F2").setDbKey("FK2"));
+ RuleDefinitionDto rule = db.rules().insert(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
+ IssueDto issue1 = db.issues().insert(rule, project, file1, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
+ IssueDto issue2 = db.issues().insert(rule, project, file2, i -> i.setKee("2bd4eac2-b650-4037-80bc-7b1182fd47d4"));
+ allowAnyoneOnProjects(project);
+ indexIssues();
+
+ ws.newRequest()
+ .setParam(IssuesWsParameters.PARAM_ORGANIZATION, organization.getKey())
.setParam(IssuesWsParameters.PARAM_COMPONENT_UUIDS, module.uuid())
.setParam(IssuesWsParameters.PARAM_MODULE_UUIDS, subModule1.uuid() + "," + subModule3.uuid())
.setParam(WebService.Param.FACETS, "moduleUuids")
@@ -443,7 +512,26 @@ public class SearchActionComponentsTest {
}
@Test
- public void display_directory_facet() throws Exception {
+ public void fail_to_display_module_facet_when_no_organization_or_project_is_set() {
+ ComponentDto project = db.components().insertPublicProject();
+ ComponentDto module = db.components().insertComponent(newModuleDto(project));
+ ComponentDto file = db.components().insertComponent(newFileDto(module, null));
+ RuleDefinitionDto rule = db.rules().insert();
+ db.issues().insert(rule, project, file);
+ allowAnyoneOnProjects(project);
+ indexIssues();
+
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("Facet(s) 'moduleUuids' require to also filter by project or organization");
+
+ ws.newRequest()
+ .setParam(IssuesWsParameters.PARAM_COMPONENT_UUIDS, module.uuid())
+ .setParam(WebService.Param.FACETS, "moduleUuids")
+ .execute();
+ }
+
+ @Test
+ public void display_directory_facet_using_project() throws Exception {
ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
ComponentDto directory = db.components().insertComponent(newDirectory(project, "D1", "src/main/java/dir"));
ComponentDto file = db.components().insertComponent(newFileDto(project, directory, "F1").setDbKey("FK1").setPath(directory.path() + "/MyComponent.java"));
@@ -455,12 +543,51 @@ public class SearchActionComponentsTest {
userSession.logIn("john");
ws.newRequest()
.setParam("resolved", "false")
+ .setParam(IssuesWsParameters.PARAM_COMPONENT_KEYS, project.getKey())
.setParam(WebService.Param.FACETS, "directories")
.execute()
.assertJson(this.getClass(), "display_directory_facet.json");
}
@Test
+ public void display_directory_facet_using_organization() throws Exception {
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto project = db.components().insertPublicProject(organization, p -> p.setDbKey("PK1"));
+ ComponentDto directory = db.components().insertComponent(newDirectory(project, "D1", "src/main/java/dir"));
+ ComponentDto file = db.components().insertComponent(newFileDto(project, directory, "F1").setDbKey("FK1").setPath(directory.path() + "/MyComponent.java"));
+ RuleDefinitionDto rule = db.rules().insert(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
+ IssueDto issue = db.issues().insert(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
+ allowAnyoneOnProjects(project);
+ indexIssues();
+
+ userSession.logIn("john");
+ ws.newRequest()
+ .setParam("resolved", "false")
+ .setParam(IssuesWsParameters.PARAM_ORGANIZATION, organization.getKey())
+ .setParam(WebService.Param.FACETS, "directories")
+ .execute()
+ .assertJson(this.getClass(), "display_directory_facet.json");
+ }
+
+ @Test
+ public void fail_to_display_directory_facet_when_no_organization_or_project_is_set() {
+ ComponentDto project = db.components().insertPublicProject();
+ ComponentDto directory = db.components().insertComponent(newDirectory(project, "src"));
+ ComponentDto file = db.components().insertComponent(newFileDto(project, directory));
+ RuleDefinitionDto rule = db.rules().insert();
+ db.issues().insert(rule, project, file);
+ allowAnyoneOnProjects(project);
+ indexIssues();
+
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("Facet(s) 'directories' require to also filter by project or organization");
+
+ ws.newRequest()
+ .setParam(WebService.Param.FACETS, "directories")
+ .execute();
+ }
+
+ @Test
public void search_by_view_uuid() throws Exception {
ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1"));
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java
index 29bacc9551b..14bea4cc667 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java
@@ -75,6 +75,7 @@ import static org.sonarqube.ws.client.issue.IssuesWsParameters.DEPRECATED_FACET_
import static org.sonarqube.ws.client.issue.IssuesWsParameters.FACET_MODE_EFFORT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ADDITIONAL_FIELDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENTS;
+import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_KEYS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CREATED_AFTER;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_HIDE_COMMENTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PAGE_INDEX;
@@ -381,6 +382,7 @@ public class SearchActionTest {
userSessionRule.logIn("john");
ws.newRequest()
.setParam("resolved", "false")
+ .setParam(PARAM_COMPONENT_KEYS, project.getKey())
.setParam(WebService.Param.FACETS, "statuses,severities,resolutions,projectUuids,rules,fileUuids,assignees,languages,actionPlans,types")
.execute()
.assertJson(this.getClass(), "display_facets.json");
@@ -405,6 +407,7 @@ public class SearchActionTest {
userSessionRule.logIn("john");
ws.newRequest()
.setParam("resolved", "false")
+ .setParam(PARAM_COMPONENT_KEYS, project.getKey())
.setParam(WebService.Param.FACETS, "statuses,severities,resolutions,projectUuids,rules,fileUuids,assignees,languages,actionPlans")
.setParam("facetMode", FACET_MODE_EFFORT)
.execute()
@@ -429,6 +432,7 @@ public class SearchActionTest {
userSessionRule.logIn("john");
ws.newRequest()
+ .setParam(PARAM_COMPONENT_KEYS, project.getKey())
.setParam("resolved", "false")
.setParam("severities", "MAJOR,MINOR")
.setParam("languages", "xoo,polop,palap")