From: Julien Lancelot Date: Wed, 3 Sep 2014 08:26:25 +0000 (+0200) Subject: SONAR-5559 Update Issue mapping to add a Issue Authorization parent (only created... X-Git-Tag: 5.0-RC1~1092 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=0b7ea43a238daaa1081bbe159418488e043a7ca1;p=sonarqube.git SONAR-5559 Update Issue mapping to add a Issue Authorization parent (only created in medium test for the moment) --- diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java index 92fd7aef6c7..b925f5e1e1e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java @@ -60,6 +60,34 @@ public class IssueIndex extends BaseIndex { return mapping; } + @Override + protected Map mapDomain() { + Map mapping = new HashMap(); + mapping.put("dynamic", false); + mapping.put("_id", mapKey()); + mapping.put("_parent", mapParent()); + mapping.put("_routing", mapRouting()); + mapping.put("properties", mapProperties()); + return mapping; + } + + private Object mapParent() { + Map mapping = new HashMap(); + mapping.put("type", getParentType()); + return mapping; + } + + private String getParentType() { + return IndexDefinition.ISSUES_AUTHENTICATION.getIndexType(); + } + + private Map mapRouting() { + Map mapping = new HashMap(); + mapping.put("required", true); + mapping.put("path", IssueNormalizer.IssueField.PROJECT.field()); + return mapping; + } + @Override protected Map mapKey() { Map mapping = new HashMap(); diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueNormalizer.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueNormalizer.java index 38ae9d97635..30f7368c168 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueNormalizer.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueNormalizer.java @@ -29,11 +29,7 @@ import org.sonar.server.search.IndexField; import org.sonar.server.search.Indexable; import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; public class IssueNormalizer extends BaseNormalizer { @@ -53,6 +49,7 @@ public class IssueNormalizer extends BaseNormalizer { public static final IndexField ISSUE_CREATED_AT = add(IndexField.Type.DATE, "issueCreatedAt"); public static final IndexField ISSUE_UPDATED_AT = add(IndexField.Type.DATE, "issueUpdatedAt"); public static final IndexField ISSUE_CLOSE_DATE = add(IndexField.Type.DATE, "issueClosedAt"); + public static final IndexField PROJECT = add(IndexField.Type.STRING, "project"); public static final IndexField COMPONENT = add(IndexField.Type.STRING, "component"); public static final IndexField EFFORT = add(IndexField.Type.NUMERIC, "effort"); public static final IndexField RESOLUTION = add(IndexField.Type.STRING, "resolution"); @@ -95,6 +92,7 @@ public class IssueNormalizer extends BaseNormalizer { public List normalize(IssueDto dto) { Map update = new HashMap(); + update.put("_parent", dto.getRootComponentKey()); update.put(IssueField.KEY.field(), dto.getKey()); update.put(IssueField.UPDATED_AT.field(), dto.getUpdatedAt()); update.put(IssueField.CREATED_AT.field(), dto.getCreatedAt()); @@ -103,6 +101,7 @@ public class IssueNormalizer extends BaseNormalizer { update.put(IssueField.ASSIGNEE.field(), dto.getAssignee()); update.put(IssueField.AUTHOR_LOGIN.field(), dto.getAuthorLogin()); update.put(IssueField.ISSUE_CLOSE_DATE.field(), dto.getIssueCloseDate()); + update.put(IssueField.PROJECT.field(), dto.getRootComponentKey()); update.put(IssueField.COMPONENT.field(), dto.getComponentKey()); update.put(IssueField.ISSUE_CREATED_AT.field(), dto.getIssueCreationDate()); update.put(IssueField.ISSUE_UPDATED_AT.field(), dto.getIssueUpdateDate()); @@ -131,6 +130,8 @@ public class IssueNormalizer extends BaseNormalizer { return ImmutableList.of( new UpdateRequest() .id(dto.getKey().toString()) + .routing(dto.getRootComponentKey()) + .parent(dto.getRootComponentKey()) .doc(update) .upsert(upsert)); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/IndexDefinition.java b/server/sonar-server/src/main/java/org/sonar/server/search/IndexDefinition.java index 0d16ff4b972..94580d1b29d 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/search/IndexDefinition.java +++ b/server/sonar-server/src/main/java/org/sonar/server/search/IndexDefinition.java @@ -52,9 +52,14 @@ public class IndexDefinition { public static final IndexDefinition RULE = new IndexDefinition("rules", "rule"); public static final IndexDefinition ACTIVE_RULE = new IndexDefinition("rules", "activeRule"); + public static final IndexDefinition ISSUES_AUTHENTICATION = new IndexDefinition("issues", "issuesAuthorization"); public static final IndexDefinition ISSUES = new IndexDefinition("issues", "issue"); public static final IndexDefinition LOG = new IndexDefinition("logs", "sonarLog"); @VisibleForTesting protected static IndexDefinition TEST = new IndexDefinition("test", "test"); + + public static IndexDefinition createFor(String indexName, String indexType) { + return new IndexDefinition(indexName, indexType); + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueBackendMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueBackendMediumTest.java index d108c22e201..5b68a40a0ec 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueBackendMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueBackendMediumTest.java @@ -19,6 +19,12 @@ */ package org.sonar.server.issue.db; +import com.google.common.collect.ImmutableMap; +import org.elasticsearch.action.search.SearchRequestBuilder; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.common.settings.ImmutableSettings; +import org.elasticsearch.index.query.FilterBuilders; +import org.elasticsearch.index.query.QueryBuilders; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -35,11 +41,15 @@ import org.sonar.server.issue.index.IssueIndex; import org.sonar.server.platform.Platform; import org.sonar.server.rule.RuleTesting; import org.sonar.server.rule.db.RuleDao; +import org.sonar.server.search.BaseIndex; import org.sonar.server.search.IndexClient; +import org.sonar.server.search.IndexDefinition; +import org.sonar.server.search.SearchClient; import org.sonar.server.tester.ServerTester; -import java.util.Date; -import java.util.UUID; +import java.io.IOException; +import java.io.Serializable; +import java.util.*; import static org.fest.assertions.Assertions.assertThat; @@ -75,14 +85,14 @@ public class IssueBackendMediumTest { tester.get(RuleDao.class).insert(dbSession, rule); ComponentDto project = new ComponentDto() + .setId(1L) .setKey("MyProject") - .setId(1L) .setProjectId(1L); tester.get(ComponentDao.class).insert(dbSession, project); ComponentDto resource = new ComponentDto() - .setKey("MyComponent") .setProjectId(1L) + .setKey("MyComponent") .setId(2L); tester.get(ComponentDao.class).insert(dbSession, resource); @@ -137,18 +147,22 @@ public class IssueBackendMediumTest { ComponentDto project = new ComponentDto() .setId(1L) + .setKey("MyProject") .setProjectId(1L); tester.get(ComponentDao.class).insert(dbSession, project); ComponentDto resource = new ComponentDto() - .setProjectId(1L) - .setId(2L); + .setId(2L) + .setKey("MyComponent") + .setProjectId(1L); tester.get(ComponentDao.class).insert(dbSession, resource); - IssueDto issue = new IssueDto().setId(1L).setRuleId(50).setComponentId(123l).setRootComponentId(100l) + IssueDto issue = new IssueDto().setId(1L) .setRuleId(rule.getId()) .setRootComponentId(project.getId()) + .setRootComponentKey_unit_test_only(project.key()) .setComponentId(resource.getId()) + .setComponentKey_unit_test_only(resource.key()) .setStatus("OPEN").setResolution("OPEN") .setKee(UUID.randomUUID().toString()); dbClient.issueDao().insert(dbSession, issue); @@ -169,6 +183,161 @@ public class IssueBackendMediumTest { assertThat(indexClient.get(IssueIndex.class).countAll()).isEqualTo(0); tester.get(Platform.class).executeStartupTasks(); assertThat(indexClient.get(IssueIndex.class).countAll()).isEqualTo(1); + } + + @Test + public void issue_authorization_on_group() throws Exception { + SearchClient searchClient = tester.get(SearchClient.class); + createIssueAuthorizationIndex(searchClient, IndexDefinition.ISSUES_AUTHENTICATION.getIndexName(), IndexDefinition.ISSUES_AUTHENTICATION.getIndexType()); + + RuleDto rule = RuleTesting.newXooX1(); + tester.get(RuleDao.class).insert(dbSession, rule); + + ComponentDto project = new ComponentDto() + .setId(1L) + .setProjectId(1L) + .setKey("SonarQube"); + tester.get(ComponentDao.class).insert(dbSession, project); + + ComponentDto resource = new ComponentDto() + .setProjectId(1L) + .setId(2L) + .setKey("IssueAction.java"); + tester.get(ComponentDao.class).insert(dbSession, resource); + + IssueDto issue = new IssueDto().setId(1L) + .setRuleId(rule.getId()) + .setRootComponentKey_unit_test_only(project.key()) + .setRootComponentId(project.getId()) + .setComponentKey_unit_test_only(resource.key()) + .setComponentId(resource.getId()) + .setStatus("OPEN").setResolution("OPEN") + .setKee(UUID.randomUUID().toString()); + dbClient.issueDao().insert(dbSession, issue); + + dbSession.commit(); + + searchClient.prepareIndex(IndexDefinition.ISSUES_AUTHENTICATION.getIndexName(), IndexDefinition.ISSUES_AUTHENTICATION.getIndexType()) + .setId(project.key()) + .setSource(ImmutableMap.of("permission", "read", "project", project.key(), "group", "user")) + .setRefresh(true) + .get(); + + // The issue is only visible for group user + assertThat(searchIssueWithAuthorization(searchClient, "user", "").getHits().getTotalHits()).isEqualTo(1); + // The issue is not visible for group reviewer + assertThat(searchIssueWithAuthorization(searchClient, "reviewer", "").getHits().getTotalHits()).isEqualTo(0); + } + + @Test + public void issue_authorization_on_user() throws Exception { + SearchClient searchClient = tester.get(SearchClient.class); + createIssueAuthorizationIndex(searchClient, IndexDefinition.ISSUES_AUTHENTICATION.getIndexName(), IndexDefinition.ISSUES_AUTHENTICATION.getIndexType()); + + RuleDto rule = RuleTesting.newXooX1(); + tester.get(RuleDao.class).insert(dbSession, rule); + + ComponentDto project = new ComponentDto() + .setId(1L) + .setProjectId(1L) + .setKey("SonarQube"); + tester.get(ComponentDao.class).insert(dbSession, project); + + ComponentDto resource = new ComponentDto() + .setProjectId(1L) + .setId(2L) + .setKey("IssueAction.java"); + tester.get(ComponentDao.class).insert(dbSession, resource); + + IssueDto issue = new IssueDto().setId(1L) + .setRuleId(rule.getId()) + .setRootComponentKey_unit_test_only(project.key()) + .setRootComponentId(project.getId()) + .setComponentKey_unit_test_only(resource.key()) + .setComponentId(resource.getId()) + .setStatus("OPEN").setResolution("OPEN") + .setKee(UUID.randomUUID().toString()); + dbClient.issueDao().insert(dbSession, issue); + + dbSession.commit(); + + searchClient.prepareIndex(IndexDefinition.ISSUES_AUTHENTICATION.getIndexName(), IndexDefinition.ISSUES_AUTHENTICATION.getIndexType()) + .setId(project.key()) + .setSource(ImmutableMap.of("permission", "read", "project", project.key(), "user", "julien")) + .setRefresh(true) + .get(); + + // The issue is visible for user julien + assertThat(searchIssueWithAuthorization(searchClient, "", "julien").getHits().getTotalHits()).isEqualTo(1); + // The issue is not visible for user simon + assertThat(searchIssueWithAuthorization(searchClient, "", "simon").getHits().getTotalHits()).isEqualTo(0); + } + + private SearchResponse searchIssueWithAuthorization(SearchClient searchClient, String group, String user){ + SearchRequestBuilder request = searchClient.prepareSearch(IndexDefinition.ISSUES.getIndexName()) + .setQuery( + QueryBuilders.filteredQuery( + QueryBuilders.matchAllQuery(), + FilterBuilders.hasParentFilter( + IndexDefinition.ISSUES_AUTHENTICATION.getIndexType(), + FilterBuilders.boolFilter().must( + FilterBuilders.termFilter("permission", "read"), + FilterBuilders.orFilter( + FilterBuilders.termFilter("group", group), + FilterBuilders.termFilter("user", user) + ) + ).cache(true) + ) + ) + ) + .setSize(Integer.MAX_VALUE); + return searchClient.execute(request); + } + + private BaseIndex createIssueAuthorizationIndex(final SearchClient searchClient, String index, String type) { + BaseIndex baseIndex = new BaseIndex( + IndexDefinition.createFor(index, type), + null, searchClient) { + @Override + protected String getKeyValue(Serializable key) { + return null; + } + + @Override + protected org.elasticsearch.common.settings.Settings getIndexSettings() throws IOException { + return ImmutableSettings.builder().build(); + } + + @Override + protected Map mapProperties() { + Map mapping = new HashMap(); + mapping.put("permission", mapStringField()); + mapping.put("project", mapStringField()); + mapping.put("group", mapStringField()); + mapping.put("user", mapStringField()); + return mapping; + } + + protected Map mapStringField() { + Map mapping = new HashMap(); + mapping.put("type", "string"); + mapping.put("index", "analyzed"); + mapping.put("index_analyzer", "keyword"); + mapping.put("search_analyzer", "whitespace"); + return mapping; + } + + @Override + protected Map mapKey() { + return Collections.emptyMap(); + } + @Override + public Object toDoc(Map fields) { + return null; + } + }; + baseIndex.start(); + return baseIndex; } }