diff options
73 files changed, 1565 insertions, 2418 deletions
diff --git a/it/it-tests/src/test/java/it/projectSearch/SearchProjectsTest.java b/it/it-tests/src/test/java/it/projectSearch/SearchProjectsTest.java index 7790ae1589e..9b969f78e6f 100644 --- a/it/it-tests/src/test/java/it/projectSearch/SearchProjectsTest.java +++ b/it/it-tests/src/test/java/it/projectSearch/SearchProjectsTest.java @@ -35,6 +35,9 @@ import static org.assertj.core.api.Java6Assertions.assertThat; import static util.ItUtils.newAdminWsClient; import static util.ItUtils.projectDir; +/** + * Tests WS api/components/search_projects + */ public class SearchProjectsTest { @ClassRule @@ -46,16 +49,16 @@ public class SearchProjectsTest { } @Test - public void search_projects_with_filter_having_one_criterion() throws Exception { + public void filter_projects_by_measure_values() throws Exception { orchestrator.executeBuild(SonarScanner.create(projectDir("shared/xoo-sample"))); - SearchProjectsWsResponse response = searchProjects("ncloc > 1"); - - assertThat(response.getComponentsList()).extracting(Component::getKey).containsOnly("sample"); + verifyFilterMatches("ncloc > 1"); + verifyFilterMatches("ncloc > 1 and comment_lines < 10000"); + verifyFilterDoesNotMatch("ncloc <= 1"); } @Test - public void return_project_even_without_analysis() throws Exception { + public void provisioned_projects_should_be_included_to_results() throws Exception { orchestrator.getServer().provisionProject("sample", "sample"); SearchProjectsWsResponse response = searchProjects(SearchProjectsRequest.builder().build()); @@ -63,6 +66,7 @@ public class SearchProjectsTest { assertThat(response.getComponentsList()).extracting(Component::getKey).containsOnly("sample"); } + private SearchProjectsWsResponse searchProjects(String filter) throws IOException { return searchProjects(SearchProjectsRequest.builder().setFilter(filter).build()); } @@ -70,4 +74,12 @@ public class SearchProjectsTest { private SearchProjectsWsResponse searchProjects(SearchProjectsRequest request) throws IOException { return newAdminWsClient(orchestrator).components().searchProjects(request); } + + private void verifyFilterMatches(String filter) throws IOException { + assertThat(searchProjects(filter).getComponentsList()).extracting(Component::getKey).containsOnly("sample"); + } + + private void verifyFilterDoesNotMatch(String filter) throws IOException { + assertThat(searchProjects(filter).getComponentsCount()).isZero(); + } } 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); diff --git a/sonar-db/src/test/java/org/sonar/db/user/UserDbTester.java b/sonar-db/src/test/java/org/sonar/db/user/UserDbTester.java index 51f1193de37..e8c834ad4b4 100644 --- a/sonar-db/src/test/java/org/sonar/db/user/UserDbTester.java +++ b/sonar-db/src/test/java/org/sonar/db/user/UserDbTester.java @@ -324,11 +324,7 @@ public class UserDbTester { } /** -<<<<<<< HEAD - * Grant permission on given project in default organization -======= * Grant permission on given project ->>>>>>> 6772c5b73a... SONAR-8704 remove error-prone params Organization in UserDbTester */ public UserPermissionDto insertProjectPermissionOnUser(UserDto user, String permission, ComponentDto project) { UserPermissionDto dto = new UserPermissionDto(project.getOrganizationUuid(), permission, user.getId(), project.getId()); |