Bläddra i källkod

SONAR-9262 Prevent using files/dirs/modules facets when no proj/org

tags/6.7-RC1
Julien Lancelot 6 år sedan
förälder
incheckning
def87ea26a

+ 11
- 0
server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java Visa fil

@@ -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);


+ 132
- 5
server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsTest.java Visa fil

@@ -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;
@@ -82,6 +83,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
@@ -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,13 +338,52 @@ 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()
.assertJson(this.getClass(), "display_file_facet.json");
}

@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"));
@@ -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,11 +543,50 @@ 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"));

+ 4
- 0
server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java Visa fil

@@ -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")

Laddar…
Avbryt
Spara