diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2015-01-30 17:05:49 +0100 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@sonarsource.com> | 2015-02-02 16:21:28 +0100 |
commit | 639d4f6e33a4d6f645f9a091945bb4c743476d12 (patch) | |
tree | 8f1d8295b63e0f110543c5a750df1aa3073313a1 | |
parent | 22e6bbd3f1b318ef74c5c21ab43e7fa445418493 (diff) | |
download | sonarqube-639d4f6e33a4d6f645f9a091945bb4c743476d12.tar.gz sonarqube-639d4f6e33a4d6f645f9a091945bb4c743476d12.zip |
SONAR-6074 Add an ability to filter issues by view
23 files changed, 345 insertions, 246 deletions
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 1472b728a55..da25046b31a 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 @@ -34,6 +34,7 @@ import org.sonar.api.ServerComponent; import org.sonar.api.resources.Qualifiers; import org.sonar.api.rule.RuleKey; import org.sonar.api.server.ws.Request; +import org.sonar.api.web.UserRole; import org.sonar.core.component.ComponentDto; import org.sonar.core.persistence.DbSession; import org.sonar.server.component.ComponentService; @@ -41,6 +42,7 @@ import org.sonar.server.db.DbClient; import org.sonar.server.issue.IssueQuery.Builder; import org.sonar.server.issue.filter.IssueFilterParameters; import org.sonar.server.search.ws.SearchRequestHandler; +import org.sonar.server.user.UserSession; import org.sonar.server.util.RubyUtils; import javax.annotation.CheckForNull; @@ -58,6 +60,7 @@ import static com.google.common.collect.Lists.newArrayList; */ public class IssueQueryService implements ServerComponent { + private static final String UNKNOWN = "<UNKNOWN>"; private final DbClient dbClient; private final ComponentService componentService; @@ -220,8 +223,18 @@ public class IssueQueryService implements ServerComponent { } String uniqueQualifier = qualifiers.iterator().next(); - if (Qualifiers.VIEW.equals(uniqueQualifier)) { - // TODO Handle views + if (Qualifiers.VIEW.equals(uniqueQualifier) || Qualifiers.SUBVIEW.equals(uniqueQualifier)) { + List<String> filteredViewUuids = newArrayList(); + for (String viewUuid : allComponentUuids) { + if ((Qualifiers.VIEW.equals(uniqueQualifier) && UserSession.get().hasProjectPermissionByUuid(UserRole.USER, viewUuid)) + || (Qualifiers.SUBVIEW.equals(uniqueQualifier) && UserSession.get().hasComponentUuidPermission(UserRole.USER, viewUuid))) { + filteredViewUuids.add(viewUuid); + } + } + if (filteredViewUuids.isEmpty()) { + filteredViewUuids.add(UNKNOWN); + } + builder.viewUuids(filteredViewUuids); addComponentsBelowView(builder, session, projects, projectUuids, moduleUuids, directories, fileUuids); } else if ("DEV".equals(uniqueQualifier)) { // XXX No constant !!! // TODO Get SCM accounts from dev, then search by author @@ -324,7 +337,7 @@ public class IssueQueryService implements ServerComponent { // If unknown components are given, but no components are found, then all issues will be returned, // so we add this hack in order to return no issue in this case. if (componentKeys != null && !componentKeys.isEmpty() && componentUuids.isEmpty()) { - componentUuids.add("<UNKNOWN>"); + componentUuids.add(UNKNOWN); } return componentUuids; } 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 688cc6b5ebb..2b9a62171af 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 @@ -202,7 +202,7 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> { QueryBuilder queryBuilder = QueryBuilders.filteredQuery( QueryBuilders.matchAllQuery(), FilterBuilders.andFilter(projectFilter, dateFilter) - ); + ); getClient().prepareDeleteByQuery(IssueIndexDefinition.INDEX).setQuery(queryBuilder).get(); } @@ -259,6 +259,7 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> { } private void addComponentRelatedFilters(IssueQuery query, Map<String, FilterBuilder> filters) { + FilterBuilder viewFilter = viewFilter(query.viewUuids()); FilterBuilder projectFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, query.projectUuids()); FilterBuilder moduleRootFilter = moduleRootFilter(query.moduleRootUuids()); FilterBuilder moduleFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, query.moduleUuids()); @@ -266,10 +267,15 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> { FilterBuilder directoryFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, query.directories()); FilterBuilder fileFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, query.fileUuids()); FilterBuilder componentFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, query.componentUuids()); - FilterBuilder viewFilter = viewFilter(query.viewUuids()); if (BooleanUtils.isTrue(query.isContextualized())) { - if (projectFilter != null) { + if (viewFilter != null) { + filters.put(FILTER_COMPONENT_ROOT, viewFilter); + filters.put(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, projectFilter); + filters.put(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, moduleFilter); + filters.put(IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, directoryFilter); + filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, fileFilter); + } else if (projectFilter != null) { filters.put(FILTER_COMPONENT_ROOT, projectFilter); filters.put(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, moduleFilter); filters.put(IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, directoryFilter); @@ -372,7 +378,7 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> { FilterBuilders.boolFilter() .must(groupsAndUser) .cache(true)) - ); + ); } private void addDatesFilter(Map<String, FilterBuilder> filters, IssueQuery query) { @@ -434,7 +440,7 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> { } private void addSimpleStickyFacetIfNeeded(QueryContext options, StickyFacetBuilder stickyFacetBuilder, SearchRequestBuilder esSearch, - String facetName, String fieldName, Object... selectedValues) { + String facetName, String fieldName, Object... selectedValues) { if (options.facets().contains(facetName)) { esSearch.addAggregation(stickyFacetBuilder.buildStickyFacet(fieldName, facetName, DEFAULT_ISSUE_FACET_SIZE, selectedValues)); } @@ -464,7 +470,7 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> { AggregationBuilders .missing(facetName + FACET_SUFFIX_MISSING) .field(fieldName) - ); + ); return AggregationBuilders .global(facetName) @@ -489,7 +495,7 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> { AggregationBuilders .missing(facetName + FACET_SUFFIX_MISSING) .field(fieldName) - ); + ); return AggregationBuilders .global(facetName) @@ -514,7 +520,7 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> { AggregationBuilders .missing(facetName + FACET_SUFFIX_MISSING) .field(fieldName) - ); + ); return AggregationBuilders .global(facetName) diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/BackendCleanup.java b/server/sonar-server/src/main/java/org/sonar/server/platform/BackendCleanup.java index 310da3a462b..4faccc21c65 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/BackendCleanup.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/BackendCleanup.java @@ -20,6 +20,7 @@ package org.sonar.server.platform; import org.apache.commons.dbutils.DbUtils; +import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest; import org.elasticsearch.index.query.QueryBuilders; import org.slf4j.LoggerFactory; import org.sonar.api.ServerComponent; @@ -79,17 +80,24 @@ public class BackendCleanup implements ServerComponent { public void clearIndexes() { LoggerFactory.getLogger(getClass()).info("Truncate Elasticsearch indices"); - searchClient.prepareDeleteByQuery(searchClient.prepareState().get() - .getState().getMetaData().concreteAllIndices()) - .setQuery(QueryBuilders.matchAllQuery()) - .get(); - searchClient.prepareRefresh(searchClient.prepareState().get() - .getState().getMetaData().concreteAllIndices()) - .setForce(true) - .get(); - searchClient.prepareFlush(searchClient.prepareState().get() - .getState().getMetaData().concreteAllIndices()) - .get(); + try { + searchClient.admin().indices() + .clearCache(new ClearIndicesCacheRequest()) + .get(); + searchClient.prepareDeleteByQuery(searchClient.prepareState().get() + .getState().getMetaData().concreteAllIndices()) + .setQuery(QueryBuilders.matchAllQuery()) + .get(); + searchClient.prepareRefresh(searchClient.prepareState().get() + .getState().getMetaData().concreteAllIndices()) + .setForce(true) + .get(); + searchClient.prepareFlush(searchClient.prepareState().get() + .getState().getMetaData().concreteAllIndices()) + .get(); + } catch (Exception e) { + throw new IllegalStateException("Unable to clear indexes", e); + } } /** diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java index 1a2169026e7..34123541de4 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java @@ -53,12 +53,7 @@ import org.sonar.core.measure.db.MeasureFilterDao; import org.sonar.core.metric.DefaultMetricFinder; import org.sonar.core.notification.DefaultNotificationManager; import org.sonar.core.permission.PermissionFacade; -import org.sonar.core.persistence.DaoUtils; -import org.sonar.core.persistence.DatabaseVersion; -import org.sonar.core.persistence.DefaultDatabase; -import org.sonar.core.persistence.MyBatis; -import org.sonar.core.persistence.SemaphoreUpdater; -import org.sonar.core.persistence.SemaphoresImpl; +import org.sonar.core.persistence.*; import org.sonar.core.profiling.Profiling; import org.sonar.core.purge.PurgeProfiler; import org.sonar.core.qualitygate.db.ProjectQgateAssociationDao; @@ -83,12 +78,7 @@ import org.sonar.server.activity.index.ActivityNormalizer; import org.sonar.server.activity.ws.ActivitiesWebService; import org.sonar.server.activity.ws.ActivityMapping; import org.sonar.server.authentication.ws.AuthenticationWs; -import org.sonar.server.batch.BatchIndex; -import org.sonar.server.batch.BatchWs; -import org.sonar.server.batch.GlobalRepositoryAction; -import org.sonar.server.batch.IssuesAction; -import org.sonar.server.batch.ProjectRepositoryAction; -import org.sonar.server.batch.ProjectRepositoryLoader; +import org.sonar.server.batch.*; import org.sonar.server.charts.ChartFactory; import org.sonar.server.component.ComponentCleanerService; import org.sonar.server.component.ComponentService; @@ -96,20 +86,12 @@ import org.sonar.server.component.DefaultComponentFinder; import org.sonar.server.component.DefaultRubyComponentService; import org.sonar.server.component.db.ComponentDao; import org.sonar.server.component.db.SnapshotDao; -import org.sonar.server.component.ws.ComponentAppAction; -import org.sonar.server.component.ws.ComponentsWs; -import org.sonar.server.component.ws.EventsWs; -import org.sonar.server.component.ws.ProjectsWs; -import org.sonar.server.component.ws.ResourcesWs; +import org.sonar.server.component.ws.*; import org.sonar.server.computation.AnalysisReportQueue; import org.sonar.server.computation.AnalysisReportQueueCleaner; import org.sonar.server.computation.ComputationThreadLauncher; import org.sonar.server.computation.db.AnalysisReportDao; -import org.sonar.server.computation.ws.ComputationWebService; -import org.sonar.server.computation.ws.HistoryWsAction; -import org.sonar.server.computation.ws.IsQueueEmptyWebService; -import org.sonar.server.computation.ws.QueueWsAction; -import org.sonar.server.computation.ws.SubmitReportWsAction; +import org.sonar.server.computation.ws.*; import org.sonar.server.config.ws.PropertiesWs; import org.sonar.server.dashboard.db.DashboardDao; import org.sonar.server.dashboard.db.WidgetDao; @@ -121,14 +103,7 @@ import org.sonar.server.db.DbClient; import org.sonar.server.db.EmbeddedDatabaseFactory; import org.sonar.server.db.migrations.DatabaseMigrations; import org.sonar.server.db.migrations.DatabaseMigrator; -import org.sonar.server.debt.DebtCharacteristicsXMLImporter; -import org.sonar.server.debt.DebtModelBackup; -import org.sonar.server.debt.DebtModelLookup; -import org.sonar.server.debt.DebtModelOperations; -import org.sonar.server.debt.DebtModelPluginRepository; -import org.sonar.server.debt.DebtModelService; -import org.sonar.server.debt.DebtModelXMLExporter; -import org.sonar.server.debt.DebtRulesXMLImporter; +import org.sonar.server.debt.*; import org.sonar.server.design.FileDesignWidget; import org.sonar.server.duplication.ws.DuplicationsJsonWriter; import org.sonar.server.duplication.ws.DuplicationsParser; @@ -136,22 +111,7 @@ import org.sonar.server.duplication.ws.DuplicationsWs; import org.sonar.server.es.EsClient; import org.sonar.server.es.IndexCreator; import org.sonar.server.es.IndexRegistry; -import org.sonar.server.issue.ActionService; -import org.sonar.server.issue.AddTagsAction; -import org.sonar.server.issue.AssignAction; -import org.sonar.server.issue.CommentAction; -import org.sonar.server.issue.InternalRubyIssueService; -import org.sonar.server.issue.IssueBulkChangeService; -import org.sonar.server.issue.IssueChangelogFormatter; -import org.sonar.server.issue.IssueChangelogService; -import org.sonar.server.issue.IssueCommentService; -import org.sonar.server.issue.IssueQueryService; -import org.sonar.server.issue.IssueService; -import org.sonar.server.issue.PlanAction; -import org.sonar.server.issue.RemoveTagsAction; -import org.sonar.server.issue.ServerIssueStorage; -import org.sonar.server.issue.SetSeverityAction; -import org.sonar.server.issue.TransitionAction; +import org.sonar.server.issue.*; import org.sonar.server.issue.actionplan.ActionPlanService; import org.sonar.server.issue.actionplan.ActionPlanWs; import org.sonar.server.issue.db.IssueDao; @@ -162,17 +122,8 @@ import org.sonar.server.issue.index.IssueAuthorizationIndexer; 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.issue.notification.ChangesOnMyIssueNotificationDispatcher; -import org.sonar.server.issue.notification.IssueChangesEmailTemplate; -import org.sonar.server.issue.notification.IssueNotifications; -import org.sonar.server.issue.notification.NewFalsePositiveNotificationDispatcher; -import org.sonar.server.issue.notification.NewIssuesEmailTemplate; -import org.sonar.server.issue.notification.NewIssuesNotificationDispatcher; -import org.sonar.server.issue.ws.ComponentTagsAction; -import org.sonar.server.issue.ws.IssueActionsWriter; -import org.sonar.server.issue.ws.IssueShowAction; -import org.sonar.server.issue.ws.IssuesWs; -import org.sonar.server.issue.ws.SetTagsAction; +import org.sonar.server.issue.notification.*; +import org.sonar.server.issue.ws.*; import org.sonar.server.language.ws.LanguageWs; import org.sonar.server.language.ws.ListAction; import org.sonar.server.measure.MeasureFilterEngine; @@ -193,117 +144,35 @@ import org.sonar.server.platform.ws.L10nWs; import org.sonar.server.platform.ws.RestartHandler; import org.sonar.server.platform.ws.ServerWs; import org.sonar.server.platform.ws.SystemWs; -import org.sonar.server.plugins.InstalledPluginReferentialFactory; -import org.sonar.server.plugins.PluginDownloader; -import org.sonar.server.plugins.ServerExtensionInstaller; -import org.sonar.server.plugins.ServerPluginJarInstaller; -import org.sonar.server.plugins.ServerPluginJarsInstaller; -import org.sonar.server.plugins.ServerPluginRepository; -import org.sonar.server.plugins.UpdateCenterClient; -import org.sonar.server.plugins.UpdateCenterMatrixFactory; +import org.sonar.server.plugins.*; import org.sonar.server.properties.ProjectSettingsFactory; import org.sonar.server.qualitygate.QgateProjectFinder; import org.sonar.server.qualitygate.QualityGates; import org.sonar.server.qualitygate.RegisterQualityGates; -import org.sonar.server.qualitygate.ws.QGatesAppAction; -import org.sonar.server.qualitygate.ws.QGatesCopyAction; -import org.sonar.server.qualitygate.ws.QGatesCreateAction; -import org.sonar.server.qualitygate.ws.QGatesCreateConditionAction; -import org.sonar.server.qualitygate.ws.QGatesDeleteConditionAction; -import org.sonar.server.qualitygate.ws.QGatesDeselectAction; -import org.sonar.server.qualitygate.ws.QGatesDestroyAction; -import org.sonar.server.qualitygate.ws.QGatesListAction; -import org.sonar.server.qualitygate.ws.QGatesRenameAction; -import org.sonar.server.qualitygate.ws.QGatesSearchAction; -import org.sonar.server.qualitygate.ws.QGatesSelectAction; -import org.sonar.server.qualitygate.ws.QGatesSetAsDefaultAction; -import org.sonar.server.qualitygate.ws.QGatesShowAction; -import org.sonar.server.qualitygate.ws.QGatesUnsetDefaultAction; -import org.sonar.server.qualitygate.ws.QGatesUpdateConditionAction; -import org.sonar.server.qualitygate.ws.QGatesWs; -import org.sonar.server.qualityprofile.BuiltInProfiles; -import org.sonar.server.qualityprofile.QProfileBackuper; -import org.sonar.server.qualityprofile.QProfileCopier; -import org.sonar.server.qualityprofile.QProfileExporters; -import org.sonar.server.qualityprofile.QProfileFactory; -import org.sonar.server.qualityprofile.QProfileLoader; -import org.sonar.server.qualityprofile.QProfileLookup; -import org.sonar.server.qualityprofile.QProfileProjectLookup; -import org.sonar.server.qualityprofile.QProfileProjectOperations; -import org.sonar.server.qualityprofile.QProfileReset; -import org.sonar.server.qualityprofile.QProfileService; -import org.sonar.server.qualityprofile.QProfiles; -import org.sonar.server.qualityprofile.RegisterQualityProfiles; -import org.sonar.server.qualityprofile.RuleActivator; -import org.sonar.server.qualityprofile.RuleActivatorContextFactory; +import org.sonar.server.qualitygate.ws.*; +import org.sonar.server.qualityprofile.*; import org.sonar.server.qualityprofile.db.ActiveRuleDao; import org.sonar.server.qualityprofile.index.ActiveRuleIndex; import org.sonar.server.qualityprofile.index.ActiveRuleNormalizer; -import org.sonar.server.qualityprofile.ws.BulkRuleActivationActions; -import org.sonar.server.qualityprofile.ws.ProfilesWs; -import org.sonar.server.qualityprofile.ws.QProfileRestoreBuiltInAction; -import org.sonar.server.qualityprofile.ws.QProfilesWs; -import org.sonar.server.qualityprofile.ws.RuleActivationActions; -import org.sonar.server.rule.DefaultRuleFinder; -import org.sonar.server.rule.DeprecatedRulesDefinitionLoader; -import org.sonar.server.rule.RegisterRules; -import org.sonar.server.rule.RubyRuleService; -import org.sonar.server.rule.RuleCreator; -import org.sonar.server.rule.RuleDefinitionsLoader; -import org.sonar.server.rule.RuleDeleter; -import org.sonar.server.rule.RuleOperations; -import org.sonar.server.rule.RuleRepositories; -import org.sonar.server.rule.RuleService; -import org.sonar.server.rule.RuleUpdater; +import org.sonar.server.qualityprofile.ws.*; +import org.sonar.server.rule.*; import org.sonar.server.rule.db.RuleDao; import org.sonar.server.rule.index.RuleIndex; import org.sonar.server.rule.index.RuleNormalizer; -import org.sonar.server.rule.ws.ActiveRuleCompleter; -import org.sonar.server.rule.ws.AppAction; -import org.sonar.server.rule.ws.DeleteAction; -import org.sonar.server.rule.ws.RepositoriesAction; -import org.sonar.server.rule.ws.RuleMapping; -import org.sonar.server.rule.ws.RulesWebService; +import org.sonar.server.rule.ws.*; import org.sonar.server.rule.ws.SearchAction; import org.sonar.server.rule.ws.TagsAction; -import org.sonar.server.rule.ws.UpdateAction; -import org.sonar.server.search.IndexClient; -import org.sonar.server.search.IndexQueue; -import org.sonar.server.search.IndexSynchronizer; -import org.sonar.server.search.SearchClient; -import org.sonar.server.search.SearchHealth; +import org.sonar.server.search.*; import org.sonar.server.source.HtmlSourceDecorator; import org.sonar.server.source.SourceService; import org.sonar.server.source.index.SourceLineIndex; import org.sonar.server.source.index.SourceLineIndexDefinition; import org.sonar.server.source.index.SourceLineIndexer; -import org.sonar.server.source.ws.HashAction; -import org.sonar.server.source.ws.IndexAction; -import org.sonar.server.source.ws.LinesAction; -import org.sonar.server.source.ws.RawAction; -import org.sonar.server.source.ws.ScmAction; -import org.sonar.server.source.ws.ScmWriter; +import org.sonar.server.source.ws.*; import org.sonar.server.source.ws.ShowAction; -import org.sonar.server.source.ws.SourcesWs; -import org.sonar.server.startup.CopyRequirementsFromCharacteristicsToRules; -import org.sonar.server.startup.GeneratePluginIndex; -import org.sonar.server.startup.JdbcDriverDeployer; -import org.sonar.server.startup.LogServerId; -import org.sonar.server.startup.RegisterDashboards; -import org.sonar.server.startup.RegisterDebtModel; -import org.sonar.server.startup.RegisterMetrics; -import org.sonar.server.startup.RegisterNewMeasureFilters; -import org.sonar.server.startup.RegisterPermissionTemplates; -import org.sonar.server.startup.RegisterServletFilters; -import org.sonar.server.startup.RenameDeprecatedPropertyKeys; -import org.sonar.server.startup.ServerMetadataPersister; +import org.sonar.server.startup.*; import org.sonar.server.test.CoverageService; -import org.sonar.server.test.ws.CoverageShowAction; -import org.sonar.server.test.ws.CoverageWs; -import org.sonar.server.test.ws.TestsCoveredFilesAction; -import org.sonar.server.test.ws.TestsShowAction; -import org.sonar.server.test.ws.TestsTestCasesAction; -import org.sonar.server.test.ws.TestsWs; +import org.sonar.server.test.ws.*; import org.sonar.server.text.MacroInterpreter; import org.sonar.server.text.RubyTextService; import org.sonar.server.ui.JRubyI18n; @@ -311,14 +180,7 @@ import org.sonar.server.ui.JRubyProfiling; import org.sonar.server.ui.PageDecorations; import org.sonar.server.ui.Views; import org.sonar.server.updatecenter.ws.UpdateCenterWs; -import org.sonar.server.user.DefaultUserService; -import org.sonar.server.user.DoPrivileged; -import org.sonar.server.user.GroupMembershipFinder; -import org.sonar.server.user.GroupMembershipService; -import org.sonar.server.user.NewUserNotifier; -import org.sonar.server.user.SecurityRealmFactory; -import org.sonar.server.user.UserService; -import org.sonar.server.user.UserUpdater; +import org.sonar.server.user.*; import org.sonar.server.user.db.GroupDao; import org.sonar.server.user.db.UserDao; import org.sonar.server.user.db.UserGroupDao; @@ -328,13 +190,8 @@ import org.sonar.server.user.index.UserIndexer; import org.sonar.server.user.ws.FavoritesWs; import org.sonar.server.user.ws.UserPropertiesWs; import org.sonar.server.user.ws.UsersWs; -import org.sonar.server.util.BooleanTypeValidation; -import org.sonar.server.util.FloatTypeValidation; -import org.sonar.server.util.IntegerTypeValidation; -import org.sonar.server.util.StringListTypeValidation; -import org.sonar.server.util.StringTypeValidation; -import org.sonar.server.util.TextTypeValidation; -import org.sonar.server.util.TypeValidations; +import org.sonar.server.util.*; +import org.sonar.server.view.index.ViewIndex; import org.sonar.server.view.index.ViewIndexDefinition; import org.sonar.server.view.index.ViewIndexer; import org.sonar.server.ws.ListingWs; @@ -655,6 +512,7 @@ class ServerComponents { // views pico.addSingleton(ViewIndexDefinition.class); pico.addSingleton(ViewIndexer.class); + pico.addSingleton(ViewIndex.class); // issues pico.addSingleton(IssueIndexDefinition.class); diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/UserSession.java b/server/sonar-server/src/main/java/org/sonar/server/user/UserSession.java index 2c2275ba836..ba6c33c9dc3 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/user/UserSession.java +++ b/server/sonar-server/src/main/java/org/sonar/server/user/UserSession.java @@ -36,13 +36,7 @@ import org.sonar.server.platform.Platform; import javax.annotation.CheckForNull; import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; +import java.util.*; import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Maps.newHashMap; @@ -69,6 +63,7 @@ public class UserSession { HashMultimap<String, String> projectKeyByPermission = HashMultimap.create(); HashMultimap<String, String> projectUuidByPermission = HashMultimap.create(); Map<String, String> projectKeyByComponentKey = newHashMap(); + Map<String, String> projectUuidByComponentUuid = newHashMap(); List<String> projectPermissions = newArrayList(); UserSession() { @@ -232,6 +227,7 @@ public class UserSession { public boolean hasComponentPermission(String permission, String componentKey) { String projectKey = projectKeyByComponentKey.get(componentKey); if (projectKey == null) { + // TODO use method using UUID ResourceDto project = resourceDao().getRootProjectByComponentKey(componentKey); if (project == null) { return false; @@ -246,6 +242,26 @@ public class UserSession { return false; } + /** + * Does the user have the given project permission for a component uuid ? + */ + public boolean hasComponentUuidPermission(String permission, String componentUuid) { + String projectUuid = projectUuidByComponentUuid.get(componentUuid); + if (projectUuid == null) { + ResourceDto project = resourceDao().getResource(componentUuid); + if (project == null) { + return false; + } + projectUuid = project.getProjectUuid(); + } + boolean hasComponentPermission = hasProjectPermissionByUuid(permission, projectUuid); + if (hasComponentPermission) { + projectUuidByComponentUuid.put(componentUuid, projectUuid); + return true; + } + return false; + } + AuthorizationDao authorizationDao() { return Platform.component(AuthorizationDao.class); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/view/index/ViewIndexer.java b/server/sonar-server/src/main/java/org/sonar/server/view/index/ViewIndexer.java index cb6ed32d19f..7476c6f9633 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/view/index/ViewIndexer.java +++ b/server/sonar-server/src/main/java/org/sonar/server/view/index/ViewIndexer.java @@ -45,6 +45,10 @@ public class ViewIndexer extends BaseIndexer { this.esClient = esClient; } + /** + * Index all views if the index is empty. + * Only used on startup . + */ @Override protected long doIndex(long lastUpdatedAt) { // Index only if index is empty @@ -64,6 +68,10 @@ public class ViewIndexer extends BaseIndexer { return 0L; } + /** + * Index a root view : it will load projects on each sub views and index it. + * Used by the compute engine to reindex a root view. + */ public void index(String rootViewUuid) { DbSession dbSession = dbClient.openSession(false); try { @@ -77,6 +85,16 @@ public class ViewIndexer extends BaseIndexer { } } + /** + * Index a single document + */ + public void index(ViewDoc viewDoc) { + final BulkIndexer bulk = new BulkIndexer(esClient, ViewIndexDefinition.INDEX); + bulk.start(); + bulk.add(newUpsertRequest(viewDoc)); + bulk.stop(); + } + private void index(DbSession dbSession, Map<String, String> viewAndProjectViewUuidMap) { final BulkIndexer bulk = new BulkIndexer(esClient, ViewIndexDefinition.INDEX); bulk.start(); diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java index 1f5f1b6eb00..97cd5b02704 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java @@ -21,8 +21,6 @@ package org.sonar.server.issue.index; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterators; -import org.elasticsearch.action.bulk.BulkRequestBuilder; -import org.elasticsearch.action.index.IndexRequest; import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; @@ -34,7 +32,6 @@ import org.sonar.api.utils.DateUtils; import org.sonar.api.utils.KeyValueFormat; import org.sonar.core.component.ComponentDto; import org.sonar.server.component.ComponentTesting; -import org.sonar.server.es.EsClient; import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.issue.IssueQuery; import org.sonar.server.issue.IssueTesting; @@ -44,7 +41,7 @@ import org.sonar.server.search.Result; import org.sonar.server.tester.ServerTester; import org.sonar.server.user.MockUserSession; import org.sonar.server.view.index.ViewDoc; -import org.sonar.server.view.index.ViewIndexDefinition; +import org.sonar.server.view.index.ViewIndexer; import javax.annotation.Nullable; @@ -61,7 +58,7 @@ import static org.assertj.core.api.Assertions.assertThat; public class IssueIndexMediumTest { @ClassRule - public static ServerTester tester = new ServerTester().setProperty("sonar.log.profilingLevel", "FULL").setProperty("sonar.search.httpPort", "9999"); + public static ServerTester tester = new ServerTester(); IssueIndex index; @@ -198,6 +195,8 @@ public class IssueIndexMediumTest { ComponentDto file1 = ComponentTesting.newFileDto(project); ComponentDto file2 = ComponentTesting.newFileDto(module); ComponentDto file3 = ComponentTesting.newFileDto(subModule); + String view = "ABCD"; + indexView(view, newArrayList(project.uuid())); indexIssues( IssueTesting.newDoc("ISSUE1", project), @@ -217,6 +216,8 @@ public class IssueIndexMediumTest { .getHits()).hasSize(4); assertThat(index.search(IssueQuery.builder().setContextualized(true).projectUuids(newArrayList(project.uuid())).build(), new QueryContext()) .getHits()).hasSize(6); + assertThat(index.search(IssueQuery.builder().setContextualized(true).viewUuids(newArrayList(view)).build(), new QueryContext()) + .getHits()).hasSize(6); assertThat(index.search(IssueQuery.builder().setContextualized(true).projectUuids(newArrayList("unknown")).build(), new QueryContext()) .getHits()).isEmpty(); } @@ -229,6 +230,8 @@ public class IssueIndexMediumTest { ComponentDto file2 = ComponentTesting.newFileDto(module, "file2"); ComponentDto subModule = ComponentTesting.newModuleDto(module).setUuid("subModule"); ComponentDto file3 = ComponentTesting.newFileDto(subModule, "file3"); + String view = "ABCD"; + indexView(view, newArrayList(project.uuid())); indexIssues( IssueTesting.newDoc("ISSUE1", project), @@ -240,8 +243,11 @@ public class IssueIndexMediumTest { assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList("unknown")).build(), new QueryContext()).getHits()).isEmpty(); assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid())).build(), new QueryContext()).getHits()).hasSize(6); + assertThat(index.search(IssueQuery.builder().viewUuids(newArrayList(view)).build(), new QueryContext()).getHits()).hasSize(6); assertThat(index.search(IssueQuery.builder().moduleUuids(newArrayList(module.uuid())).build(), new QueryContext()).getHits()).hasSize(2); - assertThat(index.search(IssueQuery.builder().moduleUuids(newArrayList(subModule.uuid())).build(), new QueryContext()).getHits()).hasSize(1); // XXX Misleading ! + assertThat(index.search(IssueQuery.builder().moduleUuids(newArrayList(subModule.uuid())).build(), new QueryContext()).getHits()).hasSize(1); // XXX + // Misleading + // ! assertThat(index.search(IssueQuery.builder().fileUuids(newArrayList(file1.uuid())).build(), new QueryContext()).getHits()).hasSize(1); assertThat(index.search(IssueQuery.builder().fileUuids(newArrayList(file1.uuid(), file2.uuid(), file3.uuid())).build(), new QueryContext()).getHits()).hasSize(3); } @@ -984,9 +990,6 @@ public class IssueIndexMediumTest { } private void indexView(String viewUuid, List<String> projects) { - EsClient client = tester.get(EsClient.class); - BulkRequestBuilder bulk = client.prepareBulk().setRefresh(true); - bulk.add(new IndexRequest(ViewIndexDefinition.INDEX, ViewIndexDefinition.TYPE_VIEW).source(new ViewDoc().setUuid(viewUuid).setProjects(projects).getFields())); - bulk.get(); + tester.get(ViewIndexer.class).index(new ViewDoc().setUuid(viewUuid).setProjects(projects)); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsMediumTest.java index bd2103c30e4..55dcc9b90ce 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsMediumTest.java @@ -45,8 +45,14 @@ import org.sonar.server.rule.RuleTesting; import org.sonar.server.rule.db.RuleDao; import org.sonar.server.tester.ServerTester; import org.sonar.server.user.MockUserSession; +import org.sonar.server.view.index.ViewDoc; +import org.sonar.server.view.index.ViewIndexer; import org.sonar.server.ws.WsTester; +import java.util.List; + +import static com.google.common.collect.Lists.newArrayList; + public class SearchActionComponentsMediumTest { @ClassRule @@ -367,6 +373,88 @@ public class SearchActionComponentsMediumTest { result.assertJson(this.getClass(), "display_directory_facet.json", false); } + @Test + public void search_by_view_uuid() throws Exception { + ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject")); + setDefaultProjectPermission(project); + ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent")); + insertIssue(IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")); + + ComponentDto view = insertComponent(ComponentTesting.newProjectDto("CDEF").setQualifier(Qualifiers.VIEW).setKey("MyView")); + indexView(view.uuid(), newArrayList(project.uuid())); + + setAnyoneProjectPermission(view, UserRole.USER); + MockUserSession.set().setLogin("john").addProjectUuidPermissions(UserRole.USER, view.uuid()); + + wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) + .setParam(IssueFilterParameters.COMPONENT_UUIDS, view.uuid()) + .execute() + .assertJson(this.getClass(), "search_by_view_uuid.json", false); + } + + @Test + public void search_by_view_uuid_return_only_authorized_view() throws Exception { + ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject")); + setDefaultProjectPermission(project); + ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent")); + insertIssue(IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")); + + ComponentDto view = insertComponent(ComponentTesting.newProjectDto("CDEF").setQualifier(Qualifiers.VIEW).setKey("MyView")); + indexView(view.uuid(), newArrayList(project.uuid())); + + setAnyoneProjectPermission(view, UserRole.USER); + // User has wrong permission on the view, no issue will be returned + MockUserSession.set().setLogin("john").addProjectUuidPermissions(UserRole.CODEVIEWER, view.uuid()); + + wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) + .setParam(IssueFilterParameters.COMPONENT_UUIDS, view.uuid()) + .execute() + .assertJson(this.getClass(), "no_issue.json", false); + } + + @Test + public void search_by_sub_view_uuid() throws Exception { + ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject")); + setDefaultProjectPermission(project); + ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent")); + insertIssue(IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")); + + ComponentDto view = insertComponent(ComponentTesting.newProjectDto("CDEF").setQualifier(Qualifiers.VIEW).setKey("MyView")); + indexView(view.uuid(), newArrayList(project.uuid())); + ComponentDto subView = insertComponent(ComponentTesting.newProjectDto("DEFG").setQualifier(Qualifiers.SUBVIEW).setKey("MySubView")); + indexView(subView.uuid(), newArrayList(project.uuid())); + + setAnyoneProjectPermission(view, UserRole.USER); + MockUserSession.set().setLogin("john").addComponentUuidPermission(UserRole.USER, view.uuid(), subView.uuid()); + + wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) + .setParam(IssueFilterParameters.COMPONENT_UUIDS, subView.uuid()) + .execute() + .assertJson(this.getClass(), "search_by_view_uuid.json", false); + } + + @Test + public void search_by_sub_view_uuid_return_only_authorized_view() throws Exception { + ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject")); + setDefaultProjectPermission(project); + ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent")); + insertIssue(IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")); + + ComponentDto view = insertComponent(ComponentTesting.newProjectDto("CDEF").setQualifier(Qualifiers.VIEW).setKey("MyView")); + indexView(view.uuid(), newArrayList(project.uuid())); + ComponentDto subView = insertComponent(ComponentTesting.newProjectDto("DEFG").setQualifier(Qualifiers.SUBVIEW).setKey("MySubView")); + indexView(subView.uuid(), newArrayList(project.uuid())); + + setAnyoneProjectPermission(view, UserRole.USER); + // User has wrong permission on the view, no issue will be returned + MockUserSession.set().setLogin("john").addComponentUuidPermission(UserRole.CODEVIEWER, view.uuid(), subView.uuid()); + + wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) + .setParam(IssueFilterParameters.COMPONENT_UUIDS, subView.uuid()) + .execute() + .assertJson(this.getClass(), "no_issue.json", false); + } + private RuleDto newRule() { RuleDto rule = RuleTesting.newXooX1() .setName("Rule name") @@ -378,16 +466,30 @@ public class SearchActionComponentsMediumTest { } private void setDefaultProjectPermission(ComponentDto project) { - // project can be seen by anyone and by code viewer + // project can be seen by anyone + setAnyoneProjectPermission(project, UserRole.USER); + } + + private void setAnyoneProjectPermission(ComponentDto project, String permission) { MockUserSession.set().setLogin("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); - tester.get(InternalPermissionService.class).addPermission(new PermissionChange().setComponentKey(project.getKey()).setGroup(DefaultGroups.ANYONE).setPermission(UserRole.USER)); + tester.get(InternalPermissionService.class).addPermission(new PermissionChange().setComponentKey(project.getKey()).setGroup(DefaultGroups.ANYONE).setPermission(permission)); MockUserSession.set(); } + private IssueDto insertIssue(IssueDto issue) { + db.issueDao().insert(session, issue); + session.commit(); + tester.get(IssueIndexer.class).indexAll(); + return issue; + } + private ComponentDto insertComponent(ComponentDto component) { db.componentDao().insert(session, component); session.commit(); return component; } + private void indexView(String viewUuid, List<String> projects) { + tester.get(ViewIndexer.class).index(new ViewDoc().setUuid(viewUuid).setProjects(projects)); + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/MockUserSession.java b/server/sonar-server/src/test/java/org/sonar/server/user/MockUserSession.java index 9af4123fef0..0080d9656cd 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/user/MockUserSession.java +++ b/server/sonar-server/src/test/java/org/sonar/server/user/MockUserSession.java @@ -86,6 +86,10 @@ public class MockUserSession extends UserSession { return this; } + /** + * Deprecated, please use {@link #addProjectUuidPermissions} + */ + @Deprecated public MockUserSession addProjectPermissions(String projectPermission, String... projectKeys) { this.projectPermissions.add(projectPermission); this.projectKeyByPermission.putAll(projectPermission, newArrayList(projectKeys)); @@ -98,12 +102,22 @@ public class MockUserSession extends UserSession { return this; } + /** + * Deprecated, please use {@link #addComponentUuidPermission} + */ + @Deprecated public MockUserSession addComponentPermission(String projectPermission, String projectKey, String componentKey) { this.projectKeyByComponentKey.put(componentKey, projectKey); addProjectPermissions(projectPermission, projectKey); return this; } + public MockUserSession addComponentUuidPermission(String projectPermission, String projectUuid, String componentUuid) { + this.projectUuidByComponentUuid.put(componentUuid, projectUuid); + addProjectUuidPermissions(projectPermission, projectUuid); + return this; + } + @Override AuthorizationDao authorizationDao() { return authorizationDao; 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 4e8485a5027..2b80ab88c5b 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 @@ -116,4 +116,16 @@ public class ViewIndexerTest { assertThat(viewsByUuid.get("FGHI").projects()).containsOnly("JKLM"); } + @Test + public void index_view_doc() throws Exception { + indexer.index(new ViewDoc().setUuid("EFGH").setProjects(newArrayList("KLMN", "JKLM"))); + + List<ViewDoc> docs = esTester.getDocuments("views", "view", ViewDoc.class); + assertThat(docs).hasSize(1); + + ViewDoc view = docs.get(0); + assertThat(view.uuid()).isEqualTo("EFGH"); + assertThat(view.projects()).containsOnly("KLMN", "JKLM"); + } + } diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionComponentsMediumTest/search_by_view_uuid.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionComponentsMediumTest/search_by_view_uuid.json new file mode 100644 index 00000000000..5df35493a30 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionComponentsMediumTest/search_by_view_uuid.json @@ -0,0 +1,13 @@ +{ + "total": 1, + "p": 1, + "ps": 100, + "issues": [ + { + "key": "82fd47d4-b650-4037-80bc-7b112bd4eac2", + "component": "MyComponent", + "project": "MyProject", + "rule": "xoo:x1" + } + ] +} diff --git a/sonar-core/src/main/java/org/sonar/core/resource/ResourceDao.java b/sonar-core/src/main/java/org/sonar/core/resource/ResourceDao.java index 26de7532558..a0ac581d2fa 100644 --- a/sonar-core/src/main/java/org/sonar/core/resource/ResourceDao.java +++ b/sonar-core/src/main/java/org/sonar/core/resource/ResourceDao.java @@ -105,6 +105,16 @@ public class ResourceDao implements DaoComponent { } } + @CheckForNull + public ResourceDto getResource(String componentUuid) { + SqlSession session = mybatis.openSession(false); + try { + return session.getMapper(ResourceMapper.class).selectResourceByUuid(componentUuid); + } finally { + MyBatis.closeQuietly(session); + } + } + public ResourceDto getResource(long projectId, SqlSession session) { return session.getMapper(ResourceMapper.class).selectResource(projectId); } diff --git a/sonar-core/src/main/java/org/sonar/core/resource/ResourceMapper.java b/sonar-core/src/main/java/org/sonar/core/resource/ResourceMapper.java index 961e6bf3e9b..be3371b2c25 100644 --- a/sonar-core/src/main/java/org/sonar/core/resource/ResourceMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/resource/ResourceMapper.java @@ -35,6 +35,8 @@ public interface ResourceMapper { ResourceDto selectResource(long id); + ResourceDto selectResourceByUuid(String uuid); + List<ResourceDto> selectDescendantProjects(long rootProjectId); /** diff --git a/sonar-core/src/main/resources/org/sonar/core/resource/ResourceMapper.xml b/sonar-core/src/main/resources/org/sonar/core/resource/ResourceMapper.xml index 9b29c8f5f70..0f995846731 100644 --- a/sonar-core/src/main/resources/org/sonar/core/resource/ResourceMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/resource/ResourceMapper.xml @@ -97,6 +97,11 @@ where p.id=#{id} </select> + <select id="selectResourceByUuid" parameterType="String" resultMap="resourceResultMap"> + select * from projects p + where p.uuid=#{uuid} + </select> + <select id="selectSnapshot" parameterType="long" resultMap="snapshotResultMap"> select * from snapshots where id=#{id} </select> diff --git a/sonar-core/src/main/resources/org/sonar/core/user/AuthorizationMapper.xml b/sonar-core/src/main/resources/org/sonar/core/user/AuthorizationMapper.xml index 88549a4ab31..12e1e32da23 100644 --- a/sonar-core/src/main/resources/org/sonar/core/user/AuthorizationMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/user/AuthorizationMapper.xml @@ -39,7 +39,7 @@ <when test="userId != null"> SELECT p.kee as root_project_kee FROM group_roles gr - INNER JOIN projects p on p.id = gr.resource_id AND p.scope = 'PRJ' AND p.qualifier = 'TRK' + INNER JOIN projects p on p.id = gr.resource_id AND p.module_uuid IS NULL <where> and gr.role=#{role} and (gr.group_id is null or gr.group_id in (select gu.group_id from groups_users gu where gu.user_id=#{userId})) @@ -47,7 +47,7 @@ UNION SELECT p.kee as root_project_kee FROM user_roles ur - INNER JOIN projects p on p.id = ur.resource_id AND p.scope = 'PRJ' AND p.qualifier = 'TRK' + INNER JOIN projects p on p.id = ur.resource_id AND p.module_uuid IS NULL <where> and ur.role=#{role} and ur.user_id = #{userId} @@ -56,7 +56,7 @@ <otherwise> SELECT p.kee as root_project_kee FROM group_roles gr - INNER JOIN projects p on p.id = gr.resource_id AND p.scope = 'PRJ' AND p.qualifier = 'TRK' + INNER JOIN projects p on p.id = gr.resource_id AND p.module_uuid IS NULL <where> and gr.role=#{role} and gr.group_id is null @@ -70,7 +70,7 @@ <when test="userId != null"> SELECT p.uuid as root_project_uuid FROM group_roles gr - INNER JOIN projects p on p.id = gr.resource_id AND p.scope = 'PRJ' AND p.qualifier = 'TRK' + INNER JOIN projects p on p.id = gr.resource_id AND p.module_uuid IS NULL <where> and gr.role=#{role} and (gr.group_id is null or gr.group_id in (select gu.group_id from groups_users gu where gu.user_id=#{userId})) @@ -78,7 +78,7 @@ UNION SELECT p.uuid as root_project_uuid FROM user_roles ur - INNER JOIN projects p on p.id = ur.resource_id AND p.scope = 'PRJ' AND p.qualifier = 'TRK' + INNER JOIN projects p on p.id = ur.resource_id AND p.module_uuid IS NULL <where> and ur.role=#{role} and ur.user_id = #{userId} @@ -87,7 +87,7 @@ <otherwise> SELECT p.uuid as root_project_uuid FROM group_roles gr - INNER JOIN projects p on p.id = gr.resource_id AND p.scope = 'PRJ' AND p.qualifier = 'TRK' + INNER JOIN projects p on p.id = gr.resource_id AND p.module_uuid IS NULL <where> and gr.role=#{role} and gr.group_id is null @@ -102,7 +102,7 @@ <when test="userId != null"> SELECT p.id as root_project_id FROM group_roles gr - INNER JOIN projects p on p.id = gr.resource_id AND p.scope = 'PRJ' AND p.qualifier = 'TRK' + INNER JOIN projects p on p.id = gr.resource_id AND p.module_uuid IS NULL <where> and gr.role=#{role} and (gr.group_id is null or gr.group_id in (select gu.group_id from groups_users gu where gu.user_id=#{userId})) @@ -110,7 +110,7 @@ UNION SELECT p.id as root_project_id FROM user_roles ur - INNER JOIN projects p on p.id = ur.resource_id AND p.scope = 'PRJ' AND p.qualifier = 'TRK' + INNER JOIN projects p on p.id = ur.resource_id AND p.module_uuid IS NULL <where> and ur.role=#{role} and ur.user_id = #{userId} @@ -119,7 +119,7 @@ <otherwise> SELECT p.id as root_project_id FROM group_roles gr - INNER JOIN projects p on p.id = gr.resource_id AND p.scope = 'PRJ' AND p.qualifier = 'TRK' + INNER JOIN projects p on p.id = gr.resource_id AND p.module_uuid IS NULL <where> and gr.role=#{role} and gr.group_id is null diff --git a/sonar-core/src/test/java/org/sonar/core/resource/ResourceDaoTest.java b/sonar-core/src/test/java/org/sonar/core/resource/ResourceDaoTest.java index 940d20690ac..e97cfa1d868 100644 --- a/sonar-core/src/test/java/org/sonar/core/resource/ResourceDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/resource/ResourceDaoTest.java @@ -103,6 +103,25 @@ public class ResourceDaoTest extends AbstractDaoTestCase { } @Test + public void get_resource_by_uuid() { + setupData("fixture"); + + ResourceDto resource = dao.getResource("ABCD"); + + assertThat(resource.getUuid()).isEqualTo("ABCD"); + assertThat(resource.getProjectUuid()).isEqualTo("ABCD"); + assertThat(resource.getPath()).isNull(); + assertThat(resource.getName()).isEqualTo("Struts"); + assertThat(resource.getLongName()).isEqualTo("Apache Struts"); + assertThat(resource.getScope()).isEqualTo("PRJ"); + assertThat(resource.getDescription()).isEqualTo("the description"); + assertThat(resource.getLanguage()).isEqualTo("java"); + assertThat(resource.isEnabled()).isTrue(); + assertThat(resource.getAuthorizationUpdatedAt()).isNotNull(); + assertThat(resource.getCreatedAt()).isNotNull(); + } + + @Test public void get_resource_path_and_module_key() { setupData("fixture"); diff --git a/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/anonymous_should_be_authorized.xml b/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/anonymous_should_be_authorized.xml index aaf6b56ff94..f5730087a21 100644 --- a/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/anonymous_should_be_authorized.xml +++ b/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/anonymous_should_be_authorized.xml @@ -5,10 +5,10 @@ <group_roles id="1" group_id="[null]" resource_id="300" role="user"/> <group_roles id="2" group_id="[null]" resource_id="400" role="user"/> - <projects id="301" kee="pj-w-snapshot:package" root_id="300" uuid="ABCD"/> - <projects id="302" kee="pj-w-snapshot:file" root_id="300" uuid="BCDE"/> - <projects id="303" kee="pj-w-snapshot:other" root_id="300" uuid="CDEF" /> - <projects id="300" kee="pj-w-snapshot" uuid="EDFG"/> - <projects id="400" kee="pj-wo-snapshot" uuid="FGHI"/> + <projects id="301" kee="pj-w-snapshot:package" root_id="300" uuid="ABCD" module_uuid="EDFG"/> + <projects id="302" kee="pj-w-snapshot:file" root_id="300" uuid="BCDE" module_uuid="EDFG"/> + <projects id="303" kee="pj-w-snapshot:other" root_id="300" uuid="CDEF" module_uuid="EDFG"/> + <projects id="300" kee="pj-w-snapshot" uuid="EDFG" module_uuid="[null]"/> + <projects id="400" kee="pj-wo-snapshot" uuid="FGHI" project_uuid="FGHI"/> </dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/group_should_be_authorized.xml b/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/group_should_be_authorized.xml index b500a05366a..7ffca0d6f5e 100644 --- a/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/group_should_be_authorized.xml +++ b/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/group_should_be_authorized.xml @@ -7,10 +7,10 @@ <group_roles id="1" group_id="200" resource_id="300" role="user"/> <group_roles id="2" group_id="200" resource_id="400" role="user"/> - <projects id="301" kee="pj-w-snapshot:package" root_id="300" uuid="ABCD"/> - <projects id="302" kee="pj-w-snapshot:file" root_id="300" uuid="BCDE"/> - <projects id="303" kee="pj-w-snapshot:other" root_id="300" uuid="CDEF"/> - <projects id="300" kee="pj-w-snapshot" uuid="DEFG"/> - <projects id="400" kee="pj-wo-snapshot" uuid="EFGH"/> + <projects id="301" kee="pj-w-snapshot:package" root_id="300" uuid="ABCD" module_uuid="DEFG"/> + <projects id="302" kee="pj-w-snapshot:file" root_id="300" uuid="BCDE" module_uuid="DEFG"/> + <projects id="303" kee="pj-w-snapshot:other" root_id="300" uuid="CDEF" module_uuid="DEFG"/> + <projects id="300" kee="pj-w-snapshot" uuid="DEFG" module_uuid="[null]"/> + <projects id="400" kee="pj-wo-snapshot" uuid="EFGH" module_uuid="[null]"/> </dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/group_should_have_global_authorization.xml b/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/group_should_have_global_authorization.xml index fe02d7bccbb..c5cd325ea5e 100644 --- a/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/group_should_have_global_authorization.xml +++ b/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/group_should_have_global_authorization.xml @@ -6,10 +6,10 @@ <groups_users user_id="100" group_id="200"/> <group_roles id="1" group_id="200" resource_id="[null]" role="user"/> - <projects id="301" kee="pj-w-snapshot:package" root_id="300" uuid="ABCD"/> - <projects id="302" kee="pj-w-snapshot:file" root_id="300" uuid="BCDE"/> - <projects id="303" kee="pj-w-snapshot:other" root_id="300" uuid="CDEF"/> - <projects id="300" kee="pj-w-snapshot" uuid="DEFG"/> - <projects id="400" kee="pj-wo-snapshot" uuid="EFGH"/> + <projects id="301" kee="pj-w-snapshot:package" root_id="300" uuid="ABCD" module_uuid="DEFG"/> + <projects id="302" kee="pj-w-snapshot:file" root_id="300" uuid="BCDE" module_uuid="DEFG"/> + <projects id="303" kee="pj-w-snapshot:other" root_id="300" uuid="CDEF" module_uuid="DEFG"/> + <projects id="300" kee="pj-w-snapshot" uuid="DEFG" module_uuid="[null]"/> + <projects id="400" kee="pj-wo-snapshot" uuid="EFGH" module_uuid="[null]"/> </dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_anonymous.xml b/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_anonymous.xml index eb7321ec20f..ed6f133f679 100644 --- a/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_anonymous.xml +++ b/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_anonymous.xml @@ -4,10 +4,10 @@ <groups_users user_id="100" group_id="200"/> <group_roles id="1" group_id="[null]" resource_id="300" role="user"/> - <projects id="300" uuid="ABCD" kee="pj-w-snapshot" scope="PRJ" qualifier="TRK" enabled="[true]"/> - <projects id="301" uuid="BCDE" kee="pj-w-snapshot1" scope="PRJ" qualifier="TRK" enabled="[true]"/> - <projects id="302" uuid="CDEF" kee="pj-w-snapshot2" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="300" uuid="ABCD" module_uuid="[null]" kee="pj-w-snapshot" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="301" uuid="BCDE" module_uuid="[null]" kee="pj-w-snapshot1" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="302" uuid="CDEF" module_uuid="[null]" kee="pj-w-snapshot2" scope="PRJ" qualifier="TRK" enabled="[true]"/> - <projects id="303" uuid="DEFG" kee="pj-w-snapshot3" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="303" uuid="DEFG" module_uuid="[null]" kee="pj-w-snapshot3" scope="PRJ" qualifier="TRK" enabled="[true]"/> </dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_group.xml b/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_group.xml index 05bca26378a..65b2ad7d372 100644 --- a/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_group.xml +++ b/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_group.xml @@ -6,10 +6,10 @@ <groups_users user_id="100" group_id="200"/> <group_roles id="1" group_id="200" resource_id="300" role="user"/> - <projects id="300" uuid="ABCD" kee="pj-w-snapshot" scope="PRJ" qualifier="TRK" enabled="[true]"/> - <projects id="301" uuid="BCDE" kee="pj-w-snapshot1" scope="PRJ" qualifier="TRK" enabled="[true]"/> - <projects id="302" uuid="CDEF" kee="pj-w-snapshot2" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="300" uuid="ABCD" module_uuid="[null]" kee="pj-w-snapshot" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="301" uuid="BCDE" module_uuid="[null]" kee="pj-w-snapshot1" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="302" uuid="CDEF" module_uuid="[null]" kee="pj-w-snapshot2" scope="PRJ" qualifier="TRK" enabled="[true]"/> - <projects id="303" uuid="DEFG" kee="pj-w-snapshot3" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="303" uuid="DEFG" module_uuid="[null]" kee="pj-w-snapshot3" scope="PRJ" qualifier="TRK" enabled="[true]"/> </dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_user.xml b/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_user.xml index 9ca62ae7ab8..706c9300fee 100644 --- a/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_user.xml +++ b/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_user.xml @@ -5,10 +5,10 @@ <groups_users user_id="100" group_id="200"/> <group_roles id="1" group_id="200" resource_id="999" role="user"/> - <projects id="300" uuid="ABCD" kee="pj-w-snapshot" scope="PRJ" qualifier="TRK" enabled="[true]"/> - <projects id="301" uuid="BCDE" kee="pj-w-snapshot1" scope="PRJ" qualifier="TRK" enabled="[true]"/> - <projects id="302" uuid="CDEF" kee="pj-w-snapshot2" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="300" uuid="ABCD" module_uuid="[null]" kee="pj-w-snapshot" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="301" uuid="BCDE" module_uuid="[null]" kee="pj-w-snapshot1" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="302" uuid="CDEF" module_uuid="[null]" kee="pj-w-snapshot2" scope="PRJ" qualifier="TRK" enabled="[true]"/> - <projects id="303" uuid="DEFG" kee="pj-w-snapshot3" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="303" uuid="DEFG" module_uuid="[null]" kee="pj-w-snapshot3" scope="PRJ" qualifier="TRK" enabled="[true]"/> </dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/user_should_be_authorized.xml b/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/user_should_be_authorized.xml index 07f8997740d..b6371a7e0b1 100644 --- a/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/user_should_be_authorized.xml +++ b/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/user_should_be_authorized.xml @@ -6,9 +6,9 @@ <groups_users user_id="100" group_id="200"/> <group_roles id="1" group_id="200" resource_id="999" role="user"/> - <projects id="301" kee="pj-w-snapshot:package" root_id="300" uuid="ABCD"/> - <projects id="302" kee="pj-w-snapshot:file" root_id="300" uuid="BCDE"/> - <projects id="303" kee="pj-w-snapshot:other" root_id="300" uuid="CDEF"/> - <projects id="300" kee="pj-w-snapshot" uuid="DEFG"/> - <projects id="400" kee="pj-wo-snapshot" uuid="EFGH"/> + <projects id="301" kee="pj-w-snapshot:package" root_id="300" uuid="ABCD" module_uuid="DEFG"/> + <projects id="302" kee="pj-w-snapshot:file" root_id="300" uuid="BCDE" module_uuid="DEFG"/> + <projects id="303" kee="pj-w-snapshot:other" root_id="300" uuid="CDEF" module_uuid="DEFG"/> + <projects id="300" kee="pj-w-snapshot" uuid="DEFG" module_uuid="[null]"/> + <projects id="400" kee="pj-wo-snapshot" uuid="EFGH" module_uuid="[null]"/> </dataset> |