summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>2015-03-05 18:24:19 +0100
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>2015-03-09 15:24:56 +0100
commitb90281447330980f6311c00f05c4da093b0bad5b (patch)
tree5c8fa78b813360f1137b660c53fe53fdb543b0ad
parent89c59ab53561a47b5067668829bb19e7067cd3be (diff)
downloadsonarqube-b90281447330980f6311c00f05c4da093b0bad5b.tar.gz
sonarqube-b90281447330980f6311c00f05c4da093b0bad5b.zip
SONAR-6244 Add parameter and facet for issues assigned to authenticated user
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java24
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/filter/IssueFilterParameters.java3
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java36
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java21
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java53
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/display_facets.json4
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/display_zero_facets.json7
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/filter_by_assigned_to_me.json42
8 files changed, 162 insertions, 28 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java
index 9eb2a6277d6..6d819a69b26 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java
@@ -82,7 +82,9 @@ public class IssueQueryService implements ServerComponent {
.rules(toRules(params.get(IssueFilterParameters.RULES)))
.actionPlans(RubyUtils.toStrings(params.get(IssueFilterParameters.ACTION_PLANS)))
.reporters(RubyUtils.toStrings(params.get(IssueFilterParameters.REPORTERS)))
- .assignees(RubyUtils.toStrings(params.get(IssueFilterParameters.ASSIGNEES)))
+ .assignees(buildAssignees(
+ RubyUtils.toStrings(params.get(IssueFilterParameters.ASSIGNEES)),
+ RubyUtils.toBoolean(params.get(IssueFilterParameters.ASSIGNED_TO_ME))))
.languages(RubyUtils.toStrings(params.get(IssueFilterParameters.LANGUAGES)))
.tags(RubyUtils.toStrings(params.get(IssueFilterParameters.TAGS)))
.assigned(RubyUtils.toBoolean(params.get(IssueFilterParameters.ASSIGNED)))
@@ -145,7 +147,9 @@ public class IssueQueryService implements ServerComponent {
.rules(stringsToRules(request.paramAsStrings(IssueFilterParameters.RULES)))
.actionPlans(request.paramAsStrings(IssueFilterParameters.ACTION_PLANS))
.reporters(request.paramAsStrings(IssueFilterParameters.REPORTERS))
- .assignees(request.paramAsStrings(IssueFilterParameters.ASSIGNEES))
+ .assignees(buildAssignees(
+ request.paramAsStrings(IssueFilterParameters.ASSIGNEES),
+ request.paramAsBoolean(IssueFilterParameters.ASSIGNED_TO_ME)))
.languages(request.paramAsStrings(IssueFilterParameters.LANGUAGES))
.tags(request.paramAsStrings(IssueFilterParameters.TAGS))
.assigned(request.paramAsBoolean(IssueFilterParameters.ASSIGNED))
@@ -186,6 +190,22 @@ public class IssueQueryService implements ServerComponent {
}
}
+ private List<String> buildAssignees(@Nullable List<String> assigneesFromParams, @Nullable Boolean assignedToMe) {
+ List<String> assignees = Lists.newArrayList();
+ if (assigneesFromParams != null) {
+ assignees.addAll(assigneesFromParams);
+ }
+ if (BooleanUtils.isTrue(assignedToMe)) {
+ String login = UserSession.get().login();
+ if (login == null) {
+ assignees.add(UNKNOWN);
+ } else {
+ assignees.add(login);
+ }
+ }
+ return assignees;
+ }
+
private boolean mergeDeprecatedComponentParameters(DbSession session, Boolean onComponentOnly,
@Nullable Collection<String> components,
@Nullable Collection<String> componentUuids,
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/filter/IssueFilterParameters.java b/server/sonar-server/src/main/java/org/sonar/server/issue/filter/IssueFilterParameters.java
index b63bce55ead..8be25e80768 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/issue/filter/IssueFilterParameters.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/filter/IssueFilterParameters.java
@@ -58,6 +58,7 @@ public class IssueFilterParameters {
public static final String LANGUAGES = "languages";
public static final String TAGS = "tags";
public static final String ASSIGNED = "assigned";
+ public static final String ASSIGNED_TO_ME = "assigned_to_me";
public static final String PLANNED = "planned";
public static final String HIDE_RULES = "hideRules";
public static final String HIDE_COMMENTS = "hideComments";
@@ -72,7 +73,7 @@ public class IssueFilterParameters {
public static final List<String> ALL = ImmutableList.of(ISSUES, SEVERITIES, STATUSES, RESOLUTIONS, RESOLVED, COMPONENTS, COMPONENT_ROOTS, RULES, ACTION_PLANS, REPORTERS, TAGS,
ASSIGNEES, LANGUAGES, ASSIGNED, PLANNED, HIDE_RULES, CREATED_AT, CREATED_AFTER, CREATED_BEFORE, PAGE_SIZE, PAGE_INDEX, SORT, ASC, COMPONENT_UUIDS, COMPONENT_ROOT_UUIDS,
- PROJECTS, PROJECT_UUIDS, IGNORE_PAGING, PROJECT_KEYS, COMPONENT_KEYS, MODULE_UUIDS, DIRECTORIES, FILE_UUIDS, AUTHORS, HIDE_COMMENTS);
+ PROJECTS, PROJECT_UUIDS, IGNORE_PAGING, PROJECT_KEYS, COMPONENT_KEYS, MODULE_UUIDS, DIRECTORIES, FILE_UUIDS, AUTHORS, HIDE_COMMENTS, ASSIGNED_TO_ME);
public static final List<String> ALL_WITHOUT_PAGINATION = newArrayList(Iterables.filter(ALL, new Predicate<String>() {
@Override
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java
index 927cd512148..0339359c085 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java
@@ -26,6 +26,7 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.lang.BooleanUtils;
+import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchScrollRequestBuilder;
@@ -87,6 +88,7 @@ public class IssueIndex extends BaseIndex {
IssueFilterParameters.PROJECT_UUIDS,
IssueFilterParameters.RULES,
IssueFilterParameters.ASSIGNEES,
+ IssueFilterParameters.ASSIGNED_TO_ME,
IssueFilterParameters.REPORTERS,
IssueFilterParameters.AUTHORS,
IssueFilterParameters.MODULE_UUIDS,
@@ -390,6 +392,7 @@ public class IssueIndex extends BaseIndex {
if (options.getFacets().contains(IssueFilterParameters.ASSIGNEES)) {
esSearch.addAggregation(createAssigneesFacet(query, filters, esQuery));
}
+ addAssignedToMeFacetIfNeeded(esSearch, options, query, filters, esQuery);
if (options.getFacets().contains(IssueFilterParameters.ACTION_PLANS)) {
esSearch.addAggregation(createActionPlansFacet(query, filters, esQuery));
}
@@ -473,16 +476,13 @@ public class IssueIndex extends BaseIndex {
Map<String, FilterBuilder> assigneeFilters = Maps.newHashMap(filters);
assigneeFilters.remove("__isAssigned");
assigneeFilters.remove(fieldName);
+ assigneeFilters.remove(IssueFilterParameters.ASSIGNED_TO_ME);
StickyFacetBuilder assigneeFacetBuilder = new StickyFacetBuilder(queryBuilder, assigneeFilters);
BoolFilterBuilder facetFilter = assigneeFacetBuilder.getStickyFacetFilter(fieldName);
FilterAggregationBuilder facetTopAggregation = assigneeFacetBuilder.buildTopFacetAggregation(fieldName, facetName, facetFilter, DEFAULT_FACET_SIZE);
- List<String> assignees = Lists.newArrayList(query.assignees());
-
- UserSession session = UserSession.get();
- if (session.isLoggedIn()) {
- assignees.add(session.login());
+ if (!query.assignees().isEmpty()) {
+ facetTopAggregation = assigneeFacetBuilder.addSelectedItemsToFacet(fieldName, facetName, facetTopAggregation, query.assignees());
}
- facetTopAggregation = assigneeFacetBuilder.addSelectedItemsToFacet(fieldName, facetName, facetTopAggregation, assignees.toArray());
// Add missing facet for unassigned issues
facetTopAggregation.subAggregation(
@@ -496,6 +496,30 @@ public class IssueIndex extends BaseIndex {
.subAggregation(facetTopAggregation);
}
+ private void addAssignedToMeFacetIfNeeded(SearchRequestBuilder builder, SearchOptions options, IssueQuery query, Map<String, FilterBuilder> filters, QueryBuilder queryBuilder) {
+ if (!options.getFacets().contains(IssueFilterParameters.ASSIGNED_TO_ME)) {
+ return;
+ }
+
+ String login = UserSession.get().login();
+ if (StringUtils.isEmpty(login)) {
+ return;
+ }
+
+ String fieldName = IssueIndexDefinition.FIELD_ISSUE_ASSIGNEE;
+ String facetName = IssueFilterParameters.ASSIGNED_TO_ME;
+
+ // Same as in super.stickyFacetBuilder
+ Map<String, FilterBuilder> assigneeFilters = Maps.newHashMap(filters);
+ StickyFacetBuilder assignedToMeFacetBuilder = new StickyFacetBuilder(queryBuilder, assigneeFilters);
+ BoolFilterBuilder facetFilter = assignedToMeFacetBuilder.getStickyFacetFilter("__assigned_to_me");
+
+ builder.addAggregation(AggregationBuilders
+ .filter(facetName)
+ .filter(facetFilter)
+ .subAggregation(AggregationBuilders.terms(facetName + "__terms").field(fieldName).include(login)));
+ }
+
private AggregationBuilder createResolutionFacet(Map<String, FilterBuilder> filters, QueryBuilder esQuery) {
String fieldName = IssueIndexDefinition.FIELD_ISSUE_RESOLUTION;
String facetName = IssueFilterParameters.RESOLUTIONS;
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 9898640cb76..0cb1635ce86 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
@@ -63,13 +63,7 @@ import org.sonar.server.user.UserSession;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
@@ -183,6 +177,9 @@ public class SearchAction implements BaseIssuesWsAction {
action.createParam(IssueFilterParameters.ASSIGNED)
.setDescription("To retrieve assigned or unassigned issues")
.setBooleanPossibleValues();
+ action.createParam(IssueFilterParameters.ASSIGNED_TO_ME)
+ .setDescription("To retrieve issues assigned to the authenticating user. Only valid when providing user credentials")
+ .setBooleanPossibleValues();
action.createParam(IssueFilterParameters.LANGUAGES)
.setDescription("Comma-separated list of languages. Available since 4.4")
.setExampleValue("java,js");
@@ -400,11 +397,8 @@ public class SearchAction implements BaseIssuesWsAction {
if (assigneesFromRequest != null) {
assignees.addAll(assigneesFromRequest);
}
- UserSession userSession = UserSession.get();
- if (userSession.isLoggedIn()) {
- assignees.add(userSession.login());
- }
addMandatoryFacetValues(results, IssueFilterParameters.ASSIGNEES, assignees);
+ addMandatoryFacetValues(results, IssueFilterParameters.ASSIGNED_TO_ME, Arrays.asList(UserSession.get().login()));
addMandatoryFacetValues(results, IssueFilterParameters.REPORTERS, request.paramAsStrings(IssueFilterParameters.REPORTERS));
addMandatoryFacetValues(results, IssueFilterParameters.RULES, request.paramAsStrings(IssueFilterParameters.RULES));
addMandatoryFacetValues(results, IssueFilterParameters.LANGUAGES, request.paramAsStrings(IssueFilterParameters.LANGUAGES));
@@ -432,7 +426,10 @@ public class SearchAction implements BaseIssuesWsAction {
json.prop("count", bucket.getValue());
json.endObject();
}
- addZeroFacetsForSelectedItems(request, facetName, itemsFromFacets, json);
+ // Prevent appearance of a glitch value due to dedicated parameter for this facet
+ if (!IssueFilterParameters.ASSIGNED_TO_ME.equals(facetName)) {
+ addZeroFacetsForSelectedItems(request, facetName, itemsFromFacets, json);
+ }
}
json.endArray().endObject();
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java
index 2c00d1216ce..8b597b89e13 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java
@@ -88,7 +88,7 @@ public class SearchActionMediumTest {
assertThat(show.isPost()).isFalse();
assertThat(show.isInternal()).isFalse();
assertThat(show.responseExampleAsString()).isNotEmpty();
- assertThat(show.params()).hasSize(39);
+ assertThat(show.params()).hasSize(40);
}
@Test
@@ -428,12 +428,61 @@ public class SearchActionMediumTest {
.setParam("resolved", "false")
.setParam("severities", "MAJOR,MINOR")
.setParam("languages", "xoo,polop,palap")
- .setParam(WebService.Param.FACETS, "statuses,severities,resolutions,projectUuids,rules,fileUuids,assignees,languages,actionPlans")
+ .setParam(WebService.Param.FACETS, "statuses,severities,resolutions,projectUuids,rules,fileUuids,assignees,assigned_to_me,languages,actionPlans")
.execute();
result.assertJson(this.getClass(), "display_zero_facets.json", false);
}
@Test
+ public void filter_by_assigned_to_me() throws Exception {
+ ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject"));
+ setDefaultProjectPermission(project);
+ ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent"));
+ RuleDto rule = newRule();
+ IssueDto issue1 = IssueTesting.newDto(rule, file, project)
+ .setIssueCreationDate(DateUtils.parseDate("2014-09-04"))
+ .setIssueUpdateDate(DateUtils.parseDate("2017-12-04"))
+ .setDebt(10L)
+ .setStatus("OPEN")
+ .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
+ .setSeverity("MAJOR")
+ .setAssignee("john");
+ IssueDto issue2 = IssueTesting.newDto(rule, file, project)
+ .setIssueCreationDate(DateUtils.parseDate("2014-09-04"))
+ .setIssueUpdateDate(DateUtils.parseDate("2017-12-04"))
+ .setDebt(10L)
+ .setStatus("OPEN")
+ .setKee("7b112bd4-b650-4037-80bc-82fd47d4eac2")
+ .setSeverity("MAJOR")
+ .setAssignee("alice");
+ IssueDto issue3 = IssueTesting.newDto(rule, file, project)
+ .setIssueCreationDate(DateUtils.parseDate("2014-09-04"))
+ .setIssueUpdateDate(DateUtils.parseDate("2017-12-04"))
+ .setDebt(10L)
+ .setStatus("OPEN")
+ .setKee("82fd47d4-4037-b650-80bc-7b112bd4eac2")
+ .setSeverity("MAJOR");
+ db.issueDao().insert(session, issue1, issue2, issue3);
+ session.commit();
+ tester.get(IssueIndexer.class).indexAll();
+
+ MockUserSession.set().setLogin("john");
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
+ .setParam("resolved", "false")
+ .setParam("assigned_to_me", "true")
+ .setParam(WebService.Param.FACETS, "assignees,assigned_to_me")
+ .execute()
+ .assertJson(this.getClass(), "filter_by_assigned_to_me.json", false);
+
+ MockUserSession.set();
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
+ .setParam("resolved", "false")
+ .setParam("assigned_to_me", "true")
+ .execute()
+ .assertJson(this.getClass(), "empty_result.json", false);
+ }
+
+ @Test
public void hide_rules() throws Exception {
ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject"));
setDefaultProjectPermission(project);
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/display_facets.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/display_facets.json
index c6f088839e6..88f059cb366 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/display_facets.json
+++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/display_facets.json
@@ -120,10 +120,6 @@
{
"val": "",
"count": 1
- },
- {
- "val": "john",
- "count": 0
}
]
},
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/display_zero_facets.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/display_zero_facets.json
index 5869e5b15c7..0cfa8bb25e2 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/display_zero_facets.json
+++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/display_zero_facets.json
@@ -120,7 +120,12 @@
{
"val": "",
"count": 1
- },
+ }
+ ]
+ },
+ {
+ "property": "assigned_to_me",
+ "values": [
{
"val": "john",
"count": 0
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/filter_by_assigned_to_me.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/filter_by_assigned_to_me.json
new file mode 100644
index 00000000000..013ff81376e
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/filter_by_assigned_to_me.json
@@ -0,0 +1,42 @@
+{
+ "issues": [
+ {
+ "key": "82fd47d4-b650-4037-80bc-7b112bd4eac2",
+ "component": "MyComponent",
+ "project": "MyProject",
+ "rule": "xoo:x1",
+ "status": "OPEN",
+ "severity": "MAJOR",
+ "debt": "10min",
+ "fUpdateAge": "less than a minute",
+ "assignee": "john"
+ }
+ ],
+ "facets": [
+ {
+ "property": "assignees",
+ "values": [
+ {
+ "val": "john",
+ "count": 1
+ },
+ {
+ "val": "alice",
+ "count": 1
+ },
+ {
+ "val": "",
+ "count": 1
+ }
+ ]
+ },
+ {
+ "property": "assigned_to_me",
+ "values": [
+ {
+ "val": "john",
+ "count": 1
+ }
+ ]
+ }
+ ]}