diff options
author | Simon Brandhof <simon.brandhof@sonarsource.com> | 2017-01-26 18:20:57 +0100 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@sonarsource.com> | 2017-01-31 13:53:44 +0100 |
commit | 934bf664b8e032c76c9e64e28ddb3ee46d7adbc3 (patch) | |
tree | 9b4c907167c91936a7b214b49d284c6f35945b23 /server | |
parent | 346e8661756f15aa105a585b1d8a05fe326e1244 (diff) | |
download | sonarqube-934bf664b8e032c76c9e64e28ddb3ee46d7adbc3.tar.gz sonarqube-934bf664b8e032c76c9e64e28ddb3ee46d7adbc3.zip |
SONAR-8704 Refactor Elasticsearch types "authorization"
Multiple indices define a type "authorization".
The related code was duplicated, and sometimes
had some minor differences. This commits share
all the management of these types in the same
bunch of classes.
It also allows to quickly create a project-related
index, without having to fix the different locations
which may require project re-indexing.
Diffstat (limited to 'server')
71 files changed, 1548 insertions, 2409 deletions
diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java index 55a562597c0..8b7449846e3 100644 --- a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java +++ b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java @@ -108,7 +108,7 @@ public class ComputeEngineContainerImplTest { COMPONENTS_IN_LEVEL_1_AT_CONSTRUCTION + 25 // level 1 + 47 // content of DaoModule - + 2 // content of EsSearchModule + + 3 // content of EsSearchModule + 63 // content of CorePropertyDefinitions + 1 // content of CePropertyDefinitions ); diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ComponentCleanerService.java b/server/sonar-server/src/main/java/org/sonar/server/component/ComponentCleanerService.java index c34b7df4292..665d6bd5651 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/ComponentCleanerService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/ComponentCleanerService.java @@ -27,34 +27,23 @@ import org.sonar.api.resources.Scopes; import org.sonar.api.server.ServerSide; import org.sonar.db.DbClient; import org.sonar.db.DbSession; -import org.sonar.db.MyBatis; import org.sonar.db.component.ComponentDto; -import org.sonar.server.component.index.ComponentIndexer; -import org.sonar.server.issue.index.IssueIndexer; -import org.sonar.server.measure.index.ProjectMeasuresIndexer; -import org.sonar.server.test.index.TestIndexer; +import org.sonar.server.es.ProjectIndexer; + +import static java.util.Arrays.asList; @ServerSide @ComputeEngineSide public class ComponentCleanerService { private final DbClient dbClient; - private final IssueIndexer issueIndexer; - private final TestIndexer testIndexer; - private final ProjectMeasuresIndexer projectMeasuresIndexer; - private final ComponentIndexer componentIndexer; private final ResourceTypes resourceTypes; - private final ComponentFinder componentFinder; + private final List<ProjectIndexer> projectIndexers; - public ComponentCleanerService(DbClient dbClient, IssueIndexer issueIndexer, TestIndexer testIndexer, ProjectMeasuresIndexer projectMeasuresIndexer, - ComponentIndexer componentIndexer, ResourceTypes resourceTypes, ComponentFinder componentFinder) { + public ComponentCleanerService(DbClient dbClient, ResourceTypes resourceTypes, ProjectIndexer[] projectIndexers) { this.dbClient = dbClient; - this.issueIndexer = issueIndexer; - this.testIndexer = testIndexer; - this.projectMeasuresIndexer = projectMeasuresIndexer; - this.componentIndexer = componentIndexer; this.resourceTypes = resourceTypes; - this.componentFinder = componentFinder; + this.projectIndexers = asList(projectIndexers); } public void delete(DbSession dbSession, List<ComponentDto> projects) { @@ -63,17 +52,7 @@ public class ComponentCleanerService { } } - public void delete(String projectKey) { - DbSession dbSession = dbClient.openSession(false); - try { - ComponentDto project = componentFinder.getByKey(dbSession, projectKey); - delete(dbSession, project); - } finally { - MyBatis.closeQuietly(dbSession); - } - } - - private void delete(DbSession dbSession, ComponentDto project) { + public void delete(DbSession dbSession, ComponentDto project) { if (hasNotProjectScope(project) || isNotDeletable(project)) { throw new IllegalArgumentException("Only projects can be deleted"); } @@ -84,10 +63,7 @@ public class ComponentCleanerService { } private void deleteFromIndices(String projectUuid) { - issueIndexer.deleteProject(projectUuid); - testIndexer.deleteByProject(projectUuid); - projectMeasuresIndexer.deleteProject(projectUuid); - componentIndexer.deleteByProjectUuid(projectUuid); + projectIndexers.forEach(i -> i.deleteProject(projectUuid)); } private static boolean hasNotProjectScope(ComponentDto project) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java b/server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java index 6a01a841473..be731da5b71 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java @@ -32,9 +32,8 @@ import org.sonar.api.web.UserRole; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.component.ComponentDto; -import org.sonar.server.component.index.ComponentIndexer; +import org.sonar.server.es.ProjectIndexer; import org.sonar.server.exceptions.NotFoundException; -import org.sonar.server.measure.index.ProjectMeasuresIndexer; import org.sonar.server.user.UserSession; import static com.google.common.collect.Lists.newArrayList; @@ -48,15 +47,12 @@ import static org.sonar.server.ws.WsUtils.checkRequest; public class ComponentService { private final DbClient dbClient; private final UserSession userSession; - private final ProjectMeasuresIndexer projectMeasuresIndexer; - private final ComponentIndexer componentIndexer; + private final ProjectIndexer[] projectIndexers; - public ComponentService(DbClient dbClient, UserSession userSession, ProjectMeasuresIndexer projectMeasuresIndexer, - ComponentIndexer componentIndexer) { + public ComponentService(DbClient dbClient, UserSession userSession, ProjectIndexer[] projectIndexers) { this.dbClient = dbClient; this.userSession = userSession; - this.projectMeasuresIndexer = projectMeasuresIndexer; - this.componentIndexer = componentIndexer; + this.projectIndexers = projectIndexers; } // TODO should be moved to ComponentUpdater @@ -77,8 +73,9 @@ public class ComponentService { } private void index(String projectUuid) { - projectMeasuresIndexer.index(projectUuid); - componentIndexer.indexByProjectUuid(projectUuid); + for (ProjectIndexer projectIndexer : projectIndexers) { + projectIndexer.indexProject(projectUuid, ProjectIndexer.Cause.PROJECT_KEY_UPDATE); + } } public Collection<String> componentUuids(@Nullable Collection<String> componentKeys) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ComponentUpdater.java b/server/sonar-server/src/main/java/org/sonar/server/component/ComponentUpdater.java index 1267089f86c..d87345898bf 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/ComponentUpdater.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/ComponentUpdater.java @@ -32,10 +32,9 @@ import org.sonar.core.util.Uuids; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.component.ComponentDto; -import org.sonar.server.component.index.ComponentIndexer; +import org.sonar.server.es.ProjectIndexer; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.favorite.FavoriteUpdater; -import org.sonar.server.measure.index.ProjectMeasuresIndexer; import org.sonar.server.permission.PermissionTemplateService; import static org.sonar.api.resources.Qualifiers.PROJECT; @@ -49,19 +48,17 @@ public class ComponentUpdater { private final System2 system2; private final PermissionTemplateService permissionTemplateService; private final FavoriteUpdater favoriteUpdater; - private final ProjectMeasuresIndexer projectMeasuresIndexer; - private final ComponentIndexer componentIndexer; + private final ProjectIndexer[] projectIndexers; public ComponentUpdater(DbClient dbClient, I18n i18n, System2 system2, PermissionTemplateService permissionTemplateService, FavoriteUpdater favoriteUpdater, - ProjectMeasuresIndexer projectMeasuresIndexer, ComponentIndexer componentIndexer) { + ProjectIndexer[] projectIndexers) { this.dbClient = dbClient; this.i18n = i18n; this.system2 = system2; - this.projectMeasuresIndexer = projectMeasuresIndexer; - this.componentIndexer = componentIndexer; this.permissionTemplateService = permissionTemplateService; this.favoriteUpdater = favoriteUpdater; + this.projectIndexers = projectIndexers; } /** @@ -76,7 +73,7 @@ public class ComponentUpdater { removeDuplicatedProjects(dbSession, componentDto.getKey()); handlePermissionTemplate(dbSession, componentDto, newComponent.getOrganizationUuid(), userId); dbSession.commit(); - index(componentDto.uuid()); + index(componentDto); return componentDto; } @@ -144,8 +141,9 @@ public class ComponentUpdater { return String.format(message, i18n.message(Locale.getDefault(), "qualifier." + qualifier, "Project"), key); } - private void index(String projectUuid) { - projectMeasuresIndexer.index(projectUuid); - componentIndexer.indexByProjectUuid(projectUuid); + private void index(ComponentDto project) { + for (ProjectIndexer projectIndexer : projectIndexers) { + projectIndexer.indexProject(project.uuid(), ProjectIndexer.Cause.PROJECT_CREATION); + } } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java b/server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java index b94a2ae58ff..c31d98ce412 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java @@ -53,14 +53,15 @@ public class DefaultRubyComponentService { @Deprecated public Long createComponent(String key, String name, String qualifier) { try (DbSession dbSession = dbClient.openSession(false)) { + NewComponent newComponent = newComponentBuilder() + .setOrganizationUuid(defaultOrganizationProvider.get().getUuid()) + .setKey(key) + .setName(name) + .setQualifier(qualifier) + .build(); return componentUpdater.create( dbSession, - newComponentBuilder() - .setOrganizationUuid(defaultOrganizationProvider.get().getUuid()) - .setKey(key) - .setName(name) - .setQualifier(qualifier) - .build(), + newComponent, userSession.isLoggedIn() ? userSession.getUserId().longValue() : null).getId(); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/index/ComponentIndex.java b/server/sonar-server/src/main/java/org/sonar/server/component/index/ComponentIndex.java index 8c1e4d15b29..549d3abe63e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/index/ComponentIndex.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/index/ComponentIndex.java @@ -24,13 +24,10 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.Optional; -import java.util.Set; import org.elasticsearch.action.search.SearchRequestBuilder; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.QueryBuilder; -import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHits; import org.elasticsearch.search.aggregations.AggregationBuilders; @@ -40,29 +37,26 @@ import org.elasticsearch.search.aggregations.bucket.filters.InternalFilters.Buck import org.elasticsearch.search.aggregations.metrics.tophits.InternalTopHits; import org.elasticsearch.search.aggregations.metrics.tophits.TopHitsBuilder; import org.sonar.core.util.stream.Collectors; -import org.sonar.server.es.BaseIndex; import org.sonar.server.es.EsClient; -import org.sonar.server.user.UserSession; +import org.sonar.server.permission.index.AuthorizationTypeSupport; import static org.elasticsearch.index.query.QueryBuilders.boolQuery; -import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; import static org.elasticsearch.index.query.QueryBuilders.termQuery; -import static org.sonar.server.component.index.ComponentIndexDefinition.FIELD_AUTHORIZATION_GROUPS; -import static org.sonar.server.component.index.ComponentIndexDefinition.FIELD_AUTHORIZATION_USERS; import static org.sonar.server.component.index.ComponentIndexDefinition.FIELD_QUALIFIER; import static org.sonar.server.component.index.ComponentIndexDefinition.INDEX_COMPONENTS; -import static org.sonar.server.component.index.ComponentIndexDefinition.TYPE_AUTHORIZATION; import static org.sonar.server.component.index.ComponentIndexDefinition.TYPE_COMPONENT; -public class ComponentIndex extends BaseIndex { +public class ComponentIndex { private static final String FILTERS_AGGREGATION_NAME = "filters"; private static final String DOCS_AGGREGATION_NAME = "docs"; - private final UserSession userSession; - public ComponentIndex(EsClient client, UserSession userSession) { - super(client); - this.userSession = userSession; + private final EsClient client; + private final AuthorizationTypeSupport authorizationTypeSupport; + + public ComponentIndex(EsClient client, AuthorizationTypeSupport authorizationTypeSupport) { + this.client = client; + this.authorizationTypeSupport = authorizationTypeSupport; } public List<ComponentsPerQualifier> search(ComponentIndexQuery query) { @@ -76,7 +70,7 @@ public class ComponentIndex extends BaseIndex { return Collections.emptyList(); } - SearchRequestBuilder request = getClient() + SearchRequestBuilder request = client .prepareSearch(INDEX_COMPONENTS) .setTypes(TYPE_COMPONENT) .setQuery(createQuery(query, features)) @@ -108,7 +102,7 @@ public class ComponentIndex extends BaseIndex { private QueryBuilder createQuery(ComponentIndexQuery query, ComponentIndexSearchFeature... features) { BoolQueryBuilder esQuery = boolQuery(); - esQuery.filter(createAuthorizationFilter()); + esQuery.filter(authorizationTypeSupport.createQueryFilter()); BoolQueryBuilder featureQuery = boolQuery(); @@ -119,22 +113,6 @@ public class ComponentIndex extends BaseIndex { return esQuery.must(featureQuery); } - private QueryBuilder createAuthorizationFilter() { - Integer userLogin = userSession.getUserId(); - Set<String> userGroupNames = userSession.getUserGroups(); - BoolQueryBuilder groupsAndUser = boolQuery(); - - Optional.ofNullable(userLogin) - .map(Integer::longValue) - .ifPresent(userId -> groupsAndUser.should(termQuery(FIELD_AUTHORIZATION_USERS, userId))); - - userGroupNames.stream() - .forEach(group -> groupsAndUser.should(termQuery(FIELD_AUTHORIZATION_GROUPS, group))); - - return QueryBuilders.hasParentQuery(TYPE_AUTHORIZATION, - QueryBuilders.boolQuery().must(matchAllQuery()).filter(groupsAndUser)); - } - private static List<ComponentsPerQualifier> aggregationsToQualifiers(SearchResponse response) { InternalFilters filtersAgg = response.getAggregations().get(FILTERS_AGGREGATION_NAME); List<Bucket> buckets = filtersAgg.getBuckets(); diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/index/ComponentIndexDefinition.java b/server/sonar-server/src/main/java/org/sonar/server/component/index/ComponentIndexDefinition.java index 651c8a404f8..5fdcbf4c4ca 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/index/ComponentIndexDefinition.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/index/ComponentIndexDefinition.java @@ -19,7 +19,6 @@ */ package org.sonar.server.component.index; -import com.google.common.collect.ImmutableMap; import org.sonar.api.config.Settings; import org.sonar.server.es.IndexDefinition; import org.sonar.server.es.NewIndex; @@ -37,11 +36,6 @@ public class ComponentIndexDefinition implements IndexDefinition { public static final String FIELD_NAME = "name"; public static final String FIELD_QUALIFIER = "qualifier"; - public static final String TYPE_AUTHORIZATION = "authorization"; - public static final String FIELD_AUTHORIZATION_GROUPS = "groupNames"; - public static final String FIELD_AUTHORIZATION_USERS = "users"; - public static final String FIELD_AUTHORIZATION_UPDATED_AT = "updatedAt"; - private static final int DEFAULT_NUMBER_OF_SHARDS = 5; private final Settings settings; @@ -56,24 +50,13 @@ public class ComponentIndexDefinition implements IndexDefinition { index.refreshHandledByIndexer(); index.configureShards(settings, DEFAULT_NUMBER_OF_SHARDS); - // type "component" - NewIndex.NewIndexType mapping = index.createType(TYPE_COMPONENT); - mapping.setAttribute("_parent", ImmutableMap.of("type", TYPE_AUTHORIZATION)); - mapping.setAttribute("_routing", ImmutableMap.of("required", "true")); + NewIndex.NewIndexType mapping = index.createType(TYPE_COMPONENT) + .requireProjectAuthorization(); + mapping.stringFieldBuilder(FIELD_PROJECT_UUID).build(); mapping.stringFieldBuilder(FIELD_KEY).enable(SORTABLE_ANALYZER).build(); mapping.stringFieldBuilder(FIELD_NAME).enable(SEARCH_GRAMS_ANALYZER).build(); mapping.stringFieldBuilder(FIELD_QUALIFIER).build(); - - // do not store document but only indexation of information mapping.setEnableSource(false); - - // type "authorization" - NewIndex.NewIndexType authorizationMapping = index.createType(TYPE_AUTHORIZATION); - authorizationMapping.setAttribute("_routing", ImmutableMap.of("required", "true")); - authorizationMapping.createDateTimeField(FIELD_AUTHORIZATION_UPDATED_AT); - authorizationMapping.stringFieldBuilder(FIELD_AUTHORIZATION_GROUPS).disableNorms().build(); - authorizationMapping.stringFieldBuilder(FIELD_AUTHORIZATION_USERS).disableNorms().build(); - authorizationMapping.setEnableSource(false); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/index/ComponentIndexer.java b/server/sonar-server/src/main/java/org/sonar/server/component/index/ComponentIndexer.java index 31a5e4c0e7d..787abe98701 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/index/ComponentIndexer.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/index/ComponentIndexer.java @@ -36,15 +36,18 @@ import org.sonar.db.DbSession; import org.sonar.db.component.ComponentDto; import org.sonar.server.es.BulkIndexer; import org.sonar.server.es.EsClient; +import org.sonar.server.es.ProjectIndexer; +import org.sonar.server.permission.index.AuthorizationScope; +import org.sonar.server.permission.index.NeedAuthorizationIndexer; -import static java.util.Objects.requireNonNull; import static org.elasticsearch.index.query.QueryBuilders.boolQuery; import static org.elasticsearch.index.query.QueryBuilders.termQuery; import static org.sonar.server.component.index.ComponentIndexDefinition.INDEX_COMPONENTS; -import static org.sonar.server.component.index.ComponentIndexDefinition.TYPE_AUTHORIZATION; import static org.sonar.server.component.index.ComponentIndexDefinition.TYPE_COMPONENT; -public class ComponentIndexer implements Startable { +public class ComponentIndexer implements ProjectIndexer, NeedAuthorizationIndexer, Startable { + + private static final AuthorizationScope AUTHORIZATION_SCOPE = new AuthorizationScope(INDEX_COMPONENTS, project -> true); private final ThreadPoolExecutor executor; private final DbClient dbClient; @@ -65,13 +68,24 @@ public class ComponentIndexer implements Startable { doIndexByProjectUuid(null); } - /** - * Update the index for one specific project. The current data from the database is used. - */ - public void indexByProjectUuid(String projectUuid) { - requireNonNull(projectUuid); - deleteComponentsByProjectUuid(projectUuid); - doIndexByProjectUuid(projectUuid); + @Override + public void indexProject(String projectUuid, Cause cause) { + switch (cause) { + case PROJECT_CREATION: + case PROJECT_KEY_UPDATE: + case NEW_ANALYSIS: + deleteProject(projectUuid); + doIndexByProjectUuid(projectUuid); + break; + default: + // defensive case + throw new IllegalStateException("Unsupported cause: " + cause); + } + } + + @Override + public AuthorizationScope getAuthorizationScope() { + return AUTHORIZATION_SCOPE; } /** @@ -95,27 +109,14 @@ public class ComponentIndexer implements Startable { bulk.stop(); } - public void deleteByProjectUuid(String projectUuid) { - requireNonNull(projectUuid); - deleteComponentsByProjectUuid(projectUuid); - deleteAuthorizationByProjectUuid(projectUuid); - } - - private void deleteComponentsByProjectUuid(String projectUuid) { + @Override + public void deleteProject(String projectUuid) { BulkIndexer.delete(esClient, INDEX_COMPONENTS, esClient.prepareSearch(INDEX_COMPONENTS) .setQuery(boolQuery() .filter( termQuery(ComponentIndexDefinition.FIELD_PROJECT_UUID, projectUuid)))); } - private void deleteAuthorizationByProjectUuid(String projectUuid) { - esClient - .prepareDelete(INDEX_COMPONENTS, TYPE_AUTHORIZATION, projectUuid) - .setRouting(projectUuid) - .setRefresh(true) - .get(); - } - void index(ComponentDto... docs) { Future<?> submit = executor.submit(() -> indexNow(docs)); try { diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/IndexComponentsStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/IndexAnalysisStep.java index 8f5a54f56ce..59b51674be1 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/IndexComponentsStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/IndexAnalysisStep.java @@ -19,28 +19,32 @@ */ package org.sonar.server.computation.task.projectanalysis.step; -import org.sonar.server.component.index.ComponentIndexer; +import org.sonar.api.utils.log.Loggers; import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder; import org.sonar.server.computation.task.step.ComputationStep; +import org.sonar.server.es.ProjectIndexer; -public class IndexComponentsStep implements ComputationStep { +public class IndexAnalysisStep implements ComputationStep { - private final ComponentIndexer elasticSearchIndexer; private final TreeRootHolder treeRootHolder; + private final ProjectIndexer[] indexers; - public IndexComponentsStep(ComponentIndexer elasticSearchIndexer, TreeRootHolder treeRootHolder) { - this.elasticSearchIndexer = elasticSearchIndexer; + public IndexAnalysisStep(TreeRootHolder treeRootHolder, ProjectIndexer[] indexers) { this.treeRootHolder = treeRootHolder; + this.indexers = indexers; } @Override public void execute() { String projectUuid = treeRootHolder.getRoot().getUuid(); - elasticSearchIndexer.indexByProjectUuid(projectUuid); + for (ProjectIndexer indexer : indexers) { + Loggers.get(IndexAnalysisStep.class).info("Index " + indexer); + indexer.indexProject(projectUuid, ProjectIndexer.Cause.NEW_ANALYSIS); + } } @Override public String getDescription() { - return "Index components"; + return "Index analysis"; } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/IndexIssuesStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/IndexIssuesStep.java deleted file mode 100644 index 065ceba8667..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/IndexIssuesStep.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program 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. - * - * This program 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.computation.task.projectanalysis.step; - -import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder; -import org.sonar.server.computation.task.step.ComputationStep; -import org.sonar.server.issue.index.IssueIndexer; - -public class IndexIssuesStep implements ComputationStep { - - private final IssueIndexer indexer; - private final TreeRootHolder treeRootHolder; - - public IndexIssuesStep(IssueIndexer indexer, TreeRootHolder treeRootHolder) { - this.indexer = indexer; - this.treeRootHolder = treeRootHolder; - } - - @Override - public void execute() { - indexer.index(treeRootHolder.getRoot().getUuid()); - } - - @Override - public String getDescription() { - return "Index issues"; - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/IndexProjectMeasuresStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/IndexProjectMeasuresStep.java deleted file mode 100644 index d25077362e8..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/IndexProjectMeasuresStep.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program 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. - * - * This program 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.computation.task.projectanalysis.step; - -import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder; -import org.sonar.server.computation.task.step.ComputationStep; -import org.sonar.server.measure.index.ProjectMeasuresIndexer; - -public class IndexProjectMeasuresStep implements ComputationStep { - - private final ProjectMeasuresIndexer indexer; - private final TreeRootHolder treeRootHolder; - - public IndexProjectMeasuresStep(ProjectMeasuresIndexer indexer, TreeRootHolder treeRootHolder) { - this.indexer = indexer; - this.treeRootHolder = treeRootHolder; - } - - @Override - public void execute() { - indexer.index(treeRootHolder.getRoot().getUuid()); - } - - @Override - public String getDescription() { - return "Index project measures"; - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ReportComputationSteps.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ReportComputationSteps.java index 55b545800e0..bbde12089c3 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ReportComputationSteps.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ReportComputationSteps.java @@ -101,12 +101,7 @@ public class ReportComputationSteps extends AbstractComputationSteps { UpdateQualityProfilesLastUsedDateStep.class, PurgeDatastoresStep.class, - - // ES indexing is done after all db changes - IndexIssuesStep.class, - IndexTestsStep.class, - IndexProjectMeasuresStep.class, - IndexComponentsStep.class, + IndexAnalysisStep.class, // notifications are sent at the end, so that webapp displays up-to-date information SendIssueNotificationsStep.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/es/NewIndex.java b/server/sonar-server/src/main/java/org/sonar/server/es/NewIndex.java index 6f79667f99c..6ce26917840 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/es/NewIndex.java +++ b/server/sonar-server/src/main/java/org/sonar/server/es/NewIndex.java @@ -33,6 +33,7 @@ import org.apache.commons.lang.StringUtils; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.common.settings.Settings; import org.sonar.process.ProcessProperties; +import org.sonar.server.permission.index.AuthorizationTypeSupport; import static com.google.common.base.Preconditions.checkArgument; import static java.lang.String.format; @@ -67,7 +68,7 @@ public class NewIndex { } public NewIndexType createType(String typeName) { - NewIndexType type = new NewIndexType(typeName); + NewIndexType type = new NewIndexType(this, typeName); types.put(typeName, type); return type; } @@ -91,11 +92,13 @@ public class NewIndex { } public static class NewIndexType { + private final NewIndex index; private final String name; private final Map<String, Object> attributes = new TreeMap<>(); private final Map<String, Object> properties = new TreeMap<>(); - private NewIndexType(String typeName) { + private NewIndexType(NewIndex index, String typeName) { + this.index = index; this.name = typeName; // defaults attributes.put("dynamic", false); @@ -104,6 +107,15 @@ public class NewIndex { attributes.put("properties", properties); } + public NewIndexType requireProjectAuthorization() { + AuthorizationTypeSupport.enableProjectAuthorization(this); + return this; + } + + public NewIndex getIndex() { + return index; + } + public String getName() { return name; } diff --git a/server/sonar-server/src/main/java/org/sonar/server/es/ProjectIndexer.java b/server/sonar-server/src/main/java/org/sonar/server/es/ProjectIndexer.java new file mode 100644 index 00000000000..8afc2061c8e --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/es/ProjectIndexer.java @@ -0,0 +1,58 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.es; + +/** + * A {@link ProjectIndexer} populates an Elasticsearch index + * containing project-related documents, for instance issues + * or tests. This interface allows to quickly integrate new + * indices in the lifecycle of projects. + * + * If the related index handles verification of authorization, + * then the implementation of {@link ProjectIndexer} must + * also implement {@link org.sonar.server.permission.index.NeedAuthorizationIndexer} + */ +public interface ProjectIndexer { + + enum Cause { + PROJECT_CREATION, PROJECT_KEY_UPDATE, NEW_ANALYSIS + } + + /** + * This method is called when a project must be (re-)indexed, + * for example when project is created or when a new analysis + * is being processed. + * @param projectUuid non-null UUID of project + * @param cause the reason why indexing is triggered. That + * allows some implementations to ignore + * re-indexing in some cases. For example + * there is no need to index measures when + * a project is being created because they + * are not computed yet. + */ + void indexProject(String projectUuid, Cause cause); + + /** + * This method is called when a project is deleted. + * @param projectUuid non-null UUID of project + */ + void deleteProject(String projectUuid); + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQuery.java b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQuery.java index 711f73f3e53..923a52718eb 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQuery.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQuery.java @@ -28,10 +28,8 @@ import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.apache.commons.lang.builder.ReflectionToStringBuilder; import org.sonar.api.rule.RuleKey; -import org.sonar.server.user.UserSession; import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.collect.Sets.newHashSet; import static org.sonar.server.es.SearchOptions.MAX_LIMIT; /** @@ -82,9 +80,6 @@ public class IssueQuery { private final String sort; private final Boolean asc; private final String facetMode; - - private final Integer userId; - private final Set<String> userGroups; private final boolean checkAuthorization; private IssueQuery(Builder builder) { @@ -115,8 +110,6 @@ public class IssueQuery { this.createdBefore = builder.createdBefore; this.sort = builder.sort; this.asc = builder.asc; - this.userId = builder.userId; - this.userGroups = builder.userGroups; this.checkAuthorization = builder.checkAuthorization; this.facetMode = builder.facetMode; } @@ -245,15 +238,6 @@ public class IssueQuery { return asc; } - @CheckForNull - public Integer userId() { - return userId; - } - - public Set<String> userGroups() { - return newHashSet(defaultCollection(userGroups)); - } - public boolean checkAuthorization() { return checkAuthorization; } @@ -267,8 +251,8 @@ public class IssueQuery { return ReflectionToStringBuilder.toString(this); } - public static Builder builder(UserSession userSession) { - return new Builder(userSession); + public static Builder builder() { + return new Builder(); } public static class Builder { @@ -299,14 +283,11 @@ public class IssueQuery { private Date createdBefore; private String sort; private Boolean asc = false; - private Integer userId; - private Set<String> userGroups; private boolean checkAuthorization = true; private String facetMode; - private Builder(UserSession userSession) { - this.userId = userSession.getUserId(); - this.userGroups = userSession.getUserGroups(); + private Builder() { + } public Builder issueKeys(@Nullable Collection<String> l) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java index 47f32928990..76c3b257061 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java @@ -106,7 +106,7 @@ public class IssueQueryService { DbSession session = dbClient.openSession(false); try { - IssueQuery.Builder builder = IssueQuery.builder(userSession) + IssueQuery.Builder builder = IssueQuery.builder() .issueKeys(RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_ISSUES))) .severities(RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_SEVERITIES))) .statuses(RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_STATUSES))) @@ -179,7 +179,7 @@ public class IssueQueryService { public IssueQuery createFromRequest(SearchWsRequest request) { DbSession session = dbClient.openSession(false); try { - IssueQuery.Builder builder = IssueQuery.builder(userSession) + IssueQuery.Builder builder = IssueQuery.builder() .issueKeys(request.getIssues()) .severities(request.getSeverities()) .statuses(request.getStatuses()) diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java index 3be220a9cbe..ce44af415db 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java @@ -88,14 +88,14 @@ public class IssueService { * Search for all tags, whatever issue resolution or user access rights */ public List<String> listTags(@Nullable String textQuery, int pageSize) { - IssueQuery query = IssueQuery.builder(userSession) + IssueQuery query = IssueQuery.builder() .checkAuthorization(false) .build(); return issueIndex.listTags(query, textQuery, pageSize); } public List<String> listAuthors(@Nullable String textQuery, int pageSize) { - IssueQuery query = IssueQuery.builder(userSession) + IssueQuery query = IssueQuery.builder() .checkAuthorization(false) .build(); return issueIndex.listAuthors(query, textQuery, pageSize); 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 2c5a57b3f89..819858746d1 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 @@ -34,7 +34,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.Set; import java.util.SortedSet; import java.util.TimeZone; import java.util.regex.Pattern; @@ -75,13 +74,12 @@ import org.sonar.server.es.SearchOptions; import org.sonar.server.es.SearchResult; import org.sonar.server.es.Sorting; import org.sonar.server.es.StickyFacetBuilder; -import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.issue.IssueQuery; +import org.sonar.server.permission.index.AuthorizationTypeSupport; import org.sonar.server.rule.index.RuleIndexDefinition; import org.sonar.server.user.UserSession; import org.sonar.server.view.index.ViewIndexDefinition; -import static com.google.common.collect.Lists.newArrayList; import static java.lang.String.format; import static org.elasticsearch.index.query.QueryBuilders.boolQuery; import static org.elasticsearch.index.query.QueryBuilders.existsQuery; @@ -164,12 +162,14 @@ public class IssueIndex extends BaseIndex { private final Sorting sorting; private final System2 system; private final UserSession userSession; + private final AuthorizationTypeSupport authorizationTypeSupport; - public IssueIndex(EsClient client, System2 system, UserSession userSession) { + public IssueIndex(EsClient client, System2 system, UserSession userSession, AuthorizationTypeSupport authorizationTypeSupport) { super(client); this.system = system; this.userSession = userSession; + this.authorizationTypeSupport = authorizationTypeSupport; this.sorting = new Sorting(); this.sorting.add(IssueQuery.SORT_BY_ASSIGNEE, IssueIndexDefinition.FIELD_ISSUE_ASSIGNEE); this.sorting.add(IssueQuery.SORT_BY_STATUS, IssueIndexDefinition.FIELD_ISSUE_STATUS); @@ -191,31 +191,6 @@ public class IssueIndex extends BaseIndex { this.sorting.addDefault(IssueIndexDefinition.FIELD_ISSUE_KEY); } - /** - * Warning, this method is not efficient as routing (the project uuid) is not known. - * All the ES cluster nodes are involved. - */ - @CheckForNull - public IssueDoc getNullableByKey(String key) { - SearchResult<IssueDoc> result = search(IssueQuery.builder(userSession).issueKeys(newArrayList(key)).build(), new SearchOptions()); - if (result.getTotal() == 1) { - return result.getDocs().get(0); - } - return null; - } - - /** - * Warning, see {@link #getNullableByKey(String)}. - * A {@link org.sonar.server.exceptions.NotFoundException} is thrown if key does not exist. - */ - public IssueDoc getByKey(String key) { - IssueDoc value = getNullableByKey(key); - if (value == null) { - throw new NotFoundException(format("Issue with key '%s' does not exist", key)); - } - return value; - } - public SearchResult<IssueDoc> search(IssueQuery query, SearchOptions options) { SearchRequestBuilder requestBuilder = getClient() .prepareSearch(IssueIndexDefinition.INDEX) @@ -258,7 +233,7 @@ public class IssueIndex extends BaseIndex { private Map<String, QueryBuilder> createFilters(IssueQuery query) { Map<String, QueryBuilder> filters = new HashMap<>(); - filters.put("__authorization", createAuthorizationFilter(query.checkAuthorization(), query.userId(), query.userGroups())); + filters.put("__authorization", createAuthorizationFilter(query.checkAuthorization())); // Issue is assigned Filter if (BooleanUtils.isTrue(query.assigned())) { @@ -337,17 +312,9 @@ public class IssueIndex extends BaseIndex { return viewsFilter; } - private static QueryBuilder createAuthorizationFilter(boolean checkAuthorization, @Nullable Integer userId, Set<String> userGroups) { + private QueryBuilder createAuthorizationFilter(boolean checkAuthorization) { if (checkAuthorization) { - BoolQueryBuilder groupsAndUser = boolQuery(); - if (userId != null) { - groupsAndUser.should(termQuery(IssueIndexDefinition.FIELD_AUTHORIZATION_USERS, userId.longValue())); - } - for (String group : userGroups) { - groupsAndUser.should(termQuery(IssueIndexDefinition.FIELD_AUTHORIZATION_GROUPS, group)); - } - return QueryBuilders.hasParentQuery(IssueIndexDefinition.TYPE_AUTHORIZATION, - QueryBuilders.boolQuery().must(matchAllQuery()).filter(groupsAndUser)); + return authorizationTypeSupport.createQueryFilter(); } return matchAllQuery(); } @@ -693,7 +660,7 @@ public class IssueIndex extends BaseIndex { */ public Iterator<IssueDoc> selectIssuesForBatch(ComponentDto component) { BoolQueryBuilder filter = boolQuery() - .must(createAuthorizationFilter(true, userSession.getUserId(), userSession.getUserGroups())) + .must(createAuthorizationFilter(true)) .mustNot(termsQuery(IssueIndexDefinition.FIELD_ISSUE_STATUS, Issue.STATUS_CLOSED)); switch (component.scope()) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndexDefinition.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndexDefinition.java index 62cf97b41cd..b0ea37b0fb6 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndexDefinition.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndexDefinition.java @@ -19,7 +19,6 @@ */ package org.sonar.server.issue.index; -import com.google.common.collect.ImmutableMap; import org.sonar.api.config.Settings; import org.sonar.server.es.IndexDefinition; import org.sonar.server.es.NewIndex; @@ -31,14 +30,8 @@ public class IssueIndexDefinition implements IndexDefinition { public static final String INDEX = "issues"; - public static final String TYPE_AUTHORIZATION = "authorization"; public static final String TYPE_ISSUE = "issue"; - public static final String FIELD_AUTHORIZATION_PROJECT_UUID = "project"; - public static final String FIELD_AUTHORIZATION_GROUPS = "groupNames"; - public static final String FIELD_AUTHORIZATION_USERS = "users"; - public static final String FIELD_AUTHORIZATION_UPDATED_AT = "updatedAt"; - public static final String FIELD_ISSUE_ASSIGNEE = "assignee"; public static final String FIELD_ISSUE_ATTRIBUTES = "attributes"; public static final String FIELD_ISSUE_AUTHOR_LOGIN = "authorLogin"; @@ -93,45 +86,34 @@ public class IssueIndexDefinition implements IndexDefinition { index.refreshHandledByIndexer(); index.configureShards(settings, 5); - // type "issue" - NewIndex.NewIndexType issueMapping = index.createType(TYPE_ISSUE); - issueMapping.setAttribute("_parent", ImmutableMap.of("type", TYPE_AUTHORIZATION)); - issueMapping.setAttribute("_routing", ImmutableMap.of("required", "true")); - issueMapping.stringFieldBuilder(FIELD_ISSUE_ASSIGNEE).disableNorms().enableSorting().build(); - issueMapping.stringFieldBuilder(FIELD_ISSUE_ATTRIBUTES).disableNorms().disableSearch().build(); - issueMapping.stringFieldBuilder(FIELD_ISSUE_AUTHOR_LOGIN).disableNorms().build(); - issueMapping.stringFieldBuilder(FIELD_ISSUE_COMPONENT_UUID).disableNorms().build(); - issueMapping.createLongField(FIELD_ISSUE_EFFORT); - issueMapping.createDoubleField(FIELD_ISSUE_GAP); - issueMapping.stringFieldBuilder(FIELD_ISSUE_FILE_PATH).disableNorms().enableSorting().build(); - issueMapping.createDateTimeField(FIELD_ISSUE_FUNC_CREATED_AT); - issueMapping.createDateTimeField(FIELD_ISSUE_FUNC_UPDATED_AT); - issueMapping.createDateTimeField(FIELD_ISSUE_FUNC_CLOSED_AT); - issueMapping.stringFieldBuilder(FIELD_ISSUE_KEY).disableNorms().enableSorting().build(); - issueMapping.stringFieldBuilder(FIELD_ISSUE_LANGUAGE).disableNorms().build(); - issueMapping.createIntegerField(FIELD_ISSUE_LINE); - issueMapping.stringFieldBuilder(FIELD_ISSUE_MESSAGE).disableNorms().build(); - issueMapping.stringFieldBuilder(FIELD_ISSUE_MODULE_UUID).disableNorms().build(); - issueMapping.createUuidPathField(FIELD_ISSUE_MODULE_PATH); - issueMapping.stringFieldBuilder(FIELD_ISSUE_PROJECT_UUID).disableNorms().enableSorting().build(); - issueMapping.stringFieldBuilder(FIELD_ISSUE_DIRECTORY_PATH).disableNorms().build(); - issueMapping.stringFieldBuilder(FIELD_ISSUE_RESOLUTION).disableNorms().build(); - issueMapping.stringFieldBuilder(FIELD_ISSUE_RULE_KEY).disableNorms().build(); - issueMapping.stringFieldBuilder(FIELD_ISSUE_SEVERITY).disableNorms().build(); - issueMapping.createByteField(FIELD_ISSUE_SEVERITY_VALUE); - issueMapping.stringFieldBuilder(FIELD_ISSUE_STATUS).disableNorms().enableSorting().build(); - issueMapping.stringFieldBuilder(FIELD_ISSUE_TAGS).disableNorms().build(); - issueMapping.createDateTimeField(FIELD_ISSUE_TECHNICAL_UPDATED_AT); - issueMapping.stringFieldBuilder(FIELD_ISSUE_TYPE).disableNorms().build(); + NewIndex.NewIndexType type = index.createType(TYPE_ISSUE); + type.requireProjectAuthorization(); - // type "authorization" - NewIndex.NewIndexType authorizationMapping = index.createType(TYPE_AUTHORIZATION); - authorizationMapping.setAttribute("_routing", ImmutableMap.of("required", "true")); - authorizationMapping.createDateTimeField(FIELD_AUTHORIZATION_UPDATED_AT); - authorizationMapping.stringFieldBuilder(FIELD_AUTHORIZATION_PROJECT_UUID).disableNorms().build(); - authorizationMapping.stringFieldBuilder(FIELD_AUTHORIZATION_GROUPS).disableNorms().build(); - authorizationMapping.stringFieldBuilder(FIELD_AUTHORIZATION_USERS).disableNorms().build(); - // do not store document but only indexation of information - authorizationMapping.setEnableSource(false); + type.stringFieldBuilder(FIELD_ISSUE_ASSIGNEE).disableNorms().enableSorting().build(); + type.stringFieldBuilder(FIELD_ISSUE_ATTRIBUTES).disableNorms().disableSearch().build(); + type.stringFieldBuilder(FIELD_ISSUE_AUTHOR_LOGIN).disableNorms().build(); + type.stringFieldBuilder(FIELD_ISSUE_COMPONENT_UUID).disableNorms().build(); + type.createLongField(FIELD_ISSUE_EFFORT); + type.createDoubleField(FIELD_ISSUE_GAP); + type.stringFieldBuilder(FIELD_ISSUE_FILE_PATH).disableNorms().enableSorting().build(); + type.createDateTimeField(FIELD_ISSUE_FUNC_CREATED_AT); + type.createDateTimeField(FIELD_ISSUE_FUNC_UPDATED_AT); + type.createDateTimeField(FIELD_ISSUE_FUNC_CLOSED_AT); + type.stringFieldBuilder(FIELD_ISSUE_KEY).disableNorms().enableSorting().build(); + type.stringFieldBuilder(FIELD_ISSUE_LANGUAGE).disableNorms().build(); + type.createIntegerField(FIELD_ISSUE_LINE); + type.stringFieldBuilder(FIELD_ISSUE_MESSAGE).disableNorms().build(); + type.stringFieldBuilder(FIELD_ISSUE_MODULE_UUID).disableNorms().build(); + type.createUuidPathField(FIELD_ISSUE_MODULE_PATH); + type.stringFieldBuilder(FIELD_ISSUE_PROJECT_UUID).disableNorms().enableSorting().build(); + type.stringFieldBuilder(FIELD_ISSUE_DIRECTORY_PATH).disableNorms().build(); + type.stringFieldBuilder(FIELD_ISSUE_RESOLUTION).disableNorms().build(); + type.stringFieldBuilder(FIELD_ISSUE_RULE_KEY).disableNorms().build(); + type.stringFieldBuilder(FIELD_ISSUE_SEVERITY).disableNorms().build(); + type.createByteField(FIELD_ISSUE_SEVERITY_VALUE); + type.stringFieldBuilder(FIELD_ISSUE_STATUS).disableNorms().enableSorting().build(); + type.stringFieldBuilder(FIELD_ISSUE_TAGS).disableNorms().build(); + type.createDateTimeField(FIELD_ISSUE_TECHNICAL_UPDATED_AT); + type.stringFieldBuilder(FIELD_ISSUE_TYPE).disableNorms().build(); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndexer.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndexer.java index 7cf8322d315..67e8c731d49 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndexer.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndexer.java @@ -25,6 +25,7 @@ import javax.annotation.Nullable; import org.elasticsearch.action.bulk.BulkRequestBuilder; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.search.SearchRequestBuilder; +import org.sonar.api.resources.Qualifiers; import org.sonar.api.utils.System2; import org.sonar.db.DbClient; import org.sonar.db.DbSession; @@ -32,19 +33,22 @@ import org.sonar.server.es.BaseIndexer; import org.sonar.server.es.BulkIndexer; import org.sonar.server.es.EsClient; import org.sonar.server.es.EsUtils; +import org.sonar.server.es.ProjectIndexer; +import org.sonar.server.permission.index.AuthorizationScope; +import org.sonar.server.permission.index.NeedAuthorizationIndexer; import static org.elasticsearch.index.query.QueryBuilders.boolQuery; import static org.elasticsearch.index.query.QueryBuilders.termQuery; import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID; import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_TECHNICAL_UPDATED_AT; import static org.sonar.server.issue.index.IssueIndexDefinition.INDEX; -import static org.sonar.server.issue.index.IssueIndexDefinition.TYPE_AUTHORIZATION; import static org.sonar.server.issue.index.IssueIndexDefinition.TYPE_ISSUE; -public class IssueIndexer extends BaseIndexer { +public class IssueIndexer extends BaseIndexer implements ProjectIndexer, NeedAuthorizationIndexer { private static final String DELETE_ERROR_MESSAGE = "Fail to delete some issues of project [%s]"; private static final int MAX_BATCH_SIZE = 1000; + private static final AuthorizationScope AUTHORIZATION_SCOPE = new AuthorizationScope(INDEX, project -> Qualifiers.PROJECT.equals(project.getQualifier())); private final DbClient dbClient; @@ -54,6 +58,11 @@ public class IssueIndexer extends BaseIndexer { } @Override + public AuthorizationScope getAuthorizationScope() { + return AUTHORIZATION_SCOPE; + } + + @Override protected long doIndex(long lastUpdatedAt) { return doIndex(createBulkIndexer(false), lastUpdatedAt, null); } @@ -62,8 +71,22 @@ public class IssueIndexer extends BaseIndexer { doIndex(createBulkIndexer(true), 0L, null); } - public void index(String projectUuid) { - super.index(lastUpdatedAt -> doIndex(createBulkIndexer(false), lastUpdatedAt, projectUuid)); + @Override + public void indexProject(String projectUuid, Cause cause) { + switch (cause) { + case PROJECT_CREATION: + // nothing to do, issues do not exist at project creation + break; + case PROJECT_KEY_UPDATE: + // nothing to do, project key is not used in this index + break; + case NEW_ANALYSIS: + super.index(lastUpdatedAt -> doIndex(createBulkIndexer(false), lastUpdatedAt, projectUuid)); + break; + default: + // defensive case + throw new IllegalStateException("Unsupported cause: " + cause); + } } /** @@ -96,11 +119,12 @@ public class IssueIndexer extends BaseIndexer { return maxDate; } + @Override public void deleteProject(String uuid) { BulkIndexer bulk = new BulkIndexer(esClient, INDEX); bulk.start(); SearchRequestBuilder search = esClient.prepareSearch(INDEX) - .setTypes(TYPE_ISSUE, TYPE_AUTHORIZATION) + .setTypes(TYPE_ISSUE) .setRouting(uuid) .setQuery(boolQuery().must(termQuery(FIELD_ISSUE_PROJECT_UUID, uuid))); bulk.addDeletion(search); @@ -143,5 +167,4 @@ public class IssueIndexer extends BaseIndexer { .parent(projectUuid) .source(issue.getFields()); } - } diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndex.java b/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndex.java index 30817986b4c..2b8bd3cce39 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndex.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndex.java @@ -25,12 +25,10 @@ import com.google.common.collect.Multimap; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.stream.IntStream; 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.aggregations.AbstractAggregationBuilder; import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.aggregations.bucket.range.RangeBuilder; @@ -43,7 +41,7 @@ import org.sonar.server.es.SearchIdResult; import org.sonar.server.es.SearchOptions; import org.sonar.server.es.StickyFacetBuilder; import org.sonar.server.measure.index.ProjectMeasuresQuery.MetricCriterion; -import org.sonar.server.user.UserSession; +import org.sonar.server.permission.index.AuthorizationTypeSupport; import static org.elasticsearch.index.query.QueryBuilders.boolQuery; import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; @@ -59,15 +57,12 @@ import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY; import static org.sonar.api.measures.CoreMetrics.RELIABILITY_RATING_KEY; import static org.sonar.api.measures.CoreMetrics.SECURITY_RATING_KEY; import static org.sonar.api.measures.CoreMetrics.SQALE_RATING_KEY; -import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_AUTHORIZATION_GROUPS; -import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_AUTHORIZATION_USERS; import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_MEASURES; import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_MEASURES_KEY; import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_MEASURES_VALUE; import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_NAME; import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_QUALITY_GATE; import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES; -import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.TYPE_AUTHORIZATION; import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.TYPE_PROJECT_MEASURE; public class ProjectMeasuresIndex extends BaseIndex { @@ -84,11 +79,11 @@ 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; - private final UserSession userSession; + private final AuthorizationTypeSupport authorizationTypeSupport; - public ProjectMeasuresIndex(EsClient client, UserSession userSession) { + public ProjectMeasuresIndex(EsClient client, AuthorizationTypeSupport authorizationTypeSupport) { super(client); - this.userSession = userSession; + this.authorizationTypeSupport = authorizationTypeSupport; } public SearchIdResult<String> search(ProjectMeasuresQuery query, SearchOptions searchOptions) { @@ -200,7 +195,7 @@ public class ProjectMeasuresIndex extends BaseIndex { private Map<String, QueryBuilder> createFilters(ProjectMeasuresQuery query) { Map<String, QueryBuilder> filters = new HashMap<>(); - filters.put("__authorization", createAuthorizationFilter()); + filters.put("__authorization", authorizationTypeSupport.createQueryFilter()); Multimap<String, MetricCriterion> metricCriterionMultimap = ArrayListMultimap.create(); query.getMetricCriteria().forEach(metricCriterion -> metricCriterionMultimap.put(metricCriterion.getMetricKey(), metricCriterion)); metricCriterionMultimap.asMap().entrySet().forEach(entry -> { @@ -242,17 +237,4 @@ public class ProjectMeasuresIndex extends BaseIndex { } } - private QueryBuilder createAuthorizationFilter() { - Integer userLogin = userSession.getUserId(); - Set<String> userGroupNames = userSession.getUserGroups(); - BoolQueryBuilder groupsAndUser = boolQuery(); - if (userLogin != null) { - groupsAndUser.should(termQuery(FIELD_AUTHORIZATION_USERS, userLogin.longValue())); - } - 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/main/java/org/sonar/server/measure/index/ProjectMeasuresIndexDefinition.java b/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndexDefinition.java index b0686cf6d67..83ee462369b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndexDefinition.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndexDefinition.java @@ -19,7 +19,6 @@ */ package org.sonar.server.measure.index; -import com.google.common.collect.ImmutableMap; import org.sonar.api.config.Settings; import org.sonar.server.es.IndexDefinition; import org.sonar.server.es.NewIndex; @@ -37,12 +36,6 @@ public class ProjectMeasuresIndexDefinition implements IndexDefinition { public static final String FIELD_MEASURES_KEY = "key"; public static final String FIELD_MEASURES_VALUE = "value"; - public static final String TYPE_AUTHORIZATION = "authorization"; - public static final String FIELD_AUTHORIZATION_PROJECT_UUID = "project"; - public static final String FIELD_AUTHORIZATION_GROUPS = "groupNames"; - public static final String FIELD_AUTHORIZATION_USERS = "users"; - public static final String FIELD_AUTHORIZATION_UPDATED_AT = "updatedAt"; - private final Settings settings; public ProjectMeasuresIndexDefinition(Settings settings) { @@ -55,10 +48,9 @@ public class ProjectMeasuresIndexDefinition implements IndexDefinition { index.refreshHandledByIndexer(); index.configureShards(settings, 5); - // type "projectmeasures" - NewIndex.NewIndexType mapping = index.createType(TYPE_PROJECT_MEASURE); - mapping.setAttribute("_parent", ImmutableMap.of("type", TYPE_AUTHORIZATION)); - mapping.setAttribute("_routing", ImmutableMap.of("required", "true")); + NewIndex.NewIndexType mapping = index.createType(TYPE_PROJECT_MEASURE) + .requireProjectAuthorization(); + mapping.stringFieldBuilder(FIELD_KEY).disableNorms().build(); mapping.stringFieldBuilder(FIELD_NAME).enableSorting().build(); mapping.stringFieldBuilder(FIELD_QUALITY_GATE).build(); @@ -67,17 +59,6 @@ public class ProjectMeasuresIndexDefinition implements IndexDefinition { .addStringFied(FIELD_MEASURES_KEY) .addDoubleField(FIELD_MEASURES_VALUE) .build(); - - // do not store document but only indexation of information mapping.setEnableSource(false); - - // type "authorization" - NewIndex.NewIndexType authorizationMapping = index.createType(TYPE_AUTHORIZATION); - authorizationMapping.setAttribute("_routing", ImmutableMap.of("required", "true")); - authorizationMapping.createDateTimeField(FIELD_AUTHORIZATION_UPDATED_AT); - authorizationMapping.stringFieldBuilder(FIELD_AUTHORIZATION_PROJECT_UUID).disableNorms().build(); - authorizationMapping.stringFieldBuilder(FIELD_AUTHORIZATION_GROUPS).disableNorms().build(); - authorizationMapping.stringFieldBuilder(FIELD_AUTHORIZATION_USERS).disableNorms().build(); - authorizationMapping.setEnableSource(false); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndexer.java b/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndexer.java index 78ed7906c4a..9309f5ac03e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndexer.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndexer.java @@ -24,6 +24,7 @@ import java.util.Date; import java.util.Iterator; import javax.annotation.Nullable; import org.elasticsearch.action.index.IndexRequest; +import org.sonar.api.resources.Qualifiers; import org.sonar.api.utils.System2; import org.sonar.db.DbClient; import org.sonar.db.DbSession; @@ -32,13 +33,17 @@ import org.sonar.db.measure.ProjectMeasuresIndexerIterator.ProjectMeasures; import org.sonar.server.es.BaseIndexer; import org.sonar.server.es.BulkIndexer; import org.sonar.server.es.EsClient; +import org.sonar.server.es.ProjectIndexer; +import org.sonar.server.permission.index.AuthorizationScope; +import org.sonar.server.permission.index.NeedAuthorizationIndexer; import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_ANALYSED_AT; import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES; -import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.TYPE_AUTHORIZATION; import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.TYPE_PROJECT_MEASURE; -public class ProjectMeasuresIndexer extends BaseIndexer { +public class ProjectMeasuresIndexer extends BaseIndexer implements ProjectIndexer, NeedAuthorizationIndexer { + + private static final AuthorizationScope AUTHORIZATION_SCOPE = new AuthorizationScope(INDEX_PROJECT_MEASURES, project -> Qualifiers.PROJECT.equals(project.getQualifier())); private final DbClient dbClient; @@ -48,25 +53,38 @@ public class ProjectMeasuresIndexer extends BaseIndexer { } @Override + public AuthorizationScope getAuthorizationScope() { + return AUTHORIZATION_SCOPE; + } + + @Override protected long doIndex(long lastUpdatedAt) { return doIndex(createBulkIndexer(false), lastUpdatedAt, null); } - public void index(String projectUuid) { - doIndex(createBulkIndexer(false), 0L, projectUuid); + @Override + public void indexProject(String projectUuid, Cause cause) { + switch (cause) { + case PROJECT_KEY_UPDATE: + // project must be re-indexed because key is used in this index + case PROJECT_CREATION: + // provisioned projects are supported by WS api/components/search_projects + case NEW_ANALYSIS: + doIndex(createBulkIndexer(false), 0L, projectUuid); + break; + default: + // defensive case + throw new IllegalStateException("Unsupported cause: " + cause); + } } + @Override public void deleteProject(String uuid) { esClient .prepareDelete(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURE, uuid) .setRouting(uuid) .setRefresh(true) .get(); - esClient - .prepareDelete(INDEX_PROJECT_MEASURES, TYPE_AUTHORIZATION, uuid) - .setRouting(uuid) - .setRefresh(true) - .get(); } private long doIndex(BulkIndexer bulk, long lastUpdatedAt, @Nullable String projectUuid) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionTemplateService.java b/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionTemplateService.java index 507e1df05d3..cac9319c624 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionTemplateService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionTemplateService.java @@ -150,7 +150,7 @@ public class PermissionTemplateService { } private void indexProjectPermissions(DbSession dbSession, List<String> projectOrViewUuids) { - permissionIndexer.index(dbSession, projectOrViewUuids); + permissionIndexer.indexProjectsByUuids(dbSession, projectOrViewUuids); } private void copyPermissions(DbSession dbSession, PermissionTemplateDto template, ComponentDto project, @Nullable Long projectCreatorUserId) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionUpdater.java b/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionUpdater.java index 0da2f221d7e..73a389ac926 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionUpdater.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionUpdater.java @@ -66,7 +66,7 @@ public class PermissionUpdater { dbSession.commit(); if (!projectIds.isEmpty()) { - permissionIndexer.index(dbSession, projectOrViewUuids); + permissionIndexer.indexProjectsByUuids(dbSession, projectOrViewUuids); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/index/AuthorizationScope.java b/server/sonar-server/src/main/java/org/sonar/server/permission/index/AuthorizationScope.java new file mode 100644 index 00000000000..bec8f0c4a68 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/index/AuthorizationScope.java @@ -0,0 +1,51 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.permission.index; + +import java.util.function.Predicate; +import javax.annotation.concurrent.Immutable; + +import static java.util.Objects.requireNonNull; + +@Immutable +public final class AuthorizationScope { + private final String indexName; + private final Predicate<PermissionIndexerDao.Dto> projectPredicate; + + public AuthorizationScope(String indexName, Predicate<PermissionIndexerDao.Dto> projectPredicate) { + this.indexName = requireNonNull(indexName); + this.projectPredicate = requireNonNull(projectPredicate); + } + + /** + * Name of the index containing a type named {@link AuthorizationTypeSupport#TYPE_AUTHORIZATION}. + */ + public String getIndexName() { + return indexName; + } + + /** + * Predicates that filters the projects to be involved in + * authorization. + */ + public Predicate<PermissionIndexerDao.Dto> getProjectPredicate() { + return projectPredicate; + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/index/AuthorizationTypeSupport.java b/server/sonar-server/src/main/java/org/sonar/server/permission/index/AuthorizationTypeSupport.java new file mode 100644 index 00000000000..1ae73cab55c --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/index/AuthorizationTypeSupport.java @@ -0,0 +1,95 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.permission.index; + +import com.google.common.collect.ImmutableMap; +import java.util.Optional; +import java.util.Set; +import org.elasticsearch.index.query.BoolQueryBuilder; +import org.elasticsearch.index.query.QueryBuilder; +import org.elasticsearch.index.query.QueryBuilders; +import org.sonar.api.ce.ComputeEngineSide; +import org.sonar.api.server.ServerSide; +import org.sonar.server.es.NewIndex; +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.termQuery; + +@ServerSide +@ComputeEngineSide +public class AuthorizationTypeSupport { + + public static final String TYPE_AUTHORIZATION = "authorization"; + public static final String FIELD_GROUP_NAMES = "groupNames"; + public static final String FIELD_USER_LOGINS = "users"; + public static final String FIELD_UPDATED_AT = "updatedAt"; + + private final UserSession userSession; + + public AuthorizationTypeSupport(UserSession userSession) { + this.userSession = userSession; + } + + /** + * Creates a type that requires to verify that user has the read permission + * when searching for documents. + * It relies on a parent type named "authorization" that is automatically + * populated by {@link org.sonar.server.permission.index.PermissionIndexer}. + * + * Both types {@code typeName} and "authorization" are created. Documents + * must be created with _parent and _routing having the parent uuid as values. + * + * @see NewIndex.NewIndexType#requireProjectAuthorization() + */ + public static NewIndex.NewIndexType enableProjectAuthorization(NewIndex.NewIndexType type) { + type.setAttribute("_parent", ImmutableMap.of("type", TYPE_AUTHORIZATION)); + type.setAttribute("_routing", ImmutableMap.of("required", true)); + + NewIndex.NewIndexType authType = type.getIndex().createType(TYPE_AUTHORIZATION); + authType.setAttribute("_routing", ImmutableMap.of("required", true)); + authType.createDateTimeField(FIELD_UPDATED_AT); + authType.stringFieldBuilder(FIELD_GROUP_NAMES).disableNorms().build(); + authType.stringFieldBuilder(FIELD_USER_LOGINS).disableNorms().build(); + authType.setEnableSource(false); + return type; + } + + /** + * Build a filter to restrict query to the documents on which + * user has read access. + */ + public QueryBuilder createQueryFilter() { + Integer userLogin = userSession.getUserId(); + Set<String> userGroupNames = userSession.getUserGroups(); + BoolQueryBuilder groupsAndUser = boolQuery(); + + Optional.ofNullable(userLogin) + .map(Integer::longValue) + .ifPresent(userId -> groupsAndUser.should(termQuery(FIELD_USER_LOGINS, userId))); + + userGroupNames + .forEach(group -> groupsAndUser.should(termQuery(FIELD_GROUP_NAMES, group))); + + return QueryBuilders.hasParentQuery(TYPE_AUTHORIZATION, + QueryBuilders.boolQuery().must(matchAllQuery()).filter(groupsAndUser)); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueAuthorizationDoc.java b/server/sonar-server/src/main/java/org/sonar/server/permission/index/NeedAuthorizationIndexer.java index e1c33c81c04..9f3e5f6d967 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueAuthorizationDoc.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/index/NeedAuthorizationIndexer.java @@ -17,38 +17,20 @@ * 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.issue.index; +package org.sonar.server.permission.index; -import com.google.common.collect.Maps; -import org.sonar.server.es.BaseDoc; - -public class IssueAuthorizationDoc extends BaseDoc { - - public IssueAuthorizationDoc() { - super(Maps.newHashMap()); - } - - @Override - public String getId() { - return projectUuid(); - } - - @Override - public String getRouting() { - return projectUuid(); - } - - @Override - public String getParent() { - return null; - } +/** + * An {@link NeedAuthorizationIndexer} defines how + * a {@link org.sonar.server.es.ProjectIndexer} populates + * the type named {@link AuthorizationTypeSupport#TYPE_AUTHORIZATION}, which + * is used to verify that a user can access to projects. + */ +public interface NeedAuthorizationIndexer { - public String projectUuid() { - return getField(IssueIndexDefinition.FIELD_AUTHORIZATION_PROJECT_UUID); - } + /** + * Returns the metadata required by {@link PermissionIndexer} to + * populate "authorization" types. + */ + AuthorizationScope getAuthorizationScope(); - public IssueAuthorizationDoc setProjectUuid(String s) { - setField(IssueIndexDefinition.FIELD_AUTHORIZATION_PROJECT_UUID, s); - return this; - } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/index/PermissionIndexer.java b/server/sonar-server/src/main/java/org/sonar/server/permission/index/PermissionIndexer.java index 0d4231cd28e..bb0d717aa0e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/index/PermissionIndexer.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/index/PermissionIndexer.java @@ -23,11 +23,11 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Throwables; import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.Uninterruptibles; +import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; @@ -37,19 +37,17 @@ import org.elasticsearch.action.bulk.BulkRequestBuilder; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.search.SearchResponse; import org.picocontainer.Startable; -import org.sonar.api.resources.Qualifiers; +import org.sonar.core.util.stream.Collectors; import org.sonar.db.DbClient; import org.sonar.db.DbSession; -import org.sonar.server.component.index.ComponentIndexDefinition; import org.sonar.server.es.BulkIndexer; import org.sonar.server.es.EsClient; import org.sonar.server.es.EsUtils; -import org.sonar.server.issue.index.IssueIndexDefinition; -import org.sonar.server.measure.index.ProjectMeasuresIndexDefinition; +import org.sonar.server.es.ProjectIndexer; import static com.google.common.base.Preconditions.checkArgument; -import static java.util.Collections.singletonList; import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; +import static org.sonar.server.permission.index.AuthorizationTypeSupport.TYPE_AUTHORIZATION; /** * Manages the synchronization of indexes with authorization settings defined in database: @@ -58,153 +56,130 @@ import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; * <li>delete project orphans from index</li> * </ul> */ -public class PermissionIndexer implements Startable { +public class PermissionIndexer implements ProjectIndexer, Startable { - private static final int MAX_BATCH_SIZE = 1000; + @VisibleForTesting + static final int MAX_BATCH_SIZE = 1000; private static final String BULK_ERROR_MESSAGE = "Fail to index authorization"; private final ThreadPoolExecutor executor; private final DbClient dbClient; private final EsClient esClient; + private final List<AuthorizationScope> authorizationScopes; + + public PermissionIndexer(DbClient dbClient, EsClient esClient, NeedAuthorizationIndexer[] needAuthorizationIndexers) { + this(dbClient, esClient, Arrays.stream(needAuthorizationIndexers) + .map(NeedAuthorizationIndexer::getAuthorizationScope) + .collect(Collectors.toList(needAuthorizationIndexers.length))); + } - public PermissionIndexer(DbClient dbClient, EsClient esClient) { + @VisibleForTesting + public PermissionIndexer(DbClient dbClient, EsClient esClient, List<AuthorizationScope> authorizationScopes) { this.executor = new ThreadPoolExecutor(0, 1, 0L, TimeUnit.SECONDS, new LinkedBlockingQueue<>()); this.dbClient = dbClient; this.esClient = esClient; + this.authorizationScopes = authorizationScopes; } - /** - * Index issues authorization and project measures authorization indexes only when they are empty - */ public void indexAllIfEmpty() { - Future submit = executor.submit(() -> { - if (isIndexEmpty(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION) || - isIndexEmpty(ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES, ProjectMeasuresIndexDefinition.TYPE_AUTHORIZATION) || - isIndexEmpty(ComponentIndexDefinition.INDEX_COMPONENTS, ComponentIndexDefinition.TYPE_AUTHORIZATION)) { - truncate(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION); - truncate(ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES, ProjectMeasuresIndexDefinition.TYPE_AUTHORIZATION); - truncate(ComponentIndexDefinition.INDEX_COMPONENTS, ComponentIndexDefinition.TYPE_AUTHORIZATION); + boolean isEmpty = false; + for (AuthorizationScope scope : authorizationScopes) { + isEmpty |= isAuthorizationTypeEmpty(scope.getIndexName()); + } + + if (isEmpty) { + Future submit = executor.submit(() -> { + + authorizationScopes.forEach(scope -> truncateAuthorizationType(scope.getIndexName())); + try (DbSession dbSession = dbClient.openSession(false)) { index(new PermissionIndexerDao().selectAll(dbClient, dbSession)); } + }); + try { + Uninterruptibles.getUninterruptibly(submit); + } catch (ExecutionException e) { + Throwables.propagate(e); } - }); - try { - Uninterruptibles.getUninterruptibly(submit); - } catch (ExecutionException e) { - Throwables.propagate(e); } } - private boolean isIndexEmpty(String index, String type) { - SearchResponse issuesAuthorizationResponse = esClient.prepareSearch(index).setTypes(type).setSize(0).get(); - return issuesAuthorizationResponse.getHits().getTotalHits() == 0; + public void indexProjectsByUuids(DbSession dbSession, List<String> viewOrProjectUuids) { + checkArgument(!viewOrProjectUuids.isEmpty(), "viewOrProjectUuids cannot be empty"); + PermissionIndexerDao dao = new PermissionIndexerDao(); + index(dao.selectByUuids(dbClient, dbSession, viewOrProjectUuids)); + } + + @Override + public void indexProject(String projectUuid, Cause cause) { + switch (cause) { + case PROJECT_CREATION: + // nothing to do, permissions are indexed explicitly + // when permission template is applied after project creation + case NEW_ANALYSIS: + // nothing to do, permissions don't change during an analysis + case PROJECT_KEY_UPDATE: + // nothing to do, key is not used in this index + break; + default: + // defensive case + throw new IllegalStateException("Unsupported cause: " + cause); + } + } + + @Override + public void deleteProject(String projectUuid) { + authorizationScopes.forEach(scope -> esClient + .prepareDelete(scope.getIndexName(), TYPE_AUTHORIZATION, projectUuid) + .setRouting(projectUuid) + .setRefresh(true) + .get()); } - private void truncate(String index, String type) { - BulkIndexer.delete(esClient, index, esClient.prepareSearch(index).setTypes(type).setQuery(matchAllQuery())); + private boolean isAuthorizationTypeEmpty(String index) { + SearchResponse response = esClient.prepareSearch(index).setTypes(TYPE_AUTHORIZATION).setSize(0).get(); + return response.getHits().getTotalHits() == 0; } - public void index(DbSession dbSession, List<String> viewOrProjectUuids) { - checkArgument(!viewOrProjectUuids.isEmpty(), "viewOrProjectUuids cannot be empty"); - PermissionIndexerDao dao = new PermissionIndexerDao(); - index(dao.selectByUuids(dbClient, dbSession, viewOrProjectUuids)); + private void truncateAuthorizationType(String index) { + BulkIndexer.delete(esClient, index, esClient.prepareSearch(index).setTypes(TYPE_AUTHORIZATION).setQuery(matchAllQuery())); } - private void index(Collection<PermissionIndexerDao.Dto> authorizations) { + @VisibleForTesting + void index(Collection<PermissionIndexerDao.Dto> authorizations) { if (authorizations.isEmpty()) { return; } int count = 0; BulkRequestBuilder bulkRequest = esClient.prepareBulk().setRefresh(false); for (PermissionIndexerDao.Dto dto : authorizations) { - newIssuesAuthorizationIndexRequest(dto).ifPresent(bulkRequest::add); - newProjectMeasuresAuthorizationIndexRequest(dto).ifPresent(bulkRequest::add); - newComponentsAuthorizationIndexRequest(dto).ifPresent(bulkRequest::add); - count++; + for (AuthorizationScope scope : authorizationScopes) { + if (scope.getProjectPredicate().test(dto)) { + bulkRequest.add(newIndexRequest(dto, scope.getIndexName())); + count++; + } + } if (count >= MAX_BATCH_SIZE) { EsUtils.executeBulkRequest(bulkRequest, BULK_ERROR_MESSAGE); bulkRequest = esClient.prepareBulk().setRefresh(false); count = 0; } } - EsUtils.executeBulkRequest(bulkRequest, BULK_ERROR_MESSAGE); - esClient.prepareRefresh(IssueIndexDefinition.INDEX).get(); - esClient.prepareRefresh(ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES).get(); - esClient.prepareRefresh(ComponentIndexDefinition.INDEX_COMPONENTS).get(); - } - - public void index(DbSession dbSession, String viewOrProjectUuid) { - PermissionIndexerDao dao = new PermissionIndexerDao(); - List<PermissionIndexerDao.Dto> dtos = dao.selectByUuids(dbClient, dbSession, singletonList(viewOrProjectUuid)); - if (dtos.size() == 1) { - index(dtos.get(0)); - } - } - - @VisibleForTesting - void index(PermissionIndexerDao.Dto dto) { - newIssuesAuthorizationIndexRequest(dto) - .ifPresent(rqst -> index(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION, rqst)); - newProjectMeasuresAuthorizationIndexRequest(dto) - .ifPresent(rqst -> index(ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES, ProjectMeasuresIndexDefinition.TYPE_AUTHORIZATION, rqst)); - newComponentsAuthorizationIndexRequest(dto) - .ifPresent(rqst -> index(ComponentIndexDefinition.INDEX_COMPONENTS, ComponentIndexDefinition.TYPE_AUTHORIZATION, rqst)); - } - - private void index(String index, String type, IndexRequest indexRequest) { - esClient.prepareIndex(index, type) - .setId(indexRequest.id()) - .setRouting(indexRequest.routing()) - .setSource(indexRequest.source()) - .setRefresh(true) - .get(); - } - - private static Optional<IndexRequest> newIssuesAuthorizationIndexRequest(PermissionIndexerDao.Dto dto) { - if (!isProject(dto)) { - return Optional.empty(); - } - Map<String, Object> doc = ImmutableMap.of( - IssueIndexDefinition.FIELD_AUTHORIZATION_PROJECT_UUID, dto.getProjectUuid(), - IssueIndexDefinition.FIELD_AUTHORIZATION_GROUPS, dto.getGroups(), - IssueIndexDefinition.FIELD_AUTHORIZATION_USERS, dto.getUsers(), - IssueIndexDefinition.FIELD_AUTHORIZATION_UPDATED_AT, new Date(dto.getUpdatedAt())); - return Optional.of( - new IndexRequest(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION, dto.getProjectUuid()) - .routing(dto.getProjectUuid()) - .source(doc)); - } - - private static Optional<IndexRequest> newProjectMeasuresAuthorizationIndexRequest(PermissionIndexerDao.Dto dto) { - if (!isProject(dto)) { - return Optional.empty(); + if (count > 0) { + EsUtils.executeBulkRequest(bulkRequest, BULK_ERROR_MESSAGE); } - Map<String, Object> doc = ImmutableMap.of( - ProjectMeasuresIndexDefinition.FIELD_AUTHORIZATION_PROJECT_UUID, dto.getProjectUuid(), - ProjectMeasuresIndexDefinition.FIELD_AUTHORIZATION_GROUPS, dto.getGroups(), - ProjectMeasuresIndexDefinition.FIELD_AUTHORIZATION_USERS, dto.getUsers(), - ProjectMeasuresIndexDefinition.FIELD_AUTHORIZATION_UPDATED_AT, new Date(dto.getUpdatedAt())); - return Optional.of( - new IndexRequest(ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES, ProjectMeasuresIndexDefinition.TYPE_AUTHORIZATION, dto.getProjectUuid()) - .routing(dto.getProjectUuid()) - .source(doc)); + authorizationScopes.forEach(type -> esClient.prepareRefresh(type.getIndexName()).get()); } - private static Optional<IndexRequest> newComponentsAuthorizationIndexRequest(PermissionIndexerDao.Dto dto) { + private static IndexRequest newIndexRequest(PermissionIndexerDao.Dto dto, String indexName) { Map<String, Object> doc = ImmutableMap.of( - ComponentIndexDefinition.FIELD_AUTHORIZATION_GROUPS, dto.getGroups(), - ComponentIndexDefinition.FIELD_AUTHORIZATION_USERS, dto.getUsers(), - ComponentIndexDefinition.FIELD_AUTHORIZATION_UPDATED_AT, new Date(dto.getUpdatedAt())); - return Optional.of( - new IndexRequest(ComponentIndexDefinition.INDEX_COMPONENTS, ComponentIndexDefinition.TYPE_AUTHORIZATION, dto.getProjectUuid()) - .routing(dto.getProjectUuid()) - .source(doc)); - } - - private static boolean isProject(PermissionIndexerDao.Dto dto) { - return dto.getQualifier().equals(Qualifiers.PROJECT); + AuthorizationTypeSupport.FIELD_GROUP_NAMES, dto.getGroups(), + AuthorizationTypeSupport.FIELD_USER_LOGINS, dto.getUsers(), + AuthorizationTypeSupport.FIELD_UPDATED_AT, new Date(dto.getUpdatedAt())); + return new IndexRequest(indexName, TYPE_AUTHORIZATION, dto.getProjectUuid()) + .routing(dto.getProjectUuid()) + .source(doc); } @Override diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ws/DeleteAction.java b/server/sonar-server/src/main/java/org/sonar/server/project/ws/DeleteAction.java index 7c7dd96e162..607e13722c8 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/project/ws/DeleteAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/project/ws/DeleteAction.java @@ -19,7 +19,6 @@ */ package org.sonar.server.project.ws; -import java.util.Arrays; import javax.annotation.Nullable; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; @@ -28,7 +27,6 @@ import org.sonar.api.web.UserRole; import org.sonar.core.permission.GlobalPermissions; import org.sonar.db.DbClient; import org.sonar.db.DbSession; -import org.sonar.db.MyBatis; import org.sonar.db.component.ComponentDto; import org.sonar.server.component.ComponentCleanerService; import org.sonar.server.component.ComponentFinder; @@ -81,12 +79,9 @@ public class DeleteAction implements ProjectsWsAction { String key = request.param(PARAM_KEY); checkPermissions(uuid, key); - DbSession dbSession = dbClient.openSession(false); - try { + try (DbSession dbSession = dbClient.openSession(false)) { ComponentDto project = componentFinder.getByUuidOrKey(dbSession, uuid, key, ID_AND_KEY); - componentCleanerService.delete(dbSession, Arrays.asList(project)); - } finally { - MyBatis.closeQuietly(dbSession); + componentCleanerService.delete(dbSession, project); } response.noContent(); diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/EsSearchModule.java b/server/sonar-server/src/main/java/org/sonar/server/search/EsSearchModule.java index 47d0b63dec8..7a8601000f9 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/search/EsSearchModule.java +++ b/server/sonar-server/src/main/java/org/sonar/server/search/EsSearchModule.java @@ -22,10 +22,12 @@ package org.sonar.server.search; import org.sonar.core.platform.Module; import org.sonar.server.es.EsClientProvider; import org.sonar.server.es.EsClientStopper; +import org.sonar.server.permission.index.AuthorizationTypeSupport; public class EsSearchModule extends Module { @Override protected void configureModule() { + add(AuthorizationTypeSupport.class); add(new EsClientProvider()); add(EsClientStopper.class); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/test/index/TestIndexer.java b/server/sonar-server/src/main/java/org/sonar/server/test/index/TestIndexer.java index 6ac3d86d8f2..81decd148ec 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/test/index/TestIndexer.java +++ b/server/sonar-server/src/main/java/org/sonar/server/test/index/TestIndexer.java @@ -29,6 +29,7 @@ import org.sonar.db.DbSession; import org.sonar.server.es.BaseIndexer; import org.sonar.server.es.BulkIndexer; import org.sonar.server.es.EsClient; +import org.sonar.server.es.ProjectIndexer; import org.sonar.server.source.index.FileSourcesUpdaterHelper; import static org.sonar.server.test.index.TestIndexDefinition.FIELD_FILE_UUID; @@ -40,7 +41,7 @@ import static org.sonar.server.test.index.TestIndexDefinition.TYPE; * Add to Elasticsearch index {@link TestIndexDefinition} the rows of * db table FILE_SOURCES of type TEST that are not indexed yet */ -public class TestIndexer extends BaseIndexer { +public class TestIndexer extends BaseIndexer implements ProjectIndexer { private final DbClient dbClient; @@ -49,9 +50,23 @@ public class TestIndexer extends BaseIndexer { this.dbClient = dbClient; } - public void index(final String projectUuid) { - deleteByProject(projectUuid); - super.index(lastUpdatedAt -> doIndex(lastUpdatedAt, projectUuid)); + @Override + public void indexProject(String projectUuid, Cause cause) { + switch (cause) { + case PROJECT_CREATION: + // no need to index, not tests at that time + break; + case PROJECT_KEY_UPDATE: + // no need to index, project key is not used + break; + case NEW_ANALYSIS: + deleteProject(projectUuid); + super.index(lastUpdatedAt -> doIndex(lastUpdatedAt, projectUuid)); + break; + default: + // defensive case + throw new IllegalStateException("Unsupported cause: " + cause); + } } public long index(Iterator<FileSourcesUpdaterHelper.Row> dbRows) { @@ -99,7 +114,8 @@ public class TestIndexer extends BaseIndexer { BulkIndexer.delete(esClient, INDEX, searchRequest); } - public void deleteByProject(String projectUuid) { + @Override + public void deleteProject(String projectUuid) { SearchRequestBuilder searchRequest = esClient.prepareSearch(INDEX) .setRouting(projectUuid) .setTypes(TYPE) diff --git a/server/sonar-server/src/test/java/org/sonar/server/batch/IssuesActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/batch/IssuesActionTest.java index 56da3266a7d..8de59281628 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/batch/IssuesActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/batch/IssuesActionTest.java @@ -27,6 +27,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonar.api.config.MapSettings; +import org.sonar.api.resources.Qualifiers; import org.sonar.api.security.DefaultGroups; import org.sonar.api.utils.System2; import org.sonar.api.web.UserRole; @@ -44,12 +45,13 @@ import org.sonar.server.issue.index.IssueDoc; import org.sonar.server.issue.index.IssueIndex; import org.sonar.server.issue.index.IssueIndexDefinition; import org.sonar.server.issue.index.IssueIndexer; +import org.sonar.server.permission.index.AuthorizationTypeSupport; +import org.sonar.server.permission.index.PermissionIndexerDao; import org.sonar.server.permission.index.PermissionIndexerTester; import org.sonar.server.platform.ServerFileSystem; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.WsTester; -import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -76,19 +78,15 @@ public class IssuesActionTest { @Rule public UserSessionRule userSessionRule = UserSessionRule.standalone(); - private IssueIndex issueIndex; - private IssueIndexer issueIndexer; - private PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(es); + private IssueIndexer issueIndexer = new IssueIndexer(system2, db.getDbClient(), es.client()); + private PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(es, issueIndexer); private ServerFileSystem fs = mock(ServerFileSystem.class); private WsTester tester; - private IssuesAction issuesAction; @Before public void before() { - issueIndex = new IssueIndex(es.client(), system2, userSessionRule); - issueIndexer = new IssueIndexer(system2, null, es.client()); - issuesAction = new IssuesAction(db.getDbClient(), issueIndex, userSessionRule, new ComponentFinder(db.getDbClient())); - + IssueIndex issueIndex = new IssueIndex(es.client(), system2, userSessionRule, new AuthorizationTypeSupport(userSessionRule)); + IssuesAction issuesAction = new IssuesAction(db.getDbClient(), issueIndex, userSessionRule, new ComponentFinder(db.getDbClient())); tester = new WsTester(new BatchWs(new BatchIndex(fs), issuesAction)); } @@ -328,7 +326,14 @@ public class IssuesActionTest { } private void addIssueAuthorization(String projectUuid, @Nullable String group, @Nullable Long user) { - authorizationIndexerTester.indexProjectPermission(projectUuid, singletonList(group), singletonList(user)); + PermissionIndexerDao.Dto access = new PermissionIndexerDao.Dto(projectUuid, system2.now(), Qualifiers.PROJECT); + if (group != null) { + access.addGroup(group); + } + if (user != null) { + access.addUser(user); + } + authorizationIndexerTester.allow(access); } private void addBrowsePermissionOnComponent(String componentKey) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ComponentCleanerServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ComponentCleanerServiceTest.java index 7f139ae791a..a435e63aa1f 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/ComponentCleanerServiceTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/ComponentCleanerServiceTest.java @@ -24,7 +24,6 @@ import java.util.Date; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.api.config.MapSettings; import org.sonar.api.resources.ResourceType; import org.sonar.api.resources.ResourceTypes; import org.sonar.api.rule.RuleKey; @@ -39,28 +38,17 @@ import org.sonar.db.issue.IssueDto; import org.sonar.db.issue.IssueTesting; import org.sonar.db.rule.RuleDto; import org.sonar.db.rule.RuleTesting; -import org.sonar.server.component.index.ComponentIndexDefinition; -import org.sonar.server.component.index.ComponentIndexer; -import org.sonar.server.es.EsTester; -import org.sonar.server.exceptions.NotFoundException; -import org.sonar.server.issue.IssueDocTesting; -import org.sonar.server.issue.index.IssueIndexDefinition; -import org.sonar.server.issue.index.IssueIndexer; -import org.sonar.server.measure.index.ProjectMeasuresIndexDefinition; -import org.sonar.server.measure.index.ProjectMeasuresIndexer; -import org.sonar.server.permission.index.PermissionIndexer; -import org.sonar.server.test.index.TestDoc; -import org.sonar.server.test.index.TestIndexDefinition; -import org.sonar.server.test.index.TestIndexer; +import org.sonar.server.es.ProjectIndexer; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.sonar.db.component.ComponentTesting.newFileDto; import static org.sonar.db.component.ComponentTesting.newProjectDto; -import static org.sonar.server.issue.index.IssueIndexDefinition.TYPE_ISSUE; public class ComponentCleanerServiceTest { @@ -70,85 +58,41 @@ public class ComponentCleanerServiceTest { public DbTester db = DbTester.create(system2); @Rule - public EsTester es = new EsTester( - new IssueIndexDefinition(new MapSettings()), - new TestIndexDefinition(new MapSettings()), - new ProjectMeasuresIndexDefinition(new MapSettings()), - new ComponentIndexDefinition(new MapSettings())); - - @Rule public ExpectedException expectedException = ExpectedException.none(); private DbClient dbClient = db.getDbClient(); private DbSession dbSession = db.getSession(); - private PermissionIndexer permissionIndexer = new PermissionIndexer(dbClient, es.client()); - private IssueIndexer issueIndexer = new IssueIndexer(system2, dbClient, es.client()); - private TestIndexer testIndexer = new TestIndexer(system2, dbClient, es.client()); - private ProjectMeasuresIndexer projectMeasuresIndexer = new ProjectMeasuresIndexer(system2, dbClient, es.client()); - private ComponentIndexer componentIndexer = new ComponentIndexer(dbClient, es.client()); + private ProjectIndexer projectIndexer = mock(ProjectIndexer.class); private ResourceTypes mockResourceTypes = mock(ResourceTypes.class); - - private ComponentCleanerService underTest = new ComponentCleanerService(dbClient, issueIndexer, testIndexer, projectMeasuresIndexer, componentIndexer, mockResourceTypes, - new ComponentFinder(dbClient)); - - @Test - public void delete_project_by_key_in_db() { - DbData data1 = insertDataInDb(1); - DbData data2 = insertDataInDb(2); - - underTest.delete(data1.project.key()); - - assertDataDoesNotExistInDB(data1); - assertDataStillExistsInDb(data2); - } - - @Test - public void delete_project_by_key_in_index() throws Exception { - IndexData data1 = insertDataInEs(1); - IndexData data2 = insertDataInEs(2); - - underTest.delete(data1.project.key()); - - assertDataDoesNotExistInIndex(data1); - assertDataStillExistsInIndex(data2); - } + private ComponentCleanerService underTest = new ComponentCleanerService(dbClient, mockResourceTypes, new ProjectIndexer[] {projectIndexer}); @Test - public void delete_projects_in_db() { - DbData data1 = insertDataInDb(1); - DbData data2 = insertDataInDb(2); - DbData data3 = insertDataInDb(3); + public void delete_project_from_db_and_index() { + DbData data1 = insertData(1); + DbData data2 = insertData(2); - underTest.delete(dbSession, asList(data1.project, data2.project)); - dbSession.commit(); + underTest.delete(dbSession, data1.project); - assertDataDoesNotExistInDB(data1); - assertDataDoesNotExistInDB(data2); - assertDataStillExistsInDb(data3); + assertNotExists(data1); + assertExists(data2); } @Test - public void delete_projects_in_index() throws Exception { - IndexData data1 = insertDataInEs(1); - IndexData data2 = insertDataInEs(2); - IndexData data3 = insertDataInEs(3); + public void delete_list_of_projects_from_db_and_index() { + DbData data1 = insertData(1); + DbData data2 = insertData(2); + DbData data3 = insertData(3); underTest.delete(dbSession, asList(data1.project, data2.project)); dbSession.commit(); - assertDataDoesNotExistInIndex(data1); - assertDataDoesNotExistInIndex(data2); - assertDataStillExistsInIndex(data3); - } - - @Test - public void fail_to_delete_unknown_project() throws Exception { - expectedException.expect(NotFoundException.class); - underTest.delete("unknown"); + assertNotExists(data1); + assertNotExists(data2); + assertExists(data3); } @Test - public void fail_to_delete_not_project_scope() throws Exception { + public void fail_with_IAE_if_not_a_project() throws Exception { mockResourceTypeAsValidProject(); ComponentDto project = newProjectDto(db.organizations().insert()); dbClient.componentDao().insert(dbSession, project); @@ -157,7 +101,7 @@ public class ComponentCleanerServiceTest { dbSession.commit(); expectedException.expect(IllegalArgumentException.class); - underTest.delete(file.key()); + underTest.delete(dbSession, file); } @Test @@ -170,7 +114,7 @@ public class ComponentCleanerServiceTest { dbSession.commit(); expectedException.expect(IllegalArgumentException.class); - underTest.delete(project.key()); + underTest.delete(dbSession, project); } @Test @@ -181,10 +125,10 @@ public class ComponentCleanerServiceTest { dbSession.commit(); expectedException.expect(IllegalArgumentException.class); - underTest.delete(project.key()); + underTest.delete(dbSession, project); } - private DbData insertDataInDb(int id) { + private DbData insertData(int id) { String suffix = String.valueOf(id); ComponentDto project = newProjectDto(db.organizations().insert(), "project-uuid-" + suffix) .setKey("project-key-" + suffix); @@ -205,12 +149,14 @@ public class ComponentCleanerServiceTest { when(mockResourceTypes.get(anyString())).thenReturn(resourceType); } - private void assertDataStillExistsInDb(DbData data) { - assertDataInDb(data, true); + private void assertNotExists(DbData data) { + assertDataInDb(data, false); + verify(projectIndexer).deleteProject(data.project.uuid()); } - private void assertDataDoesNotExistInDB(DbData data) { - assertDataInDb(data, false); + private void assertExists(DbData data) { + assertDataInDb(data, true); + verify(projectIndexer, never()).deleteProject(data.project.uuid()); } private void assertDataInDb(DbData data, boolean exists) { @@ -219,76 +165,15 @@ public class ComponentCleanerServiceTest { assertThat(dbClient.issueDao().selectByKey(dbSession, data.issue.getKey()).isPresent()).isEqualTo(exists); } - private IndexData insertDataInEs(int id) throws Exception { - mockResourceTypeAsValidProject(); - - String suffix = String.valueOf(id); - ComponentDto project = newProjectDto(db.organizations().insert(), "project-uuid-" + suffix) - .setKey("project-key-" + suffix); - dbClient.componentDao().insert(dbSession, project); - dbSession.commit(); - projectMeasuresIndexer.index(); - componentIndexer.index(); - permissionIndexer.index(dbSession, project.uuid()); - - String issueKey = "issue-key-" + suffix; - es.putDocuments(IssueIndexDefinition.INDEX, TYPE_ISSUE, IssueDocTesting.newDoc(issueKey, project)); - - TestDoc testDoc = new TestDoc().setUuid("test-uuid-" + suffix).setProjectUuid(project.uuid()).setFileUuid(project.uuid()); - es.putDocuments(TestIndexDefinition.INDEX, TestIndexDefinition.TYPE, testDoc); - - return new IndexData(project, issueKey, testDoc.getId()); - } - - private void assertDataStillExistsInIndex(IndexData data) { - assertDataInIndex(data, true); - } - - private void assertDataDoesNotExistInIndex(IndexData data) { - assertDataInIndex(data, false); - } - - private void assertDataInIndex(IndexData data, boolean exists) { - if (exists) { - assertThat(es.getIds(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_ISSUE)).contains(data.issueKey); - assertThat(es.getIds(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION)).contains(data.project.uuid()); - assertThat(es.getIds(TestIndexDefinition.INDEX, TestIndexDefinition.TYPE)).contains(data.testId); - assertThat(es.getIds(ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES, ProjectMeasuresIndexDefinition.TYPE_PROJECT_MEASURE)).contains(data.project.uuid()); - assertThat(es.getIds(ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES, ProjectMeasuresIndexDefinition.TYPE_AUTHORIZATION)).contains(data.project.uuid()); - assertThat(es.getIds(ComponentIndexDefinition.INDEX_COMPONENTS, ComponentIndexDefinition.TYPE_COMPONENT)).contains(data.project.uuid()); - assertThat(es.getIds(ComponentIndexDefinition.INDEX_COMPONENTS, ComponentIndexDefinition.TYPE_AUTHORIZATION)).contains(data.project.uuid()); - } else { - assertThat(es.getIds(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_ISSUE)).doesNotContain(data.issueKey); - assertThat(es.getIds(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION)).doesNotContain(data.project.uuid()); - assertThat(es.getIds(TestIndexDefinition.INDEX, TestIndexDefinition.TYPE)).doesNotContain(data.testId); - assertThat(es.getIds(ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES, ProjectMeasuresIndexDefinition.TYPE_PROJECT_MEASURE)).doesNotContain(data.project.uuid()); - assertThat(es.getIds(ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES, ProjectMeasuresIndexDefinition.TYPE_AUTHORIZATION)).doesNotContain(data.project.uuid()); - assertThat(es.getIds(ComponentIndexDefinition.INDEX_COMPONENTS, ComponentIndexDefinition.TYPE_COMPONENT)).doesNotContain(data.project.uuid()); - assertThat(es.getIds(ComponentIndexDefinition.INDEX_COMPONENTS, ComponentIndexDefinition.TYPE_AUTHORIZATION)).doesNotContain(data.project.uuid()); - } - } - private static class DbData { final ComponentDto project; final SnapshotDto snapshot; final IssueDto issue; - public DbData(ComponentDto project, SnapshotDto snapshot, IssueDto issue) { + DbData(ComponentDto project, SnapshotDto snapshot, IssueDto issue) { this.project = project; this.snapshot = snapshot; this.issue = issue; } } - - private static class IndexData { - final ComponentDto project; - final String issueKey; - final String testId; - - public IndexData(ComponentDto project, String issueKey, String testId) { - this.project = project; - this.issueKey = issueKey; - this.testId = testId; - } - } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceTest.java index 89111722a9f..e22fd6d91ca 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceTest.java @@ -23,22 +23,18 @@ import java.util.Arrays; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.api.config.MapSettings; import org.sonar.api.utils.System2; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDbTester; import org.sonar.db.component.ComponentDto; -import org.sonar.server.component.index.ComponentIndexDefinition; -import org.sonar.server.component.index.ComponentIndexer; -import org.sonar.server.es.EsTester; -import org.sonar.server.measure.index.ProjectMeasuresIndexDefinition; -import org.sonar.server.measure.index.ProjectMeasuresIndexer; +import org.sonar.server.es.ProjectIndexer; import org.sonar.server.tester.UserSessionRule; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.guava.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; import static org.sonar.db.component.ComponentTesting.newFileDto; import static org.sonar.db.component.ComponentTesting.newModuleDto; import static org.sonar.db.component.ComponentTesting.newProjectDto; @@ -50,18 +46,14 @@ public class ComponentServiceTest { @Rule public ExpectedException expectedException = ExpectedException.none(); @Rule - public EsTester es = new EsTester(new ProjectMeasuresIndexDefinition(new MapSettings()), - new ComponentIndexDefinition(new MapSettings())); - @Rule public DbTester dbTester = DbTester.create(System2.INSTANCE); private ComponentDbTester componentDb = new ComponentDbTester(dbTester); private DbClient dbClient = dbTester.getDbClient(); private DbSession dbSession = dbTester.getSession(); - private ProjectMeasuresIndexer projectMeasuresIndexer = new ProjectMeasuresIndexer(System2.INSTANCE, dbClient, es.client()); - private ComponentIndexer componentIndexer = new ComponentIndexer(dbClient, es.client()); + private ProjectIndexer projectIndexer = mock(ProjectIndexer.class); - private ComponentService underTest = new ComponentService(dbClient, userSession, projectMeasuresIndexer, componentIndexer); + private ComponentService underTest = new ComponentService(dbClient, userSession, new ProjectIndexer[] {projectIndexer}); @Test public void should_fail_silently_on_components_not_found_if_told_so() { @@ -97,8 +89,4 @@ public class ComponentServiceTest { assertThat(dbClient.componentDao().selectByKey(dbSession, key)).isPresent(); } - private ComponentDto insertSampleProject() { - return componentDb.insertComponent(newProjectDto(dbTester.organizations().insert()).setKey("sample:root")); - } - } diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceUpdateKeyTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceUpdateKeyTest.java index abe3040e5b7..62e1ee7484a 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceUpdateKeyTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceUpdateKeyTest.java @@ -20,11 +20,9 @@ package org.sonar.server.component; -import org.elasticsearch.action.search.SearchRequestBuilder; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.api.config.MapSettings; import org.sonar.api.utils.System2; import org.sonar.api.web.UserRole; import org.sonar.core.permission.GlobalPermissions; @@ -34,27 +32,17 @@ import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDbTester; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ComponentTesting; -import org.sonar.server.component.index.ComponentIndexDefinition; -import org.sonar.server.component.index.ComponentIndexer; -import org.sonar.server.es.EsTester; +import org.sonar.server.es.ProjectIndexer; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.ForbiddenException; -import org.sonar.server.measure.index.ProjectMeasuresIndexDefinition; -import org.sonar.server.measure.index.ProjectMeasuresIndexer; import org.sonar.server.tester.UserSessionRule; -import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.guava.api.Assertions.assertThat; -import static org.elasticsearch.index.query.QueryBuilders.boolQuery; -import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; -import static org.elasticsearch.index.query.QueryBuilders.termQuery; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.sonar.db.component.ComponentTesting.newFileDto; import static org.sonar.db.component.ComponentTesting.newModuleDto; import static org.sonar.db.component.ComponentTesting.newProjectDto; -import static org.sonar.server.component.index.ComponentIndexDefinition.INDEX_COMPONENTS; -import static org.sonar.server.component.index.ComponentIndexDefinition.TYPE_COMPONENT; -import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES; -import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.TYPE_PROJECT_MEASURE; public class ComponentServiceUpdateKeyTest { @@ -65,18 +53,13 @@ public class ComponentServiceUpdateKeyTest { @Rule public ExpectedException expectedException = ExpectedException.none(); @Rule - public EsTester es = new EsTester(new ProjectMeasuresIndexDefinition(new MapSettings()), - new ComponentIndexDefinition(new MapSettings())); - @Rule public DbTester db = DbTester.create(system2); private ComponentDbTester componentDb = new ComponentDbTester(db); private DbClient dbClient = db.getDbClient(); private DbSession dbSession = db.getSession(); - - private ProjectMeasuresIndexer projectMeasuresIndexer = new ProjectMeasuresIndexer(system2, dbClient, es.client()); - private ComponentIndexer componentIndexer = new ComponentIndexer(dbClient, es.client()); - private ComponentService underTest = new ComponentService(dbClient, userSession, projectMeasuresIndexer, componentIndexer); + private ProjectIndexer projectIndexer = mock(ProjectIndexer.class); + private ComponentService underTest = new ComponentService(dbClient, userSession, new ProjectIndexer[] {projectIndexer}); @Test public void update_project_key() { @@ -100,7 +83,7 @@ public class ComponentServiceUpdateKeyTest { assertThat(dbClient.componentDao().selectByKey(dbSession, inactiveFile.getKey())).isPresent(); - assertProjectKeyExistsInIndex("sample2:root"); + verify(projectIndexer).indexProject(project.uuid(), ProjectIndexer.Cause.PROJECT_KEY_UPDATE); } @Test @@ -120,7 +103,7 @@ public class ComponentServiceUpdateKeyTest { assertComponentKeyHasBeenUpdated(module.key(), "sample:root2:module"); assertComponentKeyHasBeenUpdated(file.key(), "sample:root2:module:src/File.xoo"); - assertProjectKeyExistsInIndex(project.key()); + verify(projectIndexer).indexProject(module.uuid(), ProjectIndexer.Cause.PROJECT_KEY_UPDATE); } @Test @@ -134,7 +117,7 @@ public class ComponentServiceUpdateKeyTest { dbSession.commit(); assertComponentKeyHasBeenUpdated(provisionedProject.key(), "provisionedProject2"); - assertProjectKeyExistsInIndex("provisionedProject2"); + verify(projectIndexer).indexProject(provisionedProject.uuid(), ProjectIndexer.Cause.PROJECT_KEY_UPDATE); } @Test @@ -208,8 +191,6 @@ public class ComponentServiceUpdateKeyTest { assertComponentKeyUpdated(file.key(), "your_project:root:module:src/File.xoo"); assertComponentKeyNotUpdated(inactiveModule.key()); assertComponentKeyNotUpdated(inactiveFile.key()); - - assertProjectKeyExistsInIndex("your_project"); } private void assertComponentKeyUpdated(String oldKey, String newKey) { @@ -231,33 +212,11 @@ public class ComponentServiceUpdateKeyTest { private ComponentDto insertProject(String key) { ComponentDto project = componentDb.insertComponent(newProjectDto(db.organizations().insert()).setKey(key)); - projectMeasuresIndexer.index(project.uuid()); - index(project.uuid()); return project; } - private void index(String projectUuid) { - projectMeasuresIndexer.index(projectUuid); - componentIndexer.indexByProjectUuid(projectUuid); - } - private void assertComponentKeyHasBeenUpdated(String oldKey, String newKey) { assertThat(dbClient.componentDao().selectByKey(dbSession, oldKey)).isAbsent(); assertThat(dbClient.componentDao().selectByKey(dbSession, newKey)).isPresent(); } - - private void assertProjectKeyExistsInIndex(String key) { - SearchRequestBuilder request = es.client() - .prepareSearch(INDEX_PROJECT_MEASURES) - .setTypes(TYPE_PROJECT_MEASURE) - .setQuery(boolQuery().must(matchAllQuery()).filter( - boolQuery().must(termQuery(ProjectMeasuresIndexDefinition.FIELD_KEY, key)))); - assertThat(request.get().getHits()).hasSize(1); - - es.client().prepareSearch(INDEX_COMPONENTS) - .setTypes(TYPE_COMPONENT) - .setQuery(boolQuery().must(matchAllQuery()).filter( - boolQuery().must(termQuery(ComponentIndexDefinition.FIELD_KEY, key)))); - assertThat(request.get().getHits()).hasSize(1); - } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ComponentUpdaterTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ComponentUpdaterTest.java index 9d0e10ce441..289f8d538d4 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/ComponentUpdaterTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/ComponentUpdaterTest.java @@ -20,51 +20,28 @@ package org.sonar.server.component; -import com.google.common.base.Optional; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.api.config.MapSettings; +import org.sonar.api.resources.Qualifiers; +import org.sonar.api.resources.Scopes; import org.sonar.api.utils.System2; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; import org.sonar.db.DbTester; -import org.sonar.db.component.ComponentDao; import org.sonar.db.component.ComponentDto; -import org.sonar.db.component.ComponentTesting; -import org.sonar.db.organization.OrganizationDto; -import org.sonar.db.permission.template.PermissionTemplateDto; import org.sonar.db.user.UserDto; -import org.sonar.server.component.index.ComponentIndexDefinition; -import org.sonar.server.component.index.ComponentIndexer; -import org.sonar.server.es.EsTester; +import org.sonar.server.es.ProjectIndexer; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.favorite.FavoriteUpdater; import org.sonar.server.i18n.I18nRule; -import org.sonar.server.issue.index.IssueIndexDefinition; -import org.sonar.server.measure.index.ProjectMeasuresIndexDefinition; -import org.sonar.server.measure.index.ProjectMeasuresIndexer; import org.sonar.server.permission.PermissionTemplateService; -import org.sonar.server.permission.index.PermissionIndexer; -import org.sonar.server.permission.ws.template.DefaultTemplatesResolverRule; -import org.sonar.server.view.index.ViewIndexDefinition; -import static com.google.common.collect.Lists.newArrayList; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.sonar.api.resources.Qualifiers.VIEW; -import static org.sonar.api.web.UserRole.USER; -import static org.sonar.server.component.NewComponent.newComponentBuilder; -import static org.sonar.server.component.index.ComponentIndexDefinition.INDEX_COMPONENTS; -import static org.sonar.server.component.index.ComponentIndexDefinition.TYPE_COMPONENT; -import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES; -import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.TYPE_PROJECT_MEASURE; public class ComponentUpdaterTest { @@ -78,53 +55,41 @@ public class ComponentUpdaterTest { @Rule public DbTester db = DbTester.create(system2); @Rule - public EsTester es = new EsTester( - new ComponentIndexDefinition(new MapSettings()), - new ProjectMeasuresIndexDefinition(new MapSettings()), - new IssueIndexDefinition(new MapSettings()), - new ViewIndexDefinition(new MapSettings())); - @Rule public I18nRule i18n = new I18nRule().put("qualifier.TRK", "Project"); - @Rule - public DefaultTemplatesResolverRule defaultTemplatesResolver = DefaultTemplatesResolverRule.withoutGovernance(); - private PermissionTemplateDto permissionTemplateDto; + private ProjectIndexer projectIndexer = mock(ProjectIndexer.class); + private PermissionTemplateService permissionTemplateService = mock(PermissionTemplateService.class); - ComponentUpdater underTest = new ComponentUpdater(db.getDbClient(), i18n, system2, - new PermissionTemplateService(db.getDbClient(), new PermissionIndexer(db.getDbClient(), es.client()), null, defaultTemplatesResolver), + private ComponentUpdater underTest = new ComponentUpdater(db.getDbClient(), i18n, system2, + permissionTemplateService, new FavoriteUpdater(db.getDbClient()), - new ProjectMeasuresIndexer(system2, db.getDbClient(), es.client()), - new ComponentIndexer(db.getDbClient(), es.client())); - - @Before - public void setUp() throws Exception { - permissionTemplateDto = db.permissionTemplates().insertTemplate(db.getDefaultOrganization()); - db.organizations().setDefaultTemplates(db.getDefaultOrganization(), permissionTemplateDto.getUuid(), null); - } + new ProjectIndexer[] {projectIndexer}); @Test - public void create_project() throws Exception { - ComponentDto project = underTest.create(db.getSession(), - NewComponent.newComponentBuilder() - .setKey(DEFAULT_PROJECT_KEY) - .setName(DEFAULT_PROJECT_NAME) - .setOrganizationUuid(db.getDefaultOrganization().getUuid()) - .build(), - null); - - assertThat(project.getKey()).isEqualTo(DEFAULT_PROJECT_KEY); - assertThat(project.deprecatedKey()).isEqualTo(DEFAULT_PROJECT_KEY); - assertThat(project.name()).isEqualTo(DEFAULT_PROJECT_NAME); - assertThat(project.longName()).isEqualTo(DEFAULT_PROJECT_NAME); - assertThat(project.qualifier()).isEqualTo("TRK"); - assertThat(project.scope()).isEqualTo("PRJ"); - assertThat(project.getOrganizationUuid()).isEqualTo(db.getDefaultOrganization().getUuid()); - assertThat(project.uuid()).isNotNull(); - assertThat(project.projectUuid()).isEqualTo(project.uuid()); - assertThat(project.moduleUuid()).isNull(); - assertThat(project.moduleUuidPath()).isEqualTo("." + project.uuid() + "."); - assertThat(project.getCreatedAt()).isNotNull(); + public void should_persist_and_index_when_creating_project() throws Exception { + NewComponent project = NewComponent.newComponentBuilder() + .setKey(DEFAULT_PROJECT_KEY) + .setName(DEFAULT_PROJECT_NAME) + .setOrganizationUuid(db.getDefaultOrganization().getUuid()) + .build(); + ComponentDto returned = underTest.create(db.getSession(), project, null); + + ComponentDto loaded = db.getDbClient().componentDao().selectOrFailByUuid(db.getSession(), returned.uuid()); + assertThat(loaded.getKey()).isEqualTo(DEFAULT_PROJECT_KEY); + assertThat(loaded.deprecatedKey()).isEqualTo(DEFAULT_PROJECT_KEY); + assertThat(loaded.name()).isEqualTo(DEFAULT_PROJECT_NAME); + assertThat(loaded.longName()).isEqualTo(DEFAULT_PROJECT_NAME); + assertThat(loaded.qualifier()).isEqualTo(Qualifiers.PROJECT); + assertThat(loaded.scope()).isEqualTo(Scopes.PROJECT); + assertThat(loaded.getOrganizationUuid()).isEqualTo(db.getDefaultOrganization().getUuid()); + assertThat(loaded.uuid()).isNotNull(); + assertThat(loaded.projectUuid()).isEqualTo(loaded.uuid()); + assertThat(loaded.moduleUuid()).isNull(); + assertThat(loaded.moduleUuidPath()).isEqualTo("." + loaded.uuid() + "."); + assertThat(loaded.getCreatedAt()).isNotNull(); assertThat(db.getDbClient().componentDao().selectOrFailByKey(db.getSession(), DEFAULT_PROJECT_KEY)).isNotNull(); + + verify(projectIndexer).indexProject(loaded.uuid(), ProjectIndexer.Cause.PROJECT_CREATION); } @Test @@ -142,80 +107,38 @@ public class ComponentUpdaterTest { } @Test - public void remove_duplicated_components_when_creating_project() throws Exception { - String projectKey = "PROJECT_KEY"; - - DbSession session = mock(DbSession.class); - - ComponentDao componentDao = mock(ComponentDao.class); - when(componentDao.selectByKey(session, projectKey)).thenReturn(Optional.absent()); - - DbClient dbClient = mock(DbClient.class); - when(dbClient.openSession(false)).thenReturn(session); - when(dbClient.componentDao()).thenReturn(componentDao); - - doAnswer(invocation -> { - ((ComponentDto) invocation.getArguments()[1]).setId(1L); - return null; - }).when(componentDao).insert(eq(session), any(ComponentDto.class)); - - OrganizationDto organization = db.getDefaultOrganization(); - when(componentDao.selectComponentsHavingSameKeyOrderedById(session, projectKey)).thenReturn(newArrayList( - ComponentTesting.newProjectDto(organization).setId(1L).setKey(projectKey), - ComponentTesting.newProjectDto(organization).setId(2L).setKey(projectKey), - ComponentTesting.newProjectDto(organization).setId(3L).setKey(projectKey))); - - underTest = new ComponentUpdater(dbClient, i18n, System2.INSTANCE, mock(PermissionTemplateService.class), null, mock(ProjectMeasuresIndexer.class), - mock(ComponentIndexer.class)); - underTest.create( - session, - newComponentBuilder() - .setOrganizationUuid(organization.getUuid()) - .setKey(projectKey) - .setName(projectKey) - .build(), - null); - - verify(componentDao).delete(session, 2L); - verify(componentDao).delete(session, 3L); - } - - @Test - public void verify_permission_template_is_applied() throws Exception { - UserDto userDto = db.users().insertUser(); - db.permissionTemplates().addUserToTemplate(permissionTemplateDto.getId(), userDto.getId(), USER); - - ComponentDto project = underTest.create(db.getSession(), - NewComponent.newComponentBuilder() - .setKey(DEFAULT_PROJECT_KEY) - .setName(DEFAULT_PROJECT_NAME) - .setOrganizationUuid(db.getDefaultOrganization().getUuid()) - .build(), - null); - - assertThat(db.users().selectProjectPermissionsOfUser(userDto, project)).containsOnly(USER); + public void should_apply_default_permission_template() throws Exception { + long userId = 42; + NewComponent project = NewComponent.newComponentBuilder() + .setKey(DEFAULT_PROJECT_KEY) + .setName(DEFAULT_PROJECT_NAME) + .setOrganizationUuid(db.getDefaultOrganization().getUuid()) + .build(); + ComponentDto dto = underTest.create(db.getSession(), project, userId); + + verify(permissionTemplateService).applyDefault(db.getSession(), dto.getOrganizationUuid(), dto, userId); } @Test - public void add_project_to_favorite_when_user() throws Exception { + public void should_add_project_to_user_favorites_if_project_creator_is_defined_in_permission_template() throws Exception { UserDto userDto = db.users().insertUser(); - db.permissionTemplates().addProjectCreatorToTemplate(permissionTemplateDto.getId(), USER); - - ComponentDto project = underTest.create(db.getSession(), - NewComponent.newComponentBuilder() - .setKey(DEFAULT_PROJECT_KEY) - .setName(DEFAULT_PROJECT_NAME) - .setOrganizationUuid(db.getDefaultOrganization().getUuid()) - .build(), + NewComponent project = NewComponent.newComponentBuilder() + .setKey(DEFAULT_PROJECT_KEY) + .setName(DEFAULT_PROJECT_NAME) + .setOrganizationUuid(db.getDefaultOrganization().getUuid()) + .build(); + when(permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(eq(db.getSession()), eq(project.getOrganizationUuid()), any(ComponentDto.class))) + .thenReturn(true); + + ComponentDto dto = underTest.create(db.getSession(), + project, userDto.getId()); - assertThat(db.favorites().hasFavorite(project, userDto.getId())).isTrue(); + assertThat(db.favorites().hasFavorite(dto, userDto.getId())).isTrue(); } @Test - public void does_not_add_project_to_favorite_when_no_user() throws Exception { - db.permissionTemplates().addProjectCreatorToTemplate(permissionTemplateDto.getId(), USER); - + public void does_not_add_project_to_favorite_when_anonymously_created() throws Exception { ComponentDto project = underTest.create(db.getSession(), NewComponent.newComponentBuilder() .setKey(DEFAULT_PROJECT_KEY) @@ -229,8 +152,6 @@ public class ComponentUpdaterTest { @Test public void does_not_add_project_to_favorite_when_project_has_no_permission_on_template() throws Exception { - UserDto userDto = db.users().insertUser(); - ComponentDto project = underTest.create(db.getSession(), NewComponent.newComponentBuilder() .setKey(DEFAULT_PROJECT_KEY) @@ -243,30 +164,17 @@ public class ComponentUpdaterTest { } @Test - public void verify_project_exists_in_es_indexes() throws Exception { - ComponentDto project = underTest.create(db.getSession(), - NewComponent.newComponentBuilder() - .setKey(DEFAULT_PROJECT_KEY) - .setName(DEFAULT_PROJECT_NAME) - .setOrganizationUuid(db.getDefaultOrganization().getUuid()) - .build(), - null); + public void fail_when_project_key_already_exists() throws Exception { + ComponentDto existing = db.components().insertProject(); - assertThat(es.getIds(INDEX_COMPONENTS, TYPE_COMPONENT)).containsOnly(project.uuid()); - assertThat(es.getIds(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURE)).containsOnly(project.uuid()); - } - - @Test - public void fail_when_project_already_exists() throws Exception { - db.components().insertComponent(ComponentTesting.newProjectDto(db.getDefaultOrganization()).setKey(DEFAULT_PROJECT_KEY)); expectedException.expect(BadRequestException.class); - expectedException.expectMessage("Could not create Project, key already exists: project-key"); + expectedException.expectMessage("Could not create Project, key already exists: " + existing.key()); underTest.create(db.getSession(), NewComponent.newComponentBuilder() - .setKey(DEFAULT_PROJECT_KEY) + .setKey(existing.key()) .setName(DEFAULT_PROJECT_NAME) - .setOrganizationUuid(db.getDefaultOrganization().getUuid()) + .setOrganizationUuid(existing.getOrganizationUuid()) .build(), null); } @@ -301,26 +209,21 @@ public class ComponentUpdaterTest { } @Test - public void create_view() { - defaultTemplatesResolver.installGovernance(); - - ComponentDto view = underTest.create(db.getSession(), - NewComponent.newComponentBuilder() - .setKey("view-key") - .setName("view-name") - .setQualifier(VIEW) - .setOrganizationUuid(db.getDefaultOrganization().getUuid()) - .build(), - null); - - assertThat(view.getKey()).isEqualTo("view-key"); - assertThat(view.name()).isEqualTo("view-name"); - assertThat(view.qualifier()).isEqualTo("VW"); - assertThat(es.getIds(INDEX_COMPONENTS, TYPE_COMPONENT)).containsOnly(view.uuid()); - // Indexes related to project measures, issues and views are not indexed - assertThat(es.getIds(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURE)).isEmpty(); - assertThat(es.getIds(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION)).isEmpty(); - assertThat(es.getIds(ViewIndexDefinition.INDEX, ViewIndexDefinition.TYPE_VIEW)).isEmpty(); + public void persist_and_index_when_creating_view() { + NewComponent view = NewComponent.newComponentBuilder() + .setKey("view-key") + .setName("view-name") + .setQualifier(VIEW) + .setOrganizationUuid(db.getDefaultOrganization().getUuid()) + .build(); + + ComponentDto returned = underTest.create(db.getSession(), view, null); + + ComponentDto loaded = db.getDbClient().componentDao().selectOrFailByUuid(db.getSession(), returned.uuid()); + assertThat(loaded.getKey()).isEqualTo("view-key"); + assertThat(loaded.name()).isEqualTo("view-name"); + assertThat(loaded.qualifier()).isEqualTo("VW"); + verify(projectIndexer).indexProject(loaded.uuid(), ProjectIndexer.Cause.PROJECT_CREATION); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java deleted file mode 100644 index 7602bc354fc..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program 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. - * - * This program 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.component; - -import java.util.List; -import java.util.Map; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.sonar.api.config.MapSettings; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.utils.System2; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; -import org.sonar.db.DbTester; -import org.sonar.db.component.ComponentDto; -import org.sonar.server.component.index.ComponentIndexDefinition; -import org.sonar.server.component.index.ComponentIndexer; -import org.sonar.server.es.EsTester; -import org.sonar.server.favorite.FavoriteUpdater; -import org.sonar.server.i18n.I18nRule; -import org.sonar.server.issue.index.IssueIndexDefinition; -import org.sonar.server.measure.index.ProjectMeasuresIndexDefinition; -import org.sonar.server.measure.index.ProjectMeasuresIndexer; -import org.sonar.server.organization.DefaultOrganizationProvider; -import org.sonar.server.organization.TestDefaultOrganizationProvider; -import org.sonar.server.permission.PermissionTemplateService; -import org.sonar.server.tester.UserSessionRule; -import org.sonar.server.view.index.ViewIndexDefinition; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class DefaultRubyComponentServiceTest { - - private System2 system2 = mock(System2.class); - - @Rule - public DbTester db = DbTester.create(system2); - @Rule - public EsTester es = new EsTester( - new ComponentIndexDefinition(new MapSettings()), - new ProjectMeasuresIndexDefinition(new MapSettings()), - new IssueIndexDefinition(new MapSettings()), - new ViewIndexDefinition(new MapSettings())); - @Rule - public UserSessionRule userSession = UserSessionRule.standalone(); - - private I18nRule i18n = new I18nRule(); - private DbClient dbClient = db.getDbClient(); - private DbSession dbSession = db.getSession(); - - private PermissionTemplateService permissionTemplateService = mock(PermissionTemplateService.class); - private FavoriteUpdater favoriteUpdater = mock(FavoriteUpdater.class); - private ComponentUpdater componentUpdater = new ComponentUpdater(db.getDbClient(), i18n, system2, permissionTemplateService, favoriteUpdater, - new ProjectMeasuresIndexer(system2, db.getDbClient(), es.client()), - new ComponentIndexer(db.getDbClient(), es.client())); - private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db); - - private DefaultRubyComponentService underTest = new DefaultRubyComponentService(userSession, dbClient, componentUpdater, defaultOrganizationProvider); - - private String defaultOrganizationUuid; - - @Before - public void setUp() throws Exception { - defaultOrganizationUuid = db.getDefaultOrganization().getUuid(); - } - - @Test - public void create_component() { - userSession.login("john").setUserId(100); - String componentKey = "new-project"; - String componentName = "New Project"; - String qualifier = Qualifiers.PROJECT; - when(permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(any(DbSession.class), eq(defaultOrganizationUuid), any(ComponentDto.class))).thenReturn(true); - - Long result = underTest.createComponent(componentKey, componentName, qualifier); - - ComponentDto project = dbClient.componentDao().selectOrFailByKey(dbSession, componentKey); - assertThat(project.key()).isEqualTo(componentKey); - assertThat(project.name()).isEqualTo(componentName); - assertThat(project.qualifier()).isEqualTo(qualifier); - assertThat(project.getId()).isEqualTo(result); - verify(permissionTemplateService).applyDefault(any(DbSession.class), eq(defaultOrganizationUuid), any(ComponentDto.class), eq(100L)); - } - -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/index/ComponentIndexLoginTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/index/ComponentIndexLoginTest.java index 8ef13a7353c..0263b7b56a6 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/index/ComponentIndexLoginTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/index/ComponentIndexLoginTest.java @@ -19,12 +19,9 @@ */ package org.sonar.server.component.index; -import java.util.Collections; import org.junit.Test; import org.sonar.db.component.ComponentDto; -import static java.util.Collections.emptyList; - public class ComponentIndexLoginTest extends ComponentIndexTest { @Test @@ -45,9 +42,7 @@ public class ComponentIndexLoginTest extends ComponentIndexTest { indexer.index(project); // give the user explicit access - authorizationIndexerTester.indexProjectPermission(project.uuid(), - emptyList(), - Collections.singletonList((long) TEST_USER_ID)); + authorizationIndexerTester.allowOnlyUser(project, TEST_USER_ID); assertSearchResults("sonarqube", project); } @@ -60,9 +55,7 @@ public class ComponentIndexLoginTest extends ComponentIndexTest { indexer.index(project); // give the user implicit access (though group) - authorizationIndexerTester.indexProjectPermission(project.uuid(), - Collections.singletonList(TEST_USER_GROUP), - emptyList()); + authorizationIndexerTester.allowOnlyGroup(project, TEST_USER_GROUP); assertSearchResults("sonarqube", project); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/index/ComponentIndexTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/index/ComponentIndexTest.java index c448386cbfb..2ee73d61a59 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/index/ComponentIndexTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/index/ComponentIndexTest.java @@ -20,7 +20,6 @@ package org.sonar.server.component.index; import java.util.Arrays; -import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; @@ -28,7 +27,6 @@ import org.assertj.core.api.AbstractListAssert; import org.junit.Before; import org.junit.Rule; import org.sonar.api.config.MapSettings; -import org.sonar.api.security.DefaultGroups; import org.sonar.api.utils.System2; import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; @@ -36,11 +34,11 @@ import org.sonar.db.component.ComponentTesting; import org.sonar.db.organization.OrganizationDto; import org.sonar.db.organization.OrganizationTesting; import org.sonar.server.es.EsTester; +import org.sonar.server.permission.index.AuthorizationTypeSupport; import org.sonar.server.permission.index.PermissionIndexerTester; import org.sonar.server.tester.UserSessionRule; import static java.util.Arrays.asList; -import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; import static org.sonar.api.resources.Qualifiers.FILE; import static org.sonar.api.resources.Qualifiers.MODULE; @@ -63,16 +61,14 @@ public abstract class ComponentIndexTest { @Rule public ComponentIndexSearchFeatureRule features = new ComponentIndexSearchFeatureRule(); - protected PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(es); + protected ComponentIndexer indexer = new ComponentIndexer(db.getDbClient(), es.client()); - protected ComponentIndex index; - protected ComponentIndexer indexer; + protected ComponentIndex index = new ComponentIndex(es.client(), new AuthorizationTypeSupport(userSession)); + protected PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(es, indexer); private OrganizationDto organization; @Before public void setUp() { - index = new ComponentIndex(es.client(), userSession); - indexer = new ComponentIndexer(db.getDbClient(), es.client()); organization = OrganizationTesting.newOrganizationDto(); } @@ -156,9 +152,7 @@ public abstract class ComponentIndexTest { protected ComponentDto index(ComponentDto dto) { indexer.index(dto); - authorizationIndexerTester.indexProjectPermission(dto.uuid(), - Collections.singletonList(DefaultGroups.ANYONE), - emptyList()); + authorizationIndexerTester.allowOnlyAnyone(dto); return dto; } diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/index/ComponentIndexerTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/index/ComponentIndexerTest.java index 789105833f8..624a6d81290 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/index/ComponentIndexerTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/index/ComponentIndexerTest.java @@ -33,6 +33,7 @@ import org.sonar.db.component.ComponentUpdateDto; import org.sonar.db.organization.OrganizationDto; import org.sonar.db.organization.OrganizationTesting; import org.sonar.server.es.EsTester; +import org.sonar.server.es.ProjectIndexer; import static org.assertj.core.api.Assertions.assertThat; import static org.elasticsearch.index.query.QueryBuilders.termQuery; @@ -163,7 +164,7 @@ public class ComponentIndexerTest { } private void index(String uuid) { - createIndexer().indexByProjectUuid(uuid); + createIndexer().indexProject(uuid, ProjectIndexer.Cause.PROJECT_CREATION); } private long count() { diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/BulkUpdateKeyActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/BulkUpdateKeyActionTest.java index 511a6afba2e..0b74934b3c6 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/ws/BulkUpdateKeyActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/ws/BulkUpdateKeyActionTest.java @@ -40,13 +40,11 @@ import org.sonar.db.organization.OrganizationDto; import org.sonar.server.component.ComponentFinder; import org.sonar.server.component.ComponentService; import org.sonar.server.component.index.ComponentIndexDefinition; -import org.sonar.server.component.index.ComponentIndexer; import org.sonar.server.es.EsTester; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.measure.index.ProjectMeasuresIndexDefinition; -import org.sonar.server.measure.index.ProjectMeasuresIndexer; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.TestRequest; import org.sonar.server.ws.WsActionTester; @@ -57,7 +55,10 @@ import org.sonarqube.ws.WsComponents.BulkUpdateKeyWsResponse.Key; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; -import static org.assertj.guava.api.Assertions.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.sonar.db.component.ComponentTesting.newFileDto; import static org.sonar.db.component.ComponentTesting.newModuleDto; import static org.sonar.db.component.ComponentTesting.newProjectDto; @@ -87,14 +88,10 @@ public class BulkUpdateKeyActionTest { private ComponentDbTester componentDb = new ComponentDbTester(db); private DbClient dbClient = db.getDbClient(); - private DbSession dbSession = db.getSession(); - private ComponentFinder componentFinder = new ComponentFinder(dbClient); - + private ComponentService componentService = mock(ComponentService.class); private WsActionTester ws = new WsActionTester( - new BulkUpdateKeyAction(dbClient, componentFinder, - new ComponentService(dbClient, null, new ProjectMeasuresIndexer(system2, dbClient, es.client()), new ComponentIndexer(dbClient, es.client())), - userSession)); + new BulkUpdateKeyAction(dbClient, componentFinder, componentService, userSession)); @Before public void setUp() { @@ -147,22 +144,17 @@ public class BulkUpdateKeyActionTest { tuple(project.key(), "your_project", false), tuple(module.key(), "your_project:root:module", false)); - assertComponentKeyUpdated(project.key(), "your_project"); - assertComponentKeyUpdated(module.key(), "your_project:root:module"); - assertComponentKeyUpdated(file.key(), "your_project:root:module:src/File.xoo"); - assertComponentKeyNotUpdated(inactiveModule.key()); - assertComponentKeyNotUpdated(inactiveFile.key()); + verify(componentService).bulkUpdateKey(any(DbSession.class), eq(project.uuid()), eq(FROM), eq(TO)); } @Test public void bulk_update_provisioned_project_key() { - String oldKey = "provisionedProject"; String newKey = "provisionedProject2"; - ComponentDto provisionedProject = componentDb.insertComponent(newProjectDto(db.getDefaultOrganization()).setKey(oldKey)); + ComponentDto provisionedProject = componentDb.insertProject(); - callByKey(provisionedProject.key(), oldKey, newKey); + callByKey(provisionedProject.key(), provisionedProject.getKey(), newKey); - assertComponentKeyUpdated(oldKey, newKey); + verify(componentService).bulkUpdateKey(any(DbSession.class), eq(provisionedProject.uuid()), eq(provisionedProject.getKey()), eq(newKey)); } @Test @@ -271,15 +263,6 @@ public class BulkUpdateKeyActionTest { .containsOnlyOnce("id", "key", "from", "to", "dryRun"); } - private void assertComponentKeyUpdated(String oldKey, String newKey) { - assertThat(dbClient.componentDao().selectByKey(dbSession, oldKey)).isAbsent(); - assertThat(dbClient.componentDao().selectByKey(dbSession, newKey)).isPresent(); - } - - private void assertComponentKeyNotUpdated(String key) { - assertThat(dbClient.componentDao().selectByKey(dbSession, key)).isPresent(); - } - private ComponentDto insertMyProject() { return componentDb.insertComponent(newProjectDto(db.organizations().insert()).setKey(MY_PROJECT_KEY)); } 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 726114b0bba..b729bd8f6db 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 @@ -24,7 +24,6 @@ import com.google.common.base.Joiner; 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; @@ -33,7 +32,6 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonar.api.config.MapSettings; -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; @@ -49,6 +47,8 @@ import org.sonar.server.es.EsTester; import org.sonar.server.measure.index.ProjectMeasuresDoc; import org.sonar.server.measure.index.ProjectMeasuresIndex; import org.sonar.server.measure.index.ProjectMeasuresIndexDefinition; +import org.sonar.server.measure.index.ProjectMeasuresIndexer; +import org.sonar.server.permission.index.AuthorizationTypeSupport; import org.sonar.server.permission.index.PermissionIndexerTester; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.KeyExamples; @@ -80,6 +80,7 @@ import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_FIL import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_ORGANIZATION; public class SearchProjectsActionTest { + private static final String NCLOC = "ncloc"; private static final String COVERAGE = "coverage"; private static final String IS_FAVOURITE_CRITERION = "isFavorite"; @@ -97,9 +98,9 @@ public class SearchProjectsActionTest { private DbClient dbClient = db.getDbClient(); private DbSession dbSession = db.getSession(); - private PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(es); - private final ProjectMeasuresIndex index = new ProjectMeasuresIndex(es.client(), userSession); - private final ProjectMeasuresQueryValidator queryValidator = new ProjectMeasuresQueryValidator(dbClient); + private PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(es, new ProjectMeasuresIndexer(System2.INSTANCE, dbClient, es.client())); + private ProjectMeasuresIndex index = new ProjectMeasuresIndex(es.client(), new AuthorizationTypeSupport(userSession)); + private ProjectMeasuresQueryValidator queryValidator = new ProjectMeasuresQueryValidator(dbClient); private WsActionTester ws = new WsActionTester( new SearchProjectsAction(dbClient, index, queryValidator, userSession)); @@ -398,7 +399,7 @@ public class SearchProjectsActionTest { try { es.putDocuments(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURE, new ProjectMeasuresDoc().setId(project.uuid()).setKey(project.key()).setName(project.name()).setMeasures(measures)); - authorizationIndexerTester.indexProjectPermission(project.uuid(), singletonList(DefaultGroups.ANYONE), Collections.emptyList()); + authorizationIndexerTester.allowOnlyAnyone(project); } catch (Exception e) { Throwables.propagate(e); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/SuggestionsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/SuggestionsActionTest.java index c6e4f3f7485..7f11f862ac3 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/ws/SuggestionsActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/ws/SuggestionsActionTest.java @@ -19,7 +19,6 @@ */ package org.sonar.server.component.ws; -import java.util.Collections; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -33,15 +32,14 @@ import org.sonar.server.component.index.ComponentIndex; import org.sonar.server.component.index.ComponentIndexDefinition; import org.sonar.server.component.index.ComponentIndexer; import org.sonar.server.es.EsTester; +import org.sonar.server.permission.index.AuthorizationTypeSupport; import org.sonar.server.permission.index.PermissionIndexerTester; import org.sonar.server.tester.UserSessionRule; import org.sonarqube.ws.WsComponents; import org.sonarqube.ws.WsComponents.SuggestionsWsResponse; -import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.groups.Tuple.tuple; -import static org.sonar.api.security.DefaultGroups.ANYONE; import static org.sonar.db.component.ComponentTesting.newProjectDto; public class SuggestionsActionTest { @@ -53,29 +51,26 @@ public class SuggestionsActionTest { @Rule public UserSessionRule userSessionRule = UserSessionRule.standalone(); - private ComponentIndexer indexer; + private ComponentIndexer componentIndexer = new ComponentIndexer(db.getDbClient(), es.client()); private SuggestionsAction action; private OrganizationDto organization; - private PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(es); + private PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(es, componentIndexer); @Before public void setUp() { - ComponentIndex index = new ComponentIndex(es.client(), userSessionRule); - indexer = new ComponentIndexer(db.getDbClient(), es.client()); + ComponentIndex index = new ComponentIndex(es.client(), new AuthorizationTypeSupport(userSessionRule)); action = new SuggestionsAction(db.getDbClient(), index); organization = db.organizations().insert(); } @Test public void exact_match_in_one_qualifier() { - ComponentDto dto = db.components().insertComponent(newProjectDto(organization)); + ComponentDto project = db.components().insertComponent(newProjectDto(organization)); - indexer.index(); - authorizationIndexerTester.indexProjectPermission(dto.uuid(), - Collections.singletonList(ANYONE), - emptyList()); + componentIndexer.index(); + authorizationIndexerTester.allowOnlyAnyone(project); - SuggestionsWsResponse response = action.doHandle(dto.getKey()); + SuggestionsWsResponse response = action.doHandle(project.getKey()); // assert match in qualifier "TRK" assertThat(response.getResultsList()) @@ -87,7 +82,7 @@ public class SuggestionsActionTest { assertThat(response.getResultsList()) .flatExtracting(SuggestionsWsResponse.Qualifier::getItemsList) .extracting(WsComponents.Component::getKey, WsComponents.Component::getOrganization) - .containsExactly(tuple(dto.getKey(), organization.getKey())); + .containsExactly(tuple(project.getKey(), organization.getKey())); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/IndexComponentsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/IndexAnalysisStepTest.java index 92da7aa3532..1b74fc8a0a9 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/IndexComponentsStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/IndexAnalysisStepTest.java @@ -21,20 +21,20 @@ package org.sonar.server.computation.task.projectanalysis.step; import org.junit.Rule; import org.junit.Test; -import org.sonar.server.component.index.ComponentIndexer; import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReaderRule; import org.sonar.server.computation.task.projectanalysis.component.Component; import org.sonar.server.computation.task.projectanalysis.component.ReportComponent; import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule; import org.sonar.server.computation.task.projectanalysis.component.ViewsComponent; import org.sonar.server.computation.task.step.ComputationStep; +import org.sonar.server.es.ProjectIndexer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.PROJECT; import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.VIEW; -public class IndexComponentsStepTest extends BaseStepTest { +public class IndexAnalysisStepTest extends BaseStepTest { private static final String PROJECT_KEY = "PROJECT_KEY"; private static final String PROJECT_UUID = "PROJECT_UUID"; @@ -44,8 +44,8 @@ public class IndexComponentsStepTest extends BaseStepTest { @Rule public BatchReportReaderRule reportReader = new BatchReportReaderRule(); - private ComponentIndexer componentIndexer = mock(ComponentIndexer.class); - private IndexComponentsStep underTest = new IndexComponentsStep(componentIndexer, treeRootHolder); + private ProjectIndexer componentIndexer = mock(ProjectIndexer.class); + private IndexAnalysisStep underTest = new IndexAnalysisStep(treeRootHolder, new ProjectIndexer[] {componentIndexer}); @Test public void call_indexByProjectUuid_of_indexer_for_project() { @@ -54,7 +54,7 @@ public class IndexComponentsStepTest extends BaseStepTest { underTest.execute(); - verify(componentIndexer).indexByProjectUuid(PROJECT_UUID); + verify(componentIndexer).indexProject(PROJECT_UUID, ProjectIndexer.Cause.NEW_ANALYSIS); } @Test @@ -64,7 +64,7 @@ public class IndexComponentsStepTest extends BaseStepTest { underTest.execute(); - verify(componentIndexer).indexByProjectUuid(PROJECT_UUID); + verify(componentIndexer).indexProject(PROJECT_UUID, ProjectIndexer.Cause.NEW_ANALYSIS); } @Override diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/IndexIssuesStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/IndexIssuesStepTest.java deleted file mode 100644 index 663b7159a69..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/IndexIssuesStepTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program 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. - * - * This program 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.computation.task.projectanalysis.step; - -import org.junit.Rule; -import org.junit.Test; -import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule; -import org.sonar.server.issue.index.IssueIndexer; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.PROJECT; -import static org.sonar.server.computation.task.projectanalysis.component.ReportComponent.builder; - -public class IndexIssuesStepTest { - - static String PROJECT_UUID = "PROJECT_UUID"; - - @Rule - public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule() - .setRoot(builder(PROJECT, 1).setUuid(PROJECT_UUID).setKey("PROJECT_KEY").build()); - - @Test - public void call_indexer() { - IssueIndexer issueIndexer = mock(IssueIndexer.class); - IndexIssuesStep underTest = new IndexIssuesStep(issueIndexer, treeRootHolder); - - underTest.execute(); - - verify(issueIndexer).index(PROJECT_UUID); - } -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/IndexProjectMeasuresStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/IndexProjectMeasuresStepTest.java deleted file mode 100644 index a00cd242300..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/IndexProjectMeasuresStepTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program 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. - * - * This program 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.computation.task.projectanalysis.step; - -import org.junit.Rule; -import org.junit.Test; -import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule; -import org.sonar.server.measure.index.ProjectMeasuresIndexer; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.PROJECT; -import static org.sonar.server.computation.task.projectanalysis.component.ReportComponent.builder; - -public class IndexProjectMeasuresStepTest { - - static String PROJECT_UUID = "PROJECT_UUID"; - - @Rule - public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule() - .setRoot(builder(PROJECT, 1).setUuid(PROJECT_UUID).setKey("PROJECT_KEY").build()); - - @Test - public void call_indexer() { - ProjectMeasuresIndexer indexer = mock(ProjectMeasuresIndexer.class); - IndexProjectMeasuresStep underTest = new IndexProjectMeasuresStep(indexer, treeRootHolder); - - underTest.execute(); - - verify(indexer).index(PROJECT_UUID); - } - -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/IndexTestsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/IndexTestsStepTest.java deleted file mode 100644 index c16a1a506ba..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/IndexTestsStepTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program 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. - * - * This program 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.computation.task.projectanalysis.step; - -import java.util.List; -import org.elasticsearch.search.SearchHit; -import org.junit.Rule; -import org.junit.Test; -import org.sonar.api.config.MapSettings; -import org.sonar.api.utils.System2; -import org.sonar.db.DbClient; -import org.sonar.db.DbTester; -import org.sonar.server.computation.task.projectanalysis.component.Component; -import org.sonar.server.computation.task.projectanalysis.component.ReportComponent; -import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule; -import org.sonar.server.computation.task.step.ComputationStep; -import org.sonar.server.es.EsTester; -import org.sonar.server.test.db.TestTesting; -import org.sonar.server.test.index.TestDoc; -import org.sonar.server.test.index.TestIndexDefinition; -import org.sonar.server.test.index.TestIndexer; - -import static org.assertj.core.api.Assertions.assertThat; - -public class IndexTestsStepTest extends BaseStepTest { - - private System2 system2 = System2.INSTANCE; - - @Rule - public DbTester dbTester = DbTester.create(system2); - - @Rule - public EsTester esTester = new EsTester(new TestIndexDefinition(new MapSettings())); - - @Rule - public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule(); - - DbClient dbClient = dbTester.getDbClient(); - - @Override - protected ComputationStep step() { - TestIndexer testIndexer = new TestIndexer(system2, dbClient, esTester.client()); - return new IndexTestsStep(testIndexer, treeRootHolder); - } - - @Test - public void index_test() throws Exception { - dbTester.prepareDbUnit(getClass(), "index_source.xml"); - TestTesting.updateDataColumn(dbTester.getSession(), "FILE1_UUID", TestTesting.newRandomTests(1)); - - treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").setKey("PROJECT_KEY").build()); - - step().execute(); - - List<SearchHit> docs = esTester.getDocuments(TestIndexDefinition.INDEX, TestIndexDefinition.TYPE); - assertThat(docs).hasSize(1); - TestDoc doc = new TestDoc(docs.get(0).sourceAsMap()); - assertThat(doc.projectUuid()).isEqualTo("ABCD"); - assertThat(doc.fileUuid()).isEqualTo("FILE1_UUID"); - assertThat(doc.coveredFiles()).isNotEmpty(); - } -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/es/EsTester.java b/server/sonar-server/src/test/java/org/sonar/server/es/EsTester.java index f20e8d2ec4f..d87bd60caa4 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/es/EsTester.java +++ b/server/sonar-server/src/test/java/org/sonar/server/es/EsTester.java @@ -55,7 +55,7 @@ import static java.util.Arrays.asList; public class EsTester extends ExternalResource { private final List<IndexDefinition> indexDefinitions; - private EsClient client = new EsClient(NodeHolder.INSTANCE.node.client()); + private final EsClient client = new EsClient(NodeHolder.INSTANCE.node.client()); private ComponentContainer container; public EsTester(IndexDefinition... defs) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/es/NewIndexTest.java b/server/sonar-server/src/test/java/org/sonar/server/es/NewIndexTest.java index e67740fbeea..72ce387091e 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/es/NewIndexTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/es/NewIndexTest.java @@ -21,7 +21,6 @@ package org.sonar.server.es; import com.google.common.collect.ImmutableMap; import java.util.Map; -import org.assertj.core.data.MapEntry; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.common.settings.Settings; import org.junit.Rule; @@ -31,6 +30,7 @@ import org.sonar.api.config.MapSettings; import org.sonar.process.ProcessProperties; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.data.MapEntry.entry; import static org.junit.Assert.fail; public class NewIndexTest { @@ -203,7 +203,7 @@ public class NewIndexTest { mapping = index.getTypes().get("issue"); assertThat(mapping).isNotNull(); - assertThat((Map<String, Object>) mapping.getAttributes().get("_source")).containsExactly(MapEntry.entry("enabled", true)); + assertThat(getAttributeAsMap(mapping, "_source")).containsExactly(entry("enabled", true)); } @Test @@ -214,6 +214,28 @@ public class NewIndexTest { mapping = index.getTypes().get("issue"); assertThat(mapping).isNotNull(); - assertThat((Map<String, Object>) mapping.getAttributes().get("_source")).containsExactly(MapEntry.entry("enabled", false)); + assertThat(getAttributeAsMap(mapping, "_source")).containsExactly(entry("enabled", false)); + } + + @Test + public void index_requires_project_authorization() { + NewIndex index = new NewIndex("issues"); + index.createType("issue") + // creates a second type "authorization" and configures _parent and _routing fields + .requireProjectAuthorization(); + + // issue type + NewIndex.NewIndexType issueType = index.getTypes().get("issue"); + assertThat(getAttributeAsMap(issueType, "_parent")).containsExactly(entry("type", "authorization")); + assertThat(getAttributeAsMap(issueType, "_routing")).containsExactly(entry("required", true)); + + // authorization type + NewIndex.NewIndexType authorizationType = index.getTypes().get("authorization"); + assertThat(getAttributeAsMap(authorizationType,"_parent")).isNull(); + assertThat(getAttributeAsMap(authorizationType,"_routing")).containsExactly(entry("required", true)); + } + + private static Map<String, Object> getAttributeAsMap(NewIndex.NewIndexType type, String attributeKey) { + return (Map<String, Object>) type.getAttributes().get(attributeKey); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueQueryTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueQueryTest.java index fbf7d253174..66f1e06cf86 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueQueryTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueQueryTest.java @@ -21,23 +21,19 @@ package org.sonar.server.issue; import com.google.common.collect.Lists; import java.util.Date; -import org.junit.Rule; import org.junit.Test; import org.sonar.api.issue.Issue; import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.Severity; -import org.sonar.server.tester.UserSessionRule; import static com.google.common.collect.Lists.newArrayList; import static org.assertj.core.api.Assertions.assertThat; public class IssueQueryTest { - @Rule - public UserSessionRule userSessionRule = UserSessionRule.standalone(); @Test public void build_query() { - IssueQuery query = IssueQuery.builder(userSessionRule) + IssueQuery query = IssueQuery.builder() .issueKeys(newArrayList("ABCDE")) .severities(newArrayList(Severity.BLOCKER)) .statuses(Lists.newArrayList(Issue.STATUS_RESOLVED)) @@ -81,7 +77,7 @@ public class IssueQueryTest { @Test public void build_query_without_dates() { - IssueQuery query = IssueQuery.builder(userSessionRule) + IssueQuery query = IssueQuery.builder() .issueKeys(newArrayList("ABCDE")) .createdAfter(null) .createdBefore(null) @@ -97,7 +93,7 @@ public class IssueQueryTest { @Test public void throw_exception_if_sort_is_not_valid() { try { - IssueQuery.builder(userSessionRule) + IssueQuery.builder() .sort("UNKNOWN") .build(); } catch (Exception e) { @@ -107,7 +103,7 @@ public class IssueQueryTest { @Test public void collection_params_should_not_be_null_but_empty() { - IssueQuery query = IssueQuery.builder(userSessionRule) + IssueQuery query = IssueQuery.builder() .issueKeys(null) .componentUuids(null) .moduleUuids(null) @@ -135,7 +131,7 @@ public class IssueQueryTest { @Test public void test_default_query() throws Exception { - IssueQuery query = IssueQuery.builder(userSessionRule).build(); + IssueQuery query = IssueQuery.builder().build(); assertThat(query.issueKeys()).isEmpty(); assertThat(query.componentUuids()).isEmpty(); assertThat(query.moduleUuids()).isEmpty(); @@ -156,7 +152,7 @@ public class IssueQueryTest { @Test public void should_accept_null_sort() { - IssueQuery query = IssueQuery.builder(userSessionRule).sort(null).build(); + IssueQuery query = IssueQuery.builder().sort(null).build(); assertThat(query.sort()).isNull(); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceMediumTest.java index 3d0c28d87ab..4b1dd6163e9 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceMediumTest.java @@ -44,7 +44,10 @@ import org.sonar.db.rule.RuleDao; import org.sonar.db.rule.RuleDto; import org.sonar.db.rule.RuleTesting; import org.sonar.db.user.UserDto; +import org.sonar.server.es.SearchOptions; +import org.sonar.server.es.SearchResult; import org.sonar.server.exceptions.BadRequestException; +import org.sonar.server.issue.index.IssueDoc; import org.sonar.server.issue.index.IssueIndex; import org.sonar.server.issue.index.IssueIndexer; import org.sonar.server.permission.GroupPermissionChange; @@ -56,6 +59,7 @@ import org.sonar.server.tester.ServerTester; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.usergroups.ws.GroupIdOrAnyone; +import static com.google.common.collect.Lists.newArrayList; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; @@ -68,7 +72,7 @@ public class IssueServiceMediumTest { @Rule public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester); - private DbClient db; + private DbClient db = tester.get(DbClient.class); private IssueIndex issueIndex; private DbSession session; private IssueService service; @@ -77,7 +81,6 @@ public class IssueServiceMediumTest { @Before public void setUp() { tester.clearDbAndIndexes(); - db = tester.get(DbClient.class); issueIndex = tester.get(IssueIndex.class); session = db.openSession(false); service = tester.get(IssueService.class); @@ -107,11 +110,11 @@ public class IssueServiceMediumTest { session.commit(); index(); - assertThat(issueIndex.getByKey(issue.getKey()).assignee()).isNull(); + assertThat(getIssueByKey(issue.getKey()).assignee()).isNull(); service.assign(issue.getKey(), user.getLogin()); - assertThat(issueIndex.getByKey(issue.getKey()).assignee()).isEqualTo("perceval"); + assertThat(getIssueByKey(issue.getKey()).assignee()).isEqualTo("perceval"); } @Test @@ -128,11 +131,11 @@ public class IssueServiceMediumTest { session.commit(); index(); - assertThat(issueIndex.getByKey(issue.getKey()).assignee()).isEqualTo("perceval"); + assertThat(getIssueByKey(issue.getKey()).assignee()).isEqualTo("perceval"); service.assign(issue.getKey(), ""); - assertThat(issueIndex.getByKey(issue.getKey()).assignee()).isNull(); + assertThat(getIssueByKey(issue.getKey()).assignee()).isNull(); } @Test @@ -180,15 +183,15 @@ public class IssueServiceMediumTest { IssueDto issue = saveIssue(IssueTesting.newDto(rule, file, project)); - assertThat(issueIndex.getByKey(issue.getKey()).tags()).isEmpty(); + assertThat(getIssueByKey(issue.getKey()).tags()).isEmpty(); // Tags are lowercased service.setTags(issue.getKey(), ImmutableSet.of("bug", "Convention")); - assertThat(issueIndex.getByKey(issue.getKey()).tags()).containsOnly("bug", "convention"); + assertThat(getIssueByKey(issue.getKey()).tags()).containsOnly("bug", "convention"); // nulls and empty tags are ignored service.setTags(issue.getKey(), Sets.newHashSet("security", null, "", "convention")); - assertThat(issueIndex.getByKey(issue.getKey()).tags()).containsOnly("security", "convention"); + assertThat(getIssueByKey(issue.getKey()).tags()).containsOnly("security", "convention"); // tag validation try { @@ -196,14 +199,14 @@ public class IssueServiceMediumTest { } catch (Exception exception) { assertThat(exception).isInstanceOf(IllegalArgumentException.class); } - assertThat(issueIndex.getByKey(issue.getKey()).tags()).containsOnly("security", "convention"); + assertThat(getIssueByKey(issue.getKey()).tags()).containsOnly("security", "convention"); // unchanged tags service.setTags(issue.getKey(), ImmutableSet.of("convention", "security")); - assertThat(issueIndex.getByKey(issue.getKey()).tags()).containsOnly("security", "convention"); + assertThat(getIssueByKey(issue.getKey()).tags()).containsOnly("security", "convention"); service.setTags(issue.getKey(), ImmutableSet.<String>of()); - assertThat(issueIndex.getByKey(issue.getKey()).tags()).isEmpty(); + assertThat(getIssueByKey(issue.getKey()).tags()).isEmpty(); } @Test @@ -223,7 +226,7 @@ public class IssueServiceMediumTest { } private IssueQuery projectQuery(String projectUuid) { - return IssueQuery.builder(userSessionRule).projectUuids(asList(projectUuid)).resolved(false).build(); + return IssueQuery.builder().projectUuids(asList(projectUuid)).resolved(false).build(); } @Test @@ -276,7 +279,8 @@ public class IssueServiceMediumTest { // project can be seen by group "anyone" // TODO correctly feed default organization. Not a problem as long as issues search does not support "anyone" // for each organization - GroupPermissionChange permissionChange = new GroupPermissionChange(PermissionChange.Operation.ADD, UserRole.USER, new ProjectId(project), GroupIdOrAnyone.forAnyone(organization.getUuid())); + GroupPermissionChange permissionChange = new GroupPermissionChange(PermissionChange.Operation.ADD, UserRole.USER, new ProjectId(project), + GroupIdOrAnyone.forAnyone(organization.getUuid())); tester.get(PermissionUpdater.class).apply(session, asList(permissionChange)); userSessionRule.login(); @@ -297,4 +301,8 @@ public class IssueServiceMediumTest { return issue; } + private Issue getIssueByKey(String key) { + SearchResult<IssueDoc> result = issueIndex.search(IssueQuery.builder().issueKeys(newArrayList(key)).build(), new SearchOptions()); + return result.getDocs().get(0); + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/IssuesFinderSortTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/IssuesFinderSortTest.java index 1ef34cb2436..2cbd6084201 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/IssuesFinderSortTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/IssuesFinderSortTest.java @@ -22,10 +22,8 @@ package org.sonar.server.issue; import java.util.Date; import java.util.List; import org.apache.commons.lang.time.DateUtils; -import org.junit.Rule; import org.junit.Test; import org.sonar.db.issue.IssueDto; -import org.sonar.server.tester.UserSessionRule; import static com.google.common.collect.Lists.newArrayList; import static org.assertj.core.api.Assertions.assertThat; @@ -33,8 +31,6 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class IssuesFinderSortTest { - @Rule - public UserSessionRule userSessionRule = UserSessionRule.standalone(); @Test public void should_sort_by_assignee() { @@ -44,7 +40,7 @@ public class IssuesFinderSortTest { IssueDto issue4 = new IssueDto().setId(4L).setAssignee(null); List<IssueDto> dtoList = newArrayList(issue1, issue2, issue3, issue4); - IssueQuery query = IssueQuery.builder(userSessionRule).sort(IssueQuery.SORT_BY_ASSIGNEE).asc(true).build(); + IssueQuery query = IssueQuery.builder().sort(IssueQuery.SORT_BY_ASSIGNEE).asc(true).build(); IssuesFinderSort issuesFinderSort = new IssuesFinderSort(dtoList, query); List<IssueDto> result = newArrayList(issuesFinderSort.sort()); @@ -63,7 +59,7 @@ public class IssuesFinderSortTest { IssueDto issue3 = new IssueDto().setId(3L).setStatus("OPEN"); List<IssueDto> dtoList = newArrayList(issue1, issue2, issue3); - IssueQuery query = IssueQuery.builder(userSessionRule).sort(IssueQuery.SORT_BY_STATUS).asc(false).build(); + IssueQuery query = IssueQuery.builder().sort(IssueQuery.SORT_BY_STATUS).asc(false).build(); IssuesFinderSort issuesFinderSort = new IssuesFinderSort(dtoList, query); List<IssueDto> result = newArrayList(issuesFinderSort.sort()); @@ -81,7 +77,7 @@ public class IssuesFinderSortTest { IssueDto issue3 = new IssueDto().setId(3L).setSeverity("MAJOR"); List<IssueDto> dtoList = newArrayList(issue1, issue2, issue3); - IssueQuery query = IssueQuery.builder(userSessionRule).sort(IssueQuery.SORT_BY_SEVERITY).asc(true).build(); + IssueQuery query = IssueQuery.builder().sort(IssueQuery.SORT_BY_SEVERITY).asc(true).build(); IssuesFinderSort issuesFinderSort = new IssuesFinderSort(dtoList, query); List<IssueDto> result = newArrayList(issuesFinderSort.sort()); @@ -99,7 +95,7 @@ public class IssuesFinderSortTest { IssueDto issue3 = new IssueDto().setId(3L).setSeverity("MAJOR"); List<IssueDto> dtoList = newArrayList(issue1, issue2, issue3); - IssueQuery query = IssueQuery.builder(userSessionRule).sort(IssueQuery.SORT_BY_SEVERITY).asc(false).build(); + IssueQuery query = IssueQuery.builder().sort(IssueQuery.SORT_BY_SEVERITY).asc(false).build(); IssuesFinderSort issuesFinderSort = new IssuesFinderSort(dtoList, query); List<IssueDto> result = newArrayList(issuesFinderSort.sort()); @@ -121,7 +117,7 @@ public class IssuesFinderSortTest { IssueDto issue3 = new IssueDto().setId(3L).setIssueCreationDate(date2); List<IssueDto> dtoList = newArrayList(issue1, issue2, issue3); - IssueQuery query = IssueQuery.builder(userSessionRule).sort(IssueQuery.SORT_BY_CREATION_DATE).asc(false).build(); + IssueQuery query = IssueQuery.builder().sort(IssueQuery.SORT_BY_CREATION_DATE).asc(false).build(); IssuesFinderSort issuesFinderSort = new IssuesFinderSort(dtoList, query); List<IssueDto> result = newArrayList(issuesFinderSort.sort()); @@ -143,7 +139,7 @@ public class IssuesFinderSortTest { IssueDto issue3 = new IssueDto().setId(3L).setIssueUpdateDate(date2); List<IssueDto> dtoList = newArrayList(issue1, issue2, issue3); - IssueQuery query = IssueQuery.builder(userSessionRule).sort(IssueQuery.SORT_BY_UPDATE_DATE).asc(false).build(); + IssueQuery query = IssueQuery.builder().sort(IssueQuery.SORT_BY_UPDATE_DATE).asc(false).build(); IssuesFinderSort issuesFinderSort = new IssuesFinderSort(dtoList, query); List<IssueDto> result = newArrayList(issuesFinderSort.sort()); @@ -165,7 +161,7 @@ public class IssuesFinderSortTest { IssueDto issue3 = new IssueDto().setId(3L).setIssueCloseDate(date2); List<IssueDto> dtoList = newArrayList(issue1, issue2, issue3); - IssueQuery query = IssueQuery.builder(userSessionRule).sort(IssueQuery.SORT_BY_CLOSE_DATE).asc(false).build(); + IssueQuery query = IssueQuery.builder().sort(IssueQuery.SORT_BY_CLOSE_DATE).asc(false).build(); IssuesFinderSort issuesFinderSort = new IssuesFinderSort(dtoList, query); List<IssueDto> result = newArrayList(issuesFinderSort.sort()); @@ -184,7 +180,7 @@ public class IssuesFinderSortTest { IssueDto issue4 = new IssueDto().setId(4L).setAssignee(null); List<IssueDto> dtoList = newArrayList(issue1, issue2, issue3, issue4); - IssueQuery query = IssueQuery.builder(userSessionRule).sort(null).build(); + IssueQuery query = IssueQuery.builder().sort(null).build(); IssuesFinderSort issuesFinderSort = new IssuesFinderSort(dtoList, query); List<IssueDto> result = newArrayList(issuesFinderSort.sort()); diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexDebtTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexDebtTest.java index 490f5a23cd2..cec3bb4fe19 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexDebtTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexDebtTest.java @@ -27,6 +27,7 @@ import org.junit.Rule; import org.junit.Test; import org.sonar.api.config.MapSettings; import org.sonar.api.issue.Issue; +import org.sonar.api.resources.Qualifiers; import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.Severity; import org.sonar.api.security.DefaultGroups; @@ -41,14 +42,14 @@ import org.sonar.server.es.SearchResult; import org.sonar.server.issue.IssueDocTesting; import org.sonar.server.issue.IssueQuery; import org.sonar.server.issue.IssueQuery.Builder; +import org.sonar.server.permission.index.AuthorizationTypeSupport; +import org.sonar.server.permission.index.PermissionIndexerDao; import org.sonar.server.permission.index.PermissionIndexerTester; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.view.index.ViewIndexDefinition; -import org.sonar.server.view.index.ViewIndexer; import static com.google.common.collect.Lists.newArrayList; import static java.util.Arrays.asList; -import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; import static org.mockito.Mockito.mock; @@ -66,20 +67,16 @@ public class IssueIndexDebtTest { public UserSessionRule userSessionRule = UserSessionRule.standalone(); private System2 system2 = System2.INSTANCE; - IssueIndex index; - - IssueIndexer issueIndexer; - PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(tester); - ViewIndexer viewIndexer; + private IssueIndex index; + private IssueIndexer issueIndexer = new IssueIndexer(system2, null, tester.client()); + private PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(tester, issueIndexer); @Before public void setUp() { - issueIndexer = new IssueIndexer(system2, null, tester.client()); - viewIndexer = new ViewIndexer(system2, null, tester.client()); System2 system = mock(System2.class); when(system.getDefaultTimeZone()).thenReturn(TimeZone.getTimeZone("+01:00")); when(system.now()).thenReturn(System.currentTimeMillis()); - index = new IssueIndex(tester.client(), system, userSessionRule); + index = new IssueIndex(tester.client(), system, userSessionRule, new AuthorizationTypeSupport(userSessionRule)); } @Test @@ -259,7 +256,7 @@ public class IssueIndexDebtTest { IssueDocTesting.newDoc("ISSUE2", ComponentTesting.newFileDto(project, null)).setEffort(10L), IssueDocTesting.newDoc("ISSUE3", ComponentTesting.newFileDto(project2, null)).setEffort(10L)); - SearchResult<IssueDoc> result = index.search(IssueQuery.builder(userSessionRule).facetMode(DEPRECATED_FACET_MODE_DEBT).build(), + SearchResult<IssueDoc> result = index.search(IssueQuery.builder().facetMode(DEPRECATED_FACET_MODE_DEBT).build(), new SearchOptions().addFacets(newArrayList("projectUuids"))); assertThat(result.getFacets().getNames()).containsOnly("projectUuids", FACET_MODE_EFFORT); assertThat(result.getFacets().get("projectUuids")).containsOnly(entry("ABCD", 20L), entry("EFGH", 10L)); @@ -291,10 +288,17 @@ public class IssueIndexDebtTest { } private void addIssueAuthorization(String projectUuid, @Nullable String group, @Nullable Long user) { - authorizationIndexerTester.indexProjectPermission(projectUuid, singletonList(group), singletonList(user)); + PermissionIndexerDao.Dto access = new PermissionIndexerDao.Dto(projectUuid, system2.now(), Qualifiers.PROJECT); + if (group != null) { + access.addGroup(group); + } + if (user != null) { + access.addUser(user); + } + authorizationIndexerTester.allow(access); } private Builder newQueryBuilder() { - return IssueQuery.builder(userSessionRule).facetMode(FACET_MODE_EFFORT); + return IssueQuery.builder().facetMode(FACET_MODE_EFFORT); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java index 5170c06ad84..cdef73a9eab 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java @@ -27,7 +27,6 @@ import java.util.Date; import java.util.List; import java.util.Map; import java.util.TimeZone; -import javax.annotation.Nullable; import org.assertj.core.api.Fail; import org.junit.Before; import org.junit.Rule; @@ -38,7 +37,6 @@ import org.sonar.api.issue.Issue; import org.sonar.api.resources.Scopes; import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.Severity; -import org.sonar.api.security.DefaultGroups; import org.sonar.api.utils.Duration; import org.sonar.api.utils.KeyValueFormat; import org.sonar.api.utils.System2; @@ -48,9 +46,10 @@ import org.sonar.db.organization.OrganizationDto; import org.sonar.server.es.EsTester; import org.sonar.server.es.SearchOptions; import org.sonar.server.es.SearchResult; -import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.issue.IssueDocTesting; import org.sonar.server.issue.IssueQuery; +import org.sonar.server.permission.index.AuthorizationTypeSupport; +import org.sonar.server.permission.index.PermissionIndexerDao; import org.sonar.server.permission.index.PermissionIndexerTester; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.view.index.ViewDoc; @@ -58,7 +57,6 @@ import org.sonar.server.view.index.ViewIndexDefinition; import org.sonar.server.view.index.ViewIndexer; 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.assertj.core.api.Assertions.entry; import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown; @@ -80,21 +78,18 @@ public class IssueIndexTest { @Rule public ExpectedException expectedException = ExpectedException.none(); - IssueIndex underTest; - - IssueIndexer issueIndexer; - PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(tester); - ViewIndexer viewIndexer; + private IssueIndex underTest; + private IssueIndexer issueIndexer = new IssueIndexer(system2, null, tester.client()); + private ViewIndexer viewIndexer = new ViewIndexer(system2, null, tester.client()); + private PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(tester, issueIndexer); @Before public void setUp() { - issueIndexer = new IssueIndexer(system2, null, tester.client()); - viewIndexer = new ViewIndexer(system2, null, tester.client()); System2 system = mock(System2.class); when(system.getDefaultTimeZone()).thenReturn(TimeZone.getTimeZone("GMT-1:00")); when(system.now()).thenReturn(System.currentTimeMillis()); - underTest = new IssueIndex(tester.client(), system, userSessionRule); + underTest = new IssueIndex(tester.client(), system, userSessionRule, new AuthorizationTypeSupport(userSessionRule)); } @Test @@ -105,13 +100,18 @@ public class IssueIndexTest { .setEffort(100L); indexIssues(issue); - Issue loaded = underTest.getByKey(issue.key()); + Issue loaded = getByKey(issue.key()); assertThat(loaded).isNotNull(); assertThat(loaded.key()).isEqualTo("ISSUE1"); assertThat(loaded.effort()).isEqualTo(Duration.create(100L)); } + private Issue getByKey(String key) { + SearchResult<IssueDoc> result = underTest.search(IssueQuery.builder().issueKeys(newArrayList(key)).build(), new SearchOptions()); + return result.getDocs().get(0); + } + @Test public void get_by_key_with_attributes() { ComponentDto project = ComponentTesting.newProjectDto(newOrganizationDto()); @@ -119,7 +119,7 @@ public class IssueIndexTest { IssueDoc issue = IssueDocTesting.newDoc("ISSUE1", file).setAttributes((KeyValueFormat.format(ImmutableMap.of("jira-issue-key", "SONAR-1234")))); indexIssues(issue); - Issue result = underTest.getByKey(issue.key()); + Issue result = getByKey(issue.key()); assertThat(result.attribute("jira-issue-key")).isEqualTo("SONAR-1234"); } @@ -130,7 +130,7 @@ public class IssueIndexTest { IssueDoc issue = IssueDocTesting.newDoc("ISSUE1", file); indexIssues(issue); - Issue result = underTest.getByKey(issue.key()); + Issue result = getByKey(issue.key()); result.comments(); } @@ -141,15 +141,10 @@ public class IssueIndexTest { IssueDoc issue = IssueDocTesting.newDoc("ISSUE1", file); indexIssues(issue); - Issue result = underTest.getByKey(issue.key()); + Issue result = getByKey(issue.key()); result.isNew(); } - @Test(expected = NotFoundException.class) - public void fail_to_get_unknown_key() { - underTest.getByKey("unknown"); - } - @Test public void filter_by_keys() { ComponentDto project = ComponentTesting.newProjectDto(newOrganizationDto()); @@ -158,9 +153,9 @@ public class IssueIndexTest { IssueDocTesting.newDoc("1", ComponentTesting.newFileDto(project, null)), IssueDocTesting.newDoc("2", ComponentTesting.newFileDto(project, null))); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).issueKeys(newArrayList("1", "2")).build(), new SearchOptions()).getDocs()).hasSize(2); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).issueKeys(newArrayList("1")).build(), new SearchOptions()).getDocs()).hasSize(1); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).issueKeys(newArrayList("3", "4")).build(), new SearchOptions()).getDocs()).isEmpty(); + assertThat(underTest.search(IssueQuery.builder().issueKeys(newArrayList("1", "2")).build(), new SearchOptions()).getDocs()).hasSize(2); + assertThat(underTest.search(IssueQuery.builder().issueKeys(newArrayList("1")).build(), new SearchOptions()).getDocs()).hasSize(1); + assertThat(underTest.search(IssueQuery.builder().issueKeys(newArrayList("3", "4")).build(), new SearchOptions()).getDocs()).isEmpty(); } @Test @@ -177,8 +172,8 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE5", subModule), IssueDocTesting.newDoc("ISSUE6", ComponentTesting.newFileDto(subModule, null))); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).projectUuids(newArrayList(project.uuid())).build(), new SearchOptions()).getDocs()).hasSize(6); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).projectUuids(newArrayList("unknown")).build(), new SearchOptions()).getDocs()).isEmpty(); + assertThat(underTest.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid())).build(), new SearchOptions()).getDocs()).hasSize(6); + assertThat(underTest.search(IssueQuery.builder().projectUuids(newArrayList("unknown")).build(), new SearchOptions()).getDocs()).isEmpty(); } @Test @@ -192,7 +187,7 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE2", ComponentTesting.newFileDto(project, null)), IssueDocTesting.newDoc("ISSUE3", ComponentTesting.newFileDto(project2, null))); - SearchResult<IssueDoc> result = underTest.search(IssueQuery.builder(userSessionRule).build(), new SearchOptions().addFacets(newArrayList("projectUuids"))); + SearchResult<IssueDoc> result = underTest.search(IssueQuery.builder().build(), new SearchOptions().addFacets(newArrayList("projectUuids"))); assertThat(result.getFacets().getNames()).containsOnly("projectUuids"); assertThat(result.getFacets().get("projectUuids")).containsOnly(entry("ABCD", 2L), entry("EFGH", 1L)); } @@ -210,23 +205,23 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE2", file)); assertThat( - underTest.search(IssueQuery.builder(userSessionRule).projectUuids(newArrayList(project.uuid())).moduleUuids(newArrayList(file.uuid())).build(), new SearchOptions()) + underTest.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid())).moduleUuids(newArrayList(file.uuid())).build(), new SearchOptions()) .getDocs()) .isEmpty(); assertThat( - underTest.search(IssueQuery.builder(userSessionRule).projectUuids(newArrayList(project.uuid())).moduleUuids(newArrayList(module.uuid())).build(), new SearchOptions()) + underTest.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid())).moduleUuids(newArrayList(module.uuid())).build(), new SearchOptions()) .getDocs()) .hasSize(1); assertThat( - underTest.search(IssueQuery.builder(userSessionRule).projectUuids(newArrayList(project.uuid())).moduleUuids(newArrayList(subModule.uuid())).build(), new SearchOptions()) + underTest.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid())).moduleUuids(newArrayList(subModule.uuid())).build(), new SearchOptions()) .getDocs()) .hasSize(2); assertThat( - underTest.search(IssueQuery.builder(userSessionRule).projectUuids(newArrayList(project.uuid())).moduleUuids(newArrayList(project.uuid())).build(), new SearchOptions()) + underTest.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid())).moduleUuids(newArrayList(project.uuid())).build(), new SearchOptions()) .getDocs()) .isEmpty(); assertThat( - underTest.search(IssueQuery.builder(userSessionRule).projectUuids(newArrayList(project.uuid())).moduleUuids(newArrayList("unknown")).build(), new SearchOptions()).getDocs()) + underTest.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid())).moduleUuids(newArrayList("unknown")).build(), new SearchOptions()).getDocs()) .isEmpty(); } @@ -249,19 +244,19 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE5", subModule), IssueDocTesting.newDoc("ISSUE6", file3)); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).fileUuids(newArrayList(file1.uuid(), file2.uuid(), file3.uuid())).build(), new SearchOptions()) + assertThat(underTest.search(IssueQuery.builder().fileUuids(newArrayList(file1.uuid(), file2.uuid(), file3.uuid())).build(), new SearchOptions()) .getDocs()).hasSize(3); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).fileUuids(newArrayList(file1.uuid())).build(), new SearchOptions()) + assertThat(underTest.search(IssueQuery.builder().fileUuids(newArrayList(file1.uuid())).build(), new SearchOptions()) .getDocs()).hasSize(1); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).moduleRootUuids(newArrayList(subModule.uuid())).build(), new SearchOptions()) + assertThat(underTest.search(IssueQuery.builder().moduleRootUuids(newArrayList(subModule.uuid())).build(), new SearchOptions()) .getDocs()).hasSize(2); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).moduleRootUuids(newArrayList(module.uuid())).build(), new SearchOptions()) + assertThat(underTest.search(IssueQuery.builder().moduleRootUuids(newArrayList(module.uuid())).build(), new SearchOptions()) .getDocs()).hasSize(4); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).projectUuids(newArrayList(project.uuid())).build(), new SearchOptions()) + assertThat(underTest.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid())).build(), new SearchOptions()) .getDocs()).hasSize(6); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).viewUuids(newArrayList(view)).build(), new SearchOptions()) + assertThat(underTest.search(IssueQuery.builder().viewUuids(newArrayList(view)).build(), new SearchOptions()) .getDocs()).hasSize(6); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).projectUuids(newArrayList("unknown")).build(), new SearchOptions()) + assertThat(underTest.search(IssueQuery.builder().projectUuids(newArrayList("unknown")).build(), new SearchOptions()) .getDocs()).isEmpty(); } @@ -284,15 +279,15 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE5", subModule), IssueDocTesting.newDoc("ISSUE6", file3)); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).projectUuids(newArrayList("unknown")).build(), new SearchOptions()).getDocs()).isEmpty(); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).projectUuids(newArrayList(project.uuid())).build(), new SearchOptions()).getDocs()).hasSize(6); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).viewUuids(newArrayList(view)).build(), new SearchOptions()).getDocs()).hasSize(6); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).moduleUuids(newArrayList(module.uuid())).build(), new SearchOptions()).getDocs()).hasSize(2); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).moduleUuids(newArrayList(subModule.uuid())).build(), new SearchOptions()).getDocs()).hasSize(2); // XXX + assertThat(underTest.search(IssueQuery.builder().projectUuids(newArrayList("unknown")).build(), new SearchOptions()).getDocs()).isEmpty(); + assertThat(underTest.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid())).build(), new SearchOptions()).getDocs()).hasSize(6); + assertThat(underTest.search(IssueQuery.builder().viewUuids(newArrayList(view)).build(), new SearchOptions()).getDocs()).hasSize(6); + assertThat(underTest.search(IssueQuery.builder().moduleUuids(newArrayList(module.uuid())).build(), new SearchOptions()).getDocs()).hasSize(2); + assertThat(underTest.search(IssueQuery.builder().moduleUuids(newArrayList(subModule.uuid())).build(), new SearchOptions()).getDocs()).hasSize(2); // XXX // Misleading // ! - assertThat(underTest.search(IssueQuery.builder(userSessionRule).fileUuids(newArrayList(file1.uuid())).build(), new SearchOptions()).getDocs()).hasSize(1); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).fileUuids(newArrayList(file1.uuid(), file2.uuid(), file3.uuid())).build(), new SearchOptions()).getDocs()) + assertThat(underTest.search(IssueQuery.builder().fileUuids(newArrayList(file1.uuid())).build(), new SearchOptions()).getDocs()).hasSize(1); + assertThat(underTest.search(IssueQuery.builder().fileUuids(newArrayList(file1.uuid(), file2.uuid(), file3.uuid())).build(), new SearchOptions()).getDocs()) .hasSize(3); } @@ -310,7 +305,7 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE4", file2), IssueDocTesting.newDoc("ISSUE5", file3)); - SearchResult<IssueDoc> result = underTest.search(IssueQuery.builder(userSessionRule).build(), new SearchOptions().addFacets(newArrayList("fileUuids"))); + SearchResult<IssueDoc> result = underTest.search(IssueQuery.builder().build(), new SearchOptions().addFacets(newArrayList("fileUuids"))); assertThat(result.getFacets().getNames()).containsOnly("fileUuids"); assertThat(result.getFacets().get("fileUuids")) .containsOnly(entry("A", 1L), entry("ABCD", 1L), entry("BCDE", 2L), entry("CDEF", 1L)); @@ -326,9 +321,9 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE1", file1).setDirectoryPath("/src/main/xoo"), IssueDocTesting.newDoc("ISSUE2", file2).setDirectoryPath("/")); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).directories(newArrayList("/src/main/xoo")).build(), new SearchOptions()).getDocs()).hasSize(1); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).directories(newArrayList("/")).build(), new SearchOptions()).getDocs()).hasSize(1); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).directories(newArrayList("unknown")).build(), new SearchOptions()).getDocs()).isEmpty(); + assertThat(underTest.search(IssueQuery.builder().directories(newArrayList("/src/main/xoo")).build(), new SearchOptions()).getDocs()).hasSize(1); + assertThat(underTest.search(IssueQuery.builder().directories(newArrayList("/")).build(), new SearchOptions()).getDocs()).hasSize(1); + assertThat(underTest.search(IssueQuery.builder().directories(newArrayList("unknown")).build(), new SearchOptions()).getDocs()).isEmpty(); } @Test @@ -341,7 +336,7 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE1", file1).setDirectoryPath("/src/main/xoo"), IssueDocTesting.newDoc("ISSUE2", file2).setDirectoryPath("/")); - SearchResult<IssueDoc> result = underTest.search(IssueQuery.builder(userSessionRule).build(), new SearchOptions().addFacets(newArrayList("directories"))); + SearchResult<IssueDoc> result = underTest.search(IssueQuery.builder().build(), new SearchOptions().addFacets(newArrayList("directories"))); assertThat(result.getFacets().getNames()).containsOnly("directories"); assertThat(result.getFacets().get("directories")).containsOnly(entry("/src/main/xoo", 1L), entry("/", 1L)); } @@ -367,10 +362,10 @@ public class IssueIndexTest { String view2 = "CDEF"; indexView(view2, newArrayList(project2.uuid())); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).viewUuids(newArrayList(view1)).build(), new SearchOptions()).getDocs()).hasSize(2); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).viewUuids(newArrayList(view2)).build(), new SearchOptions()).getDocs()).hasSize(1); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).viewUuids(newArrayList(view1, view2)).build(), new SearchOptions()).getDocs()).hasSize(3); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).viewUuids(newArrayList("unknown")).build(), new SearchOptions()).getDocs()).isEmpty(); + assertThat(underTest.search(IssueQuery.builder().viewUuids(newArrayList(view1)).build(), new SearchOptions()).getDocs()).hasSize(2); + assertThat(underTest.search(IssueQuery.builder().viewUuids(newArrayList(view2)).build(), new SearchOptions()).getDocs()).hasSize(1); + assertThat(underTest.search(IssueQuery.builder().viewUuids(newArrayList(view1, view2)).build(), new SearchOptions()).getDocs()).hasSize(3); + assertThat(underTest.search(IssueQuery.builder().viewUuids(newArrayList("unknown")).build(), new SearchOptions()).getDocs()).isEmpty(); } @Test @@ -382,9 +377,9 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE1", file).setSeverity(Severity.INFO), IssueDocTesting.newDoc("ISSUE2", file).setSeverity(Severity.MAJOR)); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).severities(newArrayList(Severity.INFO, Severity.MAJOR)).build(), new SearchOptions()).getDocs()).hasSize(2); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).severities(newArrayList(Severity.INFO)).build(), new SearchOptions()).getDocs()).hasSize(1); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).severities(newArrayList(Severity.BLOCKER)).build(), new SearchOptions()).getDocs()).isEmpty(); + assertThat(underTest.search(IssueQuery.builder().severities(newArrayList(Severity.INFO, Severity.MAJOR)).build(), new SearchOptions()).getDocs()).hasSize(2); + assertThat(underTest.search(IssueQuery.builder().severities(newArrayList(Severity.INFO)).build(), new SearchOptions()).getDocs()).hasSize(1); + assertThat(underTest.search(IssueQuery.builder().severities(newArrayList(Severity.BLOCKER)).build(), new SearchOptions()).getDocs()).isEmpty(); } @Test @@ -397,7 +392,7 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE2", file).setSeverity(Severity.INFO), IssueDocTesting.newDoc("ISSUE3", file).setSeverity(Severity.MAJOR)); - SearchResult<IssueDoc> result = underTest.search(IssueQuery.builder(userSessionRule).build(), new SearchOptions().addFacets(newArrayList("severities"))); + SearchResult<IssueDoc> result = underTest.search(IssueQuery.builder().build(), new SearchOptions().addFacets(newArrayList("severities"))); assertThat(result.getFacets().getNames()).containsOnly("severities"); assertThat(result.getFacets().get("severities")).containsOnly(entry("INFO", 2L), entry("MAJOR", 1L)); } @@ -411,10 +406,10 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE1", file).setStatus(Issue.STATUS_CLOSED), IssueDocTesting.newDoc("ISSUE2", file).setStatus(Issue.STATUS_OPEN)); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).statuses(newArrayList(Issue.STATUS_CLOSED, Issue.STATUS_OPEN)).build(), new SearchOptions()).getDocs()) + assertThat(underTest.search(IssueQuery.builder().statuses(newArrayList(Issue.STATUS_CLOSED, Issue.STATUS_OPEN)).build(), new SearchOptions()).getDocs()) .hasSize(2); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).statuses(newArrayList(Issue.STATUS_CLOSED)).build(), new SearchOptions()).getDocs()).hasSize(1); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).statuses(newArrayList(Issue.STATUS_CONFIRMED)).build(), new SearchOptions()).getDocs()).isEmpty(); + assertThat(underTest.search(IssueQuery.builder().statuses(newArrayList(Issue.STATUS_CLOSED)).build(), new SearchOptions()).getDocs()).hasSize(1); + assertThat(underTest.search(IssueQuery.builder().statuses(newArrayList(Issue.STATUS_CONFIRMED)).build(), new SearchOptions()).getDocs()).isEmpty(); } @Test @@ -427,7 +422,7 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE2", file).setStatus(Issue.STATUS_CLOSED), IssueDocTesting.newDoc("ISSUE3", file).setStatus(Issue.STATUS_OPEN)); - SearchResult<IssueDoc> result = underTest.search(IssueQuery.builder(userSessionRule).build(), new SearchOptions().addFacets(newArrayList("statuses"))); + SearchResult<IssueDoc> result = underTest.search(IssueQuery.builder().build(), new SearchOptions().addFacets(newArrayList("statuses"))); assertThat(result.getFacets().getNames()).containsOnly("statuses"); assertThat(result.getFacets().get("statuses")).containsOnly(entry("CLOSED", 2L), entry("OPEN", 1L)); } @@ -442,11 +437,11 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE2", file).setResolution(Issue.RESOLUTION_FIXED)); assertThat( - underTest.search(IssueQuery.builder(userSessionRule).resolutions(newArrayList(Issue.RESOLUTION_FALSE_POSITIVE, Issue.RESOLUTION_FIXED)).build(), new SearchOptions()) + underTest.search(IssueQuery.builder().resolutions(newArrayList(Issue.RESOLUTION_FALSE_POSITIVE, Issue.RESOLUTION_FIXED)).build(), new SearchOptions()) .getDocs()) .hasSize(2); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).resolutions(newArrayList(Issue.RESOLUTION_FALSE_POSITIVE)).build(), new SearchOptions()).getDocs()).hasSize(1); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).resolutions(newArrayList(Issue.RESOLUTION_REMOVED)).build(), new SearchOptions()).getDocs()).isEmpty(); + assertThat(underTest.search(IssueQuery.builder().resolutions(newArrayList(Issue.RESOLUTION_FALSE_POSITIVE)).build(), new SearchOptions()).getDocs()).hasSize(1); + assertThat(underTest.search(IssueQuery.builder().resolutions(newArrayList(Issue.RESOLUTION_REMOVED)).build(), new SearchOptions()).getDocs()).isEmpty(); } @Test @@ -459,7 +454,7 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE2", file).setResolution(Issue.RESOLUTION_FALSE_POSITIVE), IssueDocTesting.newDoc("ISSUE3", file).setResolution(Issue.RESOLUTION_FIXED)); - SearchResult<IssueDoc> result = underTest.search(IssueQuery.builder(userSessionRule).build(), new SearchOptions().addFacets(newArrayList("resolutions"))); + SearchResult<IssueDoc> result = underTest.search(IssueQuery.builder().build(), new SearchOptions().addFacets(newArrayList("resolutions"))); assertThat(result.getFacets().getNames()).containsOnly("resolutions"); assertThat(result.getFacets().get("resolutions")).containsOnly(entry("FALSE-POSITIVE", 2L), entry("FIXED", 1L)); } @@ -474,9 +469,9 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE2", file).setStatus(Issue.STATUS_OPEN).setResolution(null), IssueDocTesting.newDoc("ISSUE3", file).setStatus(Issue.STATUS_OPEN).setResolution(null)); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).resolved(true).build(), new SearchOptions()).getDocs()).hasSize(1); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).resolved(false).build(), new SearchOptions()).getDocs()).hasSize(2); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).resolved(null).build(), new SearchOptions()).getDocs()).hasSize(3); + assertThat(underTest.search(IssueQuery.builder().resolved(true).build(), new SearchOptions()).getDocs()).hasSize(1); + assertThat(underTest.search(IssueQuery.builder().resolved(false).build(), new SearchOptions()).getDocs()).hasSize(2); + assertThat(underTest.search(IssueQuery.builder().resolved(null).build(), new SearchOptions()).getDocs()).hasSize(3); } @Test @@ -487,8 +482,8 @@ public class IssueIndexTest { indexIssues(IssueDocTesting.newDoc("ISSUE1", file).setRuleKey(ruleKey.toString())); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).rules(newArrayList(ruleKey)).build(), new SearchOptions()).getDocs()).hasSize(1); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).rules(newArrayList(RuleKey.of("rule", "without issue"))).build(), new SearchOptions()).getDocs()).isEmpty(); + assertThat(underTest.search(IssueQuery.builder().rules(newArrayList(ruleKey)).build(), new SearchOptions()).getDocs()).hasSize(1); + assertThat(underTest.search(IssueQuery.builder().rules(newArrayList(RuleKey.of("rule", "without issue"))).build(), new SearchOptions()).getDocs()).isEmpty(); } @Test @@ -499,9 +494,9 @@ public class IssueIndexTest { indexIssues(IssueDocTesting.newDoc("ISSUE1", file).setRuleKey(ruleKey.toString()).setLanguage("xoo")); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).languages(newArrayList("xoo")).build(), + assertThat(underTest.search(IssueQuery.builder().languages(newArrayList("xoo")).build(), new SearchOptions()).getDocs()).hasSize(1); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).languages(newArrayList("unknown")).build(), new SearchOptions()).getDocs()).isEmpty(); + assertThat(underTest.search(IssueQuery.builder().languages(newArrayList("unknown")).build(), new SearchOptions()).getDocs()).isEmpty(); } @Test @@ -512,7 +507,7 @@ public class IssueIndexTest { indexIssues(IssueDocTesting.newDoc("ISSUE1", file).setRuleKey(ruleKey.toString()).setLanguage("xoo")); - SearchResult<IssueDoc> result = underTest.search(IssueQuery.builder(userSessionRule).build(), new SearchOptions().addFacets(newArrayList("languages"))); + SearchResult<IssueDoc> result = underTest.search(IssueQuery.builder().build(), new SearchOptions().addFacets(newArrayList("languages"))); assertThat(result.getFacets().getNames()).containsOnly("languages"); assertThat(result.getFacets().get("languages")).containsOnly(entry("xoo", 1L)); } @@ -527,9 +522,9 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE2", file).setAssignee("simon"), IssueDocTesting.newDoc("ISSUE3", file).setAssignee(null)); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).assignees(newArrayList("steph")).build(), new SearchOptions()).getDocs()).hasSize(1); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).assignees(newArrayList("steph", "simon")).build(), new SearchOptions()).getDocs()).hasSize(2); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).assignees(newArrayList("unknown")).build(), new SearchOptions()).getDocs()).isEmpty(); + assertThat(underTest.search(IssueQuery.builder().assignees(newArrayList("steph")).build(), new SearchOptions()).getDocs()).hasSize(1); + assertThat(underTest.search(IssueQuery.builder().assignees(newArrayList("steph", "simon")).build(), new SearchOptions()).getDocs()).hasSize(2); + assertThat(underTest.search(IssueQuery.builder().assignees(newArrayList("unknown")).build(), new SearchOptions()).getDocs()).isEmpty(); } @Test @@ -543,7 +538,7 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE3", file).setAssignee("simon"), IssueDocTesting.newDoc("ISSUE4", file).setAssignee(null)); - SearchResult<IssueDoc> result = underTest.search(IssueQuery.builder(userSessionRule).build(), new SearchOptions().addFacets(newArrayList("assignees"))); + SearchResult<IssueDoc> result = underTest.search(IssueQuery.builder().build(), new SearchOptions().addFacets(newArrayList("assignees"))); assertThat(result.getFacets().getNames()).containsOnly("assignees"); assertThat(result.getFacets().get("assignees")).containsOnly(entry("steph", 1L), entry("simon", 2L), entry("", 1L)); } @@ -559,7 +554,7 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE3", file).setAssignee("simon"), IssueDocTesting.newDoc("ISSUE4", file).setAssignee(null)); - SearchResult<IssueDoc> result = underTest.search(IssueQuery.builder(userSessionRule).assignees(Arrays.asList("j-b")).build(), + SearchResult<IssueDoc> result = underTest.search(IssueQuery.builder().assignees(Arrays.asList("j-b")).build(), new SearchOptions().addFacets(newArrayList("assignees"))); assertThat(result.getFacets().getNames()).containsOnly("assignees"); assertThat(result.getFacets().get("assignees")).containsOnly(entry("j-b", 1L), entry("simon", 2L), entry("", 1L)); @@ -575,9 +570,9 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE2", file).setAssignee(null), IssueDocTesting.newDoc("ISSUE3", file).setAssignee(null)); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).assigned(true).build(), new SearchOptions()).getDocs()).hasSize(1); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).assigned(false).build(), new SearchOptions()).getDocs()).hasSize(2); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).assigned(null).build(), new SearchOptions()).getDocs()).hasSize(3); + assertThat(underTest.search(IssueQuery.builder().assigned(true).build(), new SearchOptions()).getDocs()).hasSize(1); + assertThat(underTest.search(IssueQuery.builder().assigned(false).build(), new SearchOptions()).getDocs()).hasSize(2); + assertThat(underTest.search(IssueQuery.builder().assigned(null).build(), new SearchOptions()).getDocs()).hasSize(3); } @Test @@ -590,9 +585,9 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE2", file).setAuthorLogin("simon"), IssueDocTesting.newDoc("ISSUE3", file).setAssignee(null)); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).authors(newArrayList("steph")).build(), new SearchOptions()).getDocs()).hasSize(1); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).authors(newArrayList("steph", "simon")).build(), new SearchOptions()).getDocs()).hasSize(2); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).authors(newArrayList("unknown")).build(), new SearchOptions()).getDocs()).isEmpty(); + assertThat(underTest.search(IssueQuery.builder().authors(newArrayList("steph")).build(), new SearchOptions()).getDocs()).hasSize(1); + assertThat(underTest.search(IssueQuery.builder().authors(newArrayList("steph", "simon")).build(), new SearchOptions()).getDocs()).hasSize(2); + assertThat(underTest.search(IssueQuery.builder().authors(newArrayList("unknown")).build(), new SearchOptions()).getDocs()).isEmpty(); } @Test @@ -606,7 +601,7 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE3", file).setAuthorLogin("simon"), IssueDocTesting.newDoc("ISSUE4", file).setAuthorLogin(null)); - SearchResult<IssueDoc> result = underTest.search(IssueQuery.builder(userSessionRule).build(), new SearchOptions().addFacets(newArrayList("authors"))); + SearchResult<IssueDoc> result = underTest.search(IssueQuery.builder().build(), new SearchOptions().addFacets(newArrayList("authors"))); assertThat(result.getFacets().getNames()).containsOnly("authors"); assertThat(result.getFacets().get("authors")).containsOnly(entry("steph", 1L), entry("simon", 2L)); } @@ -620,11 +615,11 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE1", file).setFuncCreationDate(parseDate("2014-09-20")), IssueDocTesting.newDoc("ISSUE2", file).setFuncCreationDate(parseDate("2014-09-23"))); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).createdAfter(parseDate("2014-09-19")).build(), new SearchOptions()).getDocs()).hasSize(2); + assertThat(underTest.search(IssueQuery.builder().createdAfter(parseDate("2014-09-19")).build(), new SearchOptions()).getDocs()).hasSize(2); // Lower bound is included - assertThat(underTest.search(IssueQuery.builder(userSessionRule).createdAfter(parseDate("2014-09-20")).build(), new SearchOptions()).getDocs()).hasSize(2); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).createdAfter(parseDate("2014-09-21")).build(), new SearchOptions()).getDocs()).hasSize(1); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).createdAfter(parseDate("2014-09-25")).build(), new SearchOptions()).getDocs()).isEmpty(); + assertThat(underTest.search(IssueQuery.builder().createdAfter(parseDate("2014-09-20")).build(), new SearchOptions()).getDocs()).hasSize(2); + assertThat(underTest.search(IssueQuery.builder().createdAfter(parseDate("2014-09-21")).build(), new SearchOptions()).getDocs()).hasSize(1); + assertThat(underTest.search(IssueQuery.builder().createdAfter(parseDate("2014-09-25")).build(), new SearchOptions()).getDocs()).isEmpty(); } @Test @@ -636,11 +631,11 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE1", file).setFuncCreationDate(parseDate("2014-09-20")), IssueDocTesting.newDoc("ISSUE2", file).setFuncCreationDate(parseDate("2014-09-23"))); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).createdBefore(parseDate("2014-09-19")).build(), new SearchOptions()).getDocs()).isEmpty(); + assertThat(underTest.search(IssueQuery.builder().createdBefore(parseDate("2014-09-19")).build(), new SearchOptions()).getDocs()).isEmpty(); // Upper bound is excluded - assertThat(underTest.search(IssueQuery.builder(userSessionRule).createdBefore(parseDate("2014-09-20")).build(), new SearchOptions()).getDocs()).isEmpty(); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).createdBefore(parseDate("2014-09-21")).build(), new SearchOptions()).getDocs()).hasSize(1); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).createdBefore(parseDate("2014-09-25")).build(), new SearchOptions()).getDocs()).hasSize(2); + assertThat(underTest.search(IssueQuery.builder().createdBefore(parseDate("2014-09-20")).build(), new SearchOptions()).getDocs()).isEmpty(); + assertThat(underTest.search(IssueQuery.builder().createdBefore(parseDate("2014-09-21")).build(), new SearchOptions()).getDocs()).hasSize(1); + assertThat(underTest.search(IssueQuery.builder().createdBefore(parseDate("2014-09-25")).build(), new SearchOptions()).getDocs()).hasSize(2); } @Test @@ -653,38 +648,38 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE2", file).setFuncCreationDate(parseDate("2014-09-23"))); // 19 < createdAt < 25 - assertThat(underTest.search(IssueQuery.builder(userSessionRule) + assertThat(underTest.search(IssueQuery.builder() .createdAfter(parseDate("2014-09-19")).createdBefore(parseDate("2014-09-25")) .build(), new SearchOptions()).getDocs()).hasSize(2); // 20 < createdAt < 25: excludes first issue - assertThat(underTest.search(IssueQuery.builder(userSessionRule) + assertThat(underTest.search(IssueQuery.builder() .createdAfter(parseDate("2014-09-20")).createdBefore(parseDate("2014-09-25")) .build(), new SearchOptions()).getDocs()).hasSize(2); // 21 < createdAt < 25 - assertThat(underTest.search(IssueQuery.builder(userSessionRule) + assertThat(underTest.search(IssueQuery.builder() .createdAfter(parseDate("2014-09-21")).createdBefore(parseDate("2014-09-25")) .build(), new SearchOptions()).getDocs()).hasSize(1); // 21 < createdAt < 24 - assertThat(underTest.search(IssueQuery.builder(userSessionRule) + assertThat(underTest.search(IssueQuery.builder() .createdAfter(parseDate("2014-09-21")).createdBefore(parseDate("2014-09-24")) .build(), new SearchOptions()).getDocs()).hasSize(1); // 21 < createdAt < 23: excludes second issue - assertThat(underTest.search(IssueQuery.builder(userSessionRule) + assertThat(underTest.search(IssueQuery.builder() .createdAfter(parseDate("2014-09-21")).createdBefore(parseDate("2014-09-23")) .build(), new SearchOptions()).getDocs()).isEmpty(); // 19 < createdAt < 21: only first issue - assertThat(underTest.search(IssueQuery.builder(userSessionRule) + assertThat(underTest.search(IssueQuery.builder() .createdAfter(parseDate("2014-09-19")).createdBefore(parseDate("2014-09-21")) .build(), new SearchOptions()).getDocs()).hasSize(1); // 20 < createdAt < 20: exception expectedException.expect(IllegalArgumentException.class); - underTest.search(IssueQuery.builder(userSessionRule) + underTest.search(IssueQuery.builder() .createdAfter(parseDate("2014-09-20")).createdBefore(parseDate("2014-09-20")) .build(), new SearchOptions()).getDocs(); } @@ -698,11 +693,11 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE1", file).setFuncCreationDate(parseDateTime("2014-09-20T00:00:00+0100")), IssueDocTesting.newDoc("ISSUE2", file).setFuncCreationDate(parseDateTime("2014-09-23T00:00:00+0100"))); - assertThat(underTest.search(IssueQuery.builder(userSessionRule) + assertThat(underTest.search(IssueQuery.builder() .createdAfter(parseDateTime("2014-09-19T23:00:00+0000")).createdBefore(parseDateTime("2014-09-22T23:00:01+0000")) .build(), new SearchOptions()).getDocs()).hasSize(2); - assertThat(underTest.search(IssueQuery.builder(userSessionRule) + assertThat(underTest.search(IssueQuery.builder() .createdAfter(parseDateTime("2014-09-19T23:00:01+0000")).createdBefore(parseDateTime("2014-09-22T23:00:00+0000")) .build(), new SearchOptions()).getDocs()).hasSize(0); } @@ -710,7 +705,7 @@ public class IssueIndexTest { @Test public void filter_by_created_before_must_be_lower_than_after() { try { - underTest.search(IssueQuery.builder(userSessionRule).createdAfter(parseDate("2014-09-20")).createdBefore(parseDate("2014-09-19")).build(), + underTest.search(IssueQuery.builder().createdAfter(parseDate("2014-09-20")).createdBefore(parseDate("2014-09-19")).build(), new SearchOptions()); Fail.failBecauseExceptionWasNotThrown(IllegalArgumentException.class); } catch (IllegalArgumentException exception) { @@ -723,13 +718,13 @@ public class IssueIndexTest { expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Start bound cannot be larger or equal to end bound"); - underTest.search(IssueQuery.builder(userSessionRule).createdAfter(parseDate("2014-09-20")).createdBefore(parseDate("2014-09-20")).build(), new SearchOptions()); + underTest.search(IssueQuery.builder().createdAfter(parseDate("2014-09-20")).createdBefore(parseDate("2014-09-20")).build(), new SearchOptions()); } @Test public void filter_by_created_after_must_not_be_in_future() { try { - underTest.search(IssueQuery.builder(userSessionRule).createdAfter(new Date(Long.MAX_VALUE)).build(), new SearchOptions()); + underTest.search(IssueQuery.builder().createdAfter(new Date(Long.MAX_VALUE)).build(), new SearchOptions()); Fail.failBecauseExceptionWasNotThrown(IllegalArgumentException.class); } catch (IllegalArgumentException exception) { assertThat(exception.getMessage()).isEqualTo("Start bound cannot be in the future"); @@ -743,8 +738,8 @@ public class IssueIndexTest { indexIssues(IssueDocTesting.newDoc("ISSUE1", file).setFuncCreationDate(parseDate("2014-09-20"))); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).createdAt(parseDate("2014-09-20")).build(), new SearchOptions()).getDocs()).hasSize(1); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).createdAt(parseDate("2014-09-21")).build(), new SearchOptions()).getDocs()).isEmpty(); + assertThat(underTest.search(IssueQuery.builder().createdAt(parseDate("2014-09-20")).build(), new SearchOptions()).getDocs()).hasSize(1); + assertThat(underTest.search(IssueQuery.builder().createdAt(parseDate("2014-09-21")).build(), new SearchOptions()).getDocs()).isEmpty(); } @Test @@ -752,7 +747,7 @@ public class IssueIndexTest { SearchOptions options = fixtureForCreatedAtFacet(); - IssueQuery query = IssueQuery.builder(userSessionRule) + IssueQuery query = IssueQuery.builder() .createdAfter(parseDateTime("2014-09-01T00:00:00+0100")) .createdBefore(parseDateTime("2014-09-08T00:00:00+0100")) .checkAuthorization(false) @@ -775,7 +770,7 @@ public class IssueIndexTest { SearchOptions SearchOptions = fixtureForCreatedAtFacet(); - Map<String, Long> createdAt = underTest.search(IssueQuery.builder(userSessionRule) + Map<String, Long> createdAt = underTest.search(IssueQuery.builder() .createdAfter(parseDateTime("2014-09-01T00:00:00+0100")) .createdBefore(parseDateTime("2014-09-21T00:00:00+0100")).build(), SearchOptions).getFacets().get("createdAt"); @@ -791,7 +786,7 @@ public class IssueIndexTest { SearchOptions SearchOptions = fixtureForCreatedAtFacet(); - Map<String, Long> createdAt = underTest.search(IssueQuery.builder(userSessionRule) + Map<String, Long> createdAt = underTest.search(IssueQuery.builder() .createdAfter(parseDateTime("2014-09-01T00:00:00+0100")) .createdBefore(parseDateTime("2015-01-19T00:00:00+0100")).build(), SearchOptions).getFacets().get("createdAt"); @@ -808,7 +803,7 @@ public class IssueIndexTest { public void facet_on_created_at_with_more_than_20_months() { SearchOptions SearchOptions = fixtureForCreatedAtFacet(); - Map<String, Long> createdAt = underTest.search(IssueQuery.builder(userSessionRule) + Map<String, Long> createdAt = underTest.search(IssueQuery.builder() .createdAfter(parseDateTime("2011-01-01T00:00:00+0100")) .createdBefore(parseDateTime("2016-01-01T00:00:00+0100")).build(), SearchOptions).getFacets().get("createdAt"); @@ -826,7 +821,7 @@ public class IssueIndexTest { public void facet_on_created_at_with_one_day() { SearchOptions SearchOptions = fixtureForCreatedAtFacet(); - Map<String, Long> createdAt = underTest.search(IssueQuery.builder(userSessionRule) + Map<String, Long> createdAt = underTest.search(IssueQuery.builder() .createdAfter(parseDateTime("2014-09-01T00:00:00-0100")) .createdBefore(parseDateTime("2014-09-02T00:00:00-0100")).build(), SearchOptions).getFacets().get("createdAt"); @@ -838,7 +833,7 @@ public class IssueIndexTest { public void facet_on_created_at_with_bounds_outside_of_data() { SearchOptions options = fixtureForCreatedAtFacet(); - Map<String, Long> createdAt = underTest.search(IssueQuery.builder(userSessionRule) + Map<String, Long> createdAt = underTest.search(IssueQuery.builder() .createdAfter(parseDateTime("2009-01-01T00:00:00+0100")) .createdBefore(parseDateTime("2016-01-01T00:00:00+0100")) .build(), options).getFacets().get("createdAt"); @@ -857,7 +852,7 @@ public class IssueIndexTest { public void facet_on_created_at_without_start_bound() { SearchOptions SearchOptions = fixtureForCreatedAtFacet(); - Map<String, Long> createdAt = underTest.search(IssueQuery.builder(userSessionRule) + Map<String, Long> createdAt = underTest.search(IssueQuery.builder() .createdBefore(parseDateTime("2016-01-01T00:00:00+0100")).build(), SearchOptions).getFacets().get("createdAt"); assertThat(createdAt).containsOnly( @@ -872,7 +867,7 @@ public class IssueIndexTest { public void facet_on_created_at_without_issues() { SearchOptions SearchOptions = new SearchOptions().addFacets("createdAt"); - Map<String, Long> createdAt = underTest.search(IssueQuery.builder(userSessionRule).build(), + Map<String, Long> createdAt = underTest.search(IssueQuery.builder().build(), SearchOptions).getFacets().get("createdAt"); assertThat(createdAt).isNull(); } @@ -902,17 +897,17 @@ public class IssueIndexTest { indexIssues(IssueDocTesting.newDoc("ISSUE" + i, file)); } - IssueQuery.Builder query = IssueQuery.builder(userSessionRule); + IssueQuery.Builder query = IssueQuery.builder(); // There are 12 issues in total, with 10 issues per page, the page 2 should only contain 2 elements SearchResult<IssueDoc> result = underTest.search(query.build(), new SearchOptions().setPage(2, 10)); assertThat(result.getDocs()).hasSize(2); assertThat(result.getTotal()).isEqualTo(12); - result = underTest.search(IssueQuery.builder(userSessionRule).build(), new SearchOptions().setOffset(0).setLimit(5)); + result = underTest.search(IssueQuery.builder().build(), new SearchOptions().setOffset(0).setLimit(5)); assertThat(result.getDocs()).hasSize(5); assertThat(result.getTotal()).isEqualTo(12); - result = underTest.search(IssueQuery.builder(userSessionRule).build(), new SearchOptions().setOffset(2).setLimit(0)); + result = underTest.search(IssueQuery.builder().build(), new SearchOptions().setOffset(2).setLimit(0)); assertThat(result.getDocs()).hasSize(10); assertThat(result.getTotal()).isEqualTo(12); } @@ -928,7 +923,7 @@ public class IssueIndexTest { } indexIssues(issues.toArray(new IssueDoc[] {})); - IssueQuery.Builder query = IssueQuery.builder(userSessionRule); + IssueQuery.Builder query = IssueQuery.builder(); SearchResult<IssueDoc> result = underTest.search(query.build(), new SearchOptions().setLimit(Integer.MAX_VALUE)); assertThat(result.getDocs()).hasSize(SearchOptions.MAX_LIMIT); } @@ -943,13 +938,13 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE2", file).setStatus(Issue.STATUS_CLOSED), IssueDocTesting.newDoc("ISSUE3", file).setStatus(Issue.STATUS_REOPENED)); - IssueQuery.Builder query = IssueQuery.builder(userSessionRule).sort(IssueQuery.SORT_BY_STATUS).asc(true); + IssueQuery.Builder query = IssueQuery.builder().sort(IssueQuery.SORT_BY_STATUS).asc(true); SearchResult<IssueDoc> result = underTest.search(query.build(), new SearchOptions()); assertThat(result.getDocs().get(0).status()).isEqualTo(Issue.STATUS_CLOSED); assertThat(result.getDocs().get(1).status()).isEqualTo(Issue.STATUS_OPEN); assertThat(result.getDocs().get(2).status()).isEqualTo(Issue.STATUS_REOPENED); - query = IssueQuery.builder(userSessionRule).sort(IssueQuery.SORT_BY_STATUS).asc(false); + query = IssueQuery.builder().sort(IssueQuery.SORT_BY_STATUS).asc(false); result = underTest.search(query.build(), new SearchOptions()); assertThat(result.getDocs().get(0).status()).isEqualTo(Issue.STATUS_REOPENED); assertThat(result.getDocs().get(1).status()).isEqualTo(Issue.STATUS_OPEN); @@ -968,7 +963,7 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE4", file).setSeverity(Severity.CRITICAL), IssueDocTesting.newDoc("ISSUE5", file).setSeverity(Severity.MAJOR)); - IssueQuery.Builder query = IssueQuery.builder(userSessionRule).sort(IssueQuery.SORT_BY_SEVERITY).asc(true); + IssueQuery.Builder query = IssueQuery.builder().sort(IssueQuery.SORT_BY_SEVERITY).asc(true); SearchResult<IssueDoc> result = underTest.search(query.build(), new SearchOptions()); assertThat(result.getDocs().get(0).severity()).isEqualTo(Severity.INFO); assertThat(result.getDocs().get(1).severity()).isEqualTo(Severity.MINOR); @@ -976,7 +971,7 @@ public class IssueIndexTest { assertThat(result.getDocs().get(3).severity()).isEqualTo(Severity.CRITICAL); assertThat(result.getDocs().get(4).severity()).isEqualTo(Severity.BLOCKER); - query = IssueQuery.builder(userSessionRule).sort(IssueQuery.SORT_BY_SEVERITY).asc(false); + query = IssueQuery.builder().sort(IssueQuery.SORT_BY_SEVERITY).asc(false); result = underTest.search(query.build(), new SearchOptions()); assertThat(result.getDocs().get(0).severity()).isEqualTo(Severity.BLOCKER); assertThat(result.getDocs().get(1).severity()).isEqualTo(Severity.CRITICAL); @@ -994,13 +989,13 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE1", file).setAssignee("steph"), IssueDocTesting.newDoc("ISSUE2", file).setAssignee("simon")); - IssueQuery.Builder query = IssueQuery.builder(userSessionRule).sort(IssueQuery.SORT_BY_ASSIGNEE).asc(true); + IssueQuery.Builder query = IssueQuery.builder().sort(IssueQuery.SORT_BY_ASSIGNEE).asc(true); SearchResult<IssueDoc> result = underTest.search(query.build(), new SearchOptions()); assertThat(result.getDocs()).hasSize(2); assertThat(result.getDocs().get(0).assignee()).isEqualTo("simon"); assertThat(result.getDocs().get(1).assignee()).isEqualTo("steph"); - query = IssueQuery.builder(userSessionRule).sort(IssueQuery.SORT_BY_ASSIGNEE).asc(false); + query = IssueQuery.builder().sort(IssueQuery.SORT_BY_ASSIGNEE).asc(false); result = underTest.search(query.build(), new SearchOptions()); assertThat(result.getDocs()).hasSize(2); assertThat(result.getDocs().get(0).assignee()).isEqualTo("steph"); @@ -1016,13 +1011,13 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE1", file).setFuncCreationDate(parseDateTime("2014-09-23T00:00:00+0100")), IssueDocTesting.newDoc("ISSUE2", file).setFuncCreationDate(parseDateTime("2014-09-24T00:00:00+0100"))); - IssueQuery.Builder query = IssueQuery.builder(userSessionRule).sort(IssueQuery.SORT_BY_CREATION_DATE).asc(true); + IssueQuery.Builder query = IssueQuery.builder().sort(IssueQuery.SORT_BY_CREATION_DATE).asc(true); SearchResult<IssueDoc> result = underTest.search(query.build(), new SearchOptions()); assertThat(result.getDocs()).hasSize(2); assertThat(result.getDocs().get(0).creationDate()).isEqualTo(parseDateTime("2014-09-23T00:00:00+0100")); assertThat(result.getDocs().get(1).creationDate()).isEqualTo(parseDateTime("2014-09-24T00:00:00+0100")); - query = IssueQuery.builder(userSessionRule).sort(IssueQuery.SORT_BY_CREATION_DATE).asc(false); + query = IssueQuery.builder().sort(IssueQuery.SORT_BY_CREATION_DATE).asc(false); result = underTest.search(query.build(), new SearchOptions()); assertThat(result.getDocs()).hasSize(2); assertThat(result.getDocs().get(0).creationDate()).isEqualTo(parseDateTime("2014-09-24T00:00:00+0100")); @@ -1038,13 +1033,13 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE1", file).setFuncUpdateDate(parseDateTime("2014-09-23T00:00:00+0100")), IssueDocTesting.newDoc("ISSUE2", file).setFuncUpdateDate(parseDateTime("2014-09-24T00:00:00+0100"))); - IssueQuery.Builder query = IssueQuery.builder(userSessionRule).sort(IssueQuery.SORT_BY_UPDATE_DATE).asc(true); + IssueQuery.Builder query = IssueQuery.builder().sort(IssueQuery.SORT_BY_UPDATE_DATE).asc(true); SearchResult<IssueDoc> result = underTest.search(query.build(), new SearchOptions()); assertThat(result.getDocs()).hasSize(2); assertThat(result.getDocs().get(0).updateDate()).isEqualTo(parseDateTime("2014-09-23T00:00:00+0100")); assertThat(result.getDocs().get(1).updateDate()).isEqualTo(parseDateTime("2014-09-24T00:00:00+0100")); - query = IssueQuery.builder(userSessionRule).sort(IssueQuery.SORT_BY_UPDATE_DATE).asc(false); + query = IssueQuery.builder().sort(IssueQuery.SORT_BY_UPDATE_DATE).asc(false); result = underTest.search(query.build(), new SearchOptions()); assertThat(result.getDocs()).hasSize(2); assertThat(result.getDocs().get(0).updateDate()).isEqualTo(parseDateTime("2014-09-24T00:00:00+0100")); @@ -1061,14 +1056,14 @@ public class IssueIndexTest { IssueDocTesting.newDoc("ISSUE2", file).setFuncCloseDate(parseDateTime("2014-09-24T00:00:00+0100")), IssueDocTesting.newDoc("ISSUE3", file).setFuncCloseDate(null)); - IssueQuery.Builder query = IssueQuery.builder(userSessionRule).sort(IssueQuery.SORT_BY_CLOSE_DATE).asc(true); + IssueQuery.Builder query = IssueQuery.builder().sort(IssueQuery.SORT_BY_CLOSE_DATE).asc(true); SearchResult<IssueDoc> result = underTest.search(query.build(), new SearchOptions()); assertThat(result.getDocs()).hasSize(3); assertThat(result.getDocs().get(0).closeDate()).isNull(); assertThat(result.getDocs().get(1).closeDate()).isEqualTo(parseDateTime("2014-09-23T00:00:00+0100")); assertThat(result.getDocs().get(2).closeDate()).isEqualTo(parseDateTime("2014-09-24T00:00:00+0100")); - query = IssueQuery.builder(userSessionRule).sort(IssueQuery.SORT_BY_CLOSE_DATE).asc(false); + query = IssueQuery.builder().sort(IssueQuery.SORT_BY_CLOSE_DATE).asc(false); result = underTest.search(query.build(), new SearchOptions()); assertThat(result.getDocs()).hasSize(3); assertThat(result.getDocs().get(0).closeDate()).isEqualTo(parseDateTime("2014-09-24T00:00:00+0100")); @@ -1095,7 +1090,7 @@ public class IssueIndexTest { IssueDocTesting.newDoc("F2_3", file2).setLine(109)); // ascending sort -> F1 then F2. Line "0" first. - IssueQuery.Builder query = IssueQuery.builder(userSessionRule).sort(IssueQuery.SORT_BY_FILE_LINE).asc(true); + IssueQuery.Builder query = IssueQuery.builder().sort(IssueQuery.SORT_BY_FILE_LINE).asc(true); SearchResult<IssueDoc> result = underTest.search(query.build(), new SearchOptions()); assertThat(result.getDocs()).hasSize(6); assertThat(result.getDocs().get(0).key()).isEqualTo("F1_1"); @@ -1106,7 +1101,7 @@ public class IssueIndexTest { assertThat(result.getDocs().get(5).key()).isEqualTo("F2_3"); // descending sort -> F2 then F1 - query = IssueQuery.builder(userSessionRule).sort(IssueQuery.SORT_BY_FILE_LINE).asc(false); + query = IssueQuery.builder().sort(IssueQuery.SORT_BY_FILE_LINE).asc(false); result = underTest.search(query.build(), new SearchOptions()); assertThat(result.getDocs()).hasSize(6); assertThat(result.getDocs().get(0).key()).isEqualTo("F2_3"); @@ -1143,7 +1138,7 @@ public class IssueIndexTest { IssueDocTesting.newDoc("F3_1", file3).setLine(20).setFuncCreationDate(parseDateTime("2014-09-24T00:00:00+0100")), IssueDocTesting.newDoc("F3_2", file3).setLine(20).setFuncCreationDate(parseDateTime("2014-09-23T00:00:00+0100"))); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).build(), new SearchOptions()).getDocs()).extracting(IssueDoc::key) + assertThat(underTest.search(IssueQuery.builder().build(), new SearchOptions()).getDocs()).extracting(IssueDoc::key) .containsExactly("F3_1", "F1_2", "F1_1", "F1_3", "F2_1", "F2_2", "F2_3", "F3_2"); } @@ -1159,26 +1154,28 @@ public class IssueIndexTest { ComponentDto file3 = ComponentTesting.newFileDto(project3, null).setKey("file3"); // project1 can be seen by sonar-users - indexIssue(IssueDocTesting.newDoc("ISSUE1", file1), "sonar-users", null); + indexIssue(IssueDocTesting.newDoc("ISSUE1", file1)); + authorizationIndexerTester.allowOnlyGroup(project1, "sonar-users"); // project2 can be seen by sonar-admins - indexIssue(IssueDocTesting.newDoc("ISSUE2", file2), "sonar-admins", null); + indexIssue(IssueDocTesting.newDoc("ISSUE2", file2)); + authorizationIndexerTester.allowOnlyGroup(project2, "sonar-admins"); // project3 can be seen by nobody - indexIssue(IssueDocTesting.newDoc("ISSUE3", file3), null, null); + indexIssue(IssueDocTesting.newDoc("ISSUE3", file3)); userSessionRule.login().setUserGroups("sonar-users"); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).build(), new SearchOptions()).getDocs()).hasSize(1); + assertThat(underTest.search(IssueQuery.builder().build(), new SearchOptions()).getDocs()).hasSize(1); userSessionRule.login().setUserGroups("sonar-admins"); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).build(), new SearchOptions()).getDocs()).hasSize(1); + assertThat(underTest.search(IssueQuery.builder().build(), new SearchOptions()).getDocs()).hasSize(1); userSessionRule.login().setUserGroups("sonar-users", "sonar-admins"); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).build(), new SearchOptions()).getDocs()).hasSize(2); + assertThat(underTest.search(IssueQuery.builder().build(), new SearchOptions()).getDocs()).hasSize(2); userSessionRule.login().setUserGroups("another group"); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).build(), new SearchOptions()).getDocs()).isEmpty(); + assertThat(underTest.search(IssueQuery.builder().build(), new SearchOptions()).getDocs()).isEmpty(); userSessionRule.login().setUserGroups("sonar-users", "sonar-admins"); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).projectUuids(newArrayList(project3.uuid())).build(), new SearchOptions()).getDocs()).isEmpty(); + assertThat(underTest.search(IssueQuery.builder().projectUuids(newArrayList(project3.uuid())).build(), new SearchOptions()).getDocs()).isEmpty(); } @Test @@ -1193,22 +1190,23 @@ public class IssueIndexTest { ComponentDto file3 = ComponentTesting.newFileDto(project3, null).setKey("file3"); // project1 can be seen by john, project2 by max, project3 cannot be seen by anyone - indexIssue(IssueDocTesting.newDoc("ISSUE1", file1), null, 10L); - indexIssue(IssueDocTesting.newDoc("ISSUE2", file2), null, 11L); - indexIssue(IssueDocTesting.newDoc("ISSUE3", file3), null, null); - + indexIssue(IssueDocTesting.newDoc("ISSUE1", file1)); + authorizationIndexerTester.allowOnlyUser(project1, 10); + indexIssue(IssueDocTesting.newDoc("ISSUE2", file2)); + authorizationIndexerTester.allowOnlyUser(project2, 11); + indexIssue(IssueDocTesting.newDoc("ISSUE3", file3)); userSessionRule.login("john").setUserId(10); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).build(), new SearchOptions()).getDocs()).hasSize(1); + assertThat(underTest.search(IssueQuery.builder().build(), new SearchOptions()).getDocs()).hasSize(1); userSessionRule.login("max").setUserId(11); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).build(), new SearchOptions()).getDocs()).hasSize(1); + assertThat(underTest.search(IssueQuery.builder().build(), new SearchOptions()).getDocs()).hasSize(1); userSessionRule.login("another guy").setUserId(33); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).build(), new SearchOptions()).getDocs()).hasSize(0); + assertThat(underTest.search(IssueQuery.builder().build(), new SearchOptions()).getDocs()).hasSize(0); userSessionRule.login("john").setUserId(10); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).projectUuids(newArrayList(project3.key())).build(), new SearchOptions()).getDocs()).hasSize(0); + assertThat(underTest.search(IssueQuery.builder().projectUuids(newArrayList(project3.key())).build(), new SearchOptions()).getDocs()).hasSize(0); } @Test @@ -1221,11 +1219,12 @@ public class IssueIndexTest { ComponentDto file2 = ComponentTesting.newFileDto(project2, null).setKey("file2"); // project1 can be seen by user 10 and by sonar-users - indexIssue(IssueDocTesting.newDoc("ISSUE1", file1), "sonar-users", 10L); - indexIssue(IssueDocTesting.newDoc("ISSUE2", file2), null, 11L); + indexIssue(IssueDocTesting.newDoc("ISSUE1", file1)); + indexIssue(IssueDocTesting.newDoc("ISSUE2", file2)); + authorizationIndexerTester.allowOnlyUser(project1, 10); - userSessionRule.login("john").setUserGroups("sonar-users"); - assertThat(underTest.search(IssueQuery.builder(userSessionRule).build(), new SearchOptions()).getDocs()).hasSize(1); + userSessionRule.login("john").setUserGroups("sonar-users").setUserId(10); + assertThat(underTest.search(IssueQuery.builder().build(), new SearchOptions()).getDocs()).hasSize(1); } @Test @@ -1305,9 +1304,10 @@ public class IssueIndexTest { ComponentDto file2 = ComponentTesting.newFileDto(project2, null).setKey("file2"); // project1 can be seen by sonar-users - indexIssue(IssueDocTesting.newDoc("ISSUE1", file1), "sonar-users", null); + indexIssue(IssueDocTesting.newDoc("ISSUE1", file1)); // project3 can be seen by nobody - indexIssue(IssueDocTesting.newDoc("ISSUE3", file2), null, null); + indexIssue(IssueDocTesting.newDoc("ISSUE3", file2)); + authorizationIndexerTester.allowOnlyGroup(project1, "sonar-users"); userSessionRule.setUserGroups("sonar-users"); assertThat(Lists.newArrayList(underTest.selectIssuesForBatch(project1))).hasSize(1); @@ -1319,17 +1319,12 @@ public class IssueIndexTest { private void indexIssues(IssueDoc... issues) { issueIndexer.index(Arrays.asList(issues).iterator()); for (IssueDoc issue : issues) { - addIssueAuthorization(issue.projectUuid(), DefaultGroups.ANYONE, null); + authorizationIndexerTester.allow(new PermissionIndexerDao.Dto(issue.projectUuid(), system2.now(), "TRK").addGroup("Anyone")); } } - private void indexIssue(IssueDoc issue, @Nullable String group, @Nullable Long user) { + private void indexIssue(IssueDoc issue) { issueIndexer.index(Iterators.singletonIterator(issue)); - addIssueAuthorization(issue.projectUuid(), group, user); - } - - private void addIssueAuthorization(String projectUuid, @Nullable String group, @Nullable Long user) { - authorizationIndexerTester.indexProjectPermission(projectUuid, singletonList(group), singletonList(user)); } private void indexView(String viewUuid, List<String> projects) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexerTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexerTest.java index cbf2216d263..5e46cb4f966 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexerTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexerTest.java @@ -19,22 +19,17 @@ */ package org.sonar.server.issue.index; -import com.google.common.base.Function; -import com.google.common.collect.FluentIterable; -import com.google.common.collect.Iterators; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import javax.annotation.Nonnull; -import org.elasticsearch.search.SearchHit; import org.junit.Rule; import org.junit.Test; import org.sonar.api.config.MapSettings; import org.sonar.api.rule.RuleKey; import org.sonar.api.utils.System2; -import org.sonar.db.DbClient; import org.sonar.db.DbTester; import org.sonar.server.es.EsTester; +import org.sonar.server.es.ProjectIndexer; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; @@ -52,19 +47,20 @@ public class IssueIndexerTest { @Rule public DbTester dbTester = DbTester.create(system2); + private IssueIndexer underTest = new IssueIndexer(system2, dbTester.getDbClient(), esTester.client()); + @Test public void index_nothing() { - IssueIndexer indexer = createIndexer(); - indexer.index(Iterators.emptyIterator()); + underTest.index(Collections.emptyIterator()); + assertThat(esTester.countDocuments(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_ISSUE)).isEqualTo(0L); } @Test - public void index() { + public void index_all_issues() { dbTester.prepareDbUnit(getClass(), "index.xml"); - IssueIndexer indexer = createIndexer(); - indexer.index(); + underTest.index(); List<IssueDoc> docs = esTester.getDocuments("issues", "issue", IssueDoc.class); assertThat(docs).hasSize(1); @@ -86,47 +82,61 @@ public class IssueIndexerTest { } @Test - public void deleteProject_deletes_issues() { - dbTester.prepareDbUnit(getClass(), "index.xml"); + public void indexProject_creates_docs_of_specific_project() { + dbTester.prepareDbUnit(getClass(), "index_project.xml"); - IssueIndexer indexer = createIndexer(); - indexer.index(); + underTest.indexProject("THE_PROJECT_1", ProjectIndexer.Cause.NEW_ANALYSIS); - List<SearchHit> docs = esTester.getDocuments("issues", "issue"); - assertThat(esTester.countDocuments("issues", "issue")).isEqualTo(1); + verifyIssueKeys("ABCDE"); + } - indexer.deleteProject("THE_PROJECT"); + @Test + public void indexProject_does_nothing_when_project_is_being_created() { + dbTester.prepareDbUnit(getClass(), "index_project.xml"); - assertThat(esTester.countDocuments("issues", "issue")).isZero(); + underTest.indexProject("THE_PROJECT_1", ProjectIndexer.Cause.PROJECT_CREATION); + + assertThat(esTester.countDocuments("issues", "issue")).isEqualTo(0); } @Test - public void index_issues_from_project() { + public void indexProject_does_nothing_when_project_key_is_being_renamed() { dbTester.prepareDbUnit(getClass(), "index_project.xml"); - IssueIndexer indexer = createIndexer(); - indexer.index("THE_PROJECT_1"); + underTest.indexProject("THE_PROJECT_1", ProjectIndexer.Cause.PROJECT_KEY_UPDATE); - verifyIssueKeys("ABCDE"); + assertThat(esTester.countDocuments("issues", "issue")).isEqualTo(0); + } + + @Test + public void deleteProject_deletes_issues_of_a_specific_project() { + dbTester.prepareDbUnit(getClass(), "index.xml"); + + underTest.index(); + + assertThat(esTester.countDocuments("issues", "issue")).isEqualTo(1); + + underTest.deleteProject("THE_PROJECT"); + + assertThat(esTester.countDocuments("issues", "issue")).isZero(); } @Test - public void delete_issues_by_keys() throws Exception { + public void deleteByKeys_deletes_docs_by_keys() throws Exception { addIssue("P1", "Issue1"); addIssue("P1", "Issue2"); addIssue("P1", "Issue3"); addIssue("P2", "Issue4"); - IssueIndexer indexer = createIndexer(); verifyIssueKeys("Issue1", "Issue2", "Issue3", "Issue4"); - indexer.deleteByKeys("P1", asList("Issue1", "Issue2")); + underTest.deleteByKeys("P1", asList("Issue1", "Issue2")); verifyIssueKeys("Issue3", "Issue4"); } @Test - public void delete_more_than_one_thousand_issues_by_keys() throws Exception { + public void deleteByKeys_deletes_more_than_one_thousand_issues_by_keys() throws Exception { int numberOfIssues = 1010; List<String> keys = new ArrayList<>(numberOfIssues); IssueDoc[] issueDocs = new IssueDoc[numberOfIssues]; @@ -136,10 +146,9 @@ public class IssueIndexerTest { keys.add(key); } esTester.putDocuments(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_ISSUE, issueDocs); - IssueIndexer indexer = createIndexer(); assertThat(esTester.countDocuments("issues", "issue")).isEqualTo(numberOfIssues); - indexer.deleteByKeys(A_PROJECT_UUID, keys); + underTest.deleteByKeys(A_PROJECT_UUID, keys); assertThat(esTester.countDocuments("issues", "issue")).isZero(); } @@ -149,36 +158,20 @@ public class IssueIndexerTest { addIssue("P1", "Issue2"); addIssue("P1", "Issue3"); - IssueIndexer indexer = createIndexer(); verifyIssueKeys("Issue1", "Issue2", "Issue3"); - indexer.deleteByKeys("P1", Collections.<String>emptyList()); + underTest.deleteByKeys("P1", Collections.emptyList()); verifyIssueKeys("Issue1", "Issue2", "Issue3"); } - private IssueIndexer createIndexer() { - return new IssueIndexer(system2, new DbClient(dbTester.database(), dbTester.myBatis()), esTester.client()); - } - private void addIssue(String projectUuid, String issueKey) throws Exception { esTester.putDocuments(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_ISSUE, newDoc().setKey(issueKey).setProjectUuid(projectUuid)); } private void verifyIssueKeys(String... expectedKeys) { - List<String> keys = FluentIterable.from(esTester.getDocuments("issues", "issue", IssueDoc.class)) - .transform(DocToKey.INSTANCE) - .toList(); - assertThat(keys).containsOnly(expectedKeys); - } - - private enum DocToKey implements Function<IssueDoc, String> { - INSTANCE; - - @Override - public String apply(@Nonnull IssueDoc input) { - return input.key(); - } + List<IssueDoc> issues = esTester.getDocuments("issues", "issue", IssueDoc.class); + assertThat(issues).extracting(IssueDoc::key).containsOnly(expectedKeys); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexTest.java index 01534788aa7..208c8d09042 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexTest.java @@ -29,23 +29,21 @@ import javax.annotation.Nullable; import org.junit.Rule; import org.junit.Test; import org.sonar.api.config.MapSettings; +import org.sonar.api.resources.Qualifiers; +import org.sonar.api.utils.System2; import org.sonar.server.es.EsTester; import org.sonar.server.es.Facets; import org.sonar.server.es.SearchIdResult; import org.sonar.server.es.SearchOptions; -import org.sonar.server.measure.index.ProjectMeasuresDoc; -import org.sonar.server.measure.index.ProjectMeasuresIndex; -import org.sonar.server.measure.index.ProjectMeasuresIndexDefinition; -import org.sonar.server.measure.index.ProjectMeasuresQuery; import org.sonar.server.measure.index.ProjectMeasuresQuery.MetricCriterion; import org.sonar.server.measure.index.ProjectMeasuresQuery.Operator; +import org.sonar.server.permission.index.AuthorizationTypeSupport; +import org.sonar.server.permission.index.PermissionIndexerDao; import org.sonar.server.permission.index.PermissionIndexerTester; import org.sonar.server.tester.UserSessionRule; import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Sets.newHashSet; -import static java.util.Collections.emptyList; -import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY; @@ -72,9 +70,10 @@ public class ProjectMeasuresIndexTest { @Rule public UserSessionRule userSession = UserSessionRule.standalone(); - private PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(es); + private ProjectMeasuresIndexer projectMeasureIndexer = new ProjectMeasuresIndexer(System2.INSTANCE, null, es.client()); + private PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(es, projectMeasureIndexer); - private ProjectMeasuresIndex underTest = new ProjectMeasuresIndex(es.client(), userSession); + private ProjectMeasuresIndex underTest = new ProjectMeasuresIndex(es.client(), new AuthorizationTypeSupport(userSession)); @Test public void empty_search() { @@ -874,10 +873,17 @@ public class ProjectMeasuresIndexTest { private void addDocs(@Nullable Long authorizeUser, @Nullable String authorizedGroup, ProjectMeasuresDoc... docs) { try { es.putDocuments(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURE, docs); + for (ProjectMeasuresDoc doc : docs) { - authorizationIndexerTester.indexProjectPermission(doc.getId(), - authorizedGroup != null ? singletonList(authorizedGroup) : emptyList(), - authorizeUser != null ? singletonList(authorizeUser) : emptyList()); + PermissionIndexerDao.Dto access = new PermissionIndexerDao.Dto(doc.getId(), System.currentTimeMillis(), Qualifiers.PROJECT); + if (authorizedGroup != null) { + access.addGroup(authorizedGroup); + } + if (authorizeUser != null) { + access.addUser(authorizeUser); + } + authorizationIndexerTester.allow(access); + } } catch (Exception e) { Throwables.propagate(e); diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexerTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexerTest.java index 9e2d7eb4b93..0fe536c8dc2 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexerTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexerTest.java @@ -32,19 +32,14 @@ import org.sonar.db.component.ComponentDto; import org.sonar.db.component.SnapshotDto; import org.sonar.db.organization.OrganizationDto; import org.sonar.server.es.EsTester; -import org.sonar.server.measure.index.ProjectMeasuresDoc; -import org.sonar.server.measure.index.ProjectMeasuresIndexDefinition; -import org.sonar.server.measure.index.ProjectMeasuresIndexer; -import org.sonar.server.permission.index.PermissionIndexerTester; +import org.sonar.server.es.ProjectIndexer; -import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; import static org.elasticsearch.index.query.QueryBuilders.boolQuery; import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; import static org.elasticsearch.index.query.QueryBuilders.termQuery; import static org.sonar.db.component.ComponentTesting.newProjectDto; import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES; -import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.TYPE_AUTHORIZATION; import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.TYPE_PROJECT_MEASURE; public class ProjectMeasuresIndexerTest { @@ -57,10 +52,8 @@ public class ProjectMeasuresIndexerTest { @Rule public DbTester dbTester = DbTester.create(system2); - ComponentDbTester componentDbTester = new ComponentDbTester(dbTester); - PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(esTester); - - ProjectMeasuresIndexer underTest = new ProjectMeasuresIndexer(system2, dbTester.getDbClient(), esTester.client()); + private ComponentDbTester componentDbTester = new ComponentDbTester(dbTester); + private ProjectMeasuresIndexer underTest = new ProjectMeasuresIndexer(system2, dbTester.getDbClient(), esTester.client()); @Test public void index_nothing() { @@ -81,8 +74,11 @@ public class ProjectMeasuresIndexerTest { assertThat(esTester.countDocuments(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURE)).isEqualTo(3); } + /** + * Provisioned projects don't have analysis yet + */ @Test - public void index_projects_even_when_no_analysis() { + public void index_provisioned_projects() { ComponentDto project = componentDbTester.insertProject(); underTest.index(); @@ -91,13 +87,31 @@ public class ProjectMeasuresIndexerTest { } @Test + public void indexProject_indexes_provisioned_project() { + ComponentDto project = componentDbTester.insertProject(); + + underTest.indexProject(project.uuid(), ProjectIndexer.Cause.PROJECT_CREATION); + + assertThat(esTester.getIds(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURE)).containsOnly(project.uuid()); + } + + @Test + public void indexProject_indexes_project_when_its_key_is_updated() { + ComponentDto project = componentDbTester.insertProject(); + + underTest.indexProject(project.uuid(), ProjectIndexer.Cause.PROJECT_KEY_UPDATE); + + assertThat(esTester.getIds(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURE)).containsOnly(project.uuid()); + } + + @Test public void index_one_project() throws Exception { OrganizationDto organizationDto = dbTester.organizations().insert(); ComponentDto project = newProjectDto(organizationDto); componentDbTester.insertProjectAndSnapshot(project); componentDbTester.insertProjectAndSnapshot(newProjectDto(organizationDto)); - underTest.index(project.uuid()); + underTest.indexProject(project.uuid(), ProjectIndexer.Cause.NEW_ANALYSIS); assertThat(esTester.getIds(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURE)).containsOnly(project.uuid()); } @@ -113,7 +127,7 @@ public class ProjectMeasuresIndexerTest { ComponentDto project = newProjectDto(dbTester.getDefaultOrganization(), uuid).setKey("New key").setName("New name"); SnapshotDto analysis = componentDbTester.insertProjectAndSnapshot(project); - underTest.index(project.uuid()); + underTest.indexProject(project.uuid(), ProjectIndexer.Cause.NEW_ANALYSIS); assertThat(esTester.getIds(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURE)).containsOnly(uuid); SearchRequestBuilder request = esTester.client() @@ -138,14 +152,10 @@ public class ProjectMeasuresIndexerTest { ComponentDto project3 = newProjectDto(organizationDto); componentDbTester.insertProjectAndSnapshot(project3); underTest.index(); - authorizationIndexerTester.indexProjectPermission(project1.uuid(), emptyList(), emptyList()); - authorizationIndexerTester.indexProjectPermission(project2.uuid(), emptyList(), emptyList()); - authorizationIndexerTester.indexProjectPermission(project3.uuid(), emptyList(), emptyList()); underTest.deleteProject(project1.uuid()); assertThat(esTester.getIds(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURE)).containsOnly(project2.uuid(), project3.uuid()); - assertThat(esTester.getIds(INDEX_PROJECT_MEASURES, TYPE_AUTHORIZATION)).containsOnly(project2.uuid(), project3.uuid()); } @Test @@ -153,11 +163,9 @@ public class ProjectMeasuresIndexerTest { ComponentDto project = newProjectDto(dbTester.organizations().insert()); componentDbTester.insertProjectAndSnapshot(project); underTest.index(); - authorizationIndexerTester.indexProjectPermission(project.uuid(), emptyList(), emptyList()); underTest.deleteProject("UNKNOWN"); assertThat(esTester.getIds(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURE)).containsOnly(project.uuid()); - assertThat(esTester.getIds(INDEX_PROJECT_MEASURES, TYPE_AUTHORIZATION)).containsOnly(project.uuid()); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/DeleteActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/DeleteActionTest.java index 4f0db1df33a..047c42d5571 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/DeleteActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/DeleteActionTest.java @@ -19,12 +19,11 @@ */ package org.sonar.server.organization.ws; -import org.junit.Before; +import java.util.List; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.api.resources.ResourceType; -import org.sonar.api.resources.ResourceTypes; +import org.mockito.ArgumentCaptor; import org.sonar.api.server.ws.WebService; import org.sonar.api.utils.System2; import org.sonar.db.DbClient; @@ -37,23 +36,18 @@ import org.sonar.db.permission.template.PermissionTemplateDto; import org.sonar.db.user.GroupDto; import org.sonar.db.user.UserDto; import org.sonar.server.component.ComponentCleanerService; -import org.sonar.server.component.ComponentFinder; -import org.sonar.server.component.index.ComponentIndexer; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.exceptions.UnauthorizedException; -import org.sonar.server.issue.index.IssueIndexer; -import org.sonar.server.measure.index.ProjectMeasuresIndexer; import org.sonar.server.organization.TestDefaultOrganizationProvider; -import org.sonar.server.test.index.TestIndexer; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.WsActionTester; import static com.google.common.collect.ImmutableList.of; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.verify; import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN; import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_KEY; @@ -68,19 +62,10 @@ public class DeleteActionTest { private DbClient dbClient = dbTester.getDbClient(); private DbSession session = dbTester.getSession(); - - private ResourceTypes resourceTypes = mock(ResourceTypes.class); - private ComponentCleanerService componentCleanerService = new ComponentCleanerService(dbTester.getDbClient(), - mock(IssueIndexer.class), mock(TestIndexer.class), mock(ProjectMeasuresIndexer.class), - mock(ComponentIndexer.class), resourceTypes, new ComponentFinder(dbTester.getDbClient())); + private ComponentCleanerService componentCleanerService = mock(ComponentCleanerService.class); private DeleteAction underTest = new DeleteAction(userSession, dbTester.getDbClient(), TestDefaultOrganizationProvider.from(dbTester), componentCleanerService); private WsActionTester wsTester = new WsActionTester(underTest); - @Before - public void setUp() throws Exception { - when(resourceTypes.get(anyString())).thenAnswer(invocation -> ResourceType.builder((String) invocation.getArguments()[0]).setProperty("deletable", true).build()); - } - @Test public void verify_define() { WebService.Action action = wsTester.getDef(); @@ -200,33 +185,32 @@ public class DeleteActionTest { sendRequest(organization); verifyOrganizationDoesNotExist(organization); - assertThat(dbTester.getDbClient().componentDao().selectByUuids( - session, - of(project.uuid(), module.uuid(), directory.uuid(), file.uuid(), view.uuid(), subview1.uuid(), subview2.uuid(), projectCopy.uuid()))) - .isEmpty(); + ArgumentCaptor<List<ComponentDto>> arg = (ArgumentCaptor<List<ComponentDto>>) ((ArgumentCaptor) ArgumentCaptor.forClass(List.class)); + verify(componentCleanerService).delete(any(DbSession.class), arg.capture()); + assertThat(arg.getValue()).containsOnly(project, view); } @Test public void request_also_deletes_permissions_templates_and_permissions_and_groups_of_specified_organization() { userSession.login().setRoot(); - OrganizationDto organizationDto = dbTester.organizations().insert(); - OrganizationDto otherOrganizationDto = dbTester.organizations().insert(); + OrganizationDto org = dbTester.organizations().insert(); + OrganizationDto otherOrg = dbTester.organizations().insert(); UserDto user1 = dbTester.users().insertUser(); UserDto user2 = dbTester.users().insertUser(); - GroupDto group1 = dbTester.users().insertGroup(organizationDto); - GroupDto group2 = dbTester.users().insertGroup(organizationDto); - GroupDto otherGroup1 = dbTester.users().insertGroup(otherOrganizationDto); - GroupDto otherGroup2 = dbTester.users().insertGroup(otherOrganizationDto); - - ComponentDto projectDto = dbTester.components().insertProject(organizationDto); - ComponentDto otherProjectDto = dbTester.components().insertProject(otherOrganizationDto); - - dbTester.users().insertPermissionOnAnyone(organizationDto, "u1"); - dbTester.users().insertPermissionOnAnyone(otherOrganizationDto, "not deleted u1"); - dbTester.users().insertPermissionOnUser(organizationDto, user1, "u2"); - dbTester.users().insertPermissionOnUser(otherOrganizationDto, user1, "not deleted u2"); + GroupDto group1 = dbTester.users().insertGroup(org); + GroupDto group2 = dbTester.users().insertGroup(org); + GroupDto otherGroup1 = dbTester.users().insertGroup(otherOrg); + GroupDto otherGroup2 = dbTester.users().insertGroup(otherOrg); + + ComponentDto projectDto = dbTester.components().insertProject(org); + ComponentDto otherProjectDto = dbTester.components().insertProject(otherOrg); + + dbTester.users().insertPermissionOnAnyone(org, "u1"); + dbTester.users().insertPermissionOnAnyone(otherOrg, "not deleted u1"); + dbTester.users().insertPermissionOnUser(org, user1, "u2"); + dbTester.users().insertPermissionOnUser(otherOrg, user1, "not deleted u2"); dbTester.users().insertPermissionOnGroup(group1, "u3"); dbTester.users().insertPermissionOnGroup(otherGroup1, "not deleted u3"); dbTester.users().insertProjectPermissionOnAnyone("u4", projectDto); @@ -236,12 +220,12 @@ public class DeleteActionTest { dbTester.users().insertProjectPermissionOnUser(user1, "u6", projectDto); dbTester.users().insertProjectPermissionOnUser(user1, "not deleted u6", otherProjectDto); - PermissionTemplateDto templateDto = dbTester.permissionTemplates().insertTemplate(organizationDto); - PermissionTemplateDto otherTemplateDto = dbTester.permissionTemplates().insertTemplate(otherOrganizationDto); + PermissionTemplateDto templateDto = dbTester.permissionTemplates().insertTemplate(org); + PermissionTemplateDto otherTemplateDto = dbTester.permissionTemplates().insertTemplate(otherOrg); - sendRequest(organizationDto); + sendRequest(org); - verifyOrganizationDoesNotExist(organizationDto); + verifyOrganizationDoesNotExist(org); assertThat(dbClient.groupDao().selectByIds(session, of(group1.getId(), otherGroup1.getId(), group2.getId(), otherGroup2.getId()))) .extracting(GroupDto::getId) .containsOnly(otherGroup1.getId(), otherGroup2.getId()); diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/index/FooIndex.java b/server/sonar-server/src/test/java/org/sonar/server/permission/index/FooIndex.java new file mode 100644 index 00000000000..4a50a3f9aa5 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/index/FooIndex.java @@ -0,0 +1,55 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.permission.index; + +import java.util.Arrays; +import java.util.List; +import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.search.SearchHits; +import org.sonar.core.util.stream.Collectors; +import org.sonar.server.es.EsClient; + +import static org.sonar.server.permission.index.FooIndexDefinition.FOO_INDEX; +import static org.sonar.server.permission.index.FooIndexDefinition.FOO_TYPE; + +public class FooIndex { + + private final EsClient esClient; + private final AuthorizationTypeSupport authorizationTypeSupport; + + public FooIndex(EsClient esClient, AuthorizationTypeSupport authorizationTypeSupport) { + this.esClient = esClient; + this.authorizationTypeSupport = authorizationTypeSupport; + } + + public boolean hasAccessToProject(String projectUuid) { + SearchHits hits = esClient.prepareSearch(FOO_INDEX) + .setTypes(FOO_TYPE) + .setQuery(QueryBuilders.boolQuery() + .must(QueryBuilders.termQuery(FooIndexDefinition.FIELD_PROJECT_UUID, projectUuid)) + .filter(authorizationTypeSupport.createQueryFilter())) + .get() + .getHits(); + List<String> names = Arrays.stream(hits.hits()) + .map(h -> h.getSource().get(FooIndexDefinition.FIELD_NAME).toString()) + .collect(Collectors.toList()); + return names.size() == 2 && names.contains("bar") && names.contains("baz"); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/IndexTestsStep.java b/server/sonar-server/src/test/java/org/sonar/server/permission/index/FooIndexDefinition.java index 32ca43eb076..d6e5abce950 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/IndexTestsStep.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/index/FooIndexDefinition.java @@ -17,30 +17,27 @@ * 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.computation.task.projectanalysis.step; +package org.sonar.server.permission.index; -import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder; -import org.sonar.server.computation.task.step.ComputationStep; -import org.sonar.server.test.index.TestIndexer; +import org.sonar.server.es.IndexDefinition; +import org.sonar.server.es.NewIndex; -public class IndexTestsStep implements ComputationStep { +public class FooIndexDefinition implements IndexDefinition { - private final TestIndexer indexer; - private final TreeRootHolder treeRootHolder; - - public IndexTestsStep(TestIndexer indexer, TreeRootHolder treeRootHolder) { - this.indexer = indexer; - this.treeRootHolder = treeRootHolder; - } + public static final String FOO_INDEX = "foos"; + public static final String FOO_TYPE = "foo"; + public static final String FIELD_NAME = "name"; + public static final String FIELD_PROJECT_UUID = "projectUuid"; @Override - public void execute() { - indexer.index(treeRootHolder.getRoot().getUuid()); - } + public void define(IndexDefinitionContext context) { + NewIndex index = context.create(FOO_INDEX); + index.refreshHandledByIndexer(); - @Override - public String getDescription() { - return "Index tests"; - } + NewIndex.NewIndexType type = index.createType(FOO_TYPE) + .requireProjectAuthorization(); + type.stringFieldBuilder(FIELD_NAME).build(); + type.stringFieldBuilder(FIELD_PROJECT_UUID).build(); + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/index/FooIndexer.java b/server/sonar-server/src/test/java/org/sonar/server/permission/index/FooIndexer.java new file mode 100644 index 00000000000..1f67cf76cf3 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/index/FooIndexer.java @@ -0,0 +1,72 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.permission.index; + +import com.google.common.collect.ImmutableMap; +import org.sonar.server.component.index.ComponentIndexDefinition; +import org.sonar.server.es.BulkIndexer; +import org.sonar.server.es.EsClient; +import org.sonar.server.es.ProjectIndexer; + +import static org.elasticsearch.index.query.QueryBuilders.boolQuery; +import static org.elasticsearch.index.query.QueryBuilders.termQuery; +import static org.sonar.server.permission.index.FooIndexDefinition.FOO_INDEX; +import static org.sonar.server.permission.index.FooIndexDefinition.FOO_TYPE; + +public class FooIndexer implements ProjectIndexer, NeedAuthorizationIndexer { + + private static final AuthorizationScope AUTHORIZATION_SCOPE = new AuthorizationScope(FOO_INDEX, p -> true); + + private final EsClient esClient; + + public FooIndexer(EsClient esClient) { + this.esClient = esClient; + } + + @Override + public AuthorizationScope getAuthorizationScope() { + return AUTHORIZATION_SCOPE; + } + + @Override + public void indexProject(String projectUuid, Cause cause) { + addToIndex(projectUuid, "bar"); + addToIndex(projectUuid, "baz"); + } + + private void addToIndex(String projectUuid, String name) { + esClient.prepareIndex(FOO_INDEX, FOO_TYPE) + .setRouting(projectUuid) + .setParent(projectUuid) + .setSource(ImmutableMap.of( + FooIndexDefinition.FIELD_NAME, name, + FooIndexDefinition.FIELD_PROJECT_UUID, projectUuid)) + .get(); + } + + @Override + public void deleteProject(String projectUuid) { + BulkIndexer.delete(esClient, FOO_INDEX, esClient.prepareSearch(FOO_INDEX) + .setTypes(FOO_TYPE) + .setQuery(boolQuery() + .filter( + termQuery(ComponentIndexDefinition.FIELD_PROJECT_UUID, projectUuid)))); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/index/PermissionIndexerTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/index/PermissionIndexerTest.java index 4efccb44cdd..434a7763a59 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/index/PermissionIndexerTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/index/PermissionIndexerTest.java @@ -19,34 +19,26 @@ */ package org.sonar.server.permission.index; -import com.google.common.collect.ImmutableMap; -import java.util.Collections; +import org.junit.After; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.api.config.MapSettings; -import org.sonar.api.resources.Qualifiers; import org.sonar.api.utils.System2; import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDbTester; import org.sonar.db.component.ComponentDto; -import org.sonar.db.component.ComponentTesting; -import org.sonar.db.permission.GroupPermissionDto; import org.sonar.db.user.GroupDto; import org.sonar.db.user.UserDbTester; import org.sonar.db.user.UserDto; -import org.sonar.server.component.index.ComponentIndexDefinition; import org.sonar.server.es.EsTester; -import org.sonar.server.issue.index.IssueIndexDefinition; -import org.sonar.server.measure.index.ProjectMeasuresIndexDefinition; +import org.sonar.server.es.ProjectIndexer; +import org.sonar.server.tester.UserSessionRule; -import static java.util.Arrays.asList; -import static java.util.Collections.emptyList; -import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; -import static org.sonar.api.security.DefaultGroups.ANYONE; import static org.sonar.api.web.UserRole.ADMIN; import static org.sonar.api.web.UserRole.USER; +import static org.sonar.server.permission.index.FooIndexDefinition.FOO_INDEX; public class PermissionIndexerTest { @@ -57,132 +49,218 @@ public class PermissionIndexerTest { public DbTester dbTester = DbTester.create(System2.INSTANCE); @Rule - public EsTester esTester = new EsTester( - new IssueIndexDefinition(new MapSettings()), - new ProjectMeasuresIndexDefinition(new MapSettings()), - new ComponentIndexDefinition(new MapSettings())); + public EsTester esTester = new EsTester(new FooIndexDefinition()); + + @Rule + public UserSessionRule userSession = UserSessionRule.standalone(); private ComponentDbTester componentDbTester = new ComponentDbTester(dbTester); private UserDbTester userDbTester = new UserDbTester(dbTester); + private FooIndex fooIndex = new FooIndex(esTester.client(), new AuthorizationTypeSupport(userSession)); + private FooIndexer fooIndexer = new FooIndexer(esTester.client()); + private PermissionIndexer underTest = new PermissionIndexer( + dbTester.getDbClient(), esTester.client(), new NeedAuthorizationIndexer[] {fooIndexer}); - private PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(esTester); + @Before + public void setUp() throws Exception { + underTest.start(); + } - private PermissionIndexer underTest = new PermissionIndexer(dbTester.getDbClient(), esTester.client()); + @After + public void tearDown() throws Exception { + underTest.stop(); + } @Test - public void index_all_does_nothing_when_no_data() { + public void indexAllIfEmpty_does_nothing_if_no_data() { underTest.indexAllIfEmpty(); - assertThat(esTester.countDocuments("issues", "authorization")).isZero(); + assertThat(esTester.countDocuments(FOO_INDEX, "authorization")).isZero(); + assertThat(fooIndex.hasAccessToProject("a_project")).isFalse(); } @Test - public void index_all() { - ComponentDto project = componentDbTester.insertProject(); - ComponentDto view = componentDbTester.insertView(); - UserDto user = userDbTester.insertUser(); - userDbTester.insertProjectPermissionOnUser(user, USER, project); - userDbTester.insertProjectPermissionOnUser(user, ADMIN, project); - userDbTester.insertProjectPermissionOnUser(user, USER, view); - userDbTester.insertProjectPermissionOnUser(user, ADMIN, view); - GroupDto group = userDbTester.insertGroup(); - userDbTester.insertProjectPermissionOnGroup(group, USER, project); - userDbTester.insertProjectPermissionOnAnyone(USER, project); - userDbTester.insertProjectPermissionOnGroup(group, USER, view); - userDbTester.insertProjectPermissionOnAnyone(USER, view); + public void indexAllIfEmpty_grants_access_to_user() { + ComponentDto project = createAndIndexProject(); + UserDto user1 = userDbTester.insertUser(); + UserDto user2 = userDbTester.insertUser(); + userDbTester.insertProjectPermissionOnUser(user1, USER, project); + userDbTester.insertProjectPermissionOnUser(user2, ADMIN, project); underTest.indexAllIfEmpty(); - authorizationIndexerTester.verifyProjectExistsWithPermission(project.uuid(), asList(group.getName(), ANYONE), singletonList(user.getId())); - authorizationIndexerTester.verifyViewExistsWithPermissionInRightIndexes(view.uuid(), asList(group.getName(), ANYONE), singletonList(user.getId())); + // anonymous + verifyAnonymousNotAuthorized(project); + + // user1 has access + verifyAuthorized(project, user1); + + // user2 has not access (only USER permission is accepted) + verifyNotAuthorized(project, user2); } @Test - public void index_all_with_huge_number_of_projects() throws Exception { - GroupDto group = userDbTester.insertGroup(); - for (int i = 0; i < 1100; i++) { - ComponentDto project = ComponentTesting.newProjectDto(dbTester.getDefaultOrganization()); - dbTester.getDbClient().componentDao().insert(dbTester.getSession(), project); - GroupPermissionDto dto = new GroupPermissionDto() - .setOrganizationUuid(group.getOrganizationUuid()) - .setGroupId(group.getId()) - .setRole(USER) - .setResourceId(project.getId()); - dbTester.getDbClient().groupPermissionDao().insert(dbTester.getSession(), dto); - } - dbTester.getSession().commit(); + public void indexAllIfEmpty_grants_access_to_group() { + ComponentDto project = createAndIndexProject(); + UserDto user1 = userDbTester.insertUser(); + UserDto user2 = userDbTester.insertUser(); + UserDto user3 = userDbTester.insertUser(); + GroupDto group1 = userDbTester.insertGroup(); + GroupDto group2 = userDbTester.insertGroup(); + userDbTester.insertProjectPermissionOnGroup(group1, USER, project); + userDbTester.insertProjectPermissionOnGroup(group2, ADMIN, project); underTest.indexAllIfEmpty(); - assertThat(esTester.countDocuments(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION)).isEqualTo(1100); - assertThat(esTester.countDocuments(ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES, ProjectMeasuresIndexDefinition.TYPE_AUTHORIZATION)).isEqualTo(1100); - assertThat(esTester.countDocuments(ComponentIndexDefinition.INDEX_COMPONENTS, ComponentIndexDefinition.TYPE_AUTHORIZATION)).isEqualTo(1100); + // anonymous + verifyAnonymousNotAuthorized(project); + + // group1 has access + verifyAuthorized(project, user1, group1); + + // group2 has not access (only USER permission is accepted) + verifyNotAuthorized(project, user2, group2); + + // user3 is not in any group + verifyNotAuthorized(project, user3); } @Test - public void index_all_is_first_truncating_indexes() throws Exception { - // Insert only one document in issues authorization => only one index is empty - esTester.client().prepareIndex(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION) - .setId("ABC") - .setRouting("ABC") - .setSource(ImmutableMap.of(IssueIndexDefinition.FIELD_AUTHORIZATION_PROJECT_UUID, "ABC")) - .setRefresh(true) - .get(); + public void indexAllIfEmpty_grants_access_to_user_and_group() { + ComponentDto project = createAndIndexProject(); + UserDto user1 = userDbTester.insertUser(); + UserDto user2 = userDbTester.insertUser(); GroupDto group = userDbTester.insertGroup(); - ComponentDto project = componentDbTester.insertProject(); + userDbTester.insertMember(group, user2); + userDbTester.insertProjectPermissionOnUser(user1, USER, project); userDbTester.insertProjectPermissionOnGroup(group, USER, project); underTest.indexAllIfEmpty(); - authorizationIndexerTester.verifyProjectExistsWithPermission(project.uuid(), asList(group.getName(), ANYONE), emptyList()); - authorizationIndexerTester.verifyProjectDoesNotExist("ABC"); + // anonymous + verifyAnonymousNotAuthorized(project); + + // has direct access + verifyAuthorized(project, user1); + + // has access through group + verifyAuthorized(project, user1, group); + + // no access + verifyNotAuthorized(project, user2); } @Test - public void index_one_project() throws Exception { + public void indexAllIfEmpty_does_not_grant_access_to_anybody() { + ComponentDto project = createAndIndexProject(); + UserDto user = userDbTester.insertUser(); GroupDto group = userDbTester.insertGroup(); - ComponentDto project1 = componentDbTester.insertProject(); - userDbTester.insertProjectPermissionOnGroup(group, USER, project1); - ComponentDto project2 = componentDbTester.insertProject(); - userDbTester.insertProjectPermissionOnGroup(group, USER, project2); - underTest.index(dbTester.getSession(), project1.uuid()); + underTest.indexAllIfEmpty(); - authorizationIndexerTester.verifyProjectExistsWithPermission(project1.uuid(), asList(group.getName(), ANYONE), emptyList()); - authorizationIndexerTester.verifyProjectDoesNotExist(project2.uuid()); + verifyAnonymousNotAuthorized(project); + verifyNotAuthorized(project, user); + verifyNotAuthorized(project, user, group); } @Test - public void index_projects() throws Exception { + public void indexAllIfEmpty_grants_access_to_anyone() { + ComponentDto project = createAndIndexProject(); + UserDto user = userDbTester.insertUser(); GroupDto group = userDbTester.insertGroup(); - ComponentDto project1 = componentDbTester.insertProject(); - userDbTester.insertProjectPermissionOnGroup(group, USER, project1); - ComponentDto project2 = componentDbTester.insertProject(); - userDbTester.insertProjectPermissionOnGroup(group, USER, project2); - ComponentDto project3 = componentDbTester.insertProject(); - userDbTester.insertProjectPermissionOnGroup(group, USER, project3); + userDbTester.insertProjectPermissionOnAnyone(USER, project); - // Only index projects 1 and 2 - underTest.index(dbTester.getSession(), asList(project1.uuid(), project2.uuid())); + underTest.indexAllIfEmpty(); - authorizationIndexerTester.verifyProjectExistsWithPermission(project1.uuid(), asList(group.getName(), ANYONE), emptyList()); - authorizationIndexerTester.verifyProjectExistsWithPermission(project2.uuid(), asList(group.getName(), ANYONE), emptyList()); - authorizationIndexerTester.verifyProjectDoesNotExist(project3.uuid()); + verifyAnonymousAuthorized(project); + verifyAuthorized(project, user); + verifyAuthorized(project, user, group); } @Test - public void update_existing_permissions() { - authorizationIndexerTester.indexProjectPermission("ABC", singletonList("dev"), singletonList(10L)); + public void indexAllIfEmpty_grants_access_on_many_projects() { + UserDto user1 = userDbTester.insertUser(); + UserDto user2 = userDbTester.insertUser(); + ComponentDto project = null; + for (int i = 0; i < PermissionIndexer.MAX_BATCH_SIZE + 10; i++) { + project = createAndIndexProject(); + userDbTester.insertProjectPermissionOnUser(user1, USER, project); + } + + underTest.indexAllIfEmpty(); - // remove permissions -> dto has no users nor groups - underTest.index(new PermissionIndexerDao.Dto("ABC", System.currentTimeMillis(), Qualifiers.PROJECT)); + verifyAnonymousNotAuthorized(project); + verifyAuthorized(project, user1); + verifyNotAuthorized(project, user2); + } - authorizationIndexerTester.verifyProjectExistsWithoutPermission("ABC"); + @Test + public void deleteProject_deletes_the_documents_related_to_the_project() { + ComponentDto project1 = createAndIndexProject(); + ComponentDto project2 = createAndIndexProject(); + userDbTester.insertProjectPermissionOnAnyone(USER, project1); + userDbTester.insertProjectPermissionOnAnyone(USER, project2); + underTest.indexAllIfEmpty(); + assertThat(esTester.countDocuments(FooIndexDefinition.FOO_INDEX, AuthorizationTypeSupport.TYPE_AUTHORIZATION)).isEqualTo(2); + + underTest.deleteProject(project1.uuid()); + assertThat(esTester.countDocuments(FooIndexDefinition.FOO_INDEX, AuthorizationTypeSupport.TYPE_AUTHORIZATION)).isEqualTo(1); } @Test - public void fail_when_trying_to_index_empty_project_uuids() throws Exception { - expectedException.expect(IllegalArgumentException.class); - underTest.index(dbTester.getSession(), Collections.emptyList()); + public void indexProject_does_nothing_because_authorizations_are_triggered_outside_standard_indexer_lifecycle() { + ComponentDto project = createAndIndexProject(); + userDbTester.insertProjectPermissionOnAnyone(USER, project); + + underTest.indexProject(project.uuid(), ProjectIndexer.Cause.NEW_ANALYSIS); + underTest.indexProject(project.uuid(), ProjectIndexer.Cause.PROJECT_CREATION); + underTest.indexProject(project.uuid(), ProjectIndexer.Cause.PROJECT_KEY_UPDATE); + + assertThat(esTester.countDocuments(FooIndexDefinition.FOO_INDEX, AuthorizationTypeSupport.TYPE_AUTHORIZATION)).isEqualTo(0); + } + + private void verifyAuthorized(ComponentDto project, UserDto user) { + logIn(user); + verifyAuthorized(project, true); + } + + private void verifyAuthorized(ComponentDto project, UserDto user, GroupDto group) { + logIn(user).setUserGroups(group.getName()); + verifyAuthorized(project, true); + } + + private void verifyNotAuthorized(ComponentDto project, UserDto user) { + logIn(user); + verifyAuthorized(project, false); + } + + private void verifyNotAuthorized(ComponentDto project, UserDto user, GroupDto group) { + logIn(user).setUserGroups(group.getName()); + verifyAuthorized(project, false); + } + + private void verifyAnonymousAuthorized(ComponentDto project) { + userSession.anonymous(); + verifyAuthorized(project, true); + } + + private void verifyAnonymousNotAuthorized(ComponentDto project) { + userSession.anonymous(); + verifyAuthorized(project, false); + } + + private void verifyAuthorized(ComponentDto project, boolean expectedAccess) { + assertThat(fooIndex.hasAccessToProject(project.uuid())).isEqualTo(expectedAccess); + } + + private UserSessionRule logIn(UserDto u) { + userSession.login(u.getLogin()).setUserId(u.getId().intValue()); + return userSession; + } + + private ComponentDto createAndIndexProject() { + ComponentDto project = componentDbTester.insertProject(); + fooIndexer.indexProject(project.uuid(), ProjectIndexer.Cause.PROJECT_CREATION); + return project; } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/index/PermissionIndexerTester.java b/server/sonar-server/src/test/java/org/sonar/server/permission/index/PermissionIndexerTester.java index 693f4a3aff2..1762f5132ae 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/index/PermissionIndexerTester.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/index/PermissionIndexerTester.java @@ -20,109 +20,45 @@ package org.sonar.server.permission.index; -import java.util.List; -import org.elasticsearch.action.search.SearchRequestBuilder; -import org.elasticsearch.index.query.BoolQueryBuilder; -import org.sonar.api.resources.Qualifiers; -import org.sonar.server.component.index.ComponentIndexDefinition; +import java.util.Arrays; +import java.util.stream.Stream; +import org.sonar.db.component.ComponentDto; import org.sonar.server.es.EsTester; -import org.sonar.server.issue.index.IssueIndexDefinition; -import org.sonar.server.measure.index.ProjectMeasuresIndexDefinition; -import static java.util.Collections.emptyList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.elasticsearch.index.query.QueryBuilders.boolQuery; -import static org.elasticsearch.index.query.QueryBuilders.existsQuery; -import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; -import static org.elasticsearch.index.query.QueryBuilders.termQuery; -import static org.elasticsearch.index.query.QueryBuilders.termsQuery; +import static java.util.Arrays.asList; public class PermissionIndexerTester { - private final EsTester esTester; - private final PermissionIndexer permissionIndexer; - public PermissionIndexerTester(EsTester esTester) { - this.esTester = esTester; - this.permissionIndexer = new PermissionIndexer(null, esTester.client()); - } - - public void indexProjectPermission(String projectUuid, List<String> groupNames, List<Long> userLogins) { - PermissionIndexerDao.Dto authorization = new PermissionIndexerDao.Dto(projectUuid, System.currentTimeMillis(), Qualifiers.PROJECT); - groupNames.forEach(authorization::addGroup); - userLogins.forEach(authorization::addUser); - permissionIndexer.index(authorization); - } - - public void verifyProjectDoesNotExist(String projectUuid) { - assertThat(esTester.getIds(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION)).doesNotContain(projectUuid); - assertThat(esTester.getIds(ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES, ProjectMeasuresIndexDefinition.TYPE_AUTHORIZATION)).doesNotContain(projectUuid); - assertThat(esTester.getIds(ComponentIndexDefinition.INDEX_COMPONENTS, ComponentIndexDefinition.TYPE_AUTHORIZATION)).doesNotContain(projectUuid); - } - - public void verifyProjectExistsWithoutPermission(String projectUuid) { - verifyProjectExistsWithPermission(projectUuid, emptyList(), emptyList()); + public PermissionIndexerTester(EsTester esTester, NeedAuthorizationIndexer indexer, NeedAuthorizationIndexer... others) { + NeedAuthorizationIndexer[] indexers = Stream.concat(Stream.of(indexer), Arrays.stream(others)).toArray(i -> new NeedAuthorizationIndexer[i]); + this.permissionIndexer = new PermissionIndexer(null, esTester.client(), indexers); } - public void verifyProjectExistsWithPermission(String projectUuid, List<String> groupNames, List<Long> userLogins) { - verifyComponentExistsWithPermissionInIndex(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION, - IssueIndexDefinition.FIELD_AUTHORIZATION_PROJECT_UUID, IssueIndexDefinition.FIELD_AUTHORIZATION_GROUPS, IssueIndexDefinition.FIELD_AUTHORIZATION_USERS, - projectUuid, groupNames, userLogins); - - verifyComponentExistsWithPermissionInIndex(ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES, ProjectMeasuresIndexDefinition.TYPE_AUTHORIZATION, - ProjectMeasuresIndexDefinition.FIELD_AUTHORIZATION_PROJECT_UUID, ProjectMeasuresIndexDefinition.FIELD_AUTHORIZATION_GROUPS, - ProjectMeasuresIndexDefinition.FIELD_AUTHORIZATION_USERS, projectUuid, groupNames, userLogins); - - verifyComponentExistsWithPermissionInIndex(ComponentIndexDefinition.INDEX_COMPONENTS, ComponentIndexDefinition.TYPE_AUTHORIZATION, - "_id", ComponentIndexDefinition.FIELD_AUTHORIZATION_GROUPS, - ComponentIndexDefinition.FIELD_AUTHORIZATION_USERS, projectUuid, groupNames, userLogins); - } - - public void verifyViewExistsWithPermissionInRightIndexes(String viewUuid, List<String> groupNames, List<Long> userLogins) { - // index issues - verifyNoAuthorization(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION, viewUuid); - - // index project_measures - verifyNoAuthorization(ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES, ProjectMeasuresIndexDefinition.TYPE_AUTHORIZATION, viewUuid); - - // index components - verifyComponentExistsWithPermissionInIndex(ComponentIndexDefinition.INDEX_COMPONENTS, ComponentIndexDefinition.TYPE_AUTHORIZATION, - "_id", ComponentIndexDefinition.FIELD_AUTHORIZATION_GROUPS, - ComponentIndexDefinition.FIELD_AUTHORIZATION_USERS, viewUuid, groupNames, userLogins); + public PermissionIndexerTester allowOnlyAnyone(ComponentDto project) { + PermissionIndexerDao.Dto dto = new PermissionIndexerDao.Dto(project.uuid(), System.currentTimeMillis(), project.qualifier()) + .addGroup("Anyone"); + permissionIndexer.index(asList(dto)); + return this; } - private void verifyComponentExistsWithPermissionInIndex(String index, String type, String projectField, String groupField, - String userField, String componentUuid, List<String> groupNames, List<Long> userLogins) { - assertThat(esTester.getIds(index, type)).contains(componentUuid); - BoolQueryBuilder queryBuilder = boolQuery().must(termQuery(projectField, componentUuid)); - if (groupNames.isEmpty()) { - queryBuilder.mustNot(existsQuery(groupField)); - } else { - queryBuilder.must(termsQuery(groupField, groupNames)); - } - if (userLogins.isEmpty()) { - queryBuilder.mustNot(existsQuery(userField)); - } else { - queryBuilder.must(termsQuery(userField, userLogins)); - } - SearchRequestBuilder request = esTester.client() - .prepareSearch(index) - .setTypes(type) - .setQuery(boolQuery().must(matchAllQuery()).filter(queryBuilder)); - assertThat(request.get().getHits()).hasSize(1); + public PermissionIndexerTester allowOnlyUser(ComponentDto project, long userId) { + PermissionIndexerDao.Dto dto = new PermissionIndexerDao.Dto(project.uuid(), System.currentTimeMillis(), project.qualifier()) + .addUser(userId); + permissionIndexer.index(asList(dto)); + return this; } - private void verifyNoAuthorization(String index, String authType, String authId) { - assertThat(esTester.getIds(index, authType)).doesNotContain(authId); + public PermissionIndexerTester allowOnlyGroup(ComponentDto project, String groupName) { + PermissionIndexerDao.Dto dto = new PermissionIndexerDao.Dto(project.uuid(), System.currentTimeMillis(), project.qualifier()) + .addGroup(groupName); + permissionIndexer.index(asList(dto)); + return this; } - private void verifyDocument(String index, String docType, String componentField, String componentUuid) { - BoolQueryBuilder queryBuilder = boolQuery().must(termQuery(componentField, componentUuid)); - SearchRequestBuilder request = esTester.client() - .prepareSearch(index) - .setTypes(docType) - .setQuery(boolQuery().must(matchAllQuery()).filter(queryBuilder)); - assertThat(request.get().getHits()).isNotEmpty(); + public PermissionIndexerTester allow(PermissionIndexerDao.Dto access) { + permissionIndexer.index(asList(access)); + return this; } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/ApplyTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/ApplyTemplateActionTest.java index 39d5fadbe25..c5c44db347d 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/ApplyTemplateActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/ApplyTemplateActionTest.java @@ -19,7 +19,6 @@ */ package org.sonar.server.permission.ws.template; -import java.util.Collections; import java.util.List; import javax.annotation.Nullable; import org.junit.Before; @@ -33,22 +32,17 @@ import org.sonar.db.permission.PermissionQuery; import org.sonar.db.permission.template.PermissionTemplateDto; import org.sonar.db.user.GroupDto; import org.sonar.db.user.UserDto; -import org.sonar.server.component.index.ComponentIndexDefinition; -import org.sonar.server.es.EsTester; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.NotFoundException; -import org.sonar.server.issue.index.IssueIndexDefinition; -import org.sonar.server.measure.index.ProjectMeasuresIndexDefinition; import org.sonar.server.permission.PermissionTemplateService; import org.sonar.server.permission.index.PermissionIndexer; -import org.sonar.server.permission.index.PermissionIndexerTester; import org.sonar.server.permission.ws.BasePermissionWsTest; import org.sonar.server.ws.TestRequest; import org.sonar.server.ws.TestResponse; -import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN; import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_ID; import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_KEY; @@ -58,13 +52,7 @@ import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_T public class ApplyTemplateActionTest extends BasePermissionWsTest<ApplyTemplateAction> { @Rule - public EsTester esTester = new EsTester( - new IssueIndexDefinition(new MapSettings()), - new ProjectMeasuresIndexDefinition(new MapSettings()), - new ComponentIndexDefinition(new MapSettings())); - @Rule public DefaultTemplatesResolverRule defaultTemplatesResolver = DefaultTemplatesResolverRule.withoutGovernance(); - private UserDto user1; private UserDto user2; private GroupDto group1; @@ -72,13 +60,12 @@ public class ApplyTemplateActionTest extends BasePermissionWsTest<ApplyTemplateA private ComponentDto project; private PermissionTemplateDto template1; private PermissionTemplateDto template2; - private PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(esTester); - private PermissionIndexer permissionIndexer = new PermissionIndexer(db.getDbClient(), esTester.client()); + + private PermissionTemplateService permissionTemplateService = new PermissionTemplateService(db.getDbClient(), + mock(PermissionIndexer.class), userSession, defaultTemplatesResolver); @Override protected ApplyTemplateAction buildWsAction() { - PermissionTemplateService permissionTemplateService = new PermissionTemplateService(db.getDbClient(), - permissionIndexer, userSession, defaultTemplatesResolver); return new ApplyTemplateAction(db.getDbClient(), userSession, permissionTemplateService, newPermissionWsSupport()); } @@ -204,8 +191,6 @@ public class ApplyTemplateActionTest extends BasePermissionWsTest<ApplyTemplateA assertThat(selectProjectPermissionUsers(project, UserRole.ADMIN)).isEmpty(); assertThat(selectProjectPermissionUsers(project, UserRole.CODEVIEWER)).containsExactly(user1.getId()); assertThat(selectProjectPermissionUsers(project, UserRole.ISSUE_ADMIN)).containsExactly(user2.getId()); - - authorizationIndexerTester.verifyProjectExistsWithPermission(project.uuid(), singletonList(group2.getName()), Collections.emptyList()); } private TestResponse newRequest(@Nullable String templateUuid, @Nullable String projectUuid, @Nullable String projectKey) throws Exception { diff --git a/server/sonar-server/src/test/java/org/sonar/server/project/ws/BulkDeleteActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/project/ws/BulkDeleteActionTest.java index 88edbeaf2ed..ae160c67135 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/project/ws/BulkDeleteActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/project/ws/BulkDeleteActionTest.java @@ -19,59 +19,29 @@ */ package org.sonar.server.project.ws; -import java.util.Arrays; -import java.util.Collections; -import java.util.stream.IntStream; +import java.util.List; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.api.config.MapSettings; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.resources.ResourceType; -import org.sonar.api.resources.ResourceTypes; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.security.DefaultGroups; +import org.mockito.ArgumentCaptor; import org.sonar.api.utils.System2; import org.sonar.api.web.UserRole; import org.sonar.core.permission.GlobalPermissions; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; +import org.sonar.db.component.ComponentDbTester; import org.sonar.db.component.ComponentDto; -import org.sonar.db.component.ComponentTesting; -import org.sonar.db.component.SnapshotDto; -import org.sonar.db.component.SnapshotTesting; -import org.sonar.db.issue.IssueDto; -import org.sonar.db.issue.IssueTesting; -import org.sonar.db.rule.RuleDto; -import org.sonar.db.rule.RuleTesting; import org.sonar.server.component.ComponentCleanerService; -import org.sonar.server.component.ComponentFinder; -import org.sonar.server.component.index.ComponentIndex; -import org.sonar.server.component.index.ComponentIndexDefinition; -import org.sonar.server.component.index.ComponentIndexer; -import org.sonar.server.es.EsTester; import org.sonar.server.exceptions.ForbiddenException; -import org.sonar.server.issue.IssueDocTesting; -import org.sonar.server.issue.index.IssueAuthorizationDoc; -import org.sonar.server.issue.index.IssueIndexDefinition; -import org.sonar.server.issue.index.IssueIndexer; -import org.sonar.server.measure.index.ProjectMeasuresIndexer; -import org.sonar.server.permission.index.PermissionIndexerTester; -import org.sonar.server.test.index.TestDoc; -import org.sonar.server.test.index.TestIndexDefinition; -import org.sonar.server.test.index.TestIndexer; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.WsTester; -import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.sonar.server.issue.index.IssueIndexDefinition.TYPE_AUTHORIZATION; -import static org.sonar.server.issue.index.IssueIndexDefinition.TYPE_ISSUE; +import static org.mockito.Mockito.verify; import static org.sonar.server.project.ws.BulkDeleteAction.PARAM_IDS; import static org.sonar.server.project.ws.BulkDeleteAction.PARAM_KEYS; @@ -85,106 +55,47 @@ public class BulkDeleteActionTest { public DbTester db = DbTester.create(system2); @Rule - public EsTester es = new EsTester(new IssueIndexDefinition(new MapSettings()), - new TestIndexDefinition(new MapSettings()), - new ComponentIndexDefinition(new MapSettings())); - - @Rule public UserSessionRule userSessionRule = UserSessionRule.standalone(); @Rule public ExpectedException expectedException = ExpectedException.none(); + private ComponentDbTester componentDbTester = new ComponentDbTester(db); + private ComponentCleanerService componentCleanerService = mock(ComponentCleanerService.class); private WsTester ws; private DbClient dbClient = db.getDbClient(); - final DbSession dbSession = db.getSession(); - private ResourceType resourceType; - private ComponentIndex componentIndex; - private ComponentIndexer componentIndexer; - private PermissionIndexerTester permissionIndexerTester; @Before public void setUp() { - resourceType = mock(ResourceType.class); - when(resourceType.getBooleanProperty(anyString())).thenReturn(true); - ResourceTypes mockResourceTypes = mock(ResourceTypes.class); - when(mockResourceTypes.get(anyString())).thenReturn(resourceType); - - componentIndex = new ComponentIndex(es.client(), userSessionRule); - componentIndexer = new ComponentIndexer(dbClient, es.client()); - permissionIndexerTester = new PermissionIndexerTester(es); - ws = new WsTester(new ProjectsWs( new BulkDeleteAction( - new ComponentCleanerService(dbClient, - new IssueIndexer(system2, dbClient, es.client()), - new TestIndexer(system2, dbClient, es.client()), - new ProjectMeasuresIndexer(system2, dbClient, es.client()), - componentIndexer, - mockResourceTypes, - new ComponentFinder(dbClient)), + componentCleanerService, dbClient, userSessionRule))); userSessionRule.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); } @Test - public void delete_projects_and_data_in_db_by_uuids() throws Exception { - long snapshotId1 = insertNewProjectInDbAndReturnSnapshotId(1); - long snapshotId2 = insertNewProjectInDbAndReturnSnapshotId(2); - long snapshotId3 = insertNewProjectInDbAndReturnSnapshotId(3); - long snapshotId4 = insertNewProjectInDbAndReturnSnapshotId(4); + public void delete_projects_by_uuids() throws Exception { + ComponentDto p1 = componentDbTester.insertProject(); + ComponentDto p2 = componentDbTester.insertProject(); - ws.newPostRequest("api/projects", ACTION) - .setParam(PARAM_IDS, "project-uuid-1, project-uuid-3, project-uuid-4").execute(); - dbSession.commit(); - - assertThat(dbClient.componentDao().selectByUuids(dbSession, Arrays.asList("project-uuid-1", "project-uuid-3", "project-uuid-4"))).isEmpty(); - assertThat(dbClient.componentDao().selectOrFailByUuid(dbSession, "project-uuid-2")).isNotNull(); - assertThat(dbClient.snapshotDao().selectById(dbSession, snapshotId1)).isNull(); - assertThat(dbClient.snapshotDao().selectById(dbSession, snapshotId3)).isNull(); - assertThat(dbClient.snapshotDao().selectById(dbSession, snapshotId4)).isNull(); - assertThat(dbClient.snapshotDao().selectById(dbSession, snapshotId2)).isNotNull(); - assertThat(dbClient.issueDao().selectByKeys(dbSession, Arrays.asList("issue-key-1", "issue-key-3", "issue-key-4"))).isEmpty(); - assertThat(dbClient.issueDao().selectOrFailByKey(dbSession, "issue-key-2")).isNotNull(); - } - - @Test - public void delete_projects_and_data_in_db_by_keys() throws Exception { - IntStream.rangeClosed(1, 4).forEach(this::insertNewProjectInDbAndReturnSnapshotId); - - ws.newPostRequest("api/projects", ACTION) - .setParam(PARAM_KEYS, "project-key-1, project-key-3, project-key-4").execute(); - dbSession.commit(); - - assertThat(dbClient.componentDao().selectByUuids(dbSession, Arrays.asList("project-uuid-1", "project-uuid-3", "project-uuid-4"))).isEmpty(); - assertThat(dbClient.componentDao().selectOrFailByUuid(dbSession, "project-uuid-2")).isNotNull(); - } - - @Test - public void delete_documents_indexes() throws Exception { - IntStream.rangeClosed(1, 4).forEach(this::insertNewProjectInIndexes); - - ws.newPostRequest("api/projects", ACTION) - .setParam(PARAM_KEYS, "project-key-1, project-key-3, project-key-4").execute(); + WsTester.Result result = ws.newPostRequest("api/projects", ACTION).setParam(PARAM_IDS, p1.uuid() + "," + p2.uuid()).execute(); + result.assertNoContent(); - String remainingProjectUuid = "project-uuid-2"; - assertThat(es.getDocumentFieldValues(IssueIndexDefinition.INDEX, TYPE_ISSUE, IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID)) - .containsOnly(remainingProjectUuid); - assertThat(es.getIds(IssueIndexDefinition.INDEX, TYPE_AUTHORIZATION)).containsOnly(remainingProjectUuid); - assertThat(es.getDocumentFieldValues(TestIndexDefinition.INDEX, TestIndexDefinition.TYPE, TestIndexDefinition.FIELD_PROJECT_UUID)) - .containsOnly(remainingProjectUuid); - assertThat(es.getIds(ComponentIndexDefinition.INDEX_COMPONENTS, ComponentIndexDefinition.TYPE_COMPONENT)).containsOnly(remainingProjectUuid); - assertThat(es.getIds(ComponentIndexDefinition.INDEX_COMPONENTS, ComponentIndexDefinition.TYPE_AUTHORIZATION)).containsOnly(remainingProjectUuid); + verifyDeleted(p1, p2); } @Test - public void web_service_returns_204() throws Exception { - insertNewProjectInDbAndReturnSnapshotId(1); - - WsTester.Result result = ws.newPostRequest("api/projects", ACTION).setParam(PARAM_IDS, "project-uuid-1").execute(); + public void delete_projects_by_keys() throws Exception { + ComponentDto p1 = componentDbTester.insertProject(); + ComponentDto p2 = componentDbTester.insertProject(); + WsTester.Result result = ws.newPostRequest("api/projects", ACTION) + .setParam(PARAM_KEYS, p1.key() + "," + p2.key()).execute(); result.assertNoContent(); + + verifyDeleted(p1, p2); } @Test @@ -195,62 +106,10 @@ public class BulkDeleteActionTest { ws.newPostRequest("api/projects", ACTION).setParam(PARAM_IDS, "whatever-the-uuid").execute(); } - @Test - public void fail_if_scope_is_not_project() throws Exception { - expectedException.expect(IllegalArgumentException.class); - dbClient.componentDao().insert(dbSession, ComponentTesting.newFileDto(ComponentTesting.newProjectDto(db.getDefaultOrganization()), null, "file-uuid")); - dbSession.commit(); - - ws.newPostRequest("api/projects", ACTION).setParam(PARAM_IDS, "file-uuid").execute(); - } - - @Test - public void fail_if_qualifier_is_not_deletable() throws Exception { - expectedException.expect(IllegalArgumentException.class); - dbClient.componentDao().insert(dbSession, ComponentTesting.newProjectDto(db.getDefaultOrganization(), "project-uuid").setQualifier(Qualifiers.FILE)); - dbSession.commit(); - when(resourceType.getBooleanProperty(anyString())).thenReturn(false); - - ws.newPostRequest("api/projects", ACTION).setParam(PARAM_IDS, "project-uuid").execute(); - } - - private long insertNewProjectInDbAndReturnSnapshotId(int id) { - String suffix = String.valueOf(id); - ComponentDto project = ComponentTesting - .newProjectDto(db.getDefaultOrganization(), "project-uuid-" + suffix) - .setKey("project-key-" + suffix); - RuleDto rule = RuleTesting.newDto(RuleKey.of("sonarqube", "rule-" + suffix)); - dbClient.ruleDao().insert(dbSession, rule); - IssueDto issue = IssueTesting.newDto(rule, project, project).setKee("issue-key-" + suffix); - dbClient.componentDao().insert(dbSession, project); - SnapshotDto snapshot = dbClient.snapshotDao().insert(dbSession, SnapshotTesting.newAnalysis(project)); - dbClient.issueDao().insert(dbSession, issue); - dbSession.commit(); - - return snapshot.getId(); - } - - private void insertNewProjectInIndexes(int id) { - String suffix = String.valueOf(id); - ComponentDto project = ComponentTesting - .newProjectDto(db.getDefaultOrganization(), "project-uuid-" + suffix) - .setKey("project-key-" + suffix); - dbClient.componentDao().insert(dbSession, project); - dbSession.commit(); - - try { - es.putDocuments(IssueIndexDefinition.INDEX, TYPE_ISSUE, IssueDocTesting.newDoc("issue-key-" + suffix, project)); - es.putDocuments(IssueIndexDefinition.INDEX, TYPE_AUTHORIZATION, new IssueAuthorizationDoc().setProjectUuid(project.uuid())); - - TestDoc testDoc = new TestDoc().setUuid("test-uuid-" + suffix).setProjectUuid(project.uuid()).setFileUuid(project.uuid()); - es.putDocuments(TestIndexDefinition.INDEX, TestIndexDefinition.TYPE, testDoc); - } catch (Exception e) { - throw new IllegalStateException("Cannot put documents to index", e); - } + private void verifyDeleted(ComponentDto... projects) { + ArgumentCaptor<List<ComponentDto>> argument = (ArgumentCaptor<List<ComponentDto>>) ((ArgumentCaptor) ArgumentCaptor.forClass(List.class)); + verify(componentCleanerService).delete(any(DbSession.class), argument.capture()); - componentIndexer.indexByProjectUuid(project.uuid()); - permissionIndexerTester.indexProjectPermission(project.uuid(), - Collections.singletonList(DefaultGroups.ANYONE), - emptyList()); + assertThat(argument.getValue()).containsOnly(projects); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/project/ws/CreateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/project/ws/CreateActionTest.java index 988ce6aad6f..a46fb7cc0d2 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/project/ws/CreateActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/project/ws/CreateActionTest.java @@ -23,33 +23,22 @@ package org.sonar.server.project.ws; import com.google.common.base.Throwables; import java.io.IOException; import org.assertj.core.api.Assertions; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.api.config.MapSettings; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; import org.sonar.api.server.ws.WebService; import org.sonar.api.utils.System2; +import org.sonar.db.DbSession; import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; -import org.sonar.db.component.ComponentTesting; -import org.sonar.db.permission.template.PermissionTemplateDto; -import org.sonar.db.user.UserDto; import org.sonar.server.component.ComponentUpdater; -import org.sonar.server.component.index.ComponentIndexDefinition; -import org.sonar.server.component.index.ComponentIndexer; -import org.sonar.server.es.EsTester; +import org.sonar.server.component.NewComponent; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.ForbiddenException; -import org.sonar.server.favorite.FavoriteUpdater; -import org.sonar.server.i18n.I18nRule; -import org.sonar.server.measure.index.ProjectMeasuresIndexDefinition; -import org.sonar.server.measure.index.ProjectMeasuresIndexer; import org.sonar.server.organization.DefaultOrganizationProvider; import org.sonar.server.organization.TestDefaultOrganizationProvider; -import org.sonar.server.permission.PermissionTemplateService; -import org.sonar.server.permission.index.PermissionIndexer; -import org.sonar.server.permission.ws.template.DefaultTemplatesResolverRule; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.TestRequest; import org.sonar.server.ws.WsActionTester; @@ -58,14 +47,14 @@ import org.sonarqube.ws.WsProjects.CreateWsResponse; import org.sonarqube.ws.client.project.CreateRequest; import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; -import static org.sonar.api.web.UserRole.USER; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import static org.sonar.core.permission.GlobalPermissions.PROVISIONING; import static org.sonar.core.permission.GlobalPermissions.QUALITY_GATE_ADMIN; import static org.sonar.core.util.Protobuf.setNullable; -import static org.sonar.server.component.index.ComponentIndexDefinition.INDEX_COMPONENTS; -import static org.sonar.server.component.index.ComponentIndexDefinition.TYPE_COMPONENT; -import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES; -import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.TYPE_PROJECT_MEASURE; import static org.sonar.test.JsonAssert.assertJson; import static org.sonarqube.ws.client.WsRequest.Method.POST; import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_NAME; @@ -82,36 +71,20 @@ public class CreateActionTest { @Rule public DbTester db = DbTester.create(system2); @Rule - public EsTester es = new EsTester(new ComponentIndexDefinition(new MapSettings()), new ProjectMeasuresIndexDefinition(new MapSettings())); - @Rule public UserSessionRule userSession = UserSessionRule.standalone(); - @Rule - public I18nRule i18n = new I18nRule().put("qualifier.TRK", "Project"); - @Rule - public DefaultTemplatesResolverRule defaultTemplatesResolver = DefaultTemplatesResolverRule.withoutGovernance(); - private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db); - private PermissionTemplateDto permissionTemplateDto; + private ComponentUpdater componentUpdater = mock(ComponentUpdater.class, Mockito.RETURNS_MOCKS); private WsActionTester ws = new WsActionTester( new CreateAction( db.getDbClient(), userSession, - new ComponentUpdater(db.getDbClient(), i18n, system2, - new PermissionTemplateService(db.getDbClient(), new PermissionIndexer(db.getDbClient(), es.client()), userSession, defaultTemplatesResolver), - new FavoriteUpdater(db.getDbClient()), - new ProjectMeasuresIndexer(system2, db.getDbClient(), es.client()), - new ComponentIndexer(db.getDbClient(), es.client())), + componentUpdater, defaultOrganizationProvider)); - @Before - public void setUp() throws Exception { - permissionTemplateDto = db.permissionTemplates().insertTemplate(db.getDefaultOrganization()); - db.organizations().setDefaultTemplates(db.getDefaultOrganization(), permissionTemplateDto.getUuid(), null); - } - @Test public void create_project() throws Exception { userSession.setGlobalPermissions(PROVISIONING); + expectSuccessfulCallToComponentUpdater(); CreateWsResponse response = call(CreateRequest.builder() .setKey(DEFAULT_PROJECT_KEY) @@ -121,95 +94,21 @@ public class CreateActionTest { assertThat(response.getProject().getKey()).isEqualTo(DEFAULT_PROJECT_KEY); assertThat(response.getProject().getName()).isEqualTo(DEFAULT_PROJECT_NAME); assertThat(response.getProject().getQualifier()).isEqualTo("TRK"); - ComponentDto project = db.getDbClient().componentDao().selectOrFailByKey(db.getSession(), DEFAULT_PROJECT_KEY); - assertThat(project.getKey()).isEqualTo(DEFAULT_PROJECT_KEY); - assertThat(project.name()).isEqualTo(DEFAULT_PROJECT_NAME); - assertThat(project.qualifier()).isEqualTo("TRK"); } @Test public void create_project_with_branch() throws Exception { userSession.setGlobalPermissions(PROVISIONING); - CreateWsResponse response = call(CreateRequest.builder() - .setKey(DEFAULT_PROJECT_KEY) - .setName(DEFAULT_PROJECT_NAME) - .setBranch("origin/master") - .build()); - - assertThat(response.getProject().getKey()).isEqualTo("project-key:origin/master"); - } - - @Test - public void verify_permission_template_is_applied() throws Exception { - UserDto userDto = db.users().insertUser(); - userSession.login(userDto).setGlobalPermissions(PROVISIONING); - db.permissionTemplates().addUserToTemplate(permissionTemplateDto.getId(), userDto.getId(), USER); - - call(CreateRequest.builder() - .setKey(DEFAULT_PROJECT_KEY) - .setName(DEFAULT_PROJECT_NAME) - .build()); - - ComponentDto project = db.getDbClient().componentDao().selectOrFailByKey(db.getSession(), DEFAULT_PROJECT_KEY); - assertThat(db.users().selectProjectPermissionsOfUser(userDto, project)).containsOnly(USER); - } - - @Test - public void add_project_to_favorite_when_logged() throws Exception { - UserDto userDto = db.users().insertUser(); - userSession.login(userDto).setGlobalPermissions(PROVISIONING); - db.permissionTemplates().addProjectCreatorToTemplate(permissionTemplateDto.getId(), USER); - - call(CreateRequest.builder() - .setKey(DEFAULT_PROJECT_KEY) - .setName(DEFAULT_PROJECT_NAME) - .build()); - - ComponentDto project = db.getDbClient().componentDao().selectOrFailByKey(db.getSession(), DEFAULT_PROJECT_KEY); - assertThat(db.favorites().hasFavorite(project, userDto.getId())).isTrue(); - } - - @Test - public void does_not_add_project_to_favorite_when_not_logged() throws Exception { - userSession.setGlobalPermissions(PROVISIONING); - db.permissionTemplates().addProjectCreatorToTemplate(permissionTemplateDto.getId(), USER); - - call(CreateRequest.builder() - .setKey(DEFAULT_PROJECT_KEY) - .setName(DEFAULT_PROJECT_NAME) - .build()); - - ComponentDto project = db.getDbClient().componentDao().selectOrFailByKey(db.getSession(), DEFAULT_PROJECT_KEY); - assertThat(db.favorites().hasNoFavorite(project)).isTrue(); - } - - @Test - public void does_not_add_project_to_favorite_when_project_create_has_no_permission_on_template() throws Exception { - UserDto userDto = db.users().insertUser(); - userSession.login(userDto).setGlobalPermissions(PROVISIONING); - - call(CreateRequest.builder() - .setKey(DEFAULT_PROJECT_KEY) - .setName(DEFAULT_PROJECT_NAME) - .build()); - - ComponentDto project = db.getDbClient().componentDao().selectOrFailByKey(db.getSession(), DEFAULT_PROJECT_KEY); - assertThat(db.favorites().hasNoFavorite(project)).isTrue(); - } - - @Test - public void verify_project_exists_in_es_indexes() throws Exception { - userSession.setGlobalPermissions(PROVISIONING); - call(CreateRequest.builder() .setKey(DEFAULT_PROJECT_KEY) .setName(DEFAULT_PROJECT_NAME) + .setBranch("origin/master") .build()); - ComponentDto project = db.getDbClient().componentDao().selectOrFailByKey(db.getSession(), DEFAULT_PROJECT_KEY); - assertThat(es.getIds(INDEX_COMPONENTS, TYPE_COMPONENT)).containsOnly(project.uuid()); - assertThat(es.getIds(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURE)).containsOnly(project.uuid()); + NewComponent called = verifyCallToComponentUpdater(); + assertThat(called.key()).isEqualTo(DEFAULT_PROJECT_KEY); + assertThat(called.branch()).isEqualTo("origin/master"); } @Test @@ -222,15 +121,17 @@ public class CreateActionTest { .setParam(PARAM_NAME, DEFAULT_PROJECT_NAME) .execute(); - assertThat(db.getDbClient().componentDao().selectByKey(db.getSession(), DEFAULT_PROJECT_KEY).isPresent()).isTrue(); + NewComponent called = verifyCallToComponentUpdater(); + assertThat(called.key()).isEqualTo(DEFAULT_PROJECT_KEY); + assertThat(called.branch()).isNull(); } @Test public void fail_when_project_already_exists() throws Exception { userSession.setGlobalPermissions(PROVISIONING); - db.components().insertComponent(ComponentTesting.newProjectDto(db.getDefaultOrganization()).setKey(DEFAULT_PROJECT_KEY)); + when(componentUpdater.create(any(DbSession.class), any(NewComponent.class), anyLong())).thenThrow(new BadRequestException("already exists")); + expectedException.expect(BadRequestException.class); - expectedException.expectMessage("Could not create Project, key already exists: project-key"); call(CreateRequest.builder() .setKey(DEFAULT_PROJECT_KEY) @@ -257,15 +158,6 @@ public class CreateActionTest { } @Test - public void fail_when_key_has_bad_format() throws Exception { - userSession.setGlobalPermissions(PROVISIONING); - expectedException.expect(BadRequestException.class); - expectedException.expectMessage("Malformed key for Project: 1234"); - - call(CreateRequest.builder().setKey("1234").setName(DEFAULT_PROJECT_NAME).build()); - } - - @Test public void fail_when_missing_create_project_permission() throws Exception { userSession.setGlobalPermissions(QUALITY_GATE_ADMIN); expectedException.expect(ForbiddenException.class); @@ -276,6 +168,7 @@ public class CreateActionTest { @Test public void test_example() { userSession.setGlobalPermissions(PROVISIONING); + expectSuccessfulCallToComponentUpdater(); String result = ws.newRequest() .setParam("key", DEFAULT_PROJECT_KEY) @@ -310,4 +203,16 @@ public class CreateActionTest { } } + private NewComponent verifyCallToComponentUpdater() { + ArgumentCaptor<NewComponent> argument = ArgumentCaptor.forClass(NewComponent.class); + verify(componentUpdater).create(any(DbSession.class), argument.capture(), anyLong()); + return argument.getValue(); + } + + private void expectSuccessfulCallToComponentUpdater() { + when(componentUpdater.create(any(DbSession.class), any(NewComponent.class), anyLong())).thenAnswer(invocation -> { + NewComponent newC = invocation.getArgumentAt(1, NewComponent.class); + return new ComponentDto().setKey(newC.key()).setQualifier(newC.qualifier()).setName(newC.name()); + }); + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/project/ws/DeleteActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/project/ws/DeleteActionTest.java index 4999cbb4bd3..9f0a8f4500d 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/project/ws/DeleteActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/project/ws/DeleteActionTest.java @@ -19,55 +19,28 @@ */ package org.sonar.server.project.ws; -import java.util.Collections; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.api.config.MapSettings; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.resources.ResourceType; -import org.sonar.api.resources.ResourceTypes; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.security.DefaultGroups; +import org.mockito.ArgumentCaptor; import org.sonar.api.utils.System2; import org.sonar.api.web.UserRole; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; +import org.sonar.db.component.ComponentDbTester; import org.sonar.db.component.ComponentDto; -import org.sonar.db.component.ComponentTesting; -import org.sonar.db.component.SnapshotDto; -import org.sonar.db.component.SnapshotTesting; -import org.sonar.db.issue.IssueDto; -import org.sonar.db.issue.IssueTesting; -import org.sonar.db.rule.RuleDto; -import org.sonar.db.rule.RuleTesting; import org.sonar.server.component.ComponentCleanerService; import org.sonar.server.component.ComponentFinder; -import org.sonar.server.component.index.ComponentIndex; -import org.sonar.server.component.index.ComponentIndexDefinition; -import org.sonar.server.component.index.ComponentIndexer; -import org.sonar.server.es.EsTester; import org.sonar.server.exceptions.ForbiddenException; -import org.sonar.server.issue.IssueDocTesting; -import org.sonar.server.issue.index.IssueAuthorizationDoc; -import org.sonar.server.issue.index.IssueIndexDefinition; -import org.sonar.server.issue.index.IssueIndexer; -import org.sonar.server.measure.index.ProjectMeasuresIndexer; -import org.sonar.server.permission.index.PermissionIndexerTester; -import org.sonar.server.test.index.TestDoc; -import org.sonar.server.test.index.TestIndexDefinition; -import org.sonar.server.test.index.TestIndexer; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.WsTester; -import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.guava.api.Assertions.assertThat; -import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.verify; import static org.sonar.server.project.ws.DeleteAction.PARAM_ID; import static org.sonar.server.project.ws.DeleteAction.PARAM_KEY; import static org.sonarqube.ws.client.project.ProjectsWsParameters.CONTROLLER; @@ -82,12 +55,6 @@ public class DeleteActionTest { public DbTester db = DbTester.create(system2); @Rule - public EsTester es = new EsTester( - new IssueIndexDefinition(new MapSettings()), - new TestIndexDefinition(new MapSettings()), - new ComponentIndexDefinition(new MapSettings())); - - @Rule public UserSessionRule userSessionRule = UserSessionRule.standalone(); @Rule @@ -95,183 +62,80 @@ public class DeleteActionTest { private WsTester ws; private DbClient dbClient = db.getDbClient(); - private final DbSession dbSession = db.getSession(); - private ResourceType resourceType; - public ComponentIndex componentIndex; - public ComponentIndexer componentIndexer; - private PermissionIndexerTester permissionIndexerTester; + private ComponentDbTester componentDbTester = new ComponentDbTester(db); + private ComponentCleanerService componentCleanerService = mock(ComponentCleanerService.class); @Before public void setUp() { - resourceType = mock(ResourceType.class); - when(resourceType.getBooleanProperty(anyString())).thenReturn(true); - ResourceTypes mockResourceTypes = mock(ResourceTypes.class); - when(mockResourceTypes.get(anyString())).thenReturn(resourceType); - - componentIndex = new ComponentIndex(es.client(), userSessionRule); - componentIndexer = new ComponentIndexer(dbClient, es.client()); - permissionIndexerTester = new PermissionIndexerTester(es); - ws = new WsTester(new ProjectsWs( new DeleteAction( - new ComponentCleanerService( - dbClient, - new IssueIndexer(system2, dbClient, es.client()), - new TestIndexer(system2, dbClient, es.client()), - new ProjectMeasuresIndexer(system2, dbClient, es.client()), - componentIndexer, - mockResourceTypes, - new ComponentFinder(dbClient)), + componentCleanerService, new ComponentFinder(dbClient), dbClient, userSessionRule))); - userSessionRule.login("login").setGlobalPermissions(UserRole.ADMIN); - } - - @Test - public void delete_project_and_data_in_db_by_uuid() throws Exception { - long snapshotId1 = insertNewProjectInDbAndReturnSnapshotId(1); - long snapshotId2 = insertNewProjectInDbAndReturnSnapshotId(2); - - newRequest() - .setParam(PARAM_ID, "project-uuid-1").execute(); - dbSession.commit(); - - assertThat(dbClient.componentDao().selectByUuid(dbSession, "project-uuid-1")).isAbsent(); - assertThat(dbClient.componentDao().selectOrFailByUuid(dbSession, "project-uuid-2")).isNotNull(); - assertThat(dbClient.snapshotDao().selectById(dbSession, snapshotId1)).isNull(); - assertThat(dbClient.snapshotDao().selectById(dbSession, snapshotId2)).isNotNull(); - assertThat(dbClient.issueDao().selectByKey(dbSession, "issue-key-1").isPresent()).isFalse(); - assertThat(dbClient.issueDao().selectOrFailByKey(dbSession, "issue-key-2")).isNotNull(); } @Test - public void delete_projects_and_data_in_db_by_key() throws Exception { - insertNewProjectInDbAndReturnSnapshotId(1); - insertNewProjectInDbAndReturnSnapshotId(2); + public void global_admin_deletes_project_by_uuid() throws Exception { + ComponentDto project = componentDbTester.insertProject(); - newRequest() - .setParam(PARAM_KEY, "project-key-1").execute(); - dbSession.commit(); + userSessionRule.login().setGlobalPermissions(UserRole.ADMIN); + WsTester.TestRequest request = newRequest().setParam(PARAM_ID, project.uuid()); + call(request); - assertThat(dbClient.componentDao().selectByUuid(dbSession, "project-uuid-1")).isAbsent(); - assertThat(dbClient.componentDao().selectOrFailByUuid(dbSession, "project-uuid-2")).isNotNull(); + assertThat(verifyDeletedKey()).isEqualTo(project.key()); } @Test - public void delete_projects_by_uuid_when_admin_on_the_project() throws Exception { - insertNewProjectInDbAndReturnSnapshotId(1); - userSessionRule.login("login").addProjectUuidPermissions(UserRole.ADMIN, "project-uuid-1"); + public void global_admin_deletes_project_by_key() throws Exception { + ComponentDto project = componentDbTester.insertProject(); - newRequest().setParam(PARAM_ID, "project-uuid-1").execute(); - dbSession.commit(); + userSessionRule.login().setGlobalPermissions(UserRole.ADMIN); + call(newRequest().setParam(PARAM_KEY, project.key())); - assertThat(dbClient.componentDao().selectByUuid(dbSession, "project-uuid-1")).isAbsent(); + assertThat(verifyDeletedKey()).isEqualTo(project.key()); } - @Test - public void delete_projects_by_key_when_admin_on_the_project() throws Exception { - insertNewProjectInDbAndReturnSnapshotId(1); - // can't use addProjectUuidPermissions as mock keep separated lists - userSessionRule.login("login").addProjectPermissions(UserRole.ADMIN, "project-key-1"); - - newRequest().setParam(PARAM_KEY, "project-key-1").execute(); - dbSession.commit(); - - assertThat(dbClient.componentDao().selectByUuid(dbSession, "project-uuid-1")).isAbsent(); + private String verifyDeletedKey() { + ArgumentCaptor<ComponentDto> argument = ArgumentCaptor.forClass(ComponentDto.class); + verify(componentCleanerService).delete(any(DbSession.class), argument.capture()); + return argument.getValue().key(); } @Test - public void delete_documents_indexes() throws Exception { - insertNewProjectInIndexes(1); - insertNewProjectInIndexes(2); + public void project_administrator_deletes_the_project_by_uuid() throws Exception { + ComponentDto project = componentDbTester.insertProject(); + userSessionRule.login().addProjectUuidPermissions(UserRole.ADMIN, project.uuid()); - newRequest() - .setParam(PARAM_KEY, "project-key-1").execute(); + call(newRequest().setParam(PARAM_ID, project.uuid())); - String remainingProjectUuid = "project-uuid-2"; - assertThat(es.getDocumentFieldValues(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_ISSUE, IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID)) - .containsOnly(remainingProjectUuid); - assertThat(es.getIds(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION)).containsOnly(remainingProjectUuid); - assertThat(es.getDocumentFieldValues(TestIndexDefinition.INDEX, TestIndexDefinition.TYPE, TestIndexDefinition.FIELD_PROJECT_UUID)) - .containsOnly(remainingProjectUuid); - assertThat(es.getIds(ComponentIndexDefinition.INDEX_COMPONENTS, ComponentIndexDefinition.TYPE_COMPONENT)).containsOnly(remainingProjectUuid); - assertThat(es.getIds(ComponentIndexDefinition.INDEX_COMPONENTS, ComponentIndexDefinition.TYPE_AUTHORIZATION)).containsOnly(remainingProjectUuid); + assertThat(verifyDeletedKey()).isEqualTo(project.key()); } @Test - public void web_service_returns_204() throws Exception { - insertNewProjectInDbAndReturnSnapshotId(1); + public void project_administrator_deletes_the_project_by_key() throws Exception { + ComponentDto project = componentDbTester.insertProject(); + userSessionRule.login().addProjectPermissions(UserRole.ADMIN, project.key()); - WsTester.Result result = newRequest().setParam(PARAM_ID, "project-uuid-1").execute(); + call(newRequest().setParam(PARAM_KEY, project.key())); - result.assertNoContent(); + assertThat(verifyDeletedKey()).isEqualTo(project.key()); } @Test public void fail_if_insufficient_privileges() throws Exception { - userSessionRule.setGlobalPermissions(UserRole.CODEVIEWER, UserRole.ISSUE_ADMIN, UserRole.USER); + userSessionRule.login().setGlobalPermissions(UserRole.CODEVIEWER, UserRole.ISSUE_ADMIN, UserRole.USER); expectedException.expect(ForbiddenException.class); - newRequest().setParam(PARAM_ID, "whatever-the-uuid").execute(); - } - - @Test - public void fail_if_scope_is_not_project() throws Exception { - expectedException.expect(IllegalArgumentException.class); - dbClient.componentDao().insert(dbSession, ComponentTesting.newFileDto(ComponentTesting.newProjectDto(db.getDefaultOrganization()), null, "file-uuid")); - dbSession.commit(); - - newRequest().setParam(PARAM_ID, "file-uuid").execute(); - } - - @Test - public void fail_if_qualifier_is_not_deletable() throws Exception { - expectedException.expect(IllegalArgumentException.class); - dbClient.componentDao().insert(dbSession, ComponentTesting.newProjectDto(db.organizations().insert(), "project-uuid").setQualifier(Qualifiers.FILE)); - dbSession.commit(); - when(resourceType.getBooleanProperty(anyString())).thenReturn(false); - - newRequest().setParam(PARAM_ID, "project-uuid").execute(); - } - - private long insertNewProjectInDbAndReturnSnapshotId(int id) { - String suffix = String.valueOf(id); - ComponentDto project = ComponentTesting - .newProjectDto(db.organizations().insert(), "project-uuid-" + suffix) - .setKey("project-key-" + suffix); - RuleDto rule = RuleTesting.newDto(RuleKey.of("sonarqube", "rule-" + suffix)); - dbClient.ruleDao().insert(dbSession, rule); - IssueDto issue = IssueTesting.newDto(rule, project, project).setKee("issue-key-" + suffix); - dbClient.componentDao().insert(dbSession, project); - SnapshotDto snapshot = dbClient.snapshotDao().insert(dbSession, SnapshotTesting.newAnalysis(project)); - dbClient.issueDao().insert(dbSession, issue); - dbSession.commit(); - - return snapshot.getId(); - } - - private void insertNewProjectInIndexes(int id) throws Exception { - String suffix = String.valueOf(id); - ComponentDto project = ComponentTesting - .newProjectDto(db.getDefaultOrganization(), "project-uuid-" + suffix) - .setKey("project-key-" + suffix); - dbClient.componentDao().insert(dbSession, project); - dbSession.commit(); - - es.putDocuments(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_ISSUE, IssueDocTesting.newDoc("issue-key-" + suffix, project)); - es.putDocuments(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION, new IssueAuthorizationDoc().setProjectUuid(project.uuid())); - - componentIndexer.indexByProjectUuid(project.uuid()); - permissionIndexerTester.indexProjectPermission(project.uuid(), - Collections.singletonList(DefaultGroups.ANYONE), - emptyList()); - - TestDoc testDoc = new TestDoc().setUuid("test-uuid-" + suffix).setProjectUuid(project.uuid()).setFileUuid(project.uuid()); - es.putDocuments(TestIndexDefinition.INDEX, TestIndexDefinition.TYPE, testDoc); + call(newRequest().setParam(PARAM_ID, "whatever-the-uuid")); } private WsTester.TestRequest newRequest() { return ws.newPostRequest(CONTROLLER, ACTION); } + + private void call(WsTester.TestRequest request) throws Exception { + WsTester.Result result = request.execute(); + result.assertNoContent(); + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/search/EsSearchModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/search/EsSearchModuleTest.java index abf95a396c8..058686bb702 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/search/EsSearchModuleTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/search/EsSearchModuleTest.java @@ -29,7 +29,7 @@ public class EsSearchModuleTest { public void verify_count_of_added_components() { ComponentContainer container = new ComponentContainer(); new EsSearchModule().configure(container); - assertThat(container.size()).isEqualTo(4); + assertThat(container.size()).isEqualTo(3 + 2); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/test/index/TestIndexerTest.java b/server/sonar-server/src/test/java/org/sonar/server/test/index/TestIndexerTest.java index 622471ecf5c..2031d2a9a21 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/test/index/TestIndexerTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/test/index/TestIndexerTest.java @@ -37,6 +37,7 @@ import org.sonar.api.utils.System2; import org.sonar.db.DbTester; import org.sonar.db.protobuf.DbFileSources; import org.sonar.server.es.EsTester; +import org.sonar.server.es.ProjectIndexer; import org.sonar.server.source.index.FileSourcesUpdaterHelper; import org.sonar.server.test.db.TestTesting; import org.sonar.test.TestUtils; @@ -83,7 +84,7 @@ public class TestIndexerTest { TestTesting.updateDataColumn(db.getSession(), "FILE_UUID", TestTesting.newRandomTests(3)); - underTest.index("PROJECT_UUID"); + underTest.indexProject("PROJECT_UUID", ProjectIndexer.Cause.NEW_ANALYSIS); assertThat(countDocuments()).isEqualTo(3); } @@ -93,7 +94,7 @@ public class TestIndexerTest { TestTesting.updateDataColumn(db.getSession(), "FILE_UUID", TestTesting.newRandomTests(3)); - underTest.index("UNKNOWN"); + underTest.indexProject("UNKNOWN", ProjectIndexer.Cause.NEW_ANALYSIS); assertThat(countDocuments()).isZero(); } @@ -138,7 +139,7 @@ public class TestIndexerTest { } @Test - public void delete_file_uuid() throws Exception { + public void delete_file_by_uuid() throws Exception { indexTest("P1", "F1", "T1", "U111"); indexTest("P1", "F1", "T2", "U112"); indexTest("P1", "F2", "T1", "U121"); @@ -153,13 +154,13 @@ public class TestIndexerTest { } @Test - public void delete_by_project_uuid() throws Exception { + public void delete_project_by_uuid() throws Exception { indexTest("P1", "F1", "T1", "U111"); indexTest("P1", "F1", "T2", "U112"); indexTest("P1", "F2", "T1", "U121"); indexTest("P2", "F3", "T1", "U231"); - underTest.deleteByProject("P1"); + underTest.deleteProject("P1"); List<SearchHit> hits = getDocuments(); assertThat(hits).hasSize(1); diff --git a/server/sonar-server/src/test/java/org/sonar/server/view/index/ViewIndexerTest.java b/server/sonar-server/src/test/java/org/sonar/server/view/index/ViewIndexerTest.java index 0b166917f81..ad95f214a91 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/view/index/ViewIndexerTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/view/index/ViewIndexerTest.java @@ -36,16 +36,8 @@ import org.sonar.db.issue.IssueDto; import org.sonar.db.issue.IssueTesting; import org.sonar.db.organization.OrganizationDto; import org.sonar.db.rule.RuleDto; -import org.sonar.db.rule.RuleTesting; import org.sonar.server.es.EsTester; -import org.sonar.server.es.SearchOptions; -import org.sonar.server.es.SearchResult; -import org.sonar.server.issue.IssueQuery; -import org.sonar.server.issue.index.IssueDoc; -import org.sonar.server.issue.index.IssueIndex; import org.sonar.server.issue.index.IssueIndexDefinition; -import org.sonar.server.issue.index.IssueIndexer; -import org.sonar.server.permission.index.PermissionIndexer; import org.sonar.server.tester.UserSessionRule; import static com.google.common.collect.Lists.newArrayList; @@ -66,11 +58,12 @@ public class ViewIndexerTest { private DbClient dbClient = dbTester.getDbClient(); private DbSession dbSession = dbTester.getSession(); - private ViewIndexer indexer = (ViewIndexer) new ViewIndexer(system2, dbClient, esTester.client()); + //private PermissionIndexer permissionIndexer = new PermissionIndexer(dbClient, esTester.client(), new NeedAuthorizationIndexer[]{underTest}); + private ViewIndexer underTest = (ViewIndexer) new ViewIndexer(system2, dbClient, esTester.client()); @Test public void index_nothing() { - indexer.index(); + underTest.index(); assertThat(esTester.countDocuments(ViewIndexDefinition.INDEX, ViewIndexDefinition.TYPE_VIEW)).isEqualTo(0L); } @@ -78,7 +71,7 @@ public class ViewIndexerTest { public void index() { dbTester.prepareDbUnit(getClass(), "index.xml"); - indexer.index(); + underTest.index(); List<ViewDoc> docs = esTester.getDocuments("views", "view", ViewDoc.class); assertThat(docs).hasSize(4); @@ -98,7 +91,7 @@ public class ViewIndexerTest { esTester.putDocuments(ViewIndexDefinition.INDEX, ViewIndexDefinition.TYPE_VIEW, new ViewDoc().setUuid("ABCD").setProjects(newArrayList("BCDE"))); - indexer.index(); + underTest.index(); // ... But they shouldn't be indexed assertThat(esTester.countDocuments(ViewIndexDefinition.INDEX, ViewIndexDefinition.TYPE_VIEW)).isEqualTo(1L); @@ -108,7 +101,7 @@ public class ViewIndexerTest { public void index_root_view() { dbTester.prepareDbUnit(getClass(), "index.xml"); - indexer.index("EFGH"); + underTest.index("EFGH"); List<ViewDoc> docs = esTester.getDocuments("views", "view", ViewDoc.class); assertThat(docs).hasSize(2); @@ -121,7 +114,7 @@ public class ViewIndexerTest { @Test public void index_view_doc() { - indexer.index(new ViewDoc().setUuid("EFGH").setProjects(newArrayList("KLMN", "JKLM"))); + underTest.index(new ViewDoc().setUuid("EFGH").setProjects(newArrayList("KLMN", "JKLM"))); List<ViewDoc> docs = esTester.getDocuments("views", "view", ViewDoc.class); assertThat(docs).hasSize(1); @@ -131,46 +124,45 @@ public class ViewIndexerTest { assertThat(view.projects()).containsOnly("KLMN", "JKLM"); } - @Test - public void clear_views_lookup_cache_on_index_view_uuid() { - IssueIndex issueIndex = new IssueIndex(esTester.client(), System2.INSTANCE, userSessionRule); - IssueIndexer issueIndexer = new IssueIndexer(system2, dbClient, esTester.client()); - PermissionIndexer permissionIndexer = new PermissionIndexer(dbClient, esTester.client()); - - String viewUuid = "ABCD"; - - RuleDto rule = RuleTesting.newXooX1(); - dbClient.ruleDao().insert(dbSession, rule); - ComponentDto project1 = addProjectWithIssue(rule, dbTester.organizations().insert()); - issueIndexer.indexAll(); - permissionIndexer.index(dbSession, project1.uuid()); - - OrganizationDto organizationDto = dbTester.organizations().insert(); - ComponentDto view = ComponentTesting.newView(organizationDto, "ABCD"); - ComponentDto techProject1 = ComponentTesting.newProjectCopy("CDEF", project1, view); - dbClient.componentDao().insert(dbSession, view, techProject1); - dbSession.commit(); - - // First view indexation - indexer.index(viewUuid); - - // Execute issue query on view -> 1 issue on view - SearchResult<IssueDoc> docs = issueIndex.search(IssueQuery.builder(userSessionRule).viewUuids(newArrayList(viewUuid)).build(), new SearchOptions()); - assertThat(docs.getDocs()).hasSize(1); - - // Add a project to the view and index it again - ComponentDto project2 = addProjectWithIssue(rule, organizationDto); - issueIndexer.indexAll(); - permissionIndexer.index(dbSession, project2.uuid()); - - ComponentDto techProject2 = ComponentTesting.newProjectCopy("EFGH", project2, view); - dbClient.componentDao().insert(dbSession, techProject2); - dbSession.commit(); - indexer.index(viewUuid); - - // Execute issue query on view -> issue of project2 are well taken into account : the cache has been cleared - assertThat(issueIndex.search(IssueQuery.builder(userSessionRule).viewUuids(newArrayList(viewUuid)).build(), new SearchOptions()).getDocs()).hasSize(2); - } +// @Test +// public void clear_views_lookup_cache_on_index_view_uuid() { +// IssueIndex issueIndex = new IssueIndex(esTester.client(), System2.INSTANCE, userSessionRule, new AuthorizationTypeSupport(userSessionRule)); +// IssueIndexer issueIndexer = new IssueIndexer(system2, dbClient, esTester.client()); +// +// String viewUuid = "ABCD"; +// +// RuleDto rule = RuleTesting.newXooX1(); +// dbClient.ruleDao().insert(dbSession, rule); +// ComponentDto project1 = addProjectWithIssue(rule, dbTester.organizations().insert()); +// issueIndexer.indexAll(); +// permissionIndexer.indexProjectsByUuids(dbSession, project1.uuid()); +// +// OrganizationDto organizationDto = dbTester.organizations().insert(); +// ComponentDto view = ComponentTesting.newView(organizationDto, "ABCD"); +// ComponentDto techProject1 = ComponentTesting.newProjectCopy("CDEF", project1, view); +// dbClient.componentDao().insert(dbSession, view, techProject1); +// dbSession.commit(); +// +// // First view indexation +// underTest.index(viewUuid); +// +// // Execute issue query on view -> 1 issue on view +// SearchResult<IssueDoc> docs = issueIndex.search(IssueQuery.builder().viewUuids(newArrayList(viewUuid)).build(), new SearchOptions()); +// assertThat(docs.getDocs()).hasSize(1); +// +// // Add a project to the view and index it again +// ComponentDto project2 = addProjectWithIssue(rule, organizationDto); +// issueIndexer.indexAll(); +// permissionIndexer.indexProjectsByUuids(dbSession, project2.uuid()); +// +// ComponentDto techProject2 = ComponentTesting.newProjectCopy("EFGH", project2, view); +// dbClient.componentDao().insert(dbSession, techProject2); +// dbSession.commit(); +// underTest.index(viewUuid); +// +// // Execute issue query on view -> issue of project2 are well taken into account : the cache has been cleared +// assertThat(issueIndex.search(IssueQuery.builder().viewUuids(newArrayList(viewUuid)).build(), new SearchOptions()).getDocs()).hasSize(2); +// } private ComponentDto addProjectWithIssue(RuleDto rule, OrganizationDto org) { ComponentDto project = ComponentTesting.newProjectDto(org); |