]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5563 Apply a permission filter when searching for issues in ES
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Tue, 9 Sep 2014 15:50:14 +0000 (17:50 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Tue, 9 Sep 2014 15:50:14 +0000 (17:50 +0200)
54 files changed:
server/sonar-server/src/main/java/org/sonar/server/activity/ActivityService.java
server/sonar-server/src/main/java/org/sonar/server/activity/RubyQProfileActivityService.java
server/sonar-server/src/main/java/org/sonar/server/activity/index/ActivityIndex.java
server/sonar-server/src/main/java/org/sonar/server/activity/ws/SearchAction.java
server/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentAppAction.java
server/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java
server/sonar-server/src/main/java/org/sonar/server/issue/db/IssueAuthorizationDao.java
server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java
server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileLoader.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileService.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java
server/sonar-server/src/main/java/org/sonar/server/rule/DefaultRuleFinder.java
server/sonar-server/src/main/java/org/sonar/server/rule/RubyRuleService.java
server/sonar-server/src/main/java/org/sonar/server/rule/RuleService.java
server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java
server/sonar-server/src/main/java/org/sonar/server/search/QueryContext.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/search/QueryOptions.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/search/ws/BaseMapping.java
server/sonar-server/src/main/java/org/sonar/server/search/ws/SearchOptions.java
server/sonar-server/src/main/java/org/sonar/server/user/RubyUserSession.java
server/sonar-server/src/main/java/org/sonar/server/user/UserSession.java
server/sonar-server/src/main/java/org/sonar/server/user/db/GroupDao.java
server/sonar-server/src/test/java/org/sonar/server/activity/ActivityBackendMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/activity/ActivityServiceMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/activity/RubyQProfileActivityServiceTest.java
server/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentAppActionTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueAuthorizationDaoTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueBackendMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssuesWsMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileServiceMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/RuleActivatorMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/rule/RubyRuleServiceTest.java
server/sonar-server/src/test/java/org/sonar/server/rule/RuleBackendMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleMappingTest.java
server/sonar-server/src/test/java/org/sonar/server/search/QueryContextTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/search/QueryOptionsTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/search/ws/SearchOptionsTest.java
server/sonar-server/src/test/java/org/sonar/server/user/MockUserSession.java
server/sonar-server/src/test/java/org/sonar/server/user/MockUserSessionTest.java
server/sonar-server/src/test/java/org/sonar/server/user/RubyUserSessionTest.java
server/sonar-server/src/test/java/org/sonar/server/user/db/GroupDaoTest.java
server/sonar-server/src/test/resources/org/sonar/server/user/db/GroupDaoTest/find_by_user_login.xml [new file with mode: 0644]
server/sonar-web/src/main/webapp/WEB-INF/app/controllers/application_controller.rb
sonar-core/src/main/java/org/sonar/core/issue/db/IssueAuthorizationMapper.java
sonar-core/src/main/java/org/sonar/core/user/GroupMapper.java
sonar-core/src/main/resources/org/sonar/core/issue/db/IssueAuthorizationMapper.xml
sonar-core/src/main/resources/org/sonar/core/user/GroupMapper.xml

index b5dd40037d5a957d3a8fe014be9b6ba3d3f5f7a1..b646957f57338d667b6e7cf7765111928c2c0fa5 100644 (file)
@@ -27,7 +27,7 @@ import org.sonar.server.activity.index.ActivityIndex;
 import org.sonar.server.activity.index.ActivityQuery;
 import org.sonar.server.db.DbClient;
 import org.sonar.server.search.IndexClient;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.Result;
 import org.sonar.server.user.UserSession;
 
@@ -79,7 +79,7 @@ public class ActivityService {
     return new ActivityQuery();
   }
 
-  public Result<Activity> search(ActivityQuery query, QueryOptions options) {
+  public Result<Activity> search(ActivityQuery query, QueryContext options) {
     ActivityIndex index = indexClient.get(ActivityIndex.class);
     return new Result<Activity>(index, index.search(query, options));
   }
index d5715a20a62e083ecd41f8ca0f1733d8b5fcf32d..9180dbf027d36088b1a58b1fcd6e239eebe74bb9 100644 (file)
@@ -26,7 +26,7 @@ import org.sonar.api.utils.Paging;
 import org.sonar.server.qualityprofile.QProfileActivity;
 import org.sonar.server.qualityprofile.QProfileActivityQuery;
 import org.sonar.server.qualityprofile.QProfileService;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.Result;
 import org.sonar.server.util.RubyUtils;
 
@@ -51,7 +51,7 @@ public class RubyQProfileActivityService implements ServerComponent, Startable {
    */
   public QProfileActivityResult search(Map<String, Object> params) {
     QProfileActivityQuery query = new QProfileActivityQuery();
-    QueryOptions queryOptions = new QueryOptions().setMaxLimit();
+    QueryContext queryContext = new QueryContext().setMaxLimit();
     List<String> profileKeys = RubyUtils.toStrings(params.get("profileKeys"));
     if (profileKeys != null) {
       query.setQprofileKeys(profileKeys);
@@ -66,10 +66,10 @@ public class RubyQProfileActivityService implements ServerComponent, Startable {
     }
     Integer page = RubyUtils.toInteger(params.get("p"));
     int pageIndex = page != null ? page : 1;
-    queryOptions.setPage(pageIndex, 50);
+    queryContext.setPage(pageIndex, 50);
 
-    Result<QProfileActivity> result = service.searchActivities(query, queryOptions);
-    return new QProfileActivityResult(result.getHits(), Paging.create(queryOptions.getLimit(), pageIndex, Long.valueOf(result.getTotal()).intValue()));
+    Result<QProfileActivity> result = service.searchActivities(query, queryContext);
+    return new QProfileActivityResult(result.getHits(), Paging.create(queryContext.getLimit(), pageIndex, Long.valueOf(result.getTotal()).intValue()));
   }
 
   @Override
index f1e45d066b2f8eaec1c118cc22881324f6c97a3d..caf237b441ff1fe06125f7ec37569b9612241291 100644 (file)
@@ -25,22 +25,14 @@ import org.elasticsearch.action.search.SearchType;
 import org.elasticsearch.common.settings.ImmutableSettings;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.unit.TimeValue;
-import org.elasticsearch.index.query.AndFilterBuilder;
-import org.elasticsearch.index.query.FilterBuilder;
-import org.elasticsearch.index.query.FilterBuilders;
-import org.elasticsearch.index.query.OrFilterBuilder;
-import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.index.query.*;
 import org.elasticsearch.search.sort.SortOrder;
 import org.sonar.core.activity.Activity;
 import org.sonar.core.activity.db.ActivityDto;
-import org.sonar.server.search.BaseIndex;
-import org.sonar.server.search.IndexDefinition;
-import org.sonar.server.search.IndexField;
-import org.sonar.server.search.QueryOptions;
-import org.sonar.server.search.Result;
-import org.sonar.server.search.SearchClient;
+import org.sonar.server.search.*;
 
 import javax.annotation.Nullable;
+
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
@@ -98,11 +90,11 @@ public class ActivityIndex extends BaseIndex<Activity, ActivityDto, String> {
     return new Result<Activity>(this, response);
   }
 
-  public SearchResponse search(ActivityQuery query, QueryOptions options) {
+  public SearchResponse search(ActivityQuery query, QueryContext options) {
     return search(query, options, null);
   }
 
-  public SearchResponse search(ActivityQuery query, QueryOptions options,
+  public SearchResponse search(ActivityQuery query, QueryContext options,
     @Nullable FilterBuilder domainFilter) {
 
     // Prepare query
index d221caad86eafd8da5e1734bbbd872ae2127e7e0..30eab19a4bd87c83bced1c4a72112b8c1cfe78a8 100644 (file)
@@ -28,7 +28,7 @@ import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.core.activity.Activity;
 import org.sonar.server.activity.ActivityService;
 import org.sonar.server.activity.index.ActivityQuery;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.Result;
 import org.sonar.server.search.ws.SearchOptions;
 
@@ -73,9 +73,9 @@ public class SearchAction implements RequestHandler {
   public void handle(Request request, Response response) {
     ActivityQuery query = logService.newActivityQuery();
     SearchOptions searchOptions = SearchOptions.create(request);
-    QueryOptions queryOptions = mapping.newQueryOptions(searchOptions);
+    QueryContext queryContext = mapping.newQueryOptions(searchOptions);
 
-    Result<Activity> results = logService.search(query, queryOptions);
+    Result<Activity> results = logService.search(query, queryContext);
 
     JsonWriter json = response.newJsonWriter().beginObject();
     searchOptions.writeStatistics(json, results);
index 4cd7bfe2dafcb590843af5c0441bb6aeeb82f069..941767dfc6ec28e514ee3c02665a93c1a2cda800 100644 (file)
@@ -55,7 +55,7 @@ import org.sonar.server.rule.Rule;
 import org.sonar.server.rule.RuleService;
 import org.sonar.server.rule.index.RuleDoc;
 import org.sonar.server.rule.index.RuleQuery;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.Result;
 import org.sonar.server.ui.ViewProxy;
 import org.sonar.server.ui.Views;
@@ -281,7 +281,7 @@ public class ComponentAppAction implements RequestHandler {
   }
 
   private void appendManualRules(JsonWriter json) {
-    Result<Rule> result = ruleService.search(new RuleQuery().setRepositories(newArrayList(RuleDoc.MANUAL_REPOSITORY)), new QueryOptions().setMaxLimit());
+    Result<Rule> result = ruleService.search(new RuleQuery().setRepositories(newArrayList(RuleDoc.MANUAL_REPOSITORY)), new QueryContext().setMaxLimit());
     if (result != null && !result.getHits().isEmpty()) {
       List<Rule> manualRules = result.getHits();
       json.name("manual_rules").beginArray();
index 4c9172902e37b7090a40fffcbac52b75a101f632..4ab13b1b6f169a31890fd37dd04e836a5ac6e224 100644 (file)
@@ -62,18 +62,12 @@ import org.sonar.server.issue.index.IssueIndex;
 import org.sonar.server.issue.index.IssueResult;
 import org.sonar.server.rule.index.RuleIndex;
 import org.sonar.server.search.IndexClient;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.user.UserSession;
 
 import javax.annotation.Nullable;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 
 /**
  * @since 3.6
@@ -341,7 +335,7 @@ public class IssueService implements ServerComponent {
     return indexClient.get(IssueIndex.class).getByKey(key);
   }
 
-  public IssueResult search(IssueQuery query, QueryOptions options) {
+  public IssueResult search(IssueQuery query, QueryContext options) {
 
     IssueIndex issueIndex = indexClient.get(IssueIndex.class);
 
index a827ee31fdcd94d27f20675ad52e4d1530543e0e..39d4cb6280c75dddd72d8bde215e1ca749909db1 100644 (file)
@@ -24,6 +24,7 @@ import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableList;
 import org.apache.ibatis.session.ResultContext;
 import org.apache.ibatis.session.ResultHandler;
+import org.sonar.api.security.DefaultGroups;
 import org.sonar.api.utils.System2;
 import org.sonar.api.web.UserRole;
 import org.sonar.core.issue.db.IssueAuthorizationDto;
@@ -101,6 +102,7 @@ public class IssueAuthorizationDao extends BaseDao<IssueAuthorizationMapper, Iss
     Map<String, Object> params = newHashMap();
     params.put("date", date);
     params.put("permission", UserRole.USER);
+    params.put("anyone", DefaultGroups.ANYONE);
 
     Map<String, IssueAuthorizationDto> authorizationDtoMap = newHashMap();
 
@@ -131,6 +133,7 @@ public class IssueAuthorizationDao extends BaseDao<IssueAuthorizationMapper, Iss
   protected Map getSynchronizationParams(Date date) {
     Map<String, Object> params = super.getSynchronizationParams(date);
     params.put("permission", UserRole.USER);
+    params.put("anyone", DefaultGroups.ANYONE);
     return params;
   }
 }
index 5819181b2f1da9fe3c1f9449118ff9c93912084b..a58b008a963dab75b3a289f733502b19f253cf9c 100644 (file)
@@ -26,23 +26,18 @@ import org.elasticsearch.action.search.SearchType;
 import org.elasticsearch.common.settings.ImmutableSettings;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.unit.TimeValue;
-import org.elasticsearch.index.query.BoolFilterBuilder;
-import org.elasticsearch.index.query.FilterBuilders;
-import org.elasticsearch.index.query.QueryBuilder;
-import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.index.query.*;
 import org.elasticsearch.search.aggregations.AggregationBuilders;
 import org.sonar.api.issue.IssueQuery;
+import org.sonar.api.web.UserRole;
 import org.sonar.core.issue.db.IssueDto;
-import org.sonar.server.search.BaseIndex;
-import org.sonar.server.search.IndexDefinition;
-import org.sonar.server.search.IndexField;
-import org.sonar.server.search.QueryOptions;
-import org.sonar.server.search.SearchClient;
+import org.sonar.server.search.*;
 
 import java.io.IOException;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 
 public class IssueIndex extends BaseIndex<IssueDoc, IssueDto, String> {
 
@@ -113,7 +108,7 @@ public class IssueIndex extends BaseIndex<IssueDoc, IssueDto, String> {
     return new IssueDoc(fields);
   }
 
-  public SearchResponse search(IssueQuery query, QueryOptions options) {
+  public SearchResponse search(IssueQuery query, QueryContext options) {
 
     SearchRequestBuilder esSearch = getClient()
       .prepareSearch(this.getIndexName())
@@ -127,6 +122,24 @@ public class IssueIndex extends BaseIndex<IssueDoc, IssueDto, String> {
 
     BoolFilterBuilder esFilter = FilterBuilders.boolFilter();
 
+    // Authorization
+    String user = options.getUserLogin();
+    Set<String> groups = options.getUserGroups();
+    OrFilterBuilder groupsAndUser = FilterBuilders.orFilter();
+    if (user != null) {
+      groupsAndUser.add(FilterBuilders.termFilter(IssueAuthorizationNormalizer.IssueAuthorizationField.USERS.field(), user));
+    }
+    for (String group : groups) {
+      groupsAndUser.add(FilterBuilders.termFilter(IssueAuthorizationNormalizer.IssueAuthorizationField.GROUPS.field(), group));
+    }
+    esFilter.must(FilterBuilders.hasParentFilter(IndexDefinition.ISSUES_AUTHORIZATION.getIndexType(),
+      QueryBuilders.filteredQuery(
+        QueryBuilders.matchAllQuery(),
+        FilterBuilders.boolFilter()
+          .must(FilterBuilders.termFilter(IssueAuthorizationNormalizer.IssueAuthorizationField.PERMISSION.field(), UserRole.USER), groupsAndUser)
+          .cache(true))
+      ));
+
     // Issue is assigned Filter
     if (query.assigned() != null && query.assigned()) {
       esFilter.must(FilterBuilders.existsFilter(IssueNormalizer.IssueField.ASSIGNEE.field()));
index daa9e27e3620b29b0988cb1a903e18ae14c16c88..f19c3248a8e9ea8de2bae8ff60232ef4c01b4130 100644 (file)
@@ -26,11 +26,7 @@ import com.google.common.collect.Iterables;
 import com.google.common.io.Resources;
 import org.sonar.api.component.Component;
 import org.sonar.api.i18n.I18n;
-import org.sonar.api.issue.ActionPlan;
-import org.sonar.api.issue.Issue;
-import org.sonar.api.issue.IssueComment;
-import org.sonar.api.issue.IssueQuery;
-import org.sonar.api.issue.IssueQueryResult;
+import org.sonar.api.issue.*;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.rules.Rule;
@@ -50,7 +46,7 @@ import org.sonar.server.issue.IssueService;
 import org.sonar.server.issue.filter.IssueFilterParameters;
 import org.sonar.server.issue.index.IssueResult;
 import org.sonar.server.search.FacetValue;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.Result;
 import org.sonar.server.search.ws.SearchOptions;
 import org.sonar.server.user.UserSession;
@@ -58,11 +54,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.List;
-import java.util.Map;
+import java.util.*;
 
 import static com.google.common.collect.Lists.newArrayList;
 
@@ -203,11 +195,11 @@ public class SearchAction implements RequestHandler {
   public void handle(Request request, Response response) {
     IssueQuery query = createQuery(request);
     SearchOptions searchOptions = SearchOptions.create(request);
-    QueryOptions queryOptions = new QueryOptions();
-    queryOptions.setPage(searchOptions.page(), searchOptions.pageSize());
-    queryOptions.setFacet(request.mandatoryParamAsBoolean(PARAM_FACETS));
+    QueryContext queryContext = new QueryContext();
+    queryContext.setPage(searchOptions.page(), searchOptions.pageSize());
+    queryContext.setFacet(request.mandatoryParamAsBoolean(PARAM_FACETS));
 
-    IssueResult results = service.search(query, queryOptions);
+    IssueResult results = service.search(query, queryContext);
 
     JsonWriter json = response.newJsonWriter();
     json.beginObject();
@@ -225,7 +217,7 @@ public class SearchAction implements RequestHandler {
     // writeUsers(results, json);
     // writeActionPlans(results, json);
 
-    if (queryOptions.isFacet()) {
+    if (queryContext.isFacet()) {
       writeFacets(results, json);
     }
 
index d55b8cdc7f8eb1c19391be5cb98d766197f8777e..1460a8950b4e02c1e3c29949b0aae06abb5a33e8 100644 (file)
@@ -33,9 +33,10 @@ import org.sonar.server.rule.index.RuleIndex;
 import org.sonar.server.rule.index.RuleQuery;
 import org.sonar.server.search.FacetValue;
 import org.sonar.server.search.IndexClient;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 
 import javax.annotation.CheckForNull;
+
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -126,7 +127,7 @@ public class QProfileLoader implements ServerComponent {
         .setQProfileKey(key)
         .setActivation(true)
         .setStatuses(Lists.newArrayList(RuleStatus.DEPRECATED)),
-      new QueryOptions().setLimit(0)).getTotal();
+      new QueryContext().setLimit(0)).getTotal();
   }
 
 
index fde5a90ed2f7344d44725992d9b8cdfdd55ff85f..43a10b1ed6bc5c9c13dfea5da11ce0904dbd05b2 100644 (file)
@@ -35,7 +35,7 @@ import org.sonar.server.activity.index.ActivityIndex;
 import org.sonar.server.db.DbClient;
 import org.sonar.server.rule.index.RuleQuery;
 import org.sonar.server.search.IndexClient;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.Result;
 import org.sonar.server.user.UserSession;
 
@@ -204,7 +204,7 @@ public class QProfileService implements ServerComponent {
     UserSession.get().checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN);
   }
 
-  public Result<QProfileActivity> searchActivities(QProfileActivityQuery query, QueryOptions options) {
+  public Result<QProfileActivity> searchActivities(QProfileActivityQuery query, QueryContext options) {
     DbSession session = db.openSession(false);
     try {
       OrFilterBuilder activityFilter = FilterBuilders.orFilter();
index 2fb2b565d6dccf07e63b59dd9ca35e07a39184b5..6bf1db54f808ec7113f174d62eea53c6b1de21a5 100644 (file)
@@ -21,7 +21,6 @@ package org.sonar.server.qualityprofile;
 
 import com.google.common.base.Splitter;
 import com.google.common.collect.Lists;
-import org.apache.commons.lang.StringUtils;
 import org.sonar.api.ServerComponent;
 import org.sonar.api.server.rule.RuleParamType;
 import org.sonar.core.activity.Activity;
@@ -42,7 +41,7 @@ import org.sonar.server.rule.index.RuleIndex;
 import org.sonar.server.rule.index.RuleNormalizer;
 import org.sonar.server.rule.index.RuleQuery;
 import org.sonar.server.search.IndexClient;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.Result;
 import org.sonar.server.util.TypeValidations;
 
@@ -390,7 +389,7 @@ public class RuleActivator implements ServerComponent {
     RuleIndex ruleIndex = index.get(RuleIndex.class);
     DbSession dbSession = db.openSession(false);
     try {
-      Result<Rule> ruleSearchResult = ruleIndex.search(ruleQuery, new QueryOptions().setScroll(true)
+      Result<Rule> ruleSearchResult = ruleIndex.search(ruleQuery, new QueryContext().setScroll(true)
         .setFieldsToReturn(Arrays.asList(RuleNormalizer.RuleField.KEY.field())));
       Iterator<Rule> rules = ruleSearchResult.scroll();
       while (rules.hasNext()) {
@@ -422,7 +421,7 @@ public class RuleActivator implements ServerComponent {
     try {
       RuleIndex ruleIndex = index.get(RuleIndex.class);
       BulkChangeResult result = new BulkChangeResult();
-      Result<Rule> ruleSearchResult = ruleIndex.search(ruleQuery, new QueryOptions().setScroll(true)
+      Result<Rule> ruleSearchResult = ruleIndex.search(ruleQuery, new QueryContext().setScroll(true)
         .setFieldsToReturn(Arrays.asList(RuleNormalizer.RuleField.KEY.field())));
       Iterator<Rule> rules = ruleSearchResult.scroll();
       while (rules.hasNext()) {
index ddcd033de8d71608e0242aea5468a61eba16be1f..bb96fd210b6ab9b1aede034eef270ad07f119da2 100644 (file)
@@ -29,7 +29,7 @@ import org.sonar.server.rule.index.RuleDoc;
 import org.sonar.server.rule.index.RuleIndex;
 import org.sonar.server.rule.index.RuleQuery;
 import org.sonar.server.search.IndexClient;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.Result;
 
 import javax.annotation.CheckForNull;
@@ -87,7 +87,7 @@ public class DefaultRuleFinder implements RuleFinder {
   }
 
   public final org.sonar.api.rules.Rule find(org.sonar.api.rules.RuleQuery query) {
-    Result<Rule> result = index.search(toQuery(query), new QueryOptions());
+    Result<Rule> result = index.search(toQuery(query), new QueryContext());
     if (!result.getHits().isEmpty()) {
       return toRule(result.getHits().get(0));
     } else {
@@ -97,7 +97,7 @@ public class DefaultRuleFinder implements RuleFinder {
 
   public final Collection<org.sonar.api.rules.Rule> findAll(org.sonar.api.rules.RuleQuery query) {
     List<org.sonar.api.rules.Rule> rules = newArrayList();
-    for (Rule rule : index.search(toQuery(query), new QueryOptions()).getHits()) {
+    for (Rule rule : index.search(toQuery(query), new QueryContext()).getHits()) {
       rules.add(toRule(rule));
     }
     return rules;
index e2d9dcced824bebc9a967ebcd69ebcc957f801d6..29d6ef12df31752a71e6f78dfd303b12accb5727 100644 (file)
@@ -31,7 +31,7 @@ import org.sonar.server.paging.PagingResult;
 import org.sonar.server.rule.index.RuleDoc;
 import org.sonar.server.rule.index.RuleNormalizer;
 import org.sonar.server.rule.index.RuleQuery;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.Result;
 import org.sonar.server.user.UserSession;
 import org.sonar.server.util.RubyUtils;
@@ -84,7 +84,7 @@ public class RubyRuleService implements ServerComponent, Startable {
     query.setHasDebtCharacteristic(RubyUtils.toBoolean(params.get("hasDebtCharacteristic")));
     query.setSortField(RuleNormalizer.RuleField.NAME);
 
-    QueryOptions options = new QueryOptions();
+    QueryContext options = new QueryContext();
     Integer pageSize = RubyUtils.toInteger(params.get("pageSize"));
     int size = pageSize != null ? pageSize : 50;
     if (size > -1) {
@@ -94,7 +94,7 @@ public class RubyRuleService implements ServerComponent, Startable {
       Result<Rule> result = service.search(query, options);
       return new PagedResult<Rule>(result.getHits(), PagingResult.create(options.getLimit(), pageIndex, result.getTotal()));
     } else {
-      options = new QueryOptions().setScroll(true);
+      options = new QueryContext().setScroll(true);
       List<Rule> rules = newArrayList(service.search(query, options).scroll());
       return new PagedResult<Rule>(rules, PagingResult.create(Integer.MAX_VALUE, 1, rules.size()));
     }
@@ -104,7 +104,7 @@ public class RubyRuleService implements ServerComponent, Startable {
    * Used in manual_rules_controller.rb
    */
   public List<Rule> searchManualRules() {
-    return service.search(new RuleQuery().setRepositories(newArrayList(RuleDoc.MANUAL_REPOSITORY)).setSortField(RuleNormalizer.RuleField.NAME), new QueryOptions()).getHits();
+    return service.search(new RuleQuery().setRepositories(newArrayList(RuleDoc.MANUAL_REPOSITORY)).setSortField(RuleNormalizer.RuleField.NAME), new QueryContext()).getHits();
   }
 
 
index 924490bcb4a496d0e5b3219368ed14081e1cb0e4..85fab0b327a2d39e604dfcf8679a86043f6f0e7c 100644 (file)
@@ -26,7 +26,7 @@ import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.rule.index.RuleIndex;
 import org.sonar.server.rule.index.RuleNormalizer;
 import org.sonar.server.rule.index.RuleQuery;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.Result;
 import org.sonar.server.user.UserSession;
 
@@ -68,7 +68,7 @@ public class RuleService implements ServerComponent {
     return new RuleQuery();
   }
 
-  public Result<Rule> search(RuleQuery query, QueryOptions options) {
+  public Result<Rule> search(RuleQuery query, QueryContext options) {
     return index.search(query, options);
   }
 
index 53b6ca26d24705acae5f294c684a7581e31f20d0..9811650de1000b733319a0ab1ff85fb992e7a729 100644 (file)
@@ -27,14 +27,7 @@ import org.elasticsearch.action.search.SearchType;
 import org.elasticsearch.common.settings.ImmutableSettings;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.unit.TimeValue;
-import org.elasticsearch.index.query.BoolFilterBuilder;
-import org.elasticsearch.index.query.BoolQueryBuilder;
-import org.elasticsearch.index.query.FilterBuilder;
-import org.elasticsearch.index.query.FilterBuilders;
-import org.elasticsearch.index.query.MatchQueryBuilder;
-import org.elasticsearch.index.query.QueryBuilder;
-import org.elasticsearch.index.query.QueryBuilders;
-import org.elasticsearch.index.query.SimpleQueryStringBuilder;
+import org.elasticsearch.index.query.*;
 import org.elasticsearch.search.SearchHit;
 import org.elasticsearch.search.aggregations.AggregationBuilders;
 import org.elasticsearch.search.aggregations.bucket.terms.Terms;
@@ -47,22 +40,12 @@ import org.sonar.api.server.debt.DebtCharacteristic;
 import org.sonar.core.rule.RuleDto;
 import org.sonar.server.qualityprofile.index.ActiveRuleNormalizer;
 import org.sonar.server.rule.Rule;
-import org.sonar.server.search.BaseIndex;
-import org.sonar.server.search.IndexDefinition;
-import org.sonar.server.search.IndexField;
-import org.sonar.server.search.QueryOptions;
-import org.sonar.server.search.Result;
-import org.sonar.server.search.SearchClient;
+import org.sonar.server.search.*;
 
 import javax.annotation.CheckForNull;
+
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 import static com.google.common.collect.Lists.newArrayList;
 
@@ -100,7 +83,7 @@ public class RuleIndex extends BaseIndex<Rule, RuleDto, RuleKey> {
     return mapping;
   }
 
-  private void setFields(QueryOptions options, SearchRequestBuilder esSearch) {
+  private void setFields(QueryContext options, SearchRequestBuilder esSearch) {
     /* integrate Option's Fields */
     Set<String> fields = new HashSet<String>();
     if (!options.getFieldsToReturn().isEmpty()) {
@@ -120,7 +103,7 @@ public class RuleIndex extends BaseIndex<Rule, RuleDto, RuleKey> {
     esSearch.setFetchSource(fields.toArray(new String[fields.size()]), null);
   }
 
-  private void setFacets(QueryOptions options, SearchRequestBuilder esSearch) {
+  private void setFacets(QueryContext options, SearchRequestBuilder esSearch) {
     /* Integrate Facets */
     if (options.isFacet()) {
       this.setFacets(esSearch);
@@ -148,7 +131,7 @@ public class RuleIndex extends BaseIndex<Rule, RuleDto, RuleKey> {
     }
   }
 
-  protected void setPagination(QueryOptions options, SearchRequestBuilder esSearch) {
+  protected void setPagination(QueryContext options, SearchRequestBuilder esSearch) {
     esSearch.setFrom(options.getOffset());
     esSearch.setSize(options.getLimit());
   }
@@ -168,7 +151,7 @@ public class RuleIndex extends BaseIndex<Rule, RuleDto, RuleKey> {
   }
 
   /* Build main query (search based) */
-  protected QueryBuilder getQuery(RuleQuery query, QueryOptions options) {
+  protected QueryBuilder getQuery(RuleQuery query, QueryContext options) {
 
     // No contextual query case
     String queryText = query.getQueryText();
@@ -202,7 +185,7 @@ public class RuleIndex extends BaseIndex<Rule, RuleDto, RuleKey> {
   }
 
   /* Build main filter (match based) */
-  protected FilterBuilder getFilter(RuleQuery query, QueryOptions options) {
+  protected FilterBuilder getFilter(RuleQuery query, QueryContext options) {
 
     BoolFilterBuilder fb = FilterBuilders.boolFilter();
 
@@ -334,7 +317,7 @@ public class RuleIndex extends BaseIndex<Rule, RuleDto, RuleKey> {
 
   }
 
-  public Result<Rule> search(RuleQuery query, QueryOptions options) {
+  public Result<Rule> search(RuleQuery query, QueryContext options) {
     SearchRequestBuilder esSearch = getClient()
       .prepareSearch(this.getIndexName())
       .setTypes(this.getIndexType())
index 2d90ff52a2b45b9921aab551db1f1f821811a5f6..9f22915bbc699b1b2f322935cdab0182a6b30b51 100644 (file)
@@ -34,7 +34,7 @@ import org.sonar.server.rule.RuleService;
 import org.sonar.server.rule.index.RuleNormalizer;
 import org.sonar.server.rule.index.RuleQuery;
 import org.sonar.server.search.FacetValue;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.Result;
 import org.sonar.server.search.ws.SearchOptions;
 
@@ -212,10 +212,10 @@ public class SearchAction implements RequestHandler {
   public void handle(Request request, Response response) {
     RuleQuery query = createRuleQuery(ruleService.newRuleQuery(), request);
     SearchOptions searchOptions = SearchOptions.create(request);
-    QueryOptions queryOptions = mapping.newQueryOptions(searchOptions);
-    queryOptions.setFacet(request.mandatoryParamAsBoolean(PARAM_FACETS));
+    QueryContext queryContext = mapping.newQueryOptions(searchOptions);
+    queryContext.setFacet(request.mandatoryParamAsBoolean(PARAM_FACETS));
 
-    Result<Rule> results = ruleService.search(query, queryOptions);
+    Result<Rule> results = ruleService.search(query, queryContext);
 
     JsonWriter json = response.newJsonWriter().beginObject();
     searchOptions.writeStatistics(json, results);
@@ -223,7 +223,7 @@ public class SearchAction implements RequestHandler {
     if (searchOptions.hasField("actives")) {
       activeRuleCompleter.completeSearch(query, results.getHits(), json);
     }
-    if (queryOptions.isFacet()) {
+    if (queryContext.isFacet()) {
       writeFacets(results, json);
     }
     json.endObject().close();
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/QueryContext.java b/server/sonar-server/src/main/java/org/sonar/server/search/QueryContext.java
new file mode 100644 (file)
index 0000000..a8dda87
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.search;
+
+import com.google.common.base.Preconditions;
+import org.sonar.server.user.UserSession;
+
+import javax.annotation.Nullable;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Set;
+
+import static com.google.common.collect.Sets.newHashSet;
+
+/**
+ * Various Elasticsearch request options: paging, sorting, fields and facets
+ *
+ * @since 4.4
+ */
+public class QueryContext {
+
+  public static final int DEFAULT_OFFSET = 0;
+  public static final int DEFAULT_LIMIT = 10;
+  public static final int MAX_LIMIT = 500;
+  public static final boolean DEFAULT_FACET = false;
+
+  private int offset = DEFAULT_OFFSET;
+  private int limit = DEFAULT_LIMIT;
+  private boolean facet = DEFAULT_FACET;
+  private Set<String> fieldsToReturn = newHashSet();
+  private boolean scroll = false;
+  private String userLogin;
+  private Set<String> userGroups = newHashSet();
+
+  public QueryContext() {
+    this.userLogin = UserSession.get().login();
+    this.userGroups = UserSession.get().userGroups();
+  }
+
+  /**
+   * Whether or not the search returns facets for the domain. Defaults to {@link #DEFAULT_OFFSET}
+   */
+  public boolean isFacet() {
+    return facet;
+  }
+
+  /**
+   * Sets whether or not the search returns facets for the domain.
+   */
+  public QueryContext setFacet(boolean facet) {
+    this.facet = facet;
+    return this;
+  }
+
+  /**
+   * Whether or not the search result will be scrollable using an iterator
+   */
+  public boolean isScroll() {
+    return scroll;
+  }
+
+  /**
+   * Sets whether or not the search result will be scrollable using an iterator
+   */
+  public QueryContext setScroll(boolean scroll) {
+    this.scroll = scroll;
+    return this;
+  }
+
+  /**
+   * Offset of the first result to return. Defaults to {@link #DEFAULT_OFFSET}
+   */
+  public int getOffset() {
+    return offset;
+  }
+
+  /**
+   * Sets the offset of the first result to return (zero-based).
+   */
+  public QueryContext setOffset(int offset) {
+    Preconditions.checkArgument(offset >= 0, "Offset must be positive");
+    this.offset = offset;
+    return this;
+  }
+
+  /**
+   * Set offset and limit according to page approach
+   */
+  public QueryContext setPage(int page, int pageSize) {
+    Preconditions.checkArgument(page >= 1, "Page must be greater or equal to 1 (got " + page + ")");
+    Preconditions.checkArgument(pageSize >= 0, "Page size must be greater or equal to 0 (got " + pageSize + ")");
+    setLimit(pageSize);
+    setOffset((page * getLimit()) - getLimit());
+    return this;
+  }
+
+  /**
+   * Limit on the number of results to return. Defaults to {@link #DEFAULT_LIMIT}.
+   */
+  public int getLimit() {
+    return limit;
+  }
+
+  /**
+   * Sets the limit on the number of results to return.
+   */
+  public QueryContext setLimit(int limit) {
+    this.limit = Math.min(limit, MAX_LIMIT);
+    return this;
+  }
+
+  public QueryContext setMaxLimit() {
+    this.limit = MAX_LIMIT;
+    return this;
+  }
+
+  public Set<String> getFieldsToReturn() {
+    return fieldsToReturn;
+  }
+
+  public QueryContext setFieldsToReturn(@Nullable Collection<String> c) {
+    fieldsToReturn.clear();
+    if (c != null) {
+      this.fieldsToReturn = newHashSet(c);
+    }
+    return this;
+  }
+
+  public QueryContext addFieldsToReturn(@Nullable Collection<String> c) {
+    if (c != null) {
+      fieldsToReturn.addAll(c);
+    }
+    return this;
+  }
+
+  public QueryContext addFieldsToReturn(String... c) {
+    return addFieldsToReturn(Arrays.asList(c));
+  }
+
+  public String getUserLogin() {
+    return userLogin;
+  }
+
+  public Set<String> getUserGroups() {
+    return userGroups;
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/QueryOptions.java b/server/sonar-server/src/main/java/org/sonar/server/search/QueryOptions.java
deleted file mode 100644 (file)
index 46a1446..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.search;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Sets;
-
-import javax.annotation.Nullable;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Set;
-
-/**
- * Various Elasticsearch request options: paging, sorting, fields and facets
- *
- * @since 4.4
- */
-public class QueryOptions {
-
-  public static final int DEFAULT_OFFSET = 0;
-  public static final int DEFAULT_LIMIT = 10;
-  public static final int MAX_LIMIT = 500;
-  public static final boolean DEFAULT_FACET = false;
-
-  private int offset = DEFAULT_OFFSET;
-  private int limit = DEFAULT_LIMIT;
-  private boolean facet = DEFAULT_FACET;
-  private Set<String> fieldsToReturn = Sets.newHashSet();
-  private boolean scroll = false;
-
-  /**
-   * Whether or not the search returns facets for the domain. Defaults to {@link #DEFAULT_OFFSET}
-   */
-  public boolean isFacet() {
-    return facet;
-  }
-
-  /**
-   * Sets whether or not the search returns facets for the domain.
-   */
-  public QueryOptions setFacet(boolean facet) {
-    this.facet = facet;
-    return this;
-  }
-
-  /**
-   * Whether or not the search result will be scrollable using an iterator
-   */
-  public boolean isScroll() {
-    return scroll;
-  }
-
-  /**
-   * Sets whether or not the search result will be scrollable using an iterator
-   */
-  public QueryOptions setScroll(boolean scroll) {
-    this.scroll = scroll;
-    return this;
-  }
-
-  /**
-   * Offset of the first result to return. Defaults to {@link #DEFAULT_OFFSET}
-   */
-  public int getOffset() {
-    return offset;
-  }
-
-  /**
-   * Sets the offset of the first result to return (zero-based).
-   */
-  public QueryOptions setOffset(int offset) {
-    Preconditions.checkArgument(offset >= 0, "Offset must be positive");
-    this.offset = offset;
-    return this;
-  }
-
-  /**
-   * Set offset and limit according to page approach
-   */
-  public QueryOptions setPage(int page, int pageSize) {
-    Preconditions.checkArgument(page >= 1, "Page must be greater or equal to 1 (got " + page + ")");
-    Preconditions.checkArgument(pageSize >= 0, "Page size must be greater or equal to 0 (got " + pageSize + ")");
-    setLimit(pageSize);
-    setOffset((page * getLimit()) - getLimit());
-    return this;
-  }
-
-  /**
-   * Limit on the number of results to return. Defaults to {@link #DEFAULT_LIMIT}.
-   */
-  public int getLimit() {
-    return limit;
-  }
-
-  /**
-   * Sets the limit on the number of results to return.
-   */
-  public QueryOptions setLimit(int limit) {
-    this.limit = Math.min(limit, MAX_LIMIT);
-    return this;
-  }
-
-  public QueryOptions setMaxLimit() {
-    this.limit = MAX_LIMIT;
-    return this;
-  }
-
-  public Set<String> getFieldsToReturn() {
-    return fieldsToReturn;
-  }
-
-  public QueryOptions setFieldsToReturn(@Nullable Collection<String> c) {
-    fieldsToReturn.clear();
-    if (c != null) {
-      this.fieldsToReturn = Sets.newHashSet(c);
-    }
-    return this;
-  }
-
-  public QueryOptions addFieldsToReturn(@Nullable Collection<String> c) {
-    if (c != null) {
-      fieldsToReturn.addAll(c);
-    }
-    return this;
-  }
-
-  public QueryOptions addFieldsToReturn(String... c) {
-    return addFieldsToReturn(Arrays.asList(c));
-  }
-}
index 8a4096a47a8a9e8757db53fd28003f6bbcc7edce..6af489f43f94a82693732b962746c35240705841 100644 (file)
@@ -25,7 +25,7 @@ import org.sonar.api.ServerComponent;
 import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.server.search.BaseDoc;
 import org.sonar.server.search.IndexUtils;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 
 import javax.annotation.Nullable;
 
@@ -48,8 +48,8 @@ public abstract class BaseMapping<DOC extends BaseDoc, CTX> implements ServerCom
     return mappers.keySet();
   }
 
-  public QueryOptions newQueryOptions(SearchOptions options) {
-    QueryOptions result = new QueryOptions();
+  public QueryContext newQueryOptions(SearchOptions options) {
+    QueryContext result = new QueryContext();
     result.setPage(options.page(), options.pageSize());
     List<String> optionFields = options.fields();
     if (optionFields != null) {
index ea246307e506fc89daa1b9add357ee103c16235a..4b8e25f137d9c29595601980add82f2d4ddad7db 100644 (file)
@@ -22,11 +22,12 @@ package org.sonar.server.search.ws;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.Result;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
+
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
@@ -126,6 +127,6 @@ public class SearchOptions {
       .createParam(PARAM_PAGE_SIZE)
       .setDescription("Page size. Must be greater than 0.")
       .setExampleValue("20")
-      .setDefaultValue(String.valueOf(QueryOptions.DEFAULT_LIMIT));
+      .setDefaultValue(String.valueOf(QueryContext.DEFAULT_LIMIT));
   }
 }
index 5ef9c1926744b46da16d9de3da7260bc517fe193..bd8dc0f9960ada02c0d15e1cba398bb133c9826e 100644 (file)
@@ -23,12 +23,19 @@ import org.sonar.server.ui.JRubyI18n;
 
 import javax.annotation.Nullable;
 
+import java.util.List;
+
 public class RubyUserSession {
   /**
    * Invoked by Ruby code - see application_controller.rb
    */
-  public static void setSession(@Nullable Integer userId, @Nullable String login, @Nullable String name, @Nullable String localeRubyKey) {
-    UserSession session = new UserSession().setLogin(login).setName(name).setUserId(userId).setLocale(JRubyI18n.toLocale(localeRubyKey));
+  public static void setSession(@Nullable Integer userId, @Nullable String login, @Nullable String name, @Nullable List<String> userGroups, @Nullable String localeRubyKey) {
+    UserSession session = new UserSession()
+      .setLogin(login)
+      .setName(name)
+      .setUserId(userId)
+      .setUserGroups(userGroups != null ? userGroups.toArray(new String[userGroups.size()]) : null)
+      .setLocale(JRubyI18n.toLocale(localeRubyKey));
     UserSession.set(session);
   }
 
index 1bfc6f48ff00ec03769a4d998b886e715bfe3b9c..98622a74b60e4c34d2f080da2338d9bd0955566d 100644 (file)
@@ -24,6 +24,7 @@ import com.google.common.base.Strings;
 import com.google.common.collect.HashMultimap;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.sonar.api.security.DefaultGroups;
 import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.core.resource.ResourceDao;
 import org.sonar.core.resource.ResourceDto;
@@ -35,14 +36,11 @@ import org.sonar.server.platform.Platform;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
+import java.util.*;
 
 import static com.google.common.collect.Lists.newArrayList;
 import static com.google.common.collect.Maps.newHashMap;
+import static com.google.common.collect.Sets.newHashSet;
 
 /**
  * Part of the current HTTP session
@@ -58,6 +56,7 @@ public class UserSession {
   private Integer userId;
   private String login;
   private String name;
+  private Set<String> userGroups;
   private Locale locale = Locale.ENGLISH;
   List<String> globalPermissions = null;
 
@@ -66,6 +65,8 @@ public class UserSession {
   List<String> projectPermissions = newArrayList();
 
   UserSession() {
+    // Do not forget that when forceAuthentication is set to true, the Anyone group should not be set (but this will be check when authentication will be done in Java)
+    userGroups = newHashSet(DefaultGroups.ANYONE);
   }
 
   @CheckForNull
@@ -98,6 +99,17 @@ public class UserSession {
     return this;
   }
 
+  public Set<String> userGroups() {
+    return userGroups;
+  }
+
+  UserSession setUserGroups(@Nullable String... userGroups) {
+    if (userGroups != null) {
+      this.userGroups.addAll(Arrays.asList(userGroups));
+    }
+    return this;
+  }
+
   public boolean isLoggedIn() {
     return login != null;
   }
index 9f6a5db3775c1eb0bb11718969b5dc011c311be3..174dd1e959d970f34f692318840daebec8b45c82 100644 (file)
@@ -27,6 +27,8 @@ import org.sonar.core.user.GroupDto;
 import org.sonar.core.user.GroupMapper;
 import org.sonar.server.db.BaseDao;
 
+import java.util.List;
+
 /**
  * @since 3.2
  */
@@ -52,4 +54,8 @@ public class GroupDao extends BaseDao<GroupMapper, GroupDto, String> {
     return item;
   }
 
+  public List<GroupDto> findByUserLogin(DbSession session, String login){
+    return mapper(session).selectByUserLogin(login);
+  }
+
 }
index 2ab0d3e88bad8cc1f59ec15c3605b378a38ed067..e20aea655835b047f118c54b54e06f095adc515b 100644 (file)
@@ -34,7 +34,7 @@ import org.sonar.server.activity.index.ActivityIndex;
 import org.sonar.server.activity.index.ActivityQuery;
 import org.sonar.server.db.DbClient;
 import org.sonar.server.platform.Platform;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.Result;
 import org.sonar.server.tester.ServerTester;
 
@@ -108,7 +108,7 @@ public class ActivityBackendMediumTest {
     service.write(dbSession, Activity.Type.QPROFILE, "now");
     dbSession.commit();
 
-    Activity activity = service.search(new ActivityQuery(), new QueryOptions()).getHits().get(0);
+    Activity activity = service.search(new ActivityQuery(), new QueryContext()).getHits().get(0);
     assertThat(System.currentTimeMillis() - activity.time().getTime()).isLessThan(1000L);
   }
 
@@ -131,7 +131,7 @@ public class ActivityBackendMediumTest {
 
     // 2. assert scrollable
     int count = 0;
-    SearchResponse result = index.search(new ActivityQuery(), new QueryOptions().setScroll(true));
+    SearchResponse result = index.search(new ActivityQuery(), new QueryContext().setScroll(true));
     Iterator<Activity> logs = new Result<Activity>(index, result).scroll();
     while (logs.hasNext()) {
       logs.next();
@@ -142,7 +142,7 @@ public class ActivityBackendMediumTest {
     // 3 assert synchronize above IndexQueue threshold
     tester.clearIndexes();
     tester.get(Platform.class).executeStartupTasks();
-    result = index.search(new ActivityQuery(), new QueryOptions().setScroll(true));
+    result = index.search(new ActivityQuery(), new QueryContext().setScroll(true));
     logs = new Result<Activity>(index, result).scroll();
     count = 0;
     while (logs.hasNext()) {
@@ -172,7 +172,7 @@ public class ActivityBackendMediumTest {
 
     // 2. assert scrollable
     int count = 0;
-    SearchResponse result = index.search(new ActivityQuery(), new QueryOptions().setScroll(true));
+    SearchResponse result = index.search(new ActivityQuery(), new QueryContext().setScroll(true));
     Iterator<Activity> logs = new Result<Activity>(index, result).scroll();
     while (logs.hasNext()) {
       logs.next();
@@ -183,7 +183,7 @@ public class ActivityBackendMediumTest {
     // 3 assert synchronize above IndexQueue threshold
     tester.clearIndexes();
     tester.get(Platform.class).executeStartupTasks();
-    result = index.search(new ActivityQuery(), new QueryOptions().setScroll(true));
+    result = index.search(new ActivityQuery(), new QueryContext().setScroll(true));
     logs = new Result<Activity>(index, result).scroll();
     count = 0;
     while (logs.hasNext()) {
index cdd596d5ca60ce85bfae376d095b288d65fe881e..d90fc8343f92d74a11314feeb77af76db0a50370 100644 (file)
@@ -36,7 +36,7 @@ import org.sonar.server.activity.db.ActivityDao;
 import org.sonar.server.activity.index.ActivityIndex;
 import org.sonar.server.activity.index.ActivityQuery;
 import org.sonar.server.db.DbClient;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.Result;
 import org.sonar.server.tester.ServerTester;
 
@@ -85,7 +85,7 @@ public class ActivityServiceMediumTest {
     dbSession.commit();
     assertThat(index.findAll().getTotal()).isEqualTo(1);
 
-    SearchResponse result = index.search(service.newActivityQuery(), new QueryOptions());
+    SearchResponse result = index.search(service.newActivityQuery(), new QueryContext());
     assertThat(result.getHits().getTotalHits()).isEqualTo(1L);
     Result<Activity> activityResult = new Result<Activity>(index, result);
     assertThat(activityResult.getHits().get(0).message()).isEqualTo(testValue);
@@ -98,7 +98,7 @@ public class ActivityServiceMediumTest {
     dbSession.commit();
     assertThat(index.findAll().getTotal()).isEqualTo(1);
 
-    SearchResponse result = index.search(service.newActivityQuery(), new QueryOptions());
+    SearchResponse result = index.search(service.newActivityQuery(), new QueryContext());
     assertThat(result.getHits().getTotalHits()).isEqualTo(1L);
     Result<Activity> activityResult = new Result<Activity>(index, result);
     assertThat(activityResult.getHits().get(0).details().get(test_key)).isEqualTo(test_value);
@@ -113,15 +113,15 @@ public class ActivityServiceMediumTest {
     dbSession.commit();
 
     assertThat(service.search(new ActivityQuery(),
-      new QueryOptions()).getHits()).hasSize(4);
+      new QueryContext()).getHits()).hasSize(4);
 
     assertThat(service.search(new ActivityQuery()
       .setTypes(ImmutableSet.of(Activity.Type.SERVER)),
-      new QueryOptions()).getHits()).hasSize(2);
+      new QueryContext()).getHits()).hasSize(2);
 
     assertThat(service.search(new ActivityQuery()
       .setTypes(ImmutableSet.of(Activity.Type.QPROFILE)),
-      new QueryOptions()).getHits()).hasSize(1);
+      new QueryContext()).getHits()).hasSize(1);
   }
 
   @Test
@@ -143,28 +143,28 @@ public class ActivityServiceMediumTest {
     DateTime t2 = new DateTime().plusHours(1);
 
     assertThat(service.search(new ActivityQuery(),
-      new QueryOptions()).getHits()).hasSize(3);
+      new QueryContext()).getHits()).hasSize(3);
 
     assertThat(service.search(new ActivityQuery()
       .setSince(t0.minusSeconds(5).toDate()),
-      new QueryOptions()).getHits()).hasSize(3);
+      new QueryContext()).getHits()).hasSize(3);
 
     assertThat(service.search(new ActivityQuery()
       .setSince(t1.minusSeconds(5).toDate()),
-      new QueryOptions()).getHits()).hasSize(1);
+      new QueryContext()).getHits()).hasSize(1);
 
     assertThat(service.search(new ActivityQuery()
       .setSince(t2.minusSeconds(5).toDate()),
-      new QueryOptions()).getHits()).hasSize(0);
+      new QueryContext()).getHits()).hasSize(0);
 
     assertThat(service.search(new ActivityQuery()
       .setTo(t1.minusSeconds(5).toDate()),
-      new QueryOptions()).getHits()).hasSize(2);
+      new QueryContext()).getHits()).hasSize(2);
 
     assertThat(service.search(new ActivityQuery()
       .setSince(t1.minusSeconds(5).toDate())
       .setTo(t2.plusSeconds(5).toDate()),
-      new QueryOptions()).getHits()).hasSize(1);
+      new QueryContext()).getHits()).hasSize(1);
   }
 
   private ActivityDto getActivityDto() {
@@ -174,7 +174,7 @@ public class ActivityServiceMediumTest {
 
   @Test
   public void iterate_all() throws InterruptedException {
-    int max = QueryOptions.DEFAULT_LIMIT + 3;
+    int max = QueryContext.DEFAULT_LIMIT + 3;
     final String testValue = "hello world";
     for (int i = 0; i < max; i++) {
       service.write(dbSession, Activity.Type.QPROFILE, testValue + "_" + i);
@@ -184,7 +184,7 @@ public class ActivityServiceMediumTest {
     // 0. assert Base case
     assertThat(dao.findAll(dbSession)).hasSize(max);
 
-    SearchResponse result = index.search(service.newActivityQuery(), new QueryOptions().setScroll(true));
+    SearchResponse result = index.search(service.newActivityQuery(), new QueryContext().setScroll(true));
     assertThat(result.getHits().getTotalHits()).isEqualTo(max);
     Result<Activity> activityResult = new Result<Activity>(index, result);
 
index 6a7d5cc2d21ed4970aa1d852156d0729bd8cb38a..ddc33112ad54ea64c4a421151d0423156de448fb 100644 (file)
@@ -34,7 +34,7 @@ import org.sonar.core.activity.Activity;
 import org.sonar.server.qualityprofile.QProfileActivity;
 import org.sonar.server.qualityprofile.QProfileActivityQuery;
 import org.sonar.server.qualityprofile.QProfileService;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.Result;
 
 import java.util.Date;
@@ -53,7 +53,7 @@ public class RubyQProfileActivityServiceTest {
   ArgumentCaptor<QProfileActivityQuery> activityArgumentCaptor;
 
   @Captor
-  ArgumentCaptor<QueryOptions> queryOptionsArgumentCaptor;
+  ArgumentCaptor<QueryContext> queryOptionsArgumentCaptor;
 
   RubyQProfileActivityService rubyQProfileActivityService;
 
@@ -70,7 +70,7 @@ public class RubyQProfileActivityServiceTest {
     Result<QProfileActivity> result = mock(Result.class);
     when(result.getHits()).thenReturn(Lists.<QProfileActivity>newArrayList());
     when(result.getTotal()).thenReturn(10L);
-    when(service.searchActivities(any(QProfileActivityQuery.class), any(QueryOptions.class))).thenReturn(result);
+    when(service.searchActivities(any(QProfileActivityQuery.class), any(QueryContext.class))).thenReturn(result);
 
     rubyQProfileActivityService.search(ImmutableMap.<String, Object>of("profileKeys", "PROFILE_KEY", "since", since, "to", to));
 
@@ -89,7 +89,7 @@ public class RubyQProfileActivityServiceTest {
     Result<QProfileActivity> result = mock(Result.class);
     when(result.getHits()).thenReturn(Lists.<QProfileActivity>newArrayList());
     when(result.getTotal()).thenReturn(10L);
-    when(service.searchActivities(any(QProfileActivityQuery.class), any(QueryOptions.class))).thenReturn(result);
+    when(service.searchActivities(any(QProfileActivityQuery.class), any(QueryContext.class))).thenReturn(result);
 
     rubyQProfileActivityService.search(ImmutableMap.<String, Object>of());
 
index c24e6e36ebf421adbeb1de6b879eeb72fc830b63..edb05332e3edf40111fcea836d7acd605fe2a372 100644 (file)
@@ -59,7 +59,7 @@ import org.sonar.server.measure.persistence.MeasureDao;
 import org.sonar.server.rule.Rule;
 import org.sonar.server.rule.RuleService;
 import org.sonar.server.rule.index.RuleQuery;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.Result;
 import org.sonar.server.ui.ViewProxy;
 import org.sonar.server.ui.Views;
@@ -470,7 +470,7 @@ public class ComponentAppActionTest {
     when(rule.key()).thenReturn(RuleKey.of("manual", "API"));
     when(rule.name()).thenReturn("API");
     when(result.getHits()).thenReturn(newArrayList(rule));
-    when(ruleService.search(any(RuleQuery.class), any(QueryOptions.class))).thenReturn(result);
+    when(ruleService.search(any(RuleQuery.class), any(QueryContext.class))).thenReturn(result);
 
     WsTester.TestRequest request = tester.newGetRequest("api/components", "app").setParam("key", COMPONENT_KEY);
     request.execute().assertJson(getClass(), "app_with_manual_rules.json");
index 53361becc3c4bed1b5a963b7cc3e496aa206b528..40813271558fad2b824e90ab7afd8551b35eeadb 100644 (file)
@@ -24,9 +24,12 @@ import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Test;
 import org.sonar.api.issue.IssueQuery;
+import org.sonar.api.security.DefaultGroups;
 import org.sonar.api.utils.DateUtils;
+import org.sonar.api.web.UserRole;
 import org.sonar.core.component.ComponentDto;
 import org.sonar.core.issue.db.IssueDto;
+import org.sonar.core.permission.PermissionFacade;
 import org.sonar.core.persistence.DbSession;
 import org.sonar.core.rule.RuleDto;
 import org.sonar.server.component.persistence.ComponentDao;
@@ -35,9 +38,10 @@ import org.sonar.server.issue.db.IssueDao;
 import org.sonar.server.issue.index.IssueResult;
 import org.sonar.server.rule.RuleTesting;
 import org.sonar.server.rule.db.RuleDao;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.tester.ServerTester;
 
+import java.util.Date;
 import java.util.UUID;
 
 import static org.fest.assertions.Assertions.assertThat;
@@ -78,6 +82,11 @@ public class IssueServiceMediumTest {
       .setKey("MyComponent")
       .setId(2L);
     tester.get(ComponentDao.class).insert(session, resource);
+
+    // project can be seen by anyone
+    tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session);
+    db.issueAuthorizationDao().synchronizeAfter(session, new Date(0));
+
     session.commit();
   }
 
@@ -93,11 +102,11 @@ public class IssueServiceMediumTest {
     tester.get(IssueDao.class).insert(session, issue1, issue2);
     session.commit();
 
-    IssueResult result = service.search(IssueQuery.builder().build(), new QueryOptions());
+    IssueResult result = service.search(IssueQuery.builder().build(), new QueryContext());
     assertThat(result.getHits()).hasSize(2);
     assertThat(result.getFacets()).isEmpty();
 
-    result = service.search(IssueQuery.builder().build(), new QueryOptions().setFacet(true));
+    result = service.search(IssueQuery.builder().build(), new QueryContext().setFacet(true));
     assertThat(result.getFacets().keySet()).hasSize(4);
     assertThat(result.getFacetKeys("actionPlan")).hasSize(2);
   }
@@ -109,7 +118,7 @@ public class IssueServiceMediumTest {
     tester.get(IssueDao.class).insert(session, issue1, issue2);
     session.commit();
 
-    IssueResult result = service.search(IssueQuery.builder().build(), new QueryOptions());
+    IssueResult result = service.search(IssueQuery.builder().build(), new QueryContext());
     assertThat(result.projects()).hasSize(1);
     assertThat(result.components()).hasSize(1);
   }
index 38a1d7e5d59ee846b5300f69cbe0856ca6c56aaf..ff7415bdc0232733572861905a16ffd660c30e89 100644 (file)
@@ -65,7 +65,7 @@ public class IssueAuthorizationDaoTest extends AbstractDaoTestCase {
     assertThat(dto.getProject()).isEqualTo("org.struts:struts");
     assertThat(dto.getKey()).isEqualTo("org.struts:struts");
     assertThat(dto.getPermission()).isEqualTo("user");
-    assertThat(dto.getGroups()).containsExactly("anyone", "devs");
+    assertThat(dto.getGroups()).containsExactly("Anyone", "devs");
     assertThat(dto.getUsers()).containsExactly("user1");
   }
 
index 01b25f0396a9d4306d8aafd460ec99bd3024b410..2e9ad9494cf5c8b9ba589529f001d59d9c14d125 100644 (file)
@@ -191,11 +191,6 @@ public class IssueBackendMediumTest {
     assertThat(indexClient.get(IssueIndex.class).countAll()).isEqualTo(1);
   }
 
-  @Test
-  public void synchronize_issue_authorization_index() throws Exception {
-
-  }
-
   @Test
   public void issue_authorization_on_group() throws Exception {
     SearchClient searchClient = tester.get(SearchClient.class);
@@ -302,14 +297,13 @@ public class IssueBackendMediumTest {
   }
 
   private SearchResponse searchIssueWithAuthorization(SearchClient searchClient, String user, String... groups) {
-    BoolFilterBuilder fb = FilterBuilders.boolFilter();
+    BoolFilterBuilder permissionFilter = FilterBuilders.boolFilter();
 
     OrFilterBuilder or = FilterBuilders.orFilter(FilterBuilders.termFilter("users", user));
     for (String group : groups) {
       or.add(FilterBuilders.termFilter("groups", group));
     }
-    fb.must(FilterBuilders.termFilter("permission", "read"), or).cache(true);
-    // fb.must(FilterBuilders.termFilter("permission", "read"), or);
+    permissionFilter.must(FilterBuilders.termFilter("permission", "read"), or).cache(true);
 
     SearchRequestBuilder request = searchClient.prepareSearch(IndexDefinition.ISSUES.getIndexName()).setTypes(IndexDefinition.ISSUES.getIndexType())
       .setQuery(
@@ -317,7 +311,7 @@ public class IssueBackendMediumTest {
           QueryBuilders.matchAllQuery(),
           FilterBuilders.hasParentFilter(IndexDefinition.ISSUES_AUTHORIZATION.getIndexType(),
             QueryBuilders.filteredQuery(
-              QueryBuilders.matchAllQuery(), fb)
+              QueryBuilders.matchAllQuery(), permissionFilter)
             )
           )
       )
index a52a5c3b1163713b41ef59dabfc616842164ade2..7a52af104c4fb7c1f1120be83d931406aa8c7441 100644 (file)
@@ -26,18 +26,25 @@ import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Test;
 import org.sonar.api.issue.IssueQuery;
+import org.sonar.api.security.DefaultGroups;
 import org.sonar.api.utils.DateUtils;
+import org.sonar.api.web.UserRole;
 import org.sonar.core.component.ComponentDto;
 import org.sonar.core.issue.db.IssueDto;
+import org.sonar.core.permission.PermissionFacade;
 import org.sonar.core.persistence.DbSession;
 import org.sonar.core.rule.RuleDto;
+import org.sonar.core.user.GroupDto;
+import org.sonar.core.user.UserDto;
 import org.sonar.server.component.persistence.ComponentDao;
 import org.sonar.server.db.DbClient;
 import org.sonar.server.rule.RuleTesting;
 import org.sonar.server.rule.db.RuleDao;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.tester.ServerTester;
+import org.sonar.server.user.MockUserSession;
 
+import java.util.Date;
 import java.util.UUID;
 
 import static org.fest.assertions.Assertions.assertThat;
@@ -76,6 +83,15 @@ public class IssueIndexMediumTest {
       .setKey("MyComponent")
       .setId(2L);
     tester.get(ComponentDao.class).insert(session, resource);
+
+    // project can be seen by anyone
+    tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session);
+    db.issueAuthorizationDao().synchronizeAfter(session, new Date(0));
+
+    MockUserSession.set();
+
+    session.commit();
+    session.clearCache();
   }
 
   @After
@@ -85,81 +101,200 @@ public class IssueIndexMediumTest {
 
   @Test
   public void filter_by_actionPlan() throws Exception {
-
     String plan1 = "plan1";
     String plan2 = "plan2";
-    IssueDto issue1 = getIssue()
+    IssueDto issue1 = createIssue()
       .setActionPlanKey(plan1);
-    IssueDto issue2 = getIssue()
+    IssueDto issue2 = createIssue()
       .setActionPlanKey(plan2);
     db.issueDao().insert(session, issue1, issue2);
     session.commit();
 
     IssueQuery.Builder query = IssueQuery.builder();
     query.actionPlans(ImmutableList.of(plan1));
-    SearchResponse result = index.search(query.build(), new QueryOptions());
+    SearchResponse result = index.search(query.build(), new QueryContext());
+
     assertThat(result.getHits().getTotalHits()).isEqualTo(1L);
 
     query = IssueQuery.builder();
     query.actionPlans(ImmutableList.of(plan2));
-    result = index.search(query.build(), new QueryOptions());
+    result = index.search(query.build(), new QueryContext());
     assertThat(result.getHits().getTotalHits()).isEqualTo(1L);
 
     query = IssueQuery.builder();
     query.actionPlans(ImmutableList.of(plan2, plan1));
-    result = index.search(query.build(), new QueryOptions());
+    result = index.search(query.build(), new QueryContext());
     assertThat(result.getHits().getTotalHits()).isEqualTo(2L);
   }
 
   @Test
   public void is_assigned_filter() throws Exception {
-
     String assignee = "steph";
-    IssueDto issue1 = getIssue()
+    IssueDto issue1 = createIssue()
       .setAssignee(assignee);
-    IssueDto issue2 = getIssue();
+    IssueDto issue2 = createIssue();
     db.issueDao().insert(session, issue1, issue2);
     session.commit();
 
     IssueQuery.Builder query = IssueQuery.builder();
-    SearchResponse result = index.search(query.build(), new QueryOptions());
+    SearchResponse result = index.search(query.build(), new QueryContext());
     assertThat(result.getHits().getTotalHits()).isEqualTo(2L);
 
     query = IssueQuery.builder();
     query.assigned(true);
-    result = index.search(query.build(), new QueryOptions());
+    result = index.search(query.build(), new QueryContext());
     assertThat(result.getHits().getTotalHits()).isEqualTo(1L);
   }
 
   @Test
   public void filter_assignee() throws Exception {
-
     String assignee1 = "steph";
     String assignee2 = "simon";
-    IssueDto issue1 = getIssue()
+    IssueDto issue1 = createIssue()
       .setAssignee(assignee1);
-    IssueDto issue2 = getIssue()
+    IssueDto issue2 = createIssue()
       .setAssignee(assignee2);
-    IssueDto issue3 = getIssue();
+    IssueDto issue3 = createIssue();
     db.issueDao().insert(session, issue1, issue2, issue3);
     session.commit();
 
     IssueQuery.Builder query = IssueQuery.builder();
-    SearchResponse result = index.search(query.build(), new QueryOptions());
+    SearchResponse result = index.search(query.build(), new QueryContext());
     assertThat(result.getHits().getTotalHits()).isEqualTo(3L);
 
     query = IssueQuery.builder();
     query.assignees(ImmutableList.of(assignee1));
-    result = index.search(query.build(), new QueryOptions());
+    result = index.search(query.build(), new QueryContext());
     assertThat(result.getHits().getTotalHits()).isEqualTo(1L);
 
     query = IssueQuery.builder();
     query.assignees(ImmutableList.of(assignee1, assignee2));
-    result = index.search(query.build(), new QueryOptions());
+    result = index.search(query.build(), new QueryContext());
     assertThat(result.getHits().getTotalHits()).isEqualTo(2L);
   }
 
-  private IssueDto getIssue() {
+  @Test
+  public void authorized_issues_on_groups() throws Exception {
+    ComponentDto project1 = new ComponentDto()
+      .setId(10L)
+      .setKey("project1");
+    ComponentDto project2 = new ComponentDto()
+      .setId(11L)
+      .setKey("project2");
+    tester.get(ComponentDao.class).insert(session, project1, project2);
+
+    IssueDto issue1 = createIssue().setRootComponent(project1);
+    IssueDto issue2 = createIssue().setRootComponent(project2);
+    db.issueDao().insert(session, issue1, issue2);
+
+    // project1 can be seen by sonar-users
+    GroupDto groupDto = new GroupDto().setName("sonar-users");
+    db.groupDao().insert(session, groupDto);
+    tester.get(PermissionFacade.class).insertGroupPermission(project1.getId(), groupDto.getName(), UserRole.USER, session);
+
+    // project2 can be seen by sonar-admins
+    groupDto = new GroupDto().setName("sonar-admins");
+    db.groupDao().insert(session, groupDto);
+    tester.get(PermissionFacade.class).insertGroupPermission(project2.getId(), groupDto.getName(), UserRole.USER, session);
+
+
+    db.issueAuthorizationDao().synchronizeAfter(session, new Date(0));
+
+    session.commit();
+    session.clearCache();
+
+    IssueQuery.Builder query = IssueQuery.builder();
+
+    MockUserSession.set().setUserGroups("sonar-users");
+    assertThat(index.search(query.build(), new QueryContext()).getHits().getTotalHits()).isEqualTo(1L);
+
+    MockUserSession.set().setUserGroups("sonar-admins");
+    assertThat(index.search(query.build(), new QueryContext()).getHits().getTotalHits()).isEqualTo(1L);
+
+    MockUserSession.set().setUserGroups("sonar-users", "sonar-admins");
+    assertThat(index.search(query.build(), new QueryContext()).getHits().getTotalHits()).isEqualTo(2L);
+
+    MockUserSession.set().setUserGroups("another group");
+    assertThat(index.search(query.build(), new QueryContext()).getHits().getTotalHits()).isEqualTo(0);
+  }
+
+  @Test
+  public void authorized_issues_on_user() throws Exception {
+    ComponentDto project1 = new ComponentDto()
+      .setId(10L)
+      .setKey("project1");
+    ComponentDto project2 = new ComponentDto()
+      .setId(11L)
+      .setKey("project2");
+    tester.get(ComponentDao.class).insert(session, project1, project2);
+
+    IssueDto issue1 = createIssue().setRootComponent(project1);
+    IssueDto issue2 = createIssue().setRootComponent(project2);
+    db.issueDao().insert(session, issue1, issue2);
+
+    // project1 can be seen by john
+    UserDto john = new UserDto().setLogin("john").setName("john").setActive(true);
+    db.userDao().insert(session, john);
+    tester.get(PermissionFacade.class).insertUserPermission(project1.getId(), john.getId(), UserRole.USER, session);
+
+    // project2 can be seen by max
+    UserDto max = new UserDto().setLogin("max").setName("max").setActive(true);
+    db.userDao().insert(session, max);
+    tester.get(PermissionFacade.class).insertUserPermission(project2.getId(), max.getId(), UserRole.USER, session);
+
+    db.issueAuthorizationDao().synchronizeAfter(session, new Date(0));
+
+    session.commit();
+    session.clearCache();
+
+    IssueQuery.Builder query = IssueQuery.builder();
+
+    MockUserSession.set().setLogin("john");
+    assertThat(index.search(query.build(), new QueryContext()).getHits().getTotalHits()).isEqualTo(1L);
+
+    MockUserSession.set().setLogin("max");
+    assertThat(index.search(query.build(), new QueryContext()).getHits().getTotalHits()).isEqualTo(1L);
+
+    MockUserSession.set().setLogin("another guy");
+    assertThat(index.search(query.build(), new QueryContext()).getHits().getTotalHits()).isEqualTo(0L);
+  }
+
+  @Test
+  public void authorized_issues_on_user_with_group() throws Exception {
+    ComponentDto project1 = new ComponentDto()
+      .setId(10L)
+      .setKey("project1");
+    ComponentDto project2 = new ComponentDto()
+      .setId(11L)
+      .setKey("project2");
+    tester.get(ComponentDao.class).insert(session, project1, project2);
+
+    IssueDto issue1 = createIssue().setRootComponent(project1);
+    IssueDto issue2 = createIssue().setRootComponent(project2);
+    db.issueDao().insert(session, issue1, issue2);
+
+    // project1 can be seen by john
+    UserDto john = new UserDto().setLogin("john").setName("john").setActive(true);
+    db.userDao().insert(session, john);
+    tester.get(PermissionFacade.class).insertUserPermission(project1.getId(), john.getId(), UserRole.USER, session);
+
+    // project1 can be seen by sonar-users
+    GroupDto groupDto = new GroupDto().setName("sonar-users");
+    db.groupDao().insert(session, groupDto);
+    tester.get(PermissionFacade.class).insertGroupPermission(project1.getId(), "sonar-users", UserRole.USER, session);
+
+    db.issueAuthorizationDao().synchronizeAfter(session, new Date(0));
+
+    session.commit();
+    session.clearCache();
+
+    IssueQuery.Builder query = IssueQuery.builder();
+
+    MockUserSession.set().setLogin("john").setUserGroups("sonar-users");
+    assertThat(index.search(query.build(), new QueryContext()).getHits().getTotalHits()).isEqualTo(1L);
+  }
+
+  private IssueDto createIssue() {
     return new IssueDto()
       .setIssueCreationDate(DateUtils.parseDate("2014-09-04"))
       .setIssueUpdateDate(DateUtils.parseDate("2014-12-04"))
index 1a301d2920fb819a4bfe95705f02c4ca8fc4ca40..094bb6c66c12abe4f248d78662c991156ab91045 100644 (file)
@@ -23,11 +23,14 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Test;
+import org.sonar.api.security.DefaultGroups;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.DateUtils;
+import org.sonar.api.web.UserRole;
 import org.sonar.core.component.ComponentDto;
 import org.sonar.core.issue.db.IssueDto;
 import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.permission.PermissionFacade;
 import org.sonar.core.persistence.DbSession;
 import org.sonar.core.rule.RuleDto;
 import org.sonar.server.component.persistence.ComponentDao;
@@ -38,6 +41,8 @@ import org.sonar.server.tester.ServerTester;
 import org.sonar.server.user.MockUserSession;
 import org.sonar.server.ws.WsTester;
 
+import java.util.Date;
+
 import static org.fest.assertions.Assertions.assertThat;
 
 public class IssuesWsMediumTest {
@@ -114,6 +119,10 @@ public class IssuesWsMediumTest {
       .setProjectId(1L);
     tester.get(ComponentDao.class).insert(session, project);
 
+    // project can be seen by anyone
+    tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session);
+    db.issueAuthorizationDao().synchronizeAfter(session, new Date(0));
+
     ComponentDto resource = new ComponentDto()
       .setProjectId(1L)
       .setKey("MyComponent")
index 6985b4815dfef118a97fbca20d3918227cc2246e..b39658b17f1244487e04ac40f3aaf0afc18ce4ef 100644 (file)
@@ -39,7 +39,7 @@ import org.sonar.server.db.DbClient;
 import org.sonar.server.qualityprofile.index.ActiveRuleNormalizer;
 import org.sonar.server.rule.RuleTesting;
 import org.sonar.server.search.FacetValue;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.Result;
 import org.sonar.server.tester.ServerTester;
 import org.sonar.server.user.MockUserSession;
@@ -154,7 +154,7 @@ public class QProfileServiceMediumTest {
     );
     dbSession.commit();
 
-    Result<QProfileActivity> activities = service.searchActivities(new QProfileActivityQuery(), new QueryOptions());
+    Result<QProfileActivity> activities = service.searchActivities(new QProfileActivityQuery(), new QueryContext());
     assertThat(activities.getHits()).hasSize(1);
 
     QProfileActivity activity = activities.getHits().get(0);
@@ -183,7 +183,7 @@ public class QProfileServiceMediumTest {
     );
     dbSession.commit();
 
-    Result<QProfileActivity> activities = service.searchActivities(new QProfileActivityQuery(), new QueryOptions());
+    Result<QProfileActivity> activities = service.searchActivities(new QProfileActivityQuery(), new QueryContext());
     assertThat(activities.getHits()).hasSize(1);
 
     QProfileActivity activity = activities.getHits().get(0);
@@ -206,7 +206,7 @@ public class QProfileServiceMediumTest {
     );
     dbSession.commit();
 
-    Result<QProfileActivity> activities = service.searchActivities(new QProfileActivityQuery(), new QueryOptions());
+    Result<QProfileActivity> activities = service.searchActivities(new QProfileActivityQuery(), new QueryContext());
     assertThat(activities.getHits()).hasSize(1);
 
     QProfileActivity activity = activities.getHits().get(0);
@@ -227,7 +227,7 @@ public class QProfileServiceMediumTest {
     );
     dbSession.commit();
 
-    Result<QProfileActivity> activities = service.searchActivities(new QProfileActivityQuery(), new QueryOptions());
+    Result<QProfileActivity> activities = service.searchActivities(new QProfileActivityQuery(), new QueryContext());
     assertThat(activities.getHits()).hasSize(1);
 
     QProfileActivity activity = activities.getHits().get(0);
@@ -245,18 +245,18 @@ public class QProfileServiceMediumTest {
     dbSession.commit();
 
     // 0. Base case verify 2 activities in index
-    assertThat(service.searchActivities(new QProfileActivityQuery(), new QueryOptions()).getHits())
+    assertThat(service.searchActivities(new QProfileActivityQuery(), new QueryContext()).getHits())
       .hasSize(2);
 
     // 1. filter by QProfile
     List<QProfileActivity> result = service.searchActivities(new QProfileActivityQuery()
-      .setQprofileKeys(ImmutableSet.of(XOO_P1_KEY)), new QueryOptions()).getHits();
+      .setQprofileKeys(ImmutableSet.of(XOO_P1_KEY)), new QueryContext()).getHits();
     assertThat(result).hasSize(1);
 
     // 1. filter by QProfiles
     assertThat(service.searchActivities(new QProfileActivityQuery()
       .setQprofileKeys(ImmutableSet.of(XOO_P1_KEY, XOO_P2_KEY))
-      , new QueryOptions()).getHits()).hasSize(2);
+      , new QueryContext()).getHits()).hasSize(2);
   }
 
   @Test
@@ -268,18 +268,18 @@ public class QProfileServiceMediumTest {
     dbSession.commit();
 
     // 0. Base case verify 2 activities in index
-    assertThat(service.searchActivities(new QProfileActivityQuery(), new QueryOptions()).getHits())
+    assertThat(service.searchActivities(new QProfileActivityQuery(), new QueryContext()).getHits())
       .hasSize(2);
 
     // 1. filter by QProfile
     List<QProfileActivity> result = service.searchActivities(new QProfileActivityQuery()
-      .setQprofileKeys(ImmutableSet.of("java-default")), new QueryOptions()).getHits();
+      .setQprofileKeys(ImmutableSet.of("java-default")), new QueryContext()).getHits();
     assertThat(result).hasSize(1);
 
     // 1. filter by QProfiles
     assertThat(service.searchActivities(new QProfileActivityQuery()
       .setQprofileKeys(ImmutableSet.of("java-default", "java-toto"))
-      , new QueryOptions()).getHits()).hasSize(2);
+      , new QueryContext()).getHits()).hasSize(2);
   }
 
   @Test
index cf4cd585bff6bd8670f5a59b3b671b765fb483f2..ae5dc30e6ce2e7b26dace5cc18545e6b7aa70c90 100644 (file)
 package org.sonar.server.qualityprofile;
 
 import com.google.common.collect.ImmutableMap;
-import org.junit.*;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rule.Severity;
@@ -38,7 +41,7 @@ import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
 import org.sonar.server.rule.RuleTesting;
 import org.sonar.server.rule.index.RuleIndex;
 import org.sonar.server.rule.index.RuleQuery;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.tester.ServerTester;
 
 import javax.annotation.Nullable;
@@ -761,7 +764,7 @@ public class RuleActivatorMediumTest {
   @Test
   public void bulk_activation() {
     // Generate more rules than the search's max limit
-    int bulkSize = QueryOptions.MAX_LIMIT + 10;
+    int bulkSize = QueryContext.MAX_LIMIT + 10;
     for (int i = 0; i < bulkSize; i++) {
       db.ruleDao().insert(dbSession, RuleTesting.newDto(RuleKey.of("bulk", "r_" + i)).setLanguage("xoo"));
     }
@@ -770,7 +773,7 @@ public class RuleActivatorMediumTest {
     // 0. No active rules so far (base case) and plenty rules available
     verifyZeroActiveRules(XOO_P1_KEY);
     assertThat(tester.get(RuleIndex.class)
-      .search(new RuleQuery().setRepositories(Arrays.asList("bulk")), new QueryOptions()).getTotal())
+      .search(new RuleQuery().setRepositories(Arrays.asList("bulk")), new QueryContext()).getTotal())
       .isEqualTo(bulkSize);
 
     // 1. bulk activate all the rules
index c99be8102625a35a16b24259013aef34735cfe75..6ec7fba2913863092db647552314c68687750019 100644 (file)
@@ -42,7 +42,7 @@ import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
 import org.sonar.server.rule.index.RuleIndex;
 import org.sonar.server.rule.index.RuleQuery;
 import org.sonar.server.rule.ws.SearchAction;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.ws.SearchOptions;
 import org.sonar.server.tester.ServerTester;
 import org.sonar.server.user.MockUserSession;
@@ -352,7 +352,7 @@ public class QProfilesWsMediumTest {
     // 2. Assert ActiveRule with BLOCKER severity
     assertThat(tester.get(RuleIndex.class).search(
       new RuleQuery().setSeverities(ImmutableSet.of("BLOCKER")),
-      new QueryOptions()).getHits()).hasSize(2);
+      new QueryContext()).getHits()).hasSize(2);
 
     // 1. Activate Rule with query returning 2 hits
     WsTester.TestRequest request = wsTester.newGetRequest(QProfilesWs.API_ENDPOINT, BulkRuleActivationActions.BULK_ACTIVATE_ACTION);
index 790c8c1b6472c1d9d880ec3679033f5015bdb04a..8e91538ac7c37326fb4eff2b46d98ae3594b7e91 100644 (file)
@@ -47,7 +47,7 @@ import org.sonar.server.qualityprofile.RuleActivation;
 import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
 import org.sonar.server.rule.index.RuleIndex;
 import org.sonar.server.rule.index.RuleQuery;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.Result;
 import org.sonar.server.tester.ServerTester;
 import org.sonar.server.user.MockUserSession;
@@ -135,7 +135,7 @@ public class RegisterRulesMediumTest {
     assertThat(ruleParams).hasSize(2);
 
     // verify es
-    Result<Rule> searchResult = ruleIndex.search(new RuleQuery(), new QueryOptions());
+    Result<Rule> searchResult = ruleIndex.search(new RuleQuery(), new QueryContext());
     assertThat(searchResult.getTotal()).isEqualTo(1);
     assertThat(searchResult.getHits()).hasSize(1);
     Rule rule = ruleIndex.getByKey(RuleKey.of("xoo", "x1"));
@@ -182,8 +182,8 @@ public class RegisterRulesMediumTest {
     register(rules);
 
     // verify that rules are indexed
-    Result<Rule> searchResult = ruleIndex.search(new RuleQuery(), new QueryOptions());
-    searchResult = ruleIndex.search(new RuleQuery().setKey("xoo:x1"), new QueryOptions());
+    Result<Rule> searchResult = ruleIndex.search(new RuleQuery(), new QueryContext());
+    searchResult = ruleIndex.search(new RuleQuery().setKey("xoo:x1"), new QueryContext());
     assertThat(searchResult.getTotal()).isEqualTo(1);
     assertThat(searchResult.getHits()).hasSize(1);
     assertThat(searchResult.getHits().get(0).key()).isEqualTo(RuleKey.of("xoo", "x1"));
index c16f5c4d890b1a52cd195546b5d6727bc74e5598..3be473ffae70e236f82f614a487e95be39130c41 100644 (file)
@@ -32,7 +32,7 @@ import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.RuleStatus;
 import org.sonar.server.paging.PagedResult;
 import org.sonar.server.rule.index.RuleQuery;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.Result;
 import org.sonar.server.user.UserSession;
 
@@ -55,7 +55,7 @@ public class RubyRuleServiceTest {
   RuleUpdater updater;
 
   @Captor
-  ArgumentCaptor<QueryOptions> optionsCaptor;
+  ArgumentCaptor<QueryContext> optionsCaptor;
 
   @Captor
   ArgumentCaptor<RuleQuery> ruleQueryCaptor;
@@ -75,7 +75,7 @@ public class RubyRuleServiceTest {
 
   @Test
   public void search_rules() throws Exception {
-    when(ruleService.search(any(RuleQuery.class), any(QueryOptions.class))).thenReturn(mock(Result.class));
+    when(ruleService.search(any(RuleQuery.class), any(QueryContext.class))).thenReturn(mock(Result.class));
 
     HashMap<String, Object> params = newHashMap();
     params.put("searchQuery", "Exception");
@@ -110,7 +110,7 @@ public class RubyRuleServiceTest {
 
   @Test
   public void search_rules_without_page_size_param() throws Exception {
-    when(ruleService.search(any(RuleQuery.class), any(QueryOptions.class))).thenReturn(mock(Result.class));
+    when(ruleService.search(any(RuleQuery.class), any(QueryContext.class))).thenReturn(mock(Result.class));
 
     HashMap<String, Object> params = newHashMap();
     params.put("p", "1");
@@ -128,7 +128,7 @@ public class RubyRuleServiceTest {
     Result serviceResult = mock(Result.class);
     when(serviceResult.scroll()).thenReturn(rules.iterator());
 
-    when(ruleService.search(any(RuleQuery.class), any(QueryOptions.class))).thenReturn(serviceResult);
+    when(ruleService.search(any(RuleQuery.class), any(QueryContext.class))).thenReturn(serviceResult);
 
     HashMap<String, Object> params = newHashMap();
     params.put("pageSize", "-1");
@@ -142,7 +142,7 @@ public class RubyRuleServiceTest {
 
   @Test
   public void update_rule() throws Exception {
-    when(ruleService.search(any(RuleQuery.class), any(QueryOptions.class))).thenReturn(mock(Result.class));
+    when(ruleService.search(any(RuleQuery.class), any(QueryContext.class))).thenReturn(mock(Result.class));
 
     service.updateRule(ImmutableMap.<String, Object>of("ruleKey", "squid:S001"));
 
@@ -151,11 +151,11 @@ public class RubyRuleServiceTest {
 
   @Test
   public void search_manual_rules() throws Exception {
-    when(ruleService.search(any(RuleQuery.class), any(QueryOptions.class))).thenReturn(mock(Result.class));
+    when(ruleService.search(any(RuleQuery.class), any(QueryContext.class))).thenReturn(mock(Result.class));
 
     service.searchManualRules();
 
-    verify(ruleService).search(any(RuleQuery.class), any(QueryOptions.class));
+    verify(ruleService).search(any(RuleQuery.class), any(QueryContext.class));
   }
 
   @Test
index 6c3f5695cdd136af55200b64a66f2bcff9b3151a..54f914775de8f1f67df5644cd0c1c100b5ded1dc 100644 (file)
@@ -37,7 +37,7 @@ import org.sonar.server.rule.db.RuleDao;
 import org.sonar.server.rule.index.RuleDoc;
 import org.sonar.server.rule.index.RuleIndex;
 import org.sonar.server.rule.index.RuleQuery;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.tester.ServerTester;
 
 import java.util.Collection;
@@ -431,7 +431,7 @@ public class RuleBackendMediumTest {
     assertThat(index.getByKey(RuleTesting.XOO_X2)).isNotNull();
 
     // 2. assert find does not get REMOVED
-    List<Rule> rules = index.search(new RuleQuery(), new QueryOptions()).getHits();
+    List<Rule> rules = index.search(new RuleQuery(), new QueryContext()).getHits();
     assertThat(rules).hasSize(1);
     assertThat(rules.get(0).key()).isEqualTo(RuleTesting.XOO_X1);
   }
index 67a74ecb90e9c356b48e8dd2f6cd12b7f2129726..4a0e06311323632461ad9c0f701577bd5afd5e11 100644 (file)
@@ -41,18 +41,12 @@ import org.sonar.server.rule.Rule;
 import org.sonar.server.rule.RuleTesting;
 import org.sonar.server.rule.db.RuleDao;
 import org.sonar.server.search.FacetValue;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.Result;
 
 import javax.annotation.Nullable;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
+
+import java.util.*;
 
 import static com.google.common.collect.Lists.newArrayList;
 import static org.fest.assertions.Assertions.assertThat;
@@ -108,11 +102,11 @@ public class RuleIndexMediumTest extends SearchMediumTest {
 
     // should not have any facet!
     RuleQuery query = new RuleQuery();
-    Result result = index.search(query, new QueryOptions().setFacet(false));
+    Result result = index.search(query, new QueryContext().setFacet(false));
     assertThat(result.getFacets()).isEmpty();
 
     // Repositories Facet is preset
-    result = index.search(query, new QueryOptions().setFacet(true));
+    result = index.search(query, new QueryContext().setFacet(true));
     assertThat(result.getFacets()).isNotNull();
     assertThat(result.getFacets()).hasSize(3);
 
@@ -136,7 +130,7 @@ public class RuleIndexMediumTest extends SearchMediumTest {
     dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("javascript", "S001")));
     dbSession.commit();
 
-    QueryOptions options = new QueryOptions().setFieldsToReturn(null);
+    QueryContext options = new QueryContext().setFieldsToReturn(null);
     Result<Rule> results = index.search(new RuleQuery(), options);
     assertThat(results.getHits()).hasSize(1);
     Rule hit = Iterables.getFirst(results.getHits(), null);
@@ -144,7 +138,7 @@ public class RuleIndexMediumTest extends SearchMediumTest {
     assertThat(hit.htmlDescription()).isNotNull();
     assertThat(hit.name()).isNotNull();
 
-    options = new QueryOptions().setFieldsToReturn(Collections.<String>emptyList());
+    options = new QueryContext().setFieldsToReturn(Collections.<String>emptyList());
     results = index.search(new RuleQuery(), options);
     assertThat(results.getHits()).hasSize(1);
     hit = Iterables.getFirst(results.getHits(), null);
@@ -158,7 +152,7 @@ public class RuleIndexMediumTest extends SearchMediumTest {
     dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("javascript", "S001")));
     dbSession.commit();
 
-    QueryOptions options = new QueryOptions();
+    QueryContext options = new QueryContext();
     options.addFieldsToReturn(RuleNormalizer.RuleField.LANGUAGE.field(), RuleNormalizer.RuleField.STATUS.field());
     Result<Rule> results = index.search(new RuleQuery(), options);
     assertThat(results.getHits()).hasSize(1);
@@ -183,19 +177,19 @@ public class RuleIndexMediumTest extends SearchMediumTest {
 
     // substring
     RuleQuery query = new RuleQuery().setQueryText("test");
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);
 
     // substring
     query = new RuleQuery().setQueryText("partial match");
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);
 
     // case-insensitive
     query = new RuleQuery().setQueryText("TESTING");
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);
 
     // not found
     query = new RuleQuery().setQueryText("not present");
-    assertThat(index.search(query, new QueryOptions()).getHits()).isEmpty();
+    assertThat(index.search(query, new QueryContext()).getHits()).isEmpty();
   }
 
   @Test
@@ -207,16 +201,16 @@ public class RuleIndexMediumTest extends SearchMediumTest {
 
     // key
     RuleQuery query = new RuleQuery().setQueryText("X001");
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(2);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);
 
     // partial key does not match
     query = new RuleQuery().setQueryText("X00");
     // TODO fix non-partial match for Key search
-    assertThat(index.search(query, new QueryOptions()).getHits()).isEmpty();
+    assertThat(index.search(query, new QueryContext()).getHits()).isEmpty();
 
     // repo:key -> nice-to-have !
     query = new RuleQuery().setQueryText("javascript:X001");
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);
   }
 
   @Test
@@ -228,12 +222,12 @@ public class RuleIndexMediumTest extends SearchMediumTest {
 
     // key
     RuleQuery query = new RuleQuery().setKey(RuleKey.of("javascript", "X001").toString());
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);
 
     // partial key does not match
     query = new RuleQuery().setKey("X001");
     // TODO fix non-partial match for Key search
-    assertThat(index.search(query, new QueryOptions()).getHits()).isEmpty();
+    assertThat(index.search(query, new QueryContext()).getHits()).isEmpty();
   }
 
   @Test
@@ -242,7 +236,7 @@ public class RuleIndexMediumTest extends SearchMediumTest {
     dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S002")));
     dbSession.commit();
 
-    Result results = index.search(new RuleQuery(), new QueryOptions());
+    Result results = index.search(new RuleQuery(), new QueryContext());
 
     assertThat(results.getTotal()).isEqualTo(2);
     assertThat(results.getHits()).hasSize(2);
@@ -256,7 +250,7 @@ public class RuleIndexMediumTest extends SearchMediumTest {
     }
     dbSession.commit();
 
-    Result results = index.search(new RuleQuery(), new QueryOptions().setScroll(true));
+    Result results = index.search(new RuleQuery(), new QueryContext().setScroll(true));
 
     assertThat(results.getTotal()).isEqualTo(max);
     assertThat(results.getHits()).hasSize(0);
@@ -300,11 +294,11 @@ public class RuleIndexMediumTest extends SearchMediumTest {
     dbSession.commit();
 
     // 0. assert base case
-    assertThat(index.search(new RuleQuery(), new QueryOptions()).getTotal()).isEqualTo(2);
+    assertThat(index.search(new RuleQuery(), new QueryContext()).getTotal()).isEqualTo(2);
     assertThat(db.debtCharacteristicDao().selectCharacteristics()).hasSize(2);
 
     // 1. assert hasSubChar filter
-    assertThat(index.search(new RuleQuery().setHasDebtCharacteristic(true), new QueryOptions()).getTotal())
+    assertThat(index.search(new RuleQuery().setHasDebtCharacteristic(true), new QueryContext()).getTotal())
       .isEqualTo(2);
   }
 
@@ -315,17 +309,17 @@ public class RuleIndexMediumTest extends SearchMediumTest {
     dbSession.commit();
 
     RuleQuery query = new RuleQuery().setRepositories(Arrays.asList("checkstyle", "pmd"));
-    Result<Rule> results = index.search(query, new QueryOptions());
+    Result<Rule> results = index.search(query, new QueryContext());
     assertThat(results.getHits()).hasSize(1);
     assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S002");
 
     // no results
     query = new RuleQuery().setRepositories(Arrays.asList("checkstyle"));
-    assertThat(index.search(query, new QueryOptions()).getHits()).isEmpty();
+    assertThat(index.search(query, new QueryContext()).getHits()).isEmpty();
 
     // empty list => no filter
     query = new RuleQuery().setRepositories(Collections.<String>emptyList());
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(2);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);
   }
 
   @Test
@@ -336,22 +330,22 @@ public class RuleIndexMediumTest extends SearchMediumTest {
     dbSession.commit();
 
     RuleQuery query = new RuleQuery().setLanguages(Arrays.asList("cobol", "js"));
-    Result<Rule> results = index.search(query, new QueryOptions());
+    Result<Rule> results = index.search(query, new QueryContext());
 
     assertThat(results.getHits()).hasSize(1);
     assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S002");
 
     // no results
     query = new RuleQuery().setLanguages(Arrays.asList("cpp"));
-    assertThat(index.search(query, new QueryOptions()).getHits()).isEmpty();
+    assertThat(index.search(query, new QueryContext()).getHits()).isEmpty();
 
     // empty list => no filter
     query = new RuleQuery().setLanguages(Collections.<String>emptyList());
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(2);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);
 
     // null list => no filter
     query = new RuleQuery().setLanguages(null);
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(2);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);
   }
 
   @Test
@@ -376,36 +370,36 @@ public class RuleIndexMediumTest extends SearchMediumTest {
     Result<Rule> results;
 
     // 0. we have 2 rules in index
-    results = index.search(new RuleQuery(), new QueryOptions());
+    results = index.search(new RuleQuery(), new QueryContext());
     assertThat(results.getHits()).hasSize(2);
 
     // filter by non-subChar
     query = new RuleQuery().setDebtCharacteristics(ImmutableSet.of("toto"));
-    assertThat(index.search(query, new QueryOptions()).getHits()).isEmpty();
+    assertThat(index.search(query, new QueryContext()).getHits()).isEmpty();
 
     // filter by subChar
     query = new RuleQuery().setDebtCharacteristics(ImmutableSet.of(char11.getKey()));
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);
 
     // filter by Char
     query = new RuleQuery().setDebtCharacteristics(ImmutableSet.of(char1.getKey()));
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);
 
     // filter by Char and SubChar
     query = new RuleQuery().setDebtCharacteristics(ImmutableSet.of(char11.getKey(), char1.getKey()));
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);
 
     // match by Char
     query = new RuleQuery().setQueryText(char1.getKey());
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);
 
     // match by SubChar
     query = new RuleQuery().setQueryText(char11.getKey());
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);
 
     // match by SubChar & Char
     query = new RuleQuery().setQueryText(char11.getKey() + " " + char1.getKey());
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);
   }
 
   @Test
@@ -453,26 +447,26 @@ public class RuleIndexMediumTest extends SearchMediumTest {
     Result<Rule> results;
 
     // 0. we have 4 rules in index
-    results = index.search(new RuleQuery(), new QueryOptions());
+    results = index.search(new RuleQuery(), new QueryContext());
     assertThat(results.getHits()).hasSize(4);
 
     // filter by subChar
     query = new RuleQuery().setDebtCharacteristics(ImmutableSet.of(char11.getKey()));
-    assertThat(ruleKeys(index.search(query, new QueryOptions()).getHits())).containsOnly("S001", "S002", "S004");
+    assertThat(ruleKeys(index.search(query, new QueryContext()).getHits())).containsOnly("S001", "S002", "S004");
 
     query = new RuleQuery().setDebtCharacteristics(ImmutableSet.of(char21.getKey()));
-    assertThat(ruleKeys(index.search(query, new QueryOptions()).getHits())).containsOnly("S003");
+    assertThat(ruleKeys(index.search(query, new QueryContext()).getHits())).containsOnly("S003");
 
     // filter by Char
     query = new RuleQuery().setDebtCharacteristics(ImmutableSet.of(char1.getKey()));
-    assertThat(ruleKeys(index.search(query, new QueryOptions()).getHits())).containsOnly("S001", "S002", "S004");
+    assertThat(ruleKeys(index.search(query, new QueryContext()).getHits())).containsOnly("S001", "S002", "S004");
 
     query = new RuleQuery().setDebtCharacteristics(ImmutableSet.of(char2.getKey()));
-    assertThat(ruleKeys(index.search(query, new QueryOptions()).getHits())).containsOnly("S003");
+    assertThat(ruleKeys(index.search(query, new QueryContext()).getHits())).containsOnly("S003");
 
     // filter by Char and SubChar
     query = new RuleQuery().setDebtCharacteristics(ImmutableSet.of(char11.getKey(), char1.getKey(), char2.getKey(), char21.getKey()));
-    assertThat(ruleKeys(index.search(query, new QueryOptions()).getHits())).containsOnly("S001", "S002", "S003", "S004");
+    assertThat(ruleKeys(index.search(query, new QueryContext()).getHits())).containsOnly("S001", "S002", "S003", "S004");
   }
 
   @Test
@@ -482,21 +476,21 @@ public class RuleIndexMediumTest extends SearchMediumTest {
     dbSession.commit();
 
     RuleQuery query = new RuleQuery().setSeverities(Arrays.asList(Severity.INFO, Severity.MINOR));
-    Result<Rule> results = index.search(query, new QueryOptions());
+    Result<Rule> results = index.search(query, new QueryContext());
     assertThat(results.getHits()).hasSize(1);
     assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S002");
 
     // no results
     query = new RuleQuery().setSeverities(Arrays.asList(Severity.MINOR));
-    assertThat(index.search(query, new QueryOptions()).getHits()).isEmpty();
+    assertThat(index.search(query, new QueryContext()).getHits()).isEmpty();
 
     // empty list => no filter
     query = new RuleQuery().setSeverities(Collections.<String>emptyList());
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(2);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);
 
     // null list => no filter
     query = new RuleQuery().setSeverities(null);
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(2);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);
   }
 
   @Test
@@ -506,21 +500,21 @@ public class RuleIndexMediumTest extends SearchMediumTest {
     dbSession.commit();
 
     RuleQuery query = new RuleQuery().setStatuses(Arrays.asList(RuleStatus.DEPRECATED, RuleStatus.READY));
-    Result<Rule> results = index.search(query, new QueryOptions());
+    Result<Rule> results = index.search(query, new QueryContext());
     assertThat(results.getHits()).hasSize(1);
     assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S002");
 
     // no results
     query = new RuleQuery().setStatuses(Arrays.asList(RuleStatus.DEPRECATED));
-    assertThat(index.search(query, new QueryOptions()).getHits()).isEmpty();
+    assertThat(index.search(query, new QueryContext()).getHits()).isEmpty();
 
     // empty list => no filter
     query = new RuleQuery().setStatuses(Collections.<RuleStatus>emptyList());
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(2);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);
 
     // null list => no filter
     query = new RuleQuery().setStatuses(null);
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(2);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);
   }
 
   @Test
@@ -532,14 +526,14 @@ public class RuleIndexMediumTest extends SearchMediumTest {
 
     // ascending
     RuleQuery query = new RuleQuery().setSortField(RuleNormalizer.RuleField.NAME);
-    Result<Rule> results = index.search(query, new QueryOptions());
+    Result<Rule> results = index.search(query, new QueryContext());
     assertThat(results.getHits()).hasSize(3);
     assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S002");
     assertThat(Iterables.getLast(results.getHits(), null).key().rule()).isEqualTo("S003");
 
     // descending
     query = new RuleQuery().setSortField(RuleNormalizer.RuleField.NAME).setAscendingSort(false);
-    results = index.search(query, new QueryOptions());
+    results = index.search(query, new QueryContext());
     assertThat(results.getHits()).hasSize(3);
     assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S003");
     assertThat(Iterables.getLast(results.getHits(), null).key().rule()).isEqualTo("S002");
@@ -577,25 +571,25 @@ public class RuleIndexMediumTest extends SearchMediumTest {
 
     // 1. get all active rules.
     Result<Rule> result = index.search(new RuleQuery().setActivation(true),
-      new QueryOptions());
+      new QueryContext());
     assertThat(result.getHits()).hasSize(2);
 
     // 2. get all inactive rules.
     result = index.search(new RuleQuery().setActivation(false),
-      new QueryOptions());
+      new QueryContext());
     assertThat(result.getHits()).hasSize(1);
     assertThat(result.getHits().get(0).name()).isEqualTo(rule3.getName());
 
     // 3. get all rules not active on profile
     index.search(new RuleQuery().setActivation(false).setQProfileKey(qualityProfileDto2.getKey()),
-      new QueryOptions());
+      new QueryContext());
     // TODO
     assertThat(result.getHits()).hasSize(1);
 
     // 4. get all active rules on profile
     result = index.search(new RuleQuery().setActivation(true)
         .setQProfileKey(qualityProfileDto2.getKey()),
-      new QueryOptions());
+      new QueryContext());
     assertThat(result.getHits()).hasSize(1);
     assertThat(result.getHits().get(0).name()).isEqualTo(rule1.getName());
 
@@ -637,17 +631,17 @@ public class RuleIndexMediumTest extends SearchMediumTest {
 
     // 0. get all rules
     Result<Rule> result = index.search(new RuleQuery(),
-      new QueryOptions());
+      new QueryContext());
     assertThat(result.getHits()).hasSize(4);
 
     // 1. get all active rules
     result = index.search(new RuleQuery().setActivation(true),
-      new QueryOptions());
+      new QueryContext());
     assertThat(result.getHits()).hasSize(3);
 
     // 2. get all inactive rules.
     result = index.search(new RuleQuery().setActivation(false),
-      new QueryOptions());
+      new QueryContext());
     assertThat(result.getHits()).hasSize(1);
     assertThat(result.getHits().get(0).name()).isEqualTo(rule4.getName());
 
@@ -655,7 +649,7 @@ public class RuleIndexMediumTest extends SearchMediumTest {
     result = index.search(new RuleQuery().setActivation(true)
         .setQProfileKey(qualityProfileDto1.getKey())
         .setInheritance(ImmutableSet.of(ActiveRule.Inheritance.INHERITED.name())),
-      new QueryOptions()
+      new QueryContext()
     );
     assertThat(result.getHits()).hasSize(0);
 
@@ -663,7 +657,7 @@ public class RuleIndexMediumTest extends SearchMediumTest {
     result = index.search(new RuleQuery().setActivation(true)
         .setQProfileKey(qualityProfileDto2.getKey())
         .setInheritance(ImmutableSet.of(ActiveRule.Inheritance.INHERITED.name())),
-      new QueryOptions()
+      new QueryContext()
     );
     assertThat(result.getHits()).hasSize(2);
 
@@ -671,7 +665,7 @@ public class RuleIndexMediumTest extends SearchMediumTest {
     result = index.search(new RuleQuery().setActivation(true)
         .setQProfileKey(qualityProfileDto1.getKey())
         .setInheritance(ImmutableSet.of(ActiveRule.Inheritance.OVERRIDES.name())),
-      new QueryOptions()
+      new QueryContext()
     );
     assertThat(result.getHits()).hasSize(0);
 
@@ -679,7 +673,7 @@ public class RuleIndexMediumTest extends SearchMediumTest {
     result = index.search(new RuleQuery().setActivation(true)
         .setQProfileKey(qualityProfileDto2.getKey())
         .setInheritance(ImmutableSet.of(ActiveRule.Inheritance.OVERRIDES.name())),
-      new QueryOptions()
+      new QueryContext()
     );
     assertThat(result.getHits()).hasSize(1);
 
@@ -688,7 +682,7 @@ public class RuleIndexMediumTest extends SearchMediumTest {
         .setQProfileKey(qualityProfileDto1.getKey())
         .setInheritance(ImmutableSet.of(
           ActiveRule.Inheritance.INHERITED.name(), ActiveRule.Inheritance.OVERRIDES.name())),
-      new QueryOptions()
+      new QueryContext()
     );
     assertThat(result.getHits()).hasSize(0);
 
@@ -697,7 +691,7 @@ public class RuleIndexMediumTest extends SearchMediumTest {
         .setQProfileKey(qualityProfileDto2.getKey())
         .setInheritance(ImmutableSet.of(
           ActiveRule.Inheritance.INHERITED.name(), ActiveRule.Inheritance.OVERRIDES.name())),
-      new QueryOptions()
+      new QueryContext()
     );
     assertThat(result.getHits()).hasSize(3);
   }
@@ -732,38 +726,38 @@ public class RuleIndexMediumTest extends SearchMediumTest {
 
     // find all
     RuleQuery query = new RuleQuery();
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(2);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);
 
     // tag1 in query
     query = new RuleQuery().setQueryText("tag1");
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1);
-    assertThat(Iterables.getFirst(index.search(query, new QueryOptions()).getHits(), null).tags()).containsExactly("tag1");
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);
+    assertThat(Iterables.getFirst(index.search(query, new QueryContext()).getHits(), null).tags()).containsExactly("tag1");
 
     // tag1 and tag2 in query
     query = new RuleQuery().setQueryText("tag1 tag2");
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(2);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);
 
     // tag2 in filter
     query = new RuleQuery().setTags(ImmutableSet.of("tag2"));
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1);
-    assertThat(Iterables.getFirst(index.search(query, new QueryOptions()).getHits(), null).tags()).containsExactly("tag2");
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);
+    assertThat(Iterables.getFirst(index.search(query, new QueryContext()).getHits(), null).tags()).containsExactly("tag2");
 
     // tag2 in filter and tag1 tag2 in query
     query = new RuleQuery().setTags(ImmutableSet.of("tag2")).setQueryText("tag1");
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(0);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(0);
 
     // tag2 in filter and tag1 in query
     query = new RuleQuery().setTags(ImmutableSet.of("tag2")).setQueryText("tag1 tag2");
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1);
-    assertThat(Iterables.getFirst(index.search(query, new QueryOptions()).getHits(), null).tags()).containsExactly("tag2");
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);
+    assertThat(Iterables.getFirst(index.search(query, new QueryContext()).getHits(), null).tags()).containsExactly("tag2");
 
     // null list => no filter
     query = new RuleQuery().setTags(Collections.<String>emptySet());
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(2);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);
 
     // null list => no filter
     query = new RuleQuery().setTags(null);
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(2);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);
   }
 
   @Test
@@ -774,26 +768,26 @@ public class RuleIndexMediumTest extends SearchMediumTest {
 
     // find all
     RuleQuery query = new RuleQuery();
-    Result<Rule> results = index.search(query, new QueryOptions());
+    Result<Rule> results = index.search(query, new QueryContext());
     assertThat(results.getHits()).hasSize(2);
 
     // Only template
     query = new RuleQuery().setIsTemplate(true);
-    results = index.search(query, new QueryOptions());
+    results = index.search(query, new QueryContext());
     assertThat(results.getHits()).hasSize(1);
     assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S002");
     assertThat(Iterables.getFirst(results.getHits(), null).isTemplate()).isTrue();
 
     // Only not template
     query = new RuleQuery().setIsTemplate(false);
-    results = index.search(query, new QueryOptions());
+    results = index.search(query, new QueryContext());
     assertThat(results.getHits()).hasSize(1);
     assertThat(Iterables.getFirst(results.getHits(), null).isTemplate()).isFalse();
     assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S001");
 
     // null => no filter
     query = new RuleQuery().setIsTemplate(null);
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(2);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);
   }
 
   @Test
@@ -805,19 +799,19 @@ public class RuleIndexMediumTest extends SearchMediumTest {
 
     // find all
     RuleQuery query = new RuleQuery();
-    Result<Rule> results = index.search(query, new QueryOptions());
+    Result<Rule> results = index.search(query, new QueryContext());
     assertThat(results.getHits()).hasSize(2);
 
     // Only custom rule
     query = new RuleQuery().setTemplateKey("java:S001");
-    results = index.search(query, new QueryOptions());
+    results = index.search(query, new QueryContext());
     assertThat(results.getHits()).hasSize(1);
     assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S001_MY_CUSTOM");
     assertThat(Iterables.getFirst(results.getHits(), null).templateKey()).isEqualTo(RuleKey.of("java", "S001"));
 
     // null => no filter
     query = new RuleQuery().setTemplateKey(null);
-    assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(2);
+    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);
   }
 
   @Test
@@ -835,7 +829,7 @@ public class RuleIndexMediumTest extends SearchMediumTest {
 
     // find all
     RuleQuery query = new RuleQuery();
-    Result<Rule> results = index.search(query, new QueryOptions());
+    Result<Rule> results = index.search(query, new QueryContext());
     assertThat(results.getHits()).hasSize(2);
 
     // get params
@@ -852,7 +846,7 @@ public class RuleIndexMediumTest extends SearchMediumTest {
 
     // find all
     RuleQuery query = new RuleQuery();
-    Result<Rule> results = index.search(query, new QueryOptions());
+    Result<Rule> results = index.search(query, new QueryContext());
     assertThat(results.getHits()).hasSize(2);
 
     // find custom rule
@@ -867,7 +861,7 @@ public class RuleIndexMediumTest extends SearchMediumTest {
     dbSession.commit();
 
     // from 0 to 1 included
-    QueryOptions options = new QueryOptions();
+    QueryContext options = new QueryContext();
     options.setOffset(0).setLimit(2);
     Result results = index.search(new RuleQuery(), options);
     assertThat(results.getTotal()).isEqualTo(3);
@@ -896,19 +890,19 @@ public class RuleIndexMediumTest extends SearchMediumTest {
     dbSession.commit();
 
     // 0. find all rules;
-    assertThat(index.search(new RuleQuery(), new QueryOptions()).getHits()).hasSize(2);
+    assertThat(index.search(new RuleQuery(), new QueryContext()).getHits()).hasSize(2);
 
     // 1. find all rules available since a date;
     RuleQuery availableSinceQuery = new RuleQuery()
       .setAvailableSince(since);
-    List<Rule> hits = index.search(availableSinceQuery, new QueryOptions()).getHits();
+    List<Rule> hits = index.search(availableSinceQuery, new QueryContext()).getHits();
     assertThat(hits).hasSize(1);
     assertThat(hits.get(0).key()).isEqualTo(RuleKey.of("java", "S002"));
 
     // 2. find no new rules since tomorrow.
     RuleQuery availableSinceNowQuery = new RuleQuery()
       .setAvailableSince(DateUtils.addDays(since, 1));
-    assertThat(index.search(availableSinceNowQuery, new QueryOptions()).getHits()).hasSize(0);
+    assertThat(index.search(availableSinceNowQuery, new QueryContext()).getHits()).hasSize(0);
   }
 
   @Test
@@ -936,7 +930,7 @@ public class RuleIndexMediumTest extends SearchMediumTest {
     assertThat(rule.name()).isEqualTo(nameWithProtectedChars);
 
     RuleQuery protectedCharsQuery = new RuleQuery().setQueryText(nameWithProtectedChars);
-    List<Rule> results = index.search(protectedCharsQuery, new QueryOptions()).getHits();
+    List<Rule> results = index.search(protectedCharsQuery, new QueryContext()).getHits();
     assertThat(results).hasSize(1);
     assertThat(results.get(0).key()).isEqualTo(RuleTesting.XOO_X1);
   }
index d809c8582cab04944d36eb42f9ff3b511699c6a5..1bc90e35cd2d8cec94c54e3d0a93e15bd004542c 100644 (file)
@@ -24,7 +24,7 @@ import org.sonar.api.resources.Languages;
 import org.sonar.api.server.debt.DebtModel;
 import org.sonar.api.server.ws.internal.SimpleGetRequest;
 import org.sonar.server.rule.index.RuleNormalizer;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.ws.SearchOptions;
 import org.sonar.server.text.MacroInterpreter;
 
@@ -43,9 +43,9 @@ public class RuleMappingTest {
     SimpleGetRequest request = new SimpleGetRequest();
     request.setParam("p", "1");
     request.setParam("ps", "10");
-    QueryOptions queryOptions = mapping.newQueryOptions(SearchOptions.create(request));
+    QueryContext queryContext = mapping.newQueryOptions(SearchOptions.create(request));
 
-    assertThat(queryOptions.getFieldsToReturn()).isEmpty();
+    assertThat(queryContext.getFieldsToReturn()).isEmpty();
   }
 
   @Test
@@ -55,9 +55,9 @@ public class RuleMappingTest {
     request.setParam("p", "1");
     request.setParam("ps", "10");
     request.setParam("f", "repo,name,lang");
-    QueryOptions queryOptions = mapping.newQueryOptions(SearchOptions.create(request));
+    QueryContext queryContext = mapping.newQueryOptions(SearchOptions.create(request));
 
-    assertThat(queryOptions.getFieldsToReturn()).containsOnly(
+    assertThat(queryContext.getFieldsToReturn()).containsOnly(
       RuleNormalizer.RuleField.REPOSITORY.field(),
       RuleNormalizer.RuleField.NAME.field(),
       RuleNormalizer.RuleField.LANGUAGE.field());
@@ -70,9 +70,9 @@ public class RuleMappingTest {
     request.setParam("p", "1");
     request.setParam("ps", "10");
     request.setParam("f", "langName");
-    QueryOptions queryOptions = mapping.newQueryOptions(SearchOptions.create(request));
+    QueryContext queryContext = mapping.newQueryOptions(SearchOptions.create(request));
 
-    assertThat(queryOptions.getFieldsToReturn()).containsOnly(RuleNormalizer.RuleField.LANGUAGE.field());
+    assertThat(queryContext.getFieldsToReturn()).containsOnly(RuleNormalizer.RuleField.LANGUAGE.field());
   }
 
   @Test
@@ -82,9 +82,9 @@ public class RuleMappingTest {
     request.setParam("p", "1");
     request.setParam("ps", "10");
     request.setParam("f", "debtRemFn");
-    QueryOptions queryOptions = mapping.newQueryOptions(SearchOptions.create(request));
+    QueryContext queryContext = mapping.newQueryOptions(SearchOptions.create(request));
 
-    assertThat(queryOptions.getFieldsToReturn()).containsOnly(
+    assertThat(queryContext.getFieldsToReturn()).containsOnly(
       RuleNormalizer.RuleField.DEBT_FUNCTION_COEFFICIENT.field(),
       RuleNormalizer.RuleField.DEBT_FUNCTION_OFFSET.field(),
       RuleNormalizer.RuleField.DEBT_FUNCTION_TYPE.field(),
@@ -100,9 +100,9 @@ public class RuleMappingTest {
     request.setParam("p", "1");
     request.setParam("ps", "10");
     request.setParam("f", "htmlNote");
-    QueryOptions queryOptions = mapping.newQueryOptions(SearchOptions.create(request));
+    QueryContext queryContext = mapping.newQueryOptions(SearchOptions.create(request));
 
-    assertThat(queryOptions.getFieldsToReturn()).containsOnly(RuleNormalizer.RuleField.NOTE.field());
+    assertThat(queryContext.getFieldsToReturn()).containsOnly(RuleNormalizer.RuleField.NOTE.field());
   }
 
   @Test
@@ -112,9 +112,9 @@ public class RuleMappingTest {
     request.setParam("p", "1");
     request.setParam("ps", "10");
     request.setParam("f", "debtChar");
-    QueryOptions queryOptions = mapping.newQueryOptions(SearchOptions.create(request));
+    QueryContext queryContext = mapping.newQueryOptions(SearchOptions.create(request));
 
-    assertThat(queryOptions.getFieldsToReturn()).containsOnly(
+    assertThat(queryContext.getFieldsToReturn()).containsOnly(
       RuleNormalizer.RuleField.CHARACTERISTIC.field(),
       RuleNormalizer.RuleField.DEFAULT_CHARACTERISTIC.field());
   }
diff --git a/server/sonar-server/src/test/java/org/sonar/server/search/QueryContextTest.java b/server/sonar-server/src/test/java/org/sonar/server/search/QueryContextTest.java
new file mode 100644 (file)
index 0000000..8999c35
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.search;
+
+import com.google.common.collect.ImmutableList;
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.server.user.MockUserSession;
+
+import java.util.Arrays;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class QueryContextTest {
+
+  QueryContext options;
+
+  @Before
+  public void setUp() throws Exception {
+    MockUserSession.set().setLogin("john").setUserGroups("sonar-users");
+    options = new QueryContext();
+  }
+
+  @Test
+  public void user_and_groups() throws Exception {
+    assertThat(options.getUserLogin()).isEqualTo("john");
+    assertThat(options.getUserGroups()).containsOnly("sonar-users", "Anyone");
+  }
+
+  @Test
+  public void page_shortcut_for_limit_and_offset() throws Exception {
+    options.setPage(3, 10);
+
+    assertThat(options.getLimit()).isEqualTo(10);
+    assertThat(options.getOffset()).isEqualTo(20);
+  }
+
+  @Test
+  public void page_starts_at_one() throws Exception {
+    options.setPage(1, 10);
+    assertThat(options.getLimit()).isEqualTo(10);
+    assertThat(options.getOffset()).isEqualTo(0);
+  }
+
+  @Test
+  public void page_must_be_strictly_positive() throws Exception {
+    try {
+      options.setPage(0, 10);
+      fail();
+    } catch (IllegalArgumentException e) {
+      assertThat(e).hasMessage("Page must be greater or equal to 1 (got 0)");
+    }
+  }
+
+  @Test
+  public void page_size_must_be_positive() throws Exception {
+    try {
+      options.setPage(2, -1);
+      fail();
+    } catch (IllegalArgumentException e) {
+      assertThat(e).hasMessage("Page size must be greater or equal to 0 (got -1)");
+    }
+  }
+
+  @Test
+  public void max_limit() throws Exception {
+    options.setLimit(42);
+    assertThat(options.getLimit()).isEqualTo(42);
+
+    options.setLimit(QueryContext.MAX_LIMIT + 10);
+    assertThat(options.getLimit()).isEqualTo(QueryContext.MAX_LIMIT);
+  }
+
+  @Test
+  public void set_max_limit() throws Exception {
+    options.setMaxLimit();
+    assertThat(options.getLimit()).isEqualTo(QueryContext.MAX_LIMIT);
+  }
+
+  @Test
+  public void max_page_size() throws Exception {
+    options.setPage(3, QueryContext.MAX_LIMIT + 10);
+    assertThat(options.getOffset()).isEqualTo(QueryContext.MAX_LIMIT * 2);
+    assertThat(options.getLimit()).isEqualTo(QueryContext.MAX_LIMIT);
+  }
+
+
+  @Test
+  public void getFieldsToReturn() throws Exception {
+    assertThat(options.getFieldsToReturn()).isEmpty();
+
+    options.setFieldsToReturn(Arrays.asList("one", "two"));
+    assertThat(options.getFieldsToReturn()).containsOnly("one", "two");
+
+    options.addFieldsToReturn(Arrays.asList("three"));
+    assertThat(options.getFieldsToReturn()).containsOnly("one", "two", "three");
+
+    options.addFieldsToReturn("four");
+    assertThat(options.getFieldsToReturn()).containsOnly("one", "two", "three", "four");
+  }
+
+  @Test
+  public void support_immutable_fields() throws Exception {
+    options.setFieldsToReturn(ImmutableList.of("one", "two"));
+    assertThat(options.getFieldsToReturn()).containsOnly("one", "two");
+
+    options.addFieldsToReturn(ImmutableList.of("three"));
+    assertThat(options.getFieldsToReturn()).containsOnly("one", "two", "three");
+
+    options.addFieldsToReturn("four");
+    assertThat(options.getFieldsToReturn()).containsOnly("one", "two", "three", "four");
+  }
+
+  @Test
+  public void do_not_request_facets_by_default() throws Exception {
+    assertThat(options.isFacet()).isFalse();
+
+    options.setFacet(true);
+    assertThat(options.isFacet()).isTrue();
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/search/QueryOptionsTest.java b/server/sonar-server/src/test/java/org/sonar/server/search/QueryOptionsTest.java
deleted file mode 100644 (file)
index 35b201f..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.search;
-
-import com.google.common.collect.ImmutableList;
-import org.junit.Test;
-
-import java.util.Arrays;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.fest.assertions.Fail.fail;
-
-public class QueryOptionsTest {
-
-  QueryOptions options = new QueryOptions();
-
-  @Test
-  public void page_shortcut_for_limit_and_offset() throws Exception {
-    options.setPage(3, 10);
-
-    assertThat(options.getLimit()).isEqualTo(10);
-    assertThat(options.getOffset()).isEqualTo(20);
-  }
-
-  @Test
-  public void page_starts_at_one() throws Exception {
-    options.setPage(1, 10);
-    assertThat(options.getLimit()).isEqualTo(10);
-    assertThat(options.getOffset()).isEqualTo(0);
-  }
-
-  @Test
-  public void page_must_be_strictly_positive() throws Exception {
-    try {
-      options.setPage(0, 10);
-      fail();
-    } catch (IllegalArgumentException e) {
-      assertThat(e).hasMessage("Page must be greater or equal to 1 (got 0)");
-    }
-  }
-
-  @Test
-  public void page_size_must_be_positive() throws Exception {
-    try {
-      options.setPage(2, -1);
-      fail();
-    } catch (IllegalArgumentException e) {
-      assertThat(e).hasMessage("Page size must be greater or equal to 0 (got -1)");
-    }
-  }
-
-  @Test
-  public void max_limit() throws Exception {
-    options.setLimit(42);
-    assertThat(options.getLimit()).isEqualTo(42);
-
-    options.setLimit(QueryOptions.MAX_LIMIT + 10);
-    assertThat(options.getLimit()).isEqualTo(QueryOptions.MAX_LIMIT);
-  }
-
-  @Test
-  public void set_max_limit() throws Exception {
-    options.setMaxLimit();
-    assertThat(options.getLimit()).isEqualTo(QueryOptions.MAX_LIMIT);
-  }
-
-  @Test
-  public void max_page_size() throws Exception {
-    options.setPage(3, QueryOptions.MAX_LIMIT + 10);
-    assertThat(options.getOffset()).isEqualTo(QueryOptions.MAX_LIMIT * 2);
-    assertThat(options.getLimit()).isEqualTo(QueryOptions.MAX_LIMIT);
-  }
-
-
-  @Test
-  public void getFieldsToReturn() throws Exception {
-    assertThat(options.getFieldsToReturn()).isEmpty();
-
-    options.setFieldsToReturn(Arrays.asList("one", "two"));
-    assertThat(options.getFieldsToReturn()).containsOnly("one", "two");
-
-    options.addFieldsToReturn(Arrays.asList("three"));
-    assertThat(options.getFieldsToReturn()).containsOnly("one", "two", "three");
-
-    options.addFieldsToReturn("four");
-    assertThat(options.getFieldsToReturn()).containsOnly("one", "two", "three", "four");
-  }
-
-  @Test
-  public void support_immutable_fields() throws Exception {
-    options.setFieldsToReturn(ImmutableList.of("one", "two"));
-    assertThat(options.getFieldsToReturn()).containsOnly("one", "two");
-
-    options.addFieldsToReturn(ImmutableList.of("three"));
-    assertThat(options.getFieldsToReturn()).containsOnly("one", "two", "three");
-
-    options.addFieldsToReturn("four");
-    assertThat(options.getFieldsToReturn()).containsOnly("one", "two", "three", "four");
-  }
-
-  @Test
-  public void do_not_request_facets_by_default() throws Exception {
-    assertThat(options.isFacet()).isFalse();
-
-    options.setFacet(true);
-    assertThat(options.isFacet()).isTrue();
-  }
-}
index f2cbdf3a3f882d4d682c2e27904ab752ffcd6288..0d802c8aa6d2a40a4ea94a29ae0e0f84f16bb3af 100644 (file)
@@ -26,7 +26,7 @@ import org.sonar.api.server.ws.RequestHandler;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.internal.SimpleGetRequest;
 import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.Result;
 
 import java.io.StringWriter;
@@ -143,7 +143,7 @@ public class SearchOptionsTest {
     assertThat(page.defaultValue()).isEqualTo("1");
     WebService.Param pageSize = searchAction.param("ps");
     assertThat(pageSize).isNotNull();
-    assertThat(pageSize.defaultValue()).isEqualTo("" + QueryOptions.DEFAULT_LIMIT);
+    assertThat(pageSize.defaultValue()).isEqualTo("" + QueryContext.DEFAULT_LIMIT);
 
   }
 }
index 8ca959dac2e239efbe529e6e86cfe15c58db169b..834611d6c930b3b9078cba83023b26b1dbc2b34e 100644 (file)
@@ -75,6 +75,11 @@ public class MockUserSession extends UserSession {
     return this;
   }
 
+  public MockUserSession setUserGroups(@Nullable String... userGroups) {
+    super.setUserGroups(userGroups);
+    return this;
+  }
+
   public MockUserSession setGlobalPermissions(String... globalPermissions) {
     this.globalPermissions = Arrays.asList(globalPermissions);
     return this;
index b125f052a047e6218a3d9465a968c942579de66d..2646b845eacb4d391bc30b33a77c2f32e1dc7130 100644 (file)
@@ -26,10 +26,11 @@ import static org.fest.assertions.Assertions.assertThat;
 public class MockUserSessionTest {
   @Test
   public void set_mock_session() {
-    MockUserSession.set().setLogin("simon");
+    MockUserSession.set().setLogin("simon").setUserGroups("sonar-users");
 
     UserSession mock = UserSession.get();
     assertThat(mock.login()).isEqualTo("simon");
+    assertThat(mock.userGroups()).containsOnly("sonar-users", "Anyone");
     assertThat(mock.globalPermissions()).isEmpty();
     assertThat(mock.isLoggedIn()).isTrue();
   }
index 725d33cb660f7e314e27ecd2f8c95b050a00b754..24737aecc3afca9784c79ca91f93730199feb785 100644 (file)
@@ -23,12 +23,13 @@ import org.junit.Test;
 
 import java.util.Locale;
 
+import static com.google.common.collect.Lists.newArrayList;
 import static org.fest.assertions.Assertions.assertThat;
 
 public class RubyUserSessionTest {
   @Test
   public void should_set_session() throws Exception {
-    RubyUserSession.setSession(123, "karadoc", "Karadoc", "fr");
+    RubyUserSession.setSession(123, "karadoc", "Karadoc", newArrayList("sonar-users"), "fr");
 
     UserSession session = UserSession.get();
 
@@ -36,13 +37,14 @@ public class RubyUserSessionTest {
     assertThat(session.login()).isEqualTo("karadoc");
     assertThat(session.name()).isEqualTo("Karadoc");
     assertThat(session.userId()).isEqualTo(123);
+    assertThat(session.userGroups()).containsOnly("sonar-users", "Anyone");
     assertThat(session.isLoggedIn()).isTrue();
     assertThat(session.locale()).isEqualTo(Locale.FRENCH);
   }
 
   @Test
   public void should_set_anonymous_session() throws Exception {
-    RubyUserSession.setSession(null, null, null, "fr");
+    RubyUserSession.setSession(null, null, null, null, "fr");
 
     UserSession session = UserSession.get();
 
@@ -50,9 +52,9 @@ public class RubyUserSessionTest {
     assertThat(session.login()).isNull();
     assertThat(session.name()).isNull();
     assertThat(session.userId()).isNull();
+    assertThat(session.userGroups()).containsOnly("Anyone");
     assertThat(session.isLoggedIn()).isFalse();
     assertThat(session.locale()).isEqualTo(Locale.FRENCH);
   }
 
-
 }
index 5a181da970f91eb5a396d1e9691921683f40df10..1a82038abb1d8cda2d45da981980d34e2392d044 100644 (file)
@@ -64,6 +64,14 @@ public class GroupDaoTest extends AbstractDaoTestCase {
     assertThat(group.getUpdatedAt()).isEqualTo(DateUtils.parseDate("2014-09-08"));
   }
 
+  @Test
+  public void find_by_user_login() throws Exception {
+    setupData("find_by_user_login");
+
+    assertThat(dao.findByUserLogin(session, "john")).hasSize(2);
+    assertThat(dao.findByUserLogin(session, "max")).isEmpty();
+  }
+
   @Test
   public void insert() throws Exception {
     when(system2.now()).thenReturn(DateUtils.parseDate("2014-09-08").getTime());
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/user/db/GroupDaoTest/find_by_user_login.xml b/server/sonar-server/src/test/resources/org/sonar/server/user/db/GroupDaoTest/find_by_user_login.xml
new file mode 100644 (file)
index 0000000..ea360dd
--- /dev/null
@@ -0,0 +1,32 @@
+<!--
+  ~ SonarQube, open source software quality management tool.
+  ~ Copyright (C) 2008-2014 SonarSource
+  ~ mailto:contact AT sonarsource DOT com
+  ~
+  ~ SonarQube 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.
+  ~
+  ~ SonarQube 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.
+  -->
+
+<dataset>
+
+  <groups id="1" name="sonar-users" description="Sonar Users" created_at="2014-09-07" updated_at="2014-09-08"/>
+  <groups id="2" name="sonar-admins" description="Sonar Admins" created_at="2014-09-07" updated_at="2014-09-08"/>
+  <groups id="3" name="sonar-reviewers" description="Sonar Reviewers" created_at="2014-09-07" updated_at="2014-09-08"/>
+
+  <groups_users user_id="100" group_id="1"/>
+  <groups_users user_id="100" group_id="2"/>
+
+  <users id="100" login="john" name="John" email="jo@hn.com" created_at="2014-06-20" updated_at="2014-06-20" active="[true]"/>
+
+</dataset>
index b01a0792d255036d3981551029b07e86d94b4abe..693dfc18a7be6e9c64121122059cbe79672732f3 100644 (file)
@@ -100,9 +100,10 @@ class ApplicationController < ActionController::Base
     end
 
     if current_user && current_user.id
-      Java::OrgSonarServerUser::RubyUserSession.setSession(current_user.id.to_i, current_user.login, current_user.name, I18n.locale.to_s)
+      user_groups_name = current_user.groups.collect {|g| g.name}.to_a
+      Java::OrgSonarServerUser::RubyUserSession.setSession(current_user.id.to_i, current_user.login, current_user.name, user_groups_name, I18n.locale.to_s)
     else
-      Java::OrgSonarServerUser::RubyUserSession.setSession(nil, nil, nil, I18n.locale.to_s)
+      Java::OrgSonarServerUser::RubyUserSession.setSession(nil, nil, nil, nil, I18n.locale.to_s)
     end
   end
 
index ca81eccafae3b7cd93c5149b8f2dae59c839bf17..689f9da6892a8b4379359c518bf4a419150033ae 100644 (file)
@@ -28,6 +28,6 @@ public interface IssueAuthorizationMapper {
 
   IssueAuthorizationDto selectByKey(String key);
 
-  IssueAuthorizationDto selectAfterDate(@Param("date") Date date, @Param("permission") String permission);
+  IssueAuthorizationDto selectAfterDate(@Param("date") Date date, @Param("permission") String permission, @Param("anyone") String anyoneGroup);
 
 }
index 0edd9c3f331db91a6cccda3982b85557c5364edd..95d0eef39c88aea31cdd11089971f88f5e38eec8 100644 (file)
@@ -22,11 +22,15 @@ package org.sonar.core.user;
 
 import javax.annotation.CheckForNull;
 
+import java.util.List;
+
 public interface GroupMapper {
 
   @CheckForNull
   GroupDto selectByKey(String name);
 
+  List<GroupDto> selectByUserLogin(String userLogin);
+
   void insert(GroupDto groupDto);
 
 }
index eb451cf51ae75eb1d4f03cc8dab81e45810a8572..2ff34885ec6780f4dd5a0aba2a88d833f9f4de28 100644 (file)
@@ -40,7 +40,7 @@
       SELECT
       projects.kee AS project,
       NULL         AS login,
-      'anyone'     AS permission_group,
+      #{anyone}     AS permission_group,
       group_roles.role as permission_role
       FROM projects
       INNER JOIN group_roles ON group_roles.resource_id = projects.id AND group_roles.role = #{permission}
index 4dd187badbea7951c8f7950263d2bd69288f0bdb..87a6ea340c240519705a82731346fdfaa44ea29b 100644 (file)
 
   <select id="selectByKey" parameterType="string" resultType="Group">
     SELECT <include refid="groupColumns"/>
-    FROM groups g WHERE g.name=#{id}
+    FROM groups g
+    <where>
+      g.name=#{id}
+    </where>
+  </select>
+
+  <select id="selectByUserLogin" parameterType="string" resultType="Group">
+    SELECT <include refid="groupColumns"/>
+    FROM groups g
+    INNER JOIN groups_users gu on gu.group_id=g.id
+    INNER JOIN users u on u.id=gu.user_id
+    <where>
+      u.login=#{login}
+    </where>
   </select>
 
   <insert id="insert" parameterType="Group" keyColumn="id" useGeneratedKeys="true" keyProperty="id">