aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2016-10-19 11:48:35 +0200
committerJulien Lancelot <julien.lancelot@sonarsource.com>2016-10-20 13:16:50 +0200
commit384c1aa3aefde97b78413d621cfc9fa60a0484c9 (patch)
treed1a45fc37cec5deafcdc9895d76c64c9e1668058 /server
parent19199a9f6db636fc2ed5316de290eb45d601f8e3 (diff)
downloadsonarqube-384c1aa3aefde97b78413d621cfc9fa60a0484c9.tar.gz
sonarqube-384c1aa3aefde97b78413d621cfc9fa60a0484c9.zip
SONAR-8227 Use authorization index when searching project measures
Diffstat (limited to 'server')
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/component/es/ProjectMeasuresIndex.java29
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/component/es/ProjectMeasuresIndexTest.java75
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchProjectsActionTest.java17
3 files changed, 115 insertions, 6 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/es/ProjectMeasuresIndex.java b/server/sonar-server/src/main/java/org/sonar/server/component/es/ProjectMeasuresIndex.java
index df2269ab79e..f9865f7684f 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/component/es/ProjectMeasuresIndex.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/component/es/ProjectMeasuresIndex.java
@@ -19,17 +19,21 @@
*/
package org.sonar.server.component.es;
+import java.util.Set;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
+import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.sonar.server.component.es.ProjectMeasuresQuery.MetricCriterion;
import org.sonar.server.es.BaseIndex;
import org.sonar.server.es.EsClient;
import org.sonar.server.es.SearchIdResult;
import org.sonar.server.es.SearchOptions;
+import org.sonar.server.user.UserSession;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
+import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
import static org.elasticsearch.index.query.QueryBuilders.nestedQuery;
import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
@@ -39,15 +43,18 @@ import static org.sonar.server.component.es.ProjectMeasuresIndexDefinition.FIELD
import static org.sonar.server.component.es.ProjectMeasuresIndexDefinition.FIELD_NAME;
import static org.sonar.server.component.es.ProjectMeasuresIndexDefinition.FIELD_QUALITY_GATE;
import static org.sonar.server.component.es.ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES;
-import static org.sonar.server.component.es.ProjectMeasuresIndexDefinition.TYPE_PROJECT_MEASURES;
+import static org.sonar.server.component.es.ProjectMeasuresIndexDefinition.*;
public class ProjectMeasuresIndex extends BaseIndex {
private static final String FIELD_KEY = FIELD_MEASURES + "." + FIELD_MEASURES_KEY;
private static final String FIELD_VALUE = FIELD_MEASURES + "." + FIELD_MEASURES_VALUE;
- public ProjectMeasuresIndex(EsClient client) {
+ private final UserSession userSession;
+
+ public ProjectMeasuresIndex(EsClient client, UserSession userSession) {
super(client);
+ this.userSession = userSession;
}
public SearchIdResult<String> search(ProjectMeasuresQuery query, SearchOptions searchOptions) {
@@ -65,8 +72,9 @@ public class ProjectMeasuresIndex extends BaseIndex {
return new SearchIdResult<>(request.get(), id -> id);
}
- private static QueryBuilder createEsQuery(ProjectMeasuresQuery query) {
- BoolQueryBuilder filters = boolQuery();
+ private QueryBuilder createEsQuery(ProjectMeasuresQuery query) {
+ BoolQueryBuilder filters = boolQuery()
+ .must(createAuthorizationFilter());
query.getMetricCriteria().stream()
.map(criterion -> nestedQuery(FIELD_MEASURES, boolQuery()
.filter(termQuery(FIELD_KEY, criterion.getMetricKey()))
@@ -91,6 +99,19 @@ public class ProjectMeasuresIndex extends BaseIndex {
default:
throw new IllegalStateException("Metric criteria non supported: " + criterion.getOperator().name());
}
+ }
+ private QueryBuilder createAuthorizationFilter() {
+ String userLogin = userSession.getLogin();
+ Set<String> userGroupNames = userSession.getUserGroups();
+ BoolQueryBuilder groupsAndUser = boolQuery();
+ if (userLogin != null) {
+ groupsAndUser.should(termQuery(FIELD_AUTHORIZATION_USERS, userLogin));
+ }
+ for (String group : userGroupNames) {
+ groupsAndUser.should(termQuery(FIELD_AUTHORIZATION_GROUPS, group));
+ }
+ return QueryBuilders.hasParentQuery(TYPE_AUTHORIZATION,
+ QueryBuilders.boolQuery().must(matchAllQuery()).filter(groupsAndUser));
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/es/ProjectMeasuresIndexTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/es/ProjectMeasuresIndexTest.java
index eaa0344eb1f..5462e3c59de 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/component/es/ProjectMeasuresIndexTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/component/es/ProjectMeasuresIndexTest.java
@@ -21,9 +21,11 @@ package org.sonar.server.component.es;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;
+import javax.annotation.Nullable;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.config.MapSettings;
@@ -32,10 +34,14 @@ import org.sonar.server.component.es.ProjectMeasuresQuery.Operator;
import org.sonar.server.es.EsTester;
import org.sonar.server.es.SearchIdResult;
import org.sonar.server.es.SearchOptions;
+import org.sonar.server.permission.index.AuthorizationIndexerTester;
+import org.sonar.server.tester.UserSessionRule;
import static com.google.common.collect.Lists.newArrayList;
+import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.api.measures.Metric.Level.OK;
+import static org.sonar.api.security.DefaultGroups.ANYONE;
import static org.sonar.server.component.es.ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES;
import static org.sonar.server.component.es.ProjectMeasuresIndexDefinition.TYPE_PROJECT_MEASURES;
@@ -43,10 +49,16 @@ public class ProjectMeasuresIndexTest {
private static final String COVERAGE = "coverage";
private static final String NCLOC = "ncloc";
+
@Rule
public EsTester es = new EsTester(new ProjectMeasuresIndexDefinition(new MapSettings()));
- private ProjectMeasuresIndex underTest = new ProjectMeasuresIndex(es.client());
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
+
+ private AuthorizationIndexerTester authorizationIndexerTester = new AuthorizationIndexerTester(es);
+
+ private ProjectMeasuresIndex underTest = new ProjectMeasuresIndex(es.client(), userSession);
@Test
public void empty_search() {
@@ -146,9 +158,70 @@ public class ProjectMeasuresIndexTest {
assertThat(result).containsExactly("P1", "P2");
}
+ @Test
+ public void return_only_projects_authorized_for_user() throws Exception {
+ userSession.login("john");
+ addDocs("john", null, newDoc("P1", "K1", "Windows"));
+ addDocs("john", "dev", newDoc("P2", "K2", "apachee"));
+ addDocs("another user", null, newDoc("P10", "K10", "N10"));
+
+ List<String> result = underTest.search(new ProjectMeasuresQuery(), new SearchOptions()).getIds();
+
+ assertThat(result).containsOnly("P1", "P2");
+ }
+
+ @Test
+ public void return_only_projects_authorized_for_user_groups() throws Exception {
+ userSession.setUserGroups("dev");
+ addDocs("john", "dev", newDoc("P1", "K1", "apachee"));
+ addDocs(null, ANYONE, newDoc("P2", "K2", "N2"));
+ addDocs(null, "admin", newDoc("P10", "K10", "N10"));
+
+ List<String> result = underTest.search(new ProjectMeasuresQuery(), new SearchOptions()).getIds();
+
+ assertThat(result).containsOnly("P1", "P2");
+ }
+
+ @Test
+ public void return_only_projects_authorized_for_user_and_groups() throws Exception {
+ userSession.login("john").setUserGroups("dev");
+ addDocs("john", null, newDoc("P1", "K1", "Windows"));
+ addDocs(null, "dev", newDoc("P2", "K2", "Apache"));
+ addDocs("john", "dev", newDoc("P3", "K3", "apachee"));
+ // Current user is not able to see following projects
+ addDocs(null, "another group", newDoc("P5", "K5", "N5"));
+ addDocs("another user", null, newDoc("P6", "K6", "N6"));
+ addDocs((String) null, null, newDoc("P7", "K7", "N7"));
+
+ List<String> result = underTest.search(new ProjectMeasuresQuery(), new SearchOptions()).getIds();
+
+ assertThat(result).containsOnly("P1", "P2", "P3");
+ }
+
+ @Test
+ public void anyone_user_can_only_access_projects_authorized_for_anyone() throws Exception {
+ userSession.anonymous();
+ addDocs(null, ANYONE, newDoc("P1", "K1", "N1"));
+ addDocs("john", null, newDoc("P2", "K2", "Windows"));
+ addDocs(null, "admin", newDoc("P3", "K3", "N3"));
+
+ List<String> result = underTest.search(new ProjectMeasuresQuery(), new SearchOptions()).getIds();
+
+ assertThat(result).containsOnly("P1");
+ }
+
private void addDocs(ProjectMeasuresDoc... docs) {
+ addDocs(null, ANYONE, docs);
+ }
+
+ private void addDocs(@Nullable String authorizeUser, @Nullable String authorizedGroup, ProjectMeasuresDoc... docs) {
try {
es.putDocuments(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURES, docs);
+ for (ProjectMeasuresDoc doc : docs) {
+ authorizationIndexerTester.insertProjectAuthorization(doc.getId(),
+ authorizedGroup != null ? singletonList(authorizedGroup) : Collections.emptyList(),
+ authorizeUser != null ? singletonList(authorizeUser) : Collections.emptyList());
+ }
} catch (Exception e) {
Throwables.propagate(e);
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchProjectsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchProjectsActionTest.java
index bfb5533b214..d0930e213bc 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchProjectsActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchProjectsActionTest.java
@@ -23,6 +23,7 @@ package org.sonar.server.component.ws;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import java.io.IOException;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;
@@ -31,6 +32,7 @@ import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.api.config.MapSettings;
import org.sonar.api.measures.Metric;
+import org.sonar.api.security.DefaultGroups;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.server.ws.WebService.Param;
import org.sonar.api.utils.System2;
@@ -44,6 +46,8 @@ import org.sonar.server.component.es.ProjectMeasuresDoc;
import org.sonar.server.component.es.ProjectMeasuresIndex;
import org.sonar.server.component.es.ProjectMeasuresIndexDefinition;
import org.sonar.server.es.EsTester;
+import org.sonar.server.permission.index.AuthorizationIndexerTester;
+import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.KeyExamples;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.WsActionTester;
@@ -55,6 +59,7 @@ import org.sonarqube.ws.client.component.SearchProjectsRequest;
import static com.google.common.collect.Lists.newArrayList;
import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.db.component.ComponentTesting.newDeveloper;
import static org.sonar.db.component.ComponentTesting.newDirectory;
@@ -71,15 +76,24 @@ import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_FIL
public class SearchProjectsActionTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
+
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
+
@Rule
public EsTester es = new EsTester(new ProjectMeasuresIndexDefinition(new MapSettings()));
+
@Rule
public DbTester db = DbTester.create(System2.INSTANCE);
+
private ComponentDbTester componentDb = new ComponentDbTester(db);
private DbClient dbClient = db.getDbClient();
private DbSession dbSession = db.getSession();
- private WsActionTester ws = new WsActionTester(new SearchProjectsAction(dbClient, new ProjectMeasuresIndex(es.client()), new ProjectMeasuresQueryValidator(dbClient)));
+ private AuthorizationIndexerTester authorizationIndexerTester = new AuthorizationIndexerTester(es);
+
+ private WsActionTester ws = new WsActionTester(
+ new SearchProjectsAction(dbClient, new ProjectMeasuresIndex(es.client(), userSession), new ProjectMeasuresQueryValidator(dbClient)));
private SearchProjectsRequest.Builder request = SearchProjectsRequest.builder();
@@ -223,6 +237,7 @@ public class SearchProjectsActionTest {
try {
es.putDocuments(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURES,
new ProjectMeasuresDoc().setId(project.uuid()).setKey(project.key()).setName(project.name()).setMeasures(measures));
+ authorizationIndexerTester.insertProjectAuthorization(project.uuid(), singletonList(DefaultGroups.ANYONE), Collections.emptyList());
} catch (Exception e) {
Throwables.propagate(e);
}