import org.sonar.core.user.UserDao;
import org.sonar.server.activity.db.ActivityDao;
import org.sonar.server.component.persistence.ComponentDao;
+import org.sonar.server.issue.db.IssueAuthorizationDao;
import org.sonar.server.issue.db.IssueDao;
import org.sonar.server.measure.persistence.MeasureDao;
import org.sonar.server.measure.persistence.MetricDao;
private final AuthorizationDao authorizationDao;
private final UserDao userDao;
private final IssueDao issueDao;
+ private final IssueAuthorizationDao issueAuthorizationDao;
public DbClient(Database db, MyBatis myBatis, DaoComponent... daoComponents) {
this.db = db;
authorizationDao = getDao(map, AuthorizationDao.class);
userDao = getDao(map, UserDao.class);
issueDao = getDao(map, IssueDao.class);
+ issueAuthorizationDao = getDao(map, IssueAuthorizationDao.class);
}
public Database database() {
return issueDao;
}
+ public IssueAuthorizationDao issueAuthorizationDao() {
+ return issueAuthorizationDao;
+ }
+
public QualityProfileDao qualityProfileDao() {
return qualityProfileDao;
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.issue.db;
+
+import com.google.common.annotations.VisibleForTesting;
+import org.sonar.api.utils.System2;
+import org.sonar.core.issue.db.IssueAuthorizationDto;
+import org.sonar.core.issue.db.IssueAuthorizationMapper;
+import org.sonar.core.persistence.DaoComponent;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.BaseDao;
+import org.sonar.server.search.IndexDefinition;
+
+import java.util.Date;
+
+public class IssueAuthorizationDao extends BaseDao<IssueAuthorizationMapper, IssueAuthorizationDto, String> implements DaoComponent {
+
+ public IssueAuthorizationDao() {
+ this(System2.INSTANCE);
+ }
+
+ @VisibleForTesting
+ public IssueAuthorizationDao(System2 system) {
+ super(IndexDefinition.ISSUES_AUTHORIZATION, IssueAuthorizationMapper.class, system);
+ }
+
+ @Override
+ protected IssueAuthorizationDto doGetNullableByKey(DbSession session, String key) {
+ return mapper(session).selectByKey(key);
+ }
+
+ @Override
+ protected IssueAuthorizationDto doUpdate(DbSession session, IssueAuthorizationDto issueAuthorization) {
+ // TODO ?
+ // mapper(session).update(issueAuthorization);
+ return issueAuthorization;
+ }
+
+ @Override
+ protected IssueAuthorizationDto doInsert(DbSession session, IssueAuthorizationDto issueAuthorization) {
+ // TODO ?
+ // Preconditions.checkNotNull(issueAuthorization.getKey(), "Cannot insert IssueAuthorization with empty key!");
+ // Preconditions.checkNotNull(issueAuthorization.getPermission(), "Cannot insert IssueAuthorization with no permission!");
+ // mapper(session).insert(issueAuthorization);
+ return issueAuthorization;
+ }
+
+ @Override
+ protected Iterable<IssueAuthorizationDto> findAfterDate(DbSession session, Date date) {
+ // TODO ?
+ // return mapper(session).selectAfterDate(new Timestamp(date.getTime()));
+ return null;
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+@ParametersAreNonnullByDefault
+package org.sonar.server.issue.db;
+
+import javax.annotation.ParametersAreNonnullByDefault;
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.issue.index;
+
+import org.sonar.server.search.BaseDoc;
+
+import java.util.List;
+import java.util.Map;
+
+public class IssueAuthorizationDoc extends BaseDoc {
+
+ public IssueAuthorizationDoc(Map<String, Object> fields) {
+ super(fields);
+ }
+
+ public String project() {
+ return getField(IssueAuthorizationNormalizer.IssueAuthorizationField.PROJECT.field());
+ }
+
+ public String permission() {
+ return getField(IssueAuthorizationNormalizer.IssueAuthorizationField.PERMISSION.field());
+ }
+
+ public List<String> groups() {
+ return (List<String>) getField(IssueAuthorizationNormalizer.IssueAuthorizationField.GROUPS.field());
+ }
+
+ public List<String> users() {
+ return (List<String>) getField(IssueAuthorizationNormalizer.IssueAuthorizationField.USERS.field());
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.issue.index;
+
+import com.google.common.base.Preconditions;
+import org.elasticsearch.common.settings.ImmutableSettings;
+import org.elasticsearch.common.settings.Settings;
+import org.sonar.core.issue.db.IssueAuthorizationDto;
+import org.sonar.server.search.BaseIndex;
+import org.sonar.server.search.IndexDefinition;
+import org.sonar.server.search.IndexField;
+import org.sonar.server.search.SearchClient;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class IssueAuthorizationIndex extends BaseIndex<IssueAuthorizationDoc, IssueAuthorizationDto, String> {
+
+ public IssueAuthorizationIndex(IssueAuthorizationNormalizer normalizer, SearchClient client) {
+ super(IndexDefinition.ISSUES_AUTHORIZATION, normalizer, client);
+ }
+
+ @Override
+ protected String getKeyValue(String s) {
+ return s;
+ }
+
+ @Override
+ protected Settings getIndexSettings() throws IOException {
+ return ImmutableSettings.builder()
+ .put("index.number_of_replicas", 0)
+ .put("index.number_of_shards", 1)
+ .build();
+ }
+
+ @Override
+ protected Map mapProperties() {
+ Map<String, Object> mapping = new HashMap<String, Object>();
+ for (IndexField field : IssueAuthorizationNormalizer.IssueAuthorizationField.ALL_FIELDS) {
+ mapping.put(field.field(), mapField(field));
+ }
+ return mapping;
+ }
+
+ @Override
+ protected Map mapKey() {
+ Map<String, Object> mapping = new HashMap<String, Object>();
+ mapping.put("path", IssueAuthorizationNormalizer.IssueAuthorizationField.PROJECT.field());
+ return mapping;
+ }
+
+ @Override
+ public IssueAuthorizationDoc toDoc(Map fields) {
+ Preconditions.checkNotNull(fields, "Cannot construct IssueAuthorization with null response");
+ return new IssueAuthorizationDoc(fields);
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.issue.index;
+
+import com.google.common.collect.ImmutableList;
+import org.elasticsearch.action.update.UpdateRequest;
+import org.sonar.core.issue.db.IssueAuthorizationDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.search.BaseNormalizer;
+import org.sonar.server.search.IndexDefinition;
+import org.sonar.server.search.IndexField;
+import org.sonar.server.search.Indexable;
+
+import java.lang.reflect.Field;
+import java.util.*;
+
+public class IssueAuthorizationNormalizer extends BaseNormalizer<IssueAuthorizationDto, String> {
+
+ public IssueAuthorizationNormalizer(DbClient db) {
+ super(IndexDefinition.ISSUES, db);
+ }
+
+ public static final class IssueAuthorizationField extends Indexable {
+
+ public static final IndexField PROJECT = add(IndexField.Type.STRING, "project");
+ public static final IndexField PERMISSION = add(IndexField.Type.STRING, "permission");
+ public static final IndexField GROUPS = add(IndexField.Type.STRING, "groups");
+ public static final IndexField USERS = add(IndexField.Type.STRING, "users");
+
+ public static final Set<IndexField> ALL_FIELDS = getAllFields();
+
+ private static final Set<IndexField> getAllFields() {
+ Set<IndexField> fields = new HashSet<IndexField>();
+ for (Field classField : IssueAuthorizationField.class.getDeclaredFields()) {
+ if (classField.getType().isAssignableFrom(IndexField.class)) {
+ try {
+ fields.add(IndexField.class.cast(classField.get(null)));
+ } catch (IllegalAccessException e) {
+ throw new IllegalStateException("Could not access Field '" + classField.getName() + "'", e);
+ }
+ }
+ }
+ return fields;
+ }
+
+ public static final IndexField of(String fieldName) {
+ for (IndexField field : ALL_FIELDS) {
+ if (field.field().equals(fieldName)) {
+ return field;
+ }
+ }
+ throw new IllegalStateException("Could not find an IndexField for '" + fieldName + "'");
+ }
+ }
+
+ @Override
+ public List<UpdateRequest> normalize(IssueAuthorizationDto dto) {
+ Map<String, Object> update = new HashMap<String, Object>();
+
+ update.put(IssueAuthorizationField.PROJECT.field(), dto.getProject());
+ update.put(IssueAuthorizationField.PERMISSION.field(), dto.getPermission());
+ update.put(IssueAuthorizationField.USERS.field(), dto.getUsers());
+ update.put(IssueAuthorizationField.GROUPS.field(), dto.getGroups());
+
+ /** Upsert elements */
+ Map<String, Object> upsert = getUpsertFor(IssueAuthorizationField.ALL_FIELDS, update);
+ upsert.put(IssueAuthorizationField.PROJECT.field(), dto.getKey());
+
+ return ImmutableList.of(
+ new UpdateRequest()
+ .id(dto.getKey())
+ .doc(update)
+ .upsert(upsert));
+ }
+}
}
private String getParentType() {
- return IndexDefinition.ISSUES_PROJECT.getIndexType();
+ return IndexDefinition.ISSUES_AUTHORIZATION.getIndexType();
}
private Map mapRouting() {
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+@ParametersAreNonnullByDefault
+package org.sonar.server.issue.index;
+
+import javax.annotation.ParametersAreNonnullByDefault;
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.PreviewDatabaseFactory;
-import org.sonar.core.persistence.SemaphoreUpdater;
-import org.sonar.core.persistence.SemaphoresImpl;
+import org.sonar.core.persistence.*;
import org.sonar.core.preview.PreviewCache;
import org.sonar.core.profiling.Profiling;
import org.sonar.core.purge.PurgeProfiler;
import org.sonar.server.component.DefaultComponentFinder;
import org.sonar.server.component.DefaultRubyComponentService;
import org.sonar.server.component.persistence.ComponentDao;
-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.config.ws.PropertiesWs;
import org.sonar.server.db.DatabaseChecker;
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.duplication.ws.DuplicationsJsonWriter;
import org.sonar.server.duplication.ws.DuplicationsParser;
import org.sonar.server.duplication.ws.DuplicationsWs;
-import org.sonar.server.issue.ActionService;
-import org.sonar.server.issue.AssignAction;
-import org.sonar.server.issue.CommentAction;
-import org.sonar.server.issue.DefaultIssueFinder;
-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.IssueService;
-import org.sonar.server.issue.IssueStatsFinder;
-import org.sonar.server.issue.PlanAction;
-import org.sonar.server.issue.PublicRubyIssueService;
-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;
import org.sonar.server.issue.filter.IssueFilterService;
import org.sonar.server.issue.filter.IssueFilterWriter;
import org.sonar.server.issue.filter.IssueFilterWs;
+import org.sonar.server.issue.index.IssueAuthorizationIndex;
+import org.sonar.server.issue.index.IssueAuthorizationNormalizer;
import org.sonar.server.issue.index.IssueIndex;
import org.sonar.server.issue.index.IssueNormalizer;
import org.sonar.server.issue.ws.IssueActionsWriter;
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.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.QProfileRepositoryExporter;
-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.DeprecatedRulesDefinition;
-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.RuleMapping;
-import org.sonar.server.rule.ws.RulesWebService;
-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.rule.ws.*;
+import org.sonar.server.search.*;
import org.sonar.server.source.CodeColorizers;
import org.sonar.server.source.DeprecatedSourceDecorator;
import org.sonar.server.source.HtmlSourceDecorator;
import org.sonar.server.source.ws.ScmWriter;
import org.sonar.server.source.ws.ShowAction;
import org.sonar.server.source.ws.SourcesWs;
-import org.sonar.server.startup.CleanPreviewAnalysisCache;
-import org.sonar.server.startup.CopyRequirementsFromCharacteristicsToRules;
-import org.sonar.server.startup.GeneratePluginIndex;
-import org.sonar.server.startup.GwtPublisher;
-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;
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.*;
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.ws.ListingWs;
import org.sonar.server.ws.WebServiceEngine;
SearchClient.class,
ActivityNormalizer.class,
IssueNormalizer.class,
+ IssueAuthorizationNormalizer.class,
RuleNormalizer.class,
ActiveRuleNormalizer.class,
RuleIndex.class,
ActiveRuleIndex.class,
IssueIndex.class,
+ IssueAuthorizationIndex.class,
ActivityIndex.class,
IndexClient.class,
SearchHealth.class,
public static final IndexDefinition RULE = new IndexDefinition("rules", "rule");
public static final IndexDefinition ACTIVE_RULE = new IndexDefinition("rules", "activeRule");
- public static final IndexDefinition ISSUES_PROJECT = new IndexDefinition("issues", "issueProject");
- public static final IndexDefinition ISSUES_PERMISSION = new IndexDefinition("issues", "issuePermission");
+ public static final IndexDefinition ISSUES_AUTHORIZATION = new IndexDefinition("issues", "issueAuthorization");
public static final IndexDefinition ISSUES = new IndexDefinition("issues", "issue");
public static final IndexDefinition LOG = new IndexDefinition("logs", "sonarLog");
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+
package org.sonar.server.issue.db;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
-import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.index.query.BoolFilterBuilder;
import org.elasticsearch.index.query.FilterBuilders;
import org.elasticsearch.index.query.OrFilterBuilder;
import org.sonar.server.platform.Platform;
import org.sonar.server.rule.RuleTesting;
import org.sonar.server.rule.db.RuleDao;
-import org.sonar.server.search.BaseIndex;
import org.sonar.server.search.IndexClient;
import org.sonar.server.search.IndexDefinition;
import org.sonar.server.search.SearchClient;
import org.sonar.server.tester.ServerTester;
-import java.io.IOException;
-import java.io.Serializable;
-import java.util.*;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
import static org.fest.assertions.Assertions.assertThat;
@Test
public void issue_authorization_on_group() throws Exception {
SearchClient searchClient = tester.get(SearchClient.class);
- createIssuePermissionIndex(searchClient);
- createIssueProjectIndex(searchClient);
RuleDto rule = RuleTesting.newXooX1();
tester.get(RuleDao.class).insert(dbSession, rule);
ComponentDto project1 = addComponent(1L, 1L, "SonarQube :: Server");
ComponentDto file1 = addComponent(2L, 1L, "IssueAction.java");
addIssue(rule, project1, file1);
- addIssueAuthorization(searchClient, project1, null, "user");
+ addIssueAuthorization(searchClient, project1, null, newArrayList("user")).get();
ComponentDto project2 = addComponent(10L, 10L, "SonarQube :: Core");
ComponentDto file2 = addComponent(11L, 10L, "IssueDao.java");
addIssue(rule, project2, file2);
- addIssueAuthorization(searchClient, project2, null, "reviewer");
+ addIssueAuthorization(searchClient, project2, null, newArrayList("reviewer")).get();
ComponentDto project3 = addComponent(20L, 20L, "SonarQube :: WS");
ComponentDto file3 = addComponent(21L, 20L, "IssueWS.java");
addIssue(rule, project3, file3);
- addIssueAuthorization(searchClient, project3, null, "user");
- addIssueAuthorization(searchClient, project3, null, "reviewer");
+ addIssueAuthorization(searchClient, project3, null, newArrayList("user", "reviewer")).get();
dbSession.commit();
@Test
public void issue_authorization_on_user() throws Exception {
SearchClient searchClient = tester.get(SearchClient.class);
- createIssuePermissionIndex(searchClient);
- createIssueProjectIndex(searchClient);
RuleDto rule = RuleTesting.newXooX1();
tester.get(RuleDao.class).insert(dbSession, rule);
ComponentDto project = addComponent(1L, 1L, "SonarQube");
ComponentDto file = addComponent(2L, 1L, "IssueAction.java");
addIssue(rule, project, file);
- addIssueAuthorization(searchClient, project, "julien", null);
+ addIssueAuthorization(searchClient, project, newArrayList("julien"), null).get();
dbSession.commit();
assertThat(searchIssueWithAuthorization(searchClient, "julien", "user").getHits().getTotalHits()).isEqualTo(1);
// The issue is not visible for user simon
assertThat(searchIssueWithAuthorization(searchClient, "simon", "user").getHits().getTotalHits()).isEqualTo(0);
-
-// Thread.sleep(Integer.MAX_VALUE);
}
@Test
public void issue_authorization_with_a_lot_of_issues() throws Exception {
SearchClient searchClient = tester.get(SearchClient.class);
- createIssuePermissionIndex(searchClient);
- createIssueProjectIndex(searchClient);
RuleDto rule = RuleTesting.newXooX1();
tester.get(RuleDao.class).insert(dbSession, rule);
Long projectId = 1L;
Long componentId = 1L;
- BulkRequestBuilder bulkRequestBuilder = new BulkRequestBuilder(searchClient);
+
+ List<String> users = newArrayList();
+ for (int u = 0; u < nbUser; u++) {
+ users.add("user-" + u);
+ }
+
+ BulkRequestBuilder bulkRequestBuilder = new BulkRequestBuilder(searchClient).setRefresh(true);
for (int p = 0; p < nbProject; p++) {
ComponentDto project = addComponent(projectId, projectId, "Project-" + projectId.toString());
- addIssueAuthorization(searchClient, bulkRequestBuilder, project, null, "anyone");
+ List<String> groups = newArrayList();
+ groups.add("anyone");
if (p % 2 == 0) {
- addIssueAuthorization(searchClient, bulkRequestBuilder, project, null, "user");
- }
- for (int u = 0; u < nbUser; u++) {
- addIssueAuthorization(searchClient, bulkRequestBuilder, project, "user-" + u, null);
+ groups.add("user");
}
+
+ bulkRequestBuilder.add(addIssueAuthorization(searchClient, project, users, groups, false));
for (int c = 0; c < componentPerProject; c++) {
ComponentDto file = addComponent(componentId, projectId, "Component-" + componentId.toString());
addIssue(rule, project, file);
// user-1 should see all issues
assertThat(searchIssueWithAuthorization(searchClient, "user-1", "").getHits().getTotalHits()).isEqualTo(nbProject * componentPerProject);
-// Thread.sleep(Integer.MAX_VALUE);
+ // Thread.sleep(Integer.MAX_VALUE);
}
private SearchResponse searchIssueWithAuthorization(SearchClient searchClient, String user, String... groups) {
BoolFilterBuilder fb = FilterBuilders.boolFilter();
- OrFilterBuilder or = FilterBuilders.orFilter(FilterBuilders.termFilter("user", user));
+ OrFilterBuilder or = FilterBuilders.orFilter(FilterBuilders.termFilter("users", user));
for (String group : groups) {
- or.add(FilterBuilders.termFilter("group", group));
+ or.add(FilterBuilders.termFilter("groups", group));
}
fb.must(FilterBuilders.termFilter("permission", "read"), or).cache(true);
// fb.must(FilterBuilders.termFilter("permission", "read"), or);
.setQuery(
QueryBuilders.filteredQuery(
QueryBuilders.matchAllQuery(),
- FilterBuilders.hasParentFilter(IndexDefinition.ISSUES_PROJECT.getIndexType(),
- QueryBuilders.hasChildQuery(IndexDefinition.ISSUES_PERMISSION.getIndexType(),
- QueryBuilders.filteredQuery(
- QueryBuilders.matchAllQuery(), fb)
- )
+ FilterBuilders.hasParentFilter(IndexDefinition.ISSUES_AUTHORIZATION.getIndexType(),
+ QueryBuilders.filteredQuery(
+ QueryBuilders.matchAllQuery(), fb)
)
)
)
return issue;
}
- private void addIssueAuthorization(SearchClient searchClient, ComponentDto project, String user, String group) {
- addIssueAuthorization(searchClient, null, project, user, group);
+ private IndexRequestBuilder addIssueAuthorization(final SearchClient searchClient, ComponentDto project, List<String> users, List<String> groups) {
+ return addIssueAuthorization(searchClient, project, users, groups, true);
}
- private void addIssueAuthorization(SearchClient searchClient, BulkRequestBuilder bulkRequestBuilder, ComponentDto project, String user, String group) {
+ private IndexRequestBuilder addIssueAuthorization(final SearchClient searchClient, ComponentDto project, List<String> users, List<String> groups, boolean refresh) {
Map<String, Object> permissionSource = newHashMap();
permissionSource.put("_parent", project.key());
permissionSource.put("permission", "read");
permissionSource.put("project", project.key());
- if (user != null) {
- permissionSource.put("user", user);
- }
- if (group != null) {
- permissionSource.put("group", group);
+ if (users != null) {
+ permissionSource.put("users", users);
}
-
- IndexRequestBuilder permissionRequestBuilder = searchClient.prepareIndex(IndexDefinition.ISSUES_PERMISSION.getIndexName(), IndexDefinition.ISSUES_PERMISSION.getIndexType())
- .setSource(permissionSource);
- if (bulkRequestBuilder != null) {
- bulkRequestBuilder.add(permissionRequestBuilder);
- } else {
- permissionRequestBuilder.setRefresh(true).get();
+ if (groups != null) {
+ permissionSource.put("groups", groups);
}
- Map<String, Object> projectSource = newHashMap();
- projectSource.put("key", project.key());
-
- IndexRequestBuilder projectRequestBuilder = searchClient.prepareIndex(IndexDefinition.ISSUES_PROJECT.getIndexName(), IndexDefinition.ISSUES_PROJECT.getIndexType())
+ return searchClient.prepareIndex(IndexDefinition.ISSUES_AUTHORIZATION.getIndexName(), IndexDefinition.ISSUES_AUTHORIZATION.getIndexType())
.setId(project.key())
- .setSource(projectSource);
- if (bulkRequestBuilder != null) {
- bulkRequestBuilder.add(projectRequestBuilder);
- } else {
- projectRequestBuilder.setRefresh(true).get();
- }
+ .setSource(permissionSource)
+ .setRefresh(refresh);
}
- private BaseIndex createIssueProjectIndex(final SearchClient searchClient) {
- BaseIndex baseIndex = new BaseIndex(
- IndexDefinition.createFor(IndexDefinition.ISSUES_PROJECT.getIndexName(), IndexDefinition.ISSUES_PROJECT.getIndexType()),
- null, searchClient) {
- @Override
- protected String getKeyValue(Serializable key) {
- return null;
- }
-
- @Override
- protected org.elasticsearch.common.settings.Settings getIndexSettings() throws IOException {
- return ImmutableSettings.builder().build();
- }
-
- @Override
- protected Map mapProperties() {
- Map<String, Object> mapping = new HashMap<String, Object>();
- mapping.put("project", mapStringField());
- return mapping;
- }
-
- protected Map mapStringField() {
- Map<String, Object> mapping = new HashMap<String, Object>();
- mapping.put("type", "string");
- mapping.put("index", "analyzed");
- mapping.put("index_analyzer", "keyword");
- mapping.put("search_analyzer", "whitespace");
- return mapping;
- }
-
- @Override
- protected Map mapKey() {
- return Collections.emptyMap();
- }
-
- @Override
- public Object toDoc(Map fields) {
- return null;
- }
- };
- baseIndex.start();
- return baseIndex;
- }
-
- private BaseIndex createIssuePermissionIndex(final SearchClient searchClient) {
- BaseIndex baseIndex = new BaseIndex(
- IndexDefinition.createFor(IndexDefinition.ISSUES_PERMISSION.getIndexName(), IndexDefinition.ISSUES_PERMISSION.getIndexType()),
- null, searchClient) {
- @Override
- protected String getKeyValue(Serializable key) {
- return null;
- }
-
- @Override
- protected org.elasticsearch.common.settings.Settings getIndexSettings() throws IOException {
- return ImmutableSettings.builder().build();
- }
-
- @Override
- protected Map mapDomain() {
- Map<String, Object> mapping = new HashMap<String, Object>();
- mapping.put("dynamic", false);
- mapping.put("_parent", mapParent());
- mapping.put("_routing", mapRouting());
- mapping.put("properties", mapProperties());
- return mapping;
- }
-
- private Object mapParent() {
- Map<String, Object> mapping = new HashMap<String, Object>();
- mapping.put("type", getParentType());
- return mapping;
- }
-
- private String getParentType() {
- return IndexDefinition.ISSUES_PROJECT.getIndexType();
- }
-
- private Map mapRouting() {
- Map<String, Object> mapping = new HashMap<String, Object>();
- mapping.put("required", true);
- mapping.put("path", "project");
- return mapping;
- }
-
- @Override
- protected Map mapProperties() {
- Map<String, Object> mapping = new HashMap<String, Object>();
- mapping.put("permission", mapStringField());
- mapping.put("project", mapStringField());
- mapping.put("group", mapStringField());
- mapping.put("user", mapStringField());
- return mapping;
- }
-
- protected Map mapStringField() {
- Map<String, Object> mapping = new HashMap<String, Object>();
- mapping.put("type", "string");
- mapping.put("index", "analyzed");
- mapping.put("index_analyzer", "keyword");
- mapping.put("search_analyzer", "whitespace");
- return mapping;
- }
-
- @Override
- protected Map mapKey() {
- Map<String, Object> mapping = new HashMap<String, Object>();
- return mapping;
- }
-
- @Override
- public Object toDoc(Map fields) {
- return null;
- }
- };
- baseIndex.start();
- return baseIndex;
- }
}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.issue.db;
-
-import org.elasticsearch.action.bulk.BulkRequestBuilder;
-import org.elasticsearch.action.index.IndexRequestBuilder;
-import org.elasticsearch.action.search.SearchRequestBuilder;
-import org.elasticsearch.action.search.SearchResponse;
-import org.elasticsearch.common.settings.ImmutableSettings;
-import org.elasticsearch.index.query.BoolFilterBuilder;
-import org.elasticsearch.index.query.FilterBuilders;
-import org.elasticsearch.index.query.OrFilterBuilder;
-import org.elasticsearch.index.query.QueryBuilders;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.issue.db.IssueDto;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.rule.RuleDto;
-import org.sonar.server.component.persistence.ComponentDao;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.issue.index.IssueDoc;
-import org.sonar.server.issue.index.IssueIndex;
-import org.sonar.server.platform.Platform;
-import org.sonar.server.rule.RuleTesting;
-import org.sonar.server.rule.db.RuleDao;
-import org.sonar.server.search.BaseIndex;
-import org.sonar.server.search.IndexClient;
-import org.sonar.server.search.IndexDefinition;
-import org.sonar.server.search.SearchClient;
-import org.sonar.server.tester.ServerTester;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.util.*;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static com.google.common.collect.Maps.newHashMap;
-import static org.fest.assertions.Assertions.assertThat;
-
-public class IssueBackendMediumTest2 {
-
- @ClassRule
- public static ServerTester tester = new ServerTester();
-
- DbClient dbClient;
- IndexClient indexClient;
- Platform platform;
- DbSession dbSession;
-
- @Before
- public void setUp() throws Exception {
- dbClient = tester.get(DbClient.class);
- indexClient = tester.get(IndexClient.class);
- platform = tester.get(Platform.class);
- dbSession = dbClient.openSession(false);
- tester.clearDbAndIndexes();
- }
-
- @After
- public void tearDown() throws Exception {
- if (dbSession != null) {
- dbSession.close();
- }
- }
-
- @Test
- public void insert_and_find_by_key() throws Exception {
- RuleDto rule = RuleTesting.newXooX1();
- tester.get(RuleDao.class).insert(dbSession, rule);
-
- ComponentDto project = new ComponentDto()
- .setId(1L)
- .setKey("MyProject")
- .setProjectId(1L);
- tester.get(ComponentDao.class).insert(dbSession, project);
-
- ComponentDto resource = new ComponentDto()
- .setProjectId(1L)
- .setKey("MyComponent")
- .setId(2L);
- tester.get(ComponentDao.class).insert(dbSession, resource);
-
- IssueDto issue = new IssueDto()
- .setIssueCreationDate(new Date())
- .setIssueUpdateDate(new Date())
- .setRule(rule)
- .setRootComponent(project)
- .setComponent(resource)
- .setStatus("OPEN").setResolution("OPEN")
- .setKee(UUID.randomUUID().toString())
- .setSeverity("MAJOR");
- dbClient.issueDao().insert(dbSession, issue);
-
- dbSession.commit();
-
- // Check that Issue is in Index
- assertThat(indexClient.get(IssueIndex.class).countAll()).isEqualTo(1);
-
- // should find by key
- IssueDoc issueDoc = indexClient.get(IssueIndex.class).getByKey(issue.getKey());
- assertThat(issueDoc).isNotNull();
-
- // Check all normalized fields
- assertThat(issueDoc.actionPlanKey()).isEqualTo(issue.getActionPlanKey());
- assertThat(issueDoc.assignee()).isEqualTo(issue.getAssignee());
- assertThat(issueDoc.authorLogin()).isEqualTo(issue.getAuthorLogin());
- assertThat(issueDoc.closeDate()).isEqualTo(issue.getIssueCloseDate());
- assertThat(issueDoc.componentKey()).isEqualTo(issue.getComponentKey());
- assertThat(issueDoc.creationDate()).isEqualTo(issue.getCreatedAt());
- assertThat(issueDoc.effortToFix()).isEqualTo(issue.getEffortToFix());
- assertThat(issueDoc.resolution()).isEqualTo(issue.getResolution());
- assertThat(issueDoc.ruleKey()).isEqualTo(RuleKey.of(issue.getRuleRepo(), issue.getRule()));
- assertThat(issueDoc.line()).isEqualTo(issue.getLine());
- assertThat(issueDoc.message()).isEqualTo(issue.getMessage());
- assertThat(issueDoc.reporter()).isEqualTo(issue.getReporter());
- assertThat(issueDoc.key()).isEqualTo(issue.getKey());
- assertThat(issueDoc.updateDate()).isEqualTo(issue.getIssueUpdateDate());
- assertThat(issueDoc.status()).isEqualTo(issue.getStatus());
- assertThat(issueDoc.severity()).isEqualTo(issue.getSeverity());
-
- // assertThat(issueDoc.attributes()).isEqualTo(issue.getIssueAttributes());
- // assertThat(issueDoc.isNew()).isEqualTo(issue.isN());
- // assertThat(issueDoc.comments()).isEqualTo(issue.());
- }
-
- @Test
- public void insert_and_find_after_date() throws Exception {
-
- RuleDto rule = RuleTesting.newXooX1();
- tester.get(RuleDao.class).insert(dbSession, rule);
-
- ComponentDto project = new ComponentDto()
- .setId(1L)
- .setKey("MyProject")
- .setProjectId(1L);
- tester.get(ComponentDao.class).insert(dbSession, project);
-
- ComponentDto resource = new ComponentDto()
- .setId(2L)
- .setKey("MyComponent")
- .setProjectId(1L);
- tester.get(ComponentDao.class).insert(dbSession, resource);
-
- IssueDto issue = new IssueDto().setId(1L)
- .setRuleId(rule.getId())
- .setRootComponentId(project.getId())
- .setRootComponentKey_unit_test_only(project.key())
- .setComponentId(resource.getId())
- .setComponentKey_unit_test_only(resource.key())
- .setStatus("OPEN").setResolution("OPEN")
- .setKee(UUID.randomUUID().toString());
- dbClient.issueDao().insert(dbSession, issue);
-
- dbSession.commit();
- assertThat(issue.getId()).isNotNull();
-
- // Find Issues since forever
- Date t0 = new Date(0);
- assertThat(dbClient.issueDao().findAfterDate(dbSession, t0)).hasSize(1);
-
- // Should not find any new issues
- Date t1 = new Date();
- assertThat(dbClient.issueDao().findAfterDate(dbSession, t1)).hasSize(0);
-
- // Should synchronise
- tester.clearIndexes();
- assertThat(indexClient.get(IssueIndex.class).countAll()).isEqualTo(0);
- tester.get(Platform.class).executeStartupTasks();
- assertThat(indexClient.get(IssueIndex.class).countAll()).isEqualTo(1);
- }
-
- @Test
- public void issue_authorization_on_group() throws Exception {
- SearchClient searchClient = tester.get(SearchClient.class);
- // createIssuePermissionIndex(searchClient);
- createIssueAuthorizationIndex(searchClient);
-
- RuleDto rule = RuleTesting.newXooX1();
- tester.get(RuleDao.class).insert(dbSession, rule);
-
- ComponentDto project1 = addComponent(1L, 1L, "SonarQube :: Server");
- ComponentDto file1 = addComponent(2L, 1L, "IssueAction.java");
- addIssue(rule, project1, file1);
- addIssueAuthorization(searchClient, project1, null, newArrayList("user")).get();
-
- ComponentDto project2 = addComponent(10L, 10L, "SonarQube :: Core");
- ComponentDto file2 = addComponent(11L, 10L, "IssueDao.java");
- addIssue(rule, project2, file2);
- addIssueAuthorization(searchClient, project2, null, newArrayList("reviewer")).get();
-
- ComponentDto project3 = addComponent(20L, 20L, "SonarQube :: WS");
- ComponentDto file3 = addComponent(21L, 20L, "IssueWS.java");
- addIssue(rule, project3, file3);
- addIssueAuthorization(searchClient, project3, null, newArrayList("user", "reviewer")).get();
-
- dbSession.commit();
-
- assertThat(searchIssueWithAuthorization(searchClient, "julien", "user", "reviewer").getHits().getTotalHits()).isEqualTo(3); // ok
- assertThat(searchIssueWithAuthorization(searchClient, "julien", "user").getHits().getTotalHits()).isEqualTo(2); // ko -> 1
- assertThat(searchIssueWithAuthorization(searchClient, "julien", "reviewer").getHits().getTotalHits()).isEqualTo(2); // ko -> 1
- assertThat(searchIssueWithAuthorization(searchClient, "julien", "unknown").getHits().getTotalHits()).isEqualTo(0);
- }
-
- @Test
- public void issue_authorization_on_user() throws Exception {
- SearchClient searchClient = tester.get(SearchClient.class);
- // createIssuePermissionIndex(searchClient);
- createIssueAuthorizationIndex(searchClient);
-
- RuleDto rule = RuleTesting.newXooX1();
- tester.get(RuleDao.class).insert(dbSession, rule);
-
- ComponentDto project = addComponent(1L, 1L, "SonarQube");
- ComponentDto file = addComponent(2L, 1L, "IssueAction.java");
- addIssue(rule, project, file);
- addIssueAuthorization(searchClient, project, newArrayList("julien"), null).get();
-
- dbSession.commit();
-
- // The issue is visible for user julien
- assertThat(searchIssueWithAuthorization(searchClient, "julien", "user").getHits().getTotalHits()).isEqualTo(1);
- // The issue is not visible for user simon
- assertThat(searchIssueWithAuthorization(searchClient, "simon", "user").getHits().getTotalHits()).isEqualTo(0);
- }
-
- @Test
- public void issue_authorization_with_a_lot_of_issues() throws Exception {
- SearchClient searchClient = tester.get(SearchClient.class);
- // createIssuePermissionIndex(searchClient);
- createIssueAuthorizationIndex(searchClient);
-
- RuleDto rule = RuleTesting.newXooX1();
- tester.get(RuleDao.class).insert(dbSession, rule);
-
- int nbProject = 10;
- int nbUser = 5;
- int componentPerProject = 5;
-
- Long projectId = 1L;
- Long componentId = 1L;
-
- List<String> users = newArrayList();
- for (int u = 0; u < nbUser; u++) {
- users.add("user-" + u);
- }
-
- BulkRequestBuilder bulkRequestBuilder = new BulkRequestBuilder(searchClient).setRefresh(true);
- for (int p = 0; p < nbProject; p++) {
- ComponentDto project = addComponent(projectId, projectId, "Project-" + projectId.toString());
-
- List<String> groups = newArrayList();
- groups.add("anyone");
- if (p % 2 == 0) {
- groups.add("user");
- }
-
- bulkRequestBuilder.add(addIssueAuthorization(searchClient, project, users, groups, false));
- for (int c = 0; c < componentPerProject; c++) {
- ComponentDto file = addComponent(componentId, projectId, "Component-" + componentId.toString());
- addIssue(rule, project, file);
- componentId++;
- }
- projectId++;
-
- if (bulkRequestBuilder.numberOfActions() == nbProject) {
- bulkRequestBuilder.get();
- dbSession.commit();
- }
- }
- bulkRequestBuilder.setRefresh(true).get();
- dbSession.commit();
-
- // All issues are visible by group anyone
- assertThat(searchIssueWithAuthorization(searchClient, "", "anyone").getHits().getTotalHits()).isEqualTo(nbProject * componentPerProject);
- // Half of issues are visible by group user
- assertThat(searchIssueWithAuthorization(searchClient, "", "user").getHits().getTotalHits()).isEqualTo(nbProject * componentPerProject / 2);
- // user-1 should see all issues
- assertThat(searchIssueWithAuthorization(searchClient, "user-1", "").getHits().getTotalHits()).isEqualTo(nbProject * componentPerProject);
-
-// Thread.sleep(Integer.MAX_VALUE);
- }
-
- private SearchResponse searchIssueWithAuthorization(SearchClient searchClient, String user, String... groups) {
- BoolFilterBuilder fb = FilterBuilders.boolFilter();
-
- OrFilterBuilder or = FilterBuilders.orFilter(FilterBuilders.termFilter("users", user));
- for (String group : groups) {
- or.add(FilterBuilders.termFilter("groups", group));
- }
- fb.must(FilterBuilders.termFilter("permission", "read"), or).cache(true);
- // fb.must(FilterBuilders.termFilter("permission", "read"), or);
-
- SearchRequestBuilder request = searchClient.prepareSearch(IndexDefinition.ISSUES.getIndexName()).setTypes(IndexDefinition.ISSUES.getIndexType())
- .setQuery(
- QueryBuilders.filteredQuery(
- QueryBuilders.matchAllQuery(),
- FilterBuilders.hasParentFilter(IndexDefinition.ISSUES_PROJECT.getIndexType(),
- QueryBuilders.filteredQuery(
- QueryBuilders.matchAllQuery(), fb)
- )
- )
- )
- .setSize(Integer.MAX_VALUE);
-
- return searchClient.execute(request);
- }
-
- private ComponentDto addComponent(Long id, Long projectId, String key) {
- ComponentDto project = new ComponentDto()
- .setId(id)
- .setProjectId(projectId)
- .setKey(key);
- tester.get(ComponentDao.class).insert(dbSession, project);
- return project;
- }
-
- private IssueDto addIssue(RuleDto rule, ComponentDto project, ComponentDto file) {
- IssueDto issue = new IssueDto()
- .setRuleId(rule.getId())
- .setRootComponentKey_unit_test_only(project.key())
- .setRootComponentId(project.getId())
- .setComponentKey_unit_test_only(file.key())
- .setComponentId(file.getId())
- .setStatus("OPEN").setResolution("OPEN")
- .setKee(UUID.randomUUID().toString());
- dbClient.issueDao().insert(dbSession, issue);
- return issue;
- }
-
- private IndexRequestBuilder addIssueAuthorization(final SearchClient searchClient, ComponentDto project, List<String> users, List<String> groups) {
- return addIssueAuthorization(searchClient, project, users, groups, true);
- }
-
- private IndexRequestBuilder addIssueAuthorization(final SearchClient searchClient, ComponentDto project, List<String> users, List<String> groups, boolean refresh) {
- Map<String, Object> permissionSource = newHashMap();
- permissionSource.put("_parent", project.key());
- permissionSource.put("permission", "read");
- permissionSource.put("project", project.key());
- if (users != null) {
- permissionSource.put("users", users);
- }
- if (groups != null) {
- permissionSource.put("groups", groups);
- }
-
- return searchClient.prepareIndex(IndexDefinition.ISSUES_PROJECT.getIndexName(), IndexDefinition.ISSUES_PROJECT.getIndexType())
- .setId(project.key())
- .setSource(permissionSource)
- .setRefresh(refresh);
- }
-
- private BaseIndex createIssueAuthorizationIndex(final SearchClient searchClient) {
- BaseIndex baseIndex = new BaseIndex(
- IndexDefinition.createFor(IndexDefinition.ISSUES_PROJECT.getIndexName(), IndexDefinition.ISSUES_PROJECT.getIndexType()),
- null, searchClient) {
- @Override
- protected String getKeyValue(Serializable key) {
- return null;
- }
-
- @Override
- protected org.elasticsearch.common.settings.Settings getIndexSettings() throws IOException {
- return ImmutableSettings.builder().build();
- }
-
- @Override
- protected Map mapProperties() {
- Map<String, Object> mapping = new HashMap<String, Object>();
- mapping.put("project", mapStringField());
- mapping.put("permission", mapStringField());
- mapping.put("groups", mapStringField());
- mapping.put("users", mapStringField());
- return mapping;
- }
-
- protected Map mapStringField() {
- Map<String, Object> mapping = new HashMap<String, Object>();
- mapping.put("type", "string");
- mapping.put("index", "analyzed");
- mapping.put("index_analyzer", "keyword");
- mapping.put("search_analyzer", "whitespace");
- return mapping;
- }
-
- @Override
- protected Map mapKey() {
- return Collections.emptyMap();
- }
-
- @Override
- public Object toDoc(Map fields) {
- return null;
- }
- };
- baseIndex.start();
- return baseIndex;
- }
-
-}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.core.issue.db;
+
+import org.sonar.core.persistence.Dto;
+
+import java.io.Serializable;
+import java.util.List;
+
+public final class IssueAuthorizationDto extends Dto<String> implements Serializable {
+
+ private String project;
+ private String permission;
+ private List<String> groups;
+ private List<String> users;
+
+ @Override
+ public String getKey() {
+ return null;
+ }
+
+ public String getProject() {
+ return project;
+ }
+
+ public IssueAuthorizationDto setProject(String project) {
+ this.project = project;
+ return this;
+ }
+
+ public String getPermission() {
+ return permission;
+ }
+
+ public IssueAuthorizationDto setPermission(String permission) {
+ this.permission = permission;
+ return this;
+ }
+
+ public List<String> getGroups() {
+ return groups;
+ }
+
+ public IssueAuthorizationDto setGroups(List<String> groups) {
+ this.groups = groups;
+ return this;
+ }
+
+ public List<String> getUsers() {
+ return users;
+ }
+
+ public IssueAuthorizationDto setUsers(List<String> users) {
+ this.users = users;
+ return this;
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.core.issue.db;
+
+public interface IssueAuthorizationMapper {
+
+ IssueAuthorizationDto selectByKey(String key);
+
+}
loadAlias(conf, "Measure", MeasureDto.class);
loadAlias(conf, "Metric", MetricDto.class);
loadAlias(conf, "Issue", IssueDto.class);
+ loadAlias(conf, "IssueAuthorization", IssueAuthorizationDto.class);
loadAlias(conf, "IssueChange", IssueChangeDto.class);
loadAlias(conf, "IssueFilter", IssueFilterDto.class);
loadAlias(conf, "IssueFilterFavourite", IssueFilterFavouriteDto.class);
loadMapper(conf, "org.sonar.core.permission.PermissionMapper");
Class<?>[] mappers = {ActivityMapper.class, ActiveDashboardMapper.class, AuthorMapper.class, DashboardMapper.class,
DependencyMapper.class, DuplicationMapper.class, GraphDtoMapper.class,
- IssueMapper.class, IssueStatsMapper.class, IssueChangeMapper.class, IssueFilterMapper.class, IssueFilterFavouriteMapper.class,
+ IssueMapper.class, IssueAuthorizationMapper.class, IssueStatsMapper.class, IssueChangeMapper.class, IssueFilterMapper.class, IssueFilterFavouriteMapper.class,
LoadedTemplateMapper.class, MeasureFilterMapper.class, Migration44Mapper.class, PermissionTemplateMapper.class, PropertiesMapper.class, PurgeMapper.class,
ResourceKeyUpdaterMapper.class, ResourceIndexerMapper.class, ResourceSnapshotMapper.class, RoleMapper.class, RuleMapper.class,
SchemaMigrationMapper.class, SemaphoreMapper.class, UserMapper.class, WidgetMapper.class, WidgetPropertyMapper.class,
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mappei.dtd">
+
+<mapper namespace="org.sonar.core.issue.db.IssueAuthorizationMapper">
+
+ <select id="selectByKey" parameterType="String" resultType="IssueAuthorization">
+ select *
+ from issues i
+ inner join rules r on r.id=i.rule_id
+ inner join projects p on p.id=i.component_id
+ inner join projects root on root.id=i.root_component_id
+ where i.kee=#{kee}
+ </select>
+
+</mapper>
+