aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2015-01-30 17:05:49 +0100
committerJulien Lancelot <julien.lancelot@sonarsource.com>2015-02-02 16:21:28 +0100
commit639d4f6e33a4d6f645f9a091945bb4c743476d12 (patch)
tree8f1d8295b63e0f110543c5a750df1aa3073313a1
parent22e6bbd3f1b318ef74c5c21ab43e7fa445418493 (diff)
downloadsonarqube-639d4f6e33a4d6f645f9a091945bb4c743476d12.tar.gz
sonarqube-639d4f6e33a4d6f645f9a091945bb4c743476d12.zip
SONAR-6074 Add an ability to filter issues by view
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java19
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java22
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/BackendCleanup.java30
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java186
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/UserSession.java30
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/view/index/ViewIndexer.java18
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java23
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsMediumTest.java106
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/MockUserSession.java14
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/view/index/ViewIndexerTest.java12
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionComponentsMediumTest/search_by_view_uuid.json13
-rw-r--r--sonar-core/src/main/java/org/sonar/core/resource/ResourceDao.java10
-rw-r--r--sonar-core/src/main/java/org/sonar/core/resource/ResourceMapper.java2
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/resource/ResourceMapper.xml5
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/user/AuthorizationMapper.xml18
-rw-r--r--sonar-core/src/test/java/org/sonar/core/resource/ResourceDaoTest.java19
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/anonymous_should_be_authorized.xml10
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/group_should_be_authorized.xml10
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/group_should_have_global_authorization.xml10
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_anonymous.xml8
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_group.xml8
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_user.xml8
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/user_should_be_authorized.xml10
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>