This indexer will also be used to feed the authorization type of projectmeasures index
import org.sonar.server.debt.DebtRulesXMLImporter;
import org.sonar.server.event.NewAlerts;
import org.sonar.server.issue.IssueUpdater;
-import org.sonar.server.issue.index.IssueAuthorizationIndexer;
import org.sonar.server.issue.index.IssueIndex;
import org.sonar.server.issue.index.IssueIndexer;
import org.sonar.server.issue.notification.ChangesOnMyIssueNotificationDispatcher;
import org.sonar.server.permission.PermissionService;
import org.sonar.server.permission.PermissionUpdater;
import org.sonar.server.permission.UserPermissionChanger;
+import org.sonar.server.permission.index.AuthorizationIndexer;
import org.sonar.server.platform.DatabaseServerCompatibility;
import org.sonar.server.platform.DefaultServerUpgradeStatus;
import org.sonar.server.platform.ServerFileSystemImpl;
// issues
IssueIndexer.class,
- IssueAuthorizationIndexer.class,
+ AuthorizationIndexer.class,
IssueUpdater.class, // used in Web Services and CE's DebtCalculator
FunctionExecutor.class, // used by IssueWorkflow
IssueWorkflow.class, // used in Web Services and CE's DebtCalculator
import org.sonar.db.DbSession;
import org.sonar.db.MyBatis;
import org.sonar.db.component.ComponentDto;
-import org.sonar.server.issue.index.IssueAuthorizationIndexer;
import org.sonar.server.issue.index.IssueIndexer;
+import org.sonar.server.permission.index.AuthorizationIndexer;
import org.sonar.server.component.es.ProjectMeasuresIndexer;
import org.sonar.server.test.index.TestIndexer;
public class ComponentCleanerService {
private final DbClient dbClient;
- private final IssueAuthorizationIndexer issueAuthorizationIndexer;
+ private final AuthorizationIndexer issueAuthorizationIndexer;
private final IssueIndexer issueIndexer;
private final TestIndexer testIndexer;
private final ProjectMeasuresIndexer projectMeasuresIndexer;
private final ResourceTypes resourceTypes;
private final ComponentFinder componentFinder;
- public ComponentCleanerService(DbClient dbClient, IssueAuthorizationIndexer issueAuthorizationIndexer, IssueIndexer issueIndexer,
+ public ComponentCleanerService(DbClient dbClient, AuthorizationIndexer issueAuthorizationIndexer, IssueIndexer issueIndexer,
TestIndexer testIndexer, ProjectMeasuresIndexer projectMeasuresIndexer, ResourceTypes resourceTypes, ComponentFinder componentFinder) {
this.dbClient = dbClient;
this.issueAuthorizationIndexer = issueAuthorizationIndexer;
import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder;
import org.sonar.server.computation.task.projectanalysis.component.TypeAwareVisitorAdapter;
import org.sonar.server.computation.task.step.ComputationStep;
-import org.sonar.server.issue.index.IssueAuthorizationIndexer;
+import org.sonar.server.permission.index.AuthorizationIndexer;
import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.PROJECT;
import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.VIEW;
private final DbClient dbClient;
private final DbIdsRepository dbIdsRepository;
- private final IssueAuthorizationIndexer indexer;
+ private final AuthorizationIndexer indexer;
private final PermissionRepository permissionRepository;
private final TreeRootHolder treeRootHolder;
- public ApplyPermissionsStep(DbClient dbClient, DbIdsRepository dbIdsRepository, IssueAuthorizationIndexer indexer, PermissionRepository permissionRepository,
- TreeRootHolder treeRootHolder) {
+ public ApplyPermissionsStep(DbClient dbClient, DbIdsRepository dbIdsRepository, AuthorizationIndexer indexer, PermissionRepository permissionRepository,
+ TreeRootHolder treeRootHolder) {
this.dbClient = dbClient;
this.dbIdsRepository = dbIdsRepository;
this.indexer = indexer;
import org.sonar.api.config.Settings;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
-import org.sonar.server.issue.index.IssueAuthorizationIndexer;
import org.sonar.server.issue.index.IssueIndexer;
+import org.sonar.server.permission.index.AuthorizationIndexer;
import org.sonar.server.component.es.ProjectMeasuresIndexer;
import org.sonar.server.test.index.TestIndexer;
import org.sonar.server.user.index.UserIndexer;
private static final Logger LOG = Loggers.get(IndexerStartupTask.class);
private final TestIndexer testIndexer;
- private final IssueAuthorizationIndexer issueAuthorizationIndexer;
+ private final AuthorizationIndexer issueAuthorizationIndexer;
private final IssueIndexer issueIndexer;
private final UserIndexer userIndexer;
private final ViewIndexer viewIndexer;
/**
* Limitation - {@link org.sonar.server.es.BaseIndexer} are not injected through an array or a collection
- * because we need {@link org.sonar.server.issue.index.IssueAuthorizationIndexer} to be executed before
+ * because we need {@link AuthorizationIndexer} to be executed before
* {@link org.sonar.server.issue.index.IssueIndexer}
*/
- public IndexerStartupTask(TestIndexer testIndexer, IssueAuthorizationIndexer issueAuthorizationIndexer, IssueIndexer issueIndexer,
- UserIndexer userIndexer, ViewIndexer viewIndexer, ProjectMeasuresIndexer projectMeasuresIndexer,
- Settings settings) {
+ public IndexerStartupTask(TestIndexer testIndexer, AuthorizationIndexer issueAuthorizationIndexer, IssueIndexer issueIndexer,
+ UserIndexer userIndexer, ViewIndexer viewIndexer, ProjectMeasuresIndexer projectMeasuresIndexer,
+ Settings settings) {
this.testIndexer = testIndexer;
this.issueAuthorizationIndexer = issueAuthorizationIndexer;
this.issueIndexer = issueIndexer;
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.issue.index;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import org.apache.commons.dbutils.DbUtils;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-
-/**
- * No streaming because of union of joins -> no need to use ResultSetIterator
- */
-public class IssueAuthorizationDao {
-
- public static final class Dto {
- private final String projectUuid;
- private final long updatedAt;
- private final List<String> users = Lists.newArrayList();
- private final List<String> groups = Lists.newArrayList();
-
- public Dto(String projectUuid, long updatedAt) {
- this.projectUuid = projectUuid;
- this.updatedAt = updatedAt;
- }
-
- public String getProjectUuid() {
- return projectUuid;
- }
-
- public long getUpdatedAt() {
- return updatedAt;
- }
-
- public List<String> getUsers() {
- return users;
- }
-
- public Dto addUser(String s) {
- users.add(s);
- return this;
- }
-
- public Dto addGroup(String s) {
- groups.add(s);
- return this;
- }
-
- public List<String> getGroups() {
- return groups;
- }
- }
-
- private static final String SQL_TEMPLATE =
- "SELECT " +
- " project_authorization.project as project, " +
- " project_authorization.login as login, " +
- " project_authorization.permission_group as permission_group, " +
- " project_authorization.updated_at as updated_at " +
- "FROM ( " +
-
- // project is returned when no authorization
- " SELECT " +
- " projects.uuid AS project, " +
- " projects.authorization_updated_at AS updated_at, " +
- " NULL AS login, " +
- " NULL AS permission_group " +
- " FROM projects " +
- " WHERE " +
- " projects.qualifier = 'TRK' " +
- " AND projects.copy_component_uuid is NULL " +
- " {dateCondition} " +
- " UNION " +
-
- // users
-
- " SELECT " +
- " projects.uuid AS project, " +
- " projects.authorization_updated_at AS updated_at, " +
- " users.login AS login, " +
- " NULL AS permission_group " +
- " FROM projects " +
- " INNER JOIN user_roles ON user_roles.resource_id = projects.id AND user_roles.role = 'user' " +
- " INNER JOIN users ON users.id = user_roles.user_id " +
- " WHERE " +
- " projects.qualifier = 'TRK' " +
- " AND projects.copy_component_uuid is NULL " +
- " {dateCondition} " +
- " UNION " +
-
- // groups without Anyone
-
- " SELECT " +
- " projects.uuid AS project, " +
- " projects.authorization_updated_at AS updated_at, " +
- " NULL AS login, " +
- " groups.name AS permission_group " +
- " FROM projects " +
- " INNER JOIN group_roles ON group_roles.resource_id = projects.id AND group_roles.role = 'user' " +
- " INNER JOIN groups ON groups.id = group_roles.group_id " +
- " WHERE " +
- " projects.qualifier = 'TRK' " +
- " AND projects.copy_component_uuid is NULL " +
- " {dateCondition} " +
- " AND group_id IS NOT NULL " +
- " UNION " +
-
- // Anyone groups
-
- " SELECT " +
- " projects.uuid AS project, " +
- " projects.authorization_updated_at AS updated_at, " +
- " NULL AS login, " +
- " 'Anyone' AS permission_group " +
- " FROM projects " +
- " INNER JOIN group_roles ON group_roles.resource_id = projects.id AND group_roles.role='user' " +
- " WHERE " +
- " projects.qualifier = 'TRK' " +
- " AND projects.copy_component_uuid is NULL " +
- " {dateCondition} " +
- " AND group_roles.group_id IS NULL " +
- " ) project_authorization";
-
- Collection<Dto> selectAfterDate(DbClient dbClient, DbSession session, long afterDate) {
- try {
- Map<String, Dto> dtosByProjectUuid = Maps.newHashMap();
- PreparedStatement stmt = null;
- ResultSet rs = null;
- try {
- stmt = createStatement(dbClient, session, afterDate);
- rs = stmt.executeQuery();
- while (rs.next()) {
- processRow(rs, dtosByProjectUuid);
- }
- return dtosByProjectUuid.values();
- } finally {
- DbUtils.closeQuietly(rs);
- DbUtils.closeQuietly(stmt);
- }
- } catch (SQLException e) {
- throw new IllegalStateException("Fail to select issue authorizations after date: " + afterDate, e);
- }
- }
-
- private static PreparedStatement createStatement(DbClient dbClient, DbSession session, long afterDate) throws SQLException {
- String sql;
- if (afterDate > 0L) {
- sql = StringUtils.replace(SQL_TEMPLATE, "{dateCondition}", " AND projects.authorization_updated_at>? ");
- } else {
- sql = StringUtils.replace(SQL_TEMPLATE, "{dateCondition}", "");
- }
- PreparedStatement stmt = dbClient.getMyBatis().newScrollingSelectStatement(session, sql);
- if (afterDate > 0L) {
- for (int i = 1; i <= 4; i++) {
- stmt.setLong(i, afterDate);
- }
- }
- return stmt;
- }
-
- private static void processRow(ResultSet rs, Map<String, Dto> dtosByProjectUuid) throws SQLException {
- String projectUuid = rs.getString(1);
- String userLogin = rs.getString(2);
- String group = rs.getString(3);
-
- Dto dto = dtosByProjectUuid.get(projectUuid);
- if (dto == null) {
- long updatedAt = rs.getLong(4);
- dto = new Dto(projectUuid, updatedAt);
- dtosByProjectUuid.put(projectUuid, dto);
- }
- if (StringUtils.isNotBlank(userLogin)) {
- dto.addUser(userLogin);
- }
- if (StringUtils.isNotBlank(group)) {
- dto.addGroup(group);
- }
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.issue.index;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ImmutableMap;
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.update.UpdateRequest;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbClient;
-import org.sonar.server.es.BaseIndexer;
-import org.sonar.server.es.BulkIndexer;
-import org.sonar.server.es.EsClient;
-
-import java.util.Collection;
-import java.util.Date;
-import java.util.Map;
-
-/**
- * Manages the synchronization of index issues/authorization with authorization settings defined in database :
- * <ul>
- * <li>index the projects with recent permission changes</li>
- * <li>delete project orphans from index</li>
- * </ul>
- */
-public class IssueAuthorizationIndexer extends BaseIndexer {
-
- private final DbClient dbClient;
-
- public IssueAuthorizationIndexer(DbClient dbClient, EsClient esClient) {
- super(esClient, 0L, IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION, IssueIndexDefinition.FIELD_ISSUE_TECHNICAL_UPDATED_AT);
- this.dbClient = dbClient;
- }
-
- @Override
- protected long doIndex(long lastUpdatedAt) {
- try (DbSession dbSession = dbClient.openSession(false)) {
- // warning - do not enable large mode, else disabling of replicas
- // will impact the type "issue" which is much bigger than issueAuthorization
- BulkIndexer bulk = new BulkIndexer(esClient, IssueIndexDefinition.INDEX);
-
- IssueAuthorizationDao dao = new IssueAuthorizationDao();
- Collection<IssueAuthorizationDao.Dto> authorizations = dao.selectAfterDate(dbClient, dbSession, lastUpdatedAt);
- return doIndex(bulk, authorizations);
- }
- }
-
- @VisibleForTesting
- public void index(Collection<IssueAuthorizationDao.Dto> authorizations) {
- final BulkIndexer bulk = new BulkIndexer(esClient, IssueIndexDefinition.INDEX);
- doIndex(bulk, authorizations);
- }
-
- private long doIndex(BulkIndexer bulk, Collection<IssueAuthorizationDao.Dto> authorizations) {
- long maxDate = 0L;
- bulk.start();
- for (IssueAuthorizationDao.Dto authorization : authorizations) {
- bulk.add(newUpdateRequest(authorization));
- maxDate = Math.max(maxDate, authorization.getUpdatedAt());
- }
- bulk.stop();
- return maxDate;
- }
-
- public void deleteProject(String uuid, boolean refresh) {
- esClient
- .prepareDelete(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION, uuid)
- .setRefresh(refresh)
- .setRouting(uuid)
- .get();
- }
-
- private static ActionRequest newUpdateRequest(IssueAuthorizationDao.Dto dto) {
- Map<String, Object> doc = ImmutableMap.of(
- IssueIndexDefinition.FIELD_AUTHORIZATION_PROJECT_UUID, dto.getProjectUuid(),
- IssueIndexDefinition.FIELD_AUTHORIZATION_GROUPS, dto.getGroups(),
- IssueIndexDefinition.FIELD_AUTHORIZATION_USERS, dto.getUsers(),
- IssueIndexDefinition.FIELD_AUTHORIZATION_UPDATED_AT, new Date(dto.getUpdatedAt()));
- return new UpdateRequest(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION, dto.getProjectUuid())
- .routing(dto.getProjectUuid())
- .doc(doc)
- .upsert(doc);
- }
-}
import org.sonar.db.permission.PermissionRepository;
import org.sonar.db.permission.template.PermissionTemplateDto;
import org.sonar.server.component.ComponentFinder;
-import org.sonar.server.issue.index.IssueAuthorizationIndexer;
+import org.sonar.server.permission.index.AuthorizationIndexer;
import org.sonar.server.user.UserSession;
import static org.sonar.server.permission.PermissionPrivilegeChecker.checkProjectAdminUserByComponentKey;
private final DbClient dbClient;
private final PermissionRepository permissionRepository;
- private final IssueAuthorizationIndexer issueAuthorizationIndexer;
+ private final AuthorizationIndexer issueAuthorizationIndexer;
private final UserSession userSession;
private final ComponentFinder componentFinder;
- public PermissionService(DbClient dbClient, PermissionRepository permissionRepository, IssueAuthorizationIndexer issueAuthorizationIndexer, UserSession userSession,
- ComponentFinder componentFinder) {
+ public PermissionService(DbClient dbClient, PermissionRepository permissionRepository, AuthorizationIndexer issueAuthorizationIndexer, UserSession userSession,
+ ComponentFinder componentFinder) {
this.dbClient = dbClient;
this.permissionRepository = permissionRepository;
this.issueAuthorizationIndexer = issueAuthorizationIndexer;
import java.util.Set;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
-import org.sonar.server.issue.index.IssueAuthorizationIndexer;
+import org.sonar.server.permission.index.AuthorizationIndexer;
/**
* Add or remove global/project permissions to a group. This class
public class PermissionUpdater {
private final DbClient dbClient;
- private final IssueAuthorizationIndexer issueAuthorizationIndexer;
+ private final AuthorizationIndexer issueAuthorizationIndexer;
private final UserPermissionChanger userPermissionChanger;
private final GroupPermissionChanger groupPermissionChanger;
- public PermissionUpdater(DbClient dbClient, IssueAuthorizationIndexer issueAuthorizationIndexer,
+ public PermissionUpdater(DbClient dbClient, AuthorizationIndexer issueAuthorizationIndexer,
UserPermissionChanger userPermissionChanger, GroupPermissionChanger groupPermissionChanger) {
this.dbClient = dbClient;
this.issueAuthorizationIndexer = issueAuthorizationIndexer;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.permission.index;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.dbutils.DbUtils;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+
+/**
+ * No streaming because of union of joins -> no need to use ResultSetIterator
+ */
+public class AuthorizationDao {
+
+ public static final class Dto {
+ private final String projectUuid;
+ private final long updatedAt;
+ private final List<String> users = Lists.newArrayList();
+ private final List<String> groups = Lists.newArrayList();
+
+ public Dto(String projectUuid, long updatedAt) {
+ this.projectUuid = projectUuid;
+ this.updatedAt = updatedAt;
+ }
+
+ public String getProjectUuid() {
+ return projectUuid;
+ }
+
+ public long getUpdatedAt() {
+ return updatedAt;
+ }
+
+ public List<String> getUsers() {
+ return users;
+ }
+
+ public Dto addUser(String s) {
+ users.add(s);
+ return this;
+ }
+
+ public Dto addGroup(String s) {
+ groups.add(s);
+ return this;
+ }
+
+ public List<String> getGroups() {
+ return groups;
+ }
+ }
+
+ private static final String SQL_TEMPLATE =
+ "SELECT " +
+ " project_authorization.project as project, " +
+ " project_authorization.login as login, " +
+ " project_authorization.permission_group as permission_group, " +
+ " project_authorization.updated_at as updated_at " +
+ "FROM ( " +
+
+ // project is returned when no authorization
+ " SELECT " +
+ " projects.uuid AS project, " +
+ " projects.authorization_updated_at AS updated_at, " +
+ " NULL AS login, " +
+ " NULL AS permission_group " +
+ " FROM projects " +
+ " WHERE " +
+ " projects.qualifier = 'TRK' " +
+ " AND projects.copy_component_uuid is NULL " +
+ " {dateCondition} " +
+ " UNION " +
+
+ // users
+
+ " SELECT " +
+ " projects.uuid AS project, " +
+ " projects.authorization_updated_at AS updated_at, " +
+ " users.login AS login, " +
+ " NULL AS permission_group " +
+ " FROM projects " +
+ " INNER JOIN user_roles ON user_roles.resource_id = projects.id AND user_roles.role = 'user' " +
+ " INNER JOIN users ON users.id = user_roles.user_id " +
+ " WHERE " +
+ " projects.qualifier = 'TRK' " +
+ " AND projects.copy_component_uuid is NULL " +
+ " {dateCondition} " +
+ " UNION " +
+
+ // groups without Anyone
+
+ " SELECT " +
+ " projects.uuid AS project, " +
+ " projects.authorization_updated_at AS updated_at, " +
+ " NULL AS login, " +
+ " groups.name AS permission_group " +
+ " FROM projects " +
+ " INNER JOIN group_roles ON group_roles.resource_id = projects.id AND group_roles.role = 'user' " +
+ " INNER JOIN groups ON groups.id = group_roles.group_id " +
+ " WHERE " +
+ " projects.qualifier = 'TRK' " +
+ " AND projects.copy_component_uuid is NULL " +
+ " {dateCondition} " +
+ " AND group_id IS NOT NULL " +
+ " UNION " +
+
+ // Anyone groups
+
+ " SELECT " +
+ " projects.uuid AS project, " +
+ " projects.authorization_updated_at AS updated_at, " +
+ " NULL AS login, " +
+ " 'Anyone' AS permission_group " +
+ " FROM projects " +
+ " INNER JOIN group_roles ON group_roles.resource_id = projects.id AND group_roles.role='user' " +
+ " WHERE " +
+ " projects.qualifier = 'TRK' " +
+ " AND projects.copy_component_uuid is NULL " +
+ " {dateCondition} " +
+ " AND group_roles.group_id IS NULL " +
+ " ) project_authorization";
+
+ Collection<Dto> selectAfterDate(DbClient dbClient, DbSession session, long afterDate) {
+ try {
+ Map<String, Dto> dtosByProjectUuid = Maps.newHashMap();
+ PreparedStatement stmt = null;
+ ResultSet rs = null;
+ try {
+ stmt = createStatement(dbClient, session, afterDate);
+ rs = stmt.executeQuery();
+ while (rs.next()) {
+ processRow(rs, dtosByProjectUuid);
+ }
+ return dtosByProjectUuid.values();
+ } finally {
+ DbUtils.closeQuietly(rs);
+ DbUtils.closeQuietly(stmt);
+ }
+ } catch (SQLException e) {
+ throw new IllegalStateException("Fail to select authorizations after date: " + afterDate, e);
+ }
+ }
+
+ private static PreparedStatement createStatement(DbClient dbClient, DbSession session, long afterDate) throws SQLException {
+ String sql;
+ if (afterDate > 0L) {
+ sql = StringUtils.replace(SQL_TEMPLATE, "{dateCondition}", " AND projects.authorization_updated_at>? ");
+ } else {
+ sql = StringUtils.replace(SQL_TEMPLATE, "{dateCondition}", "");
+ }
+ PreparedStatement stmt = dbClient.getMyBatis().newScrollingSelectStatement(session, sql);
+ if (afterDate > 0L) {
+ for (int i = 1; i <= 4; i++) {
+ stmt.setLong(i, afterDate);
+ }
+ }
+ return stmt;
+ }
+
+ private static void processRow(ResultSet rs, Map<String, Dto> dtosByProjectUuid) throws SQLException {
+ String projectUuid = rs.getString(1);
+ String userLogin = rs.getString(2);
+ String group = rs.getString(3);
+
+ Dto dto = dtosByProjectUuid.get(projectUuid);
+ if (dto == null) {
+ long updatedAt = rs.getLong(4);
+ dto = new Dto(projectUuid, updatedAt);
+ dtosByProjectUuid.put(projectUuid, dto);
+ }
+ if (StringUtils.isNotBlank(userLogin)) {
+ dto.addUser(userLogin);
+ }
+ if (StringUtils.isNotBlank(group)) {
+ dto.addGroup(group);
+ }
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.permission.index;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableMap;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Map;
+import org.elasticsearch.action.ActionRequest;
+import org.elasticsearch.action.update.UpdateRequest;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.server.es.BaseIndexer;
+import org.sonar.server.es.BulkIndexer;
+import org.sonar.server.es.EsClient;
+import org.sonar.server.issue.index.IssueIndexDefinition;
+
+/**
+ * Manages the synchronization of index issues/authorization with authorization settings defined in database :
+ * <ul>
+ * <li>index the projects with recent permission changes</li>
+ * <li>delete project orphans from index</li>
+ * </ul>
+ */
+public class AuthorizationIndexer extends BaseIndexer {
+
+ private final DbClient dbClient;
+
+ public AuthorizationIndexer(DbClient dbClient, EsClient esClient) {
+ super(esClient, 0L, IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION, IssueIndexDefinition.FIELD_ISSUE_TECHNICAL_UPDATED_AT);
+ this.dbClient = dbClient;
+ }
+
+ @Override
+ protected long doIndex(long lastUpdatedAt) {
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ // warning - do not enable large mode, else disabling of replicas
+ // will impact the type "issue" which is much bigger than issueAuthorization
+ BulkIndexer bulk = new BulkIndexer(esClient, IssueIndexDefinition.INDEX);
+
+ AuthorizationDao dao = new AuthorizationDao();
+ Collection<AuthorizationDao.Dto> authorizations = dao.selectAfterDate(dbClient, dbSession, lastUpdatedAt);
+ return doIndex(bulk, authorizations);
+ }
+ }
+
+ @VisibleForTesting
+ public void index(Collection<AuthorizationDao.Dto> authorizations) {
+ final BulkIndexer bulk = new BulkIndexer(esClient, IssueIndexDefinition.INDEX);
+ doIndex(bulk, authorizations);
+ }
+
+ private long doIndex(BulkIndexer bulk, Collection<AuthorizationDao.Dto> authorizations) {
+ long maxDate = 0L;
+ bulk.start();
+ for (AuthorizationDao.Dto authorization : authorizations) {
+ bulk.add(newIssueUpdateRequest(authorization));
+ maxDate = Math.max(maxDate, authorization.getUpdatedAt());
+ }
+ bulk.stop();
+ return maxDate;
+ }
+
+ public void deleteProject(String uuid, boolean refresh) {
+ esClient
+ .prepareDelete(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION, uuid)
+ .setRefresh(refresh)
+ .setRouting(uuid)
+ .get();
+ }
+
+ private static ActionRequest newIssueUpdateRequest(AuthorizationDao.Dto dto) {
+ Map<String, Object> doc = ImmutableMap.of(
+ IssueIndexDefinition.FIELD_AUTHORIZATION_PROJECT_UUID, dto.getProjectUuid(),
+ IssueIndexDefinition.FIELD_AUTHORIZATION_GROUPS, dto.getGroups(),
+ IssueIndexDefinition.FIELD_AUTHORIZATION_USERS, dto.getUsers(),
+ IssueIndexDefinition.FIELD_AUTHORIZATION_UPDATED_AT, new Date(dto.getUpdatedAt()));
+ return new UpdateRequest(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION, dto.getProjectUuid())
+ .routing(dto.getProjectUuid())
+ .doc(doc)
+ .upsert(doc);
+ }
+}
import org.sonar.server.issue.SetTypeAction;
import org.sonar.server.issue.TransitionAction;
import org.sonar.server.issue.filter.IssueFilterWsModule;
-import org.sonar.server.issue.index.IssueAuthorizationIndexer;
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.permission.PermissionService;
import org.sonar.server.permission.PermissionUpdater;
import org.sonar.server.permission.UserPermissionChanger;
+import org.sonar.server.permission.index.AuthorizationIndexer;
import org.sonar.server.permission.ws.PermissionsWsModule;
import org.sonar.server.platform.BackendCleanup;
import org.sonar.server.platform.PersistentSettings;
// issues
IssueIndexDefinition.class,
IssueIndexer.class,
- IssueAuthorizationIndexer.class,
+ AuthorizationIndexer.class,
ServerIssueStorage.class,
IssueUpdater.class,
FunctionExecutor.class,
import org.sonar.server.es.EsTester;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.issue.IssueTesting;
-import org.sonar.server.issue.index.IssueAuthorizationDao;
-import org.sonar.server.issue.index.IssueAuthorizationIndexer;
import org.sonar.server.issue.index.IssueDoc;
import org.sonar.server.issue.index.IssueIndex;
import org.sonar.server.issue.index.IssueIndexDefinition;
import org.sonar.server.issue.index.IssueIndexer;
+import org.sonar.server.permission.index.AuthorizationDao;
+import org.sonar.server.permission.index.AuthorizationIndexer;
import org.sonar.server.platform.ServerFileSystem;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.WsTester;
private IssueIndex issueIndex;
private IssueIndexer issueIndexer;
- private IssueAuthorizationIndexer issueAuthorizationIndexer;
+ private AuthorizationIndexer issueAuthorizationIndexer;
private ServerFileSystem fs = mock(ServerFileSystem.class);
WsTester tester;
public void before() {
issueIndex = new IssueIndex(es.client(), System2.INSTANCE, userSessionRule);
issueIndexer = new IssueIndexer(null, es.client());
- issueAuthorizationIndexer = new IssueAuthorizationIndexer(null, es.client());
+ issueAuthorizationIndexer = new AuthorizationIndexer(null, es.client());
issuesAction = new IssuesAction(db.getDbClient(), issueIndex, userSessionRule, new ComponentFinder(db.getDbClient()));
tester = new WsTester(new BatchWs(new BatchIndex(fs), issuesAction));
}
private void addIssueAuthorization(String projectUuid, @Nullable String group, @Nullable String user) {
- issueAuthorizationIndexer.index(newArrayList(new IssueAuthorizationDao.Dto(projectUuid, 1).addGroup(group).addUser(user)));
+ issueAuthorizationIndexer.index(newArrayList(new AuthorizationDao.Dto(projectUuid, 1).addGroup(group).addUser(user)));
}
private void addBrowsePermissionOnComponent(String componentKey) {
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.issue.IssueTesting;
import org.sonar.server.issue.index.IssueAuthorizationDoc;
-import org.sonar.server.issue.index.IssueAuthorizationIndexer;
import org.sonar.server.issue.index.IssueIndexDefinition;
import org.sonar.server.issue.index.IssueIndexer;
+import org.sonar.server.permission.index.AuthorizationIndexer;
import org.sonar.server.component.es.ProjectMeasuresIndexDefinition;
import org.sonar.server.component.es.ProjectMeasuresIndexer;
import org.sonar.server.test.index.TestDoc;
DbClient dbClient = db.getDbClient();
DbSession dbSession = db.getSession();
- IssueAuthorizationIndexer issueAuthorizationIndexer = new IssueAuthorizationIndexer(dbClient, es.client());
+ AuthorizationIndexer issueAuthorizationIndexer = new AuthorizationIndexer(dbClient, es.client());
IssueIndexer issueIndexer = new IssueIndexer(dbClient, es.client());
TestIndexer testIndexer = new TestIndexer(dbClient, es.client());
ProjectMeasuresIndexer projectMeasuresIndexer = new ProjectMeasuresIndexer(dbClient, es.client());
import org.sonar.server.computation.task.projectanalysis.component.ViewsComponent;
import org.sonar.server.computation.task.step.ComputationStep;
import org.sonar.server.es.EsTester;
-import org.sonar.server.issue.index.IssueAuthorizationIndexer;
import org.sonar.server.issue.index.IssueIndexDefinition;
+import org.sonar.server.permission.index.AuthorizationIndexer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.db.component.ComponentTesting.newView;
private DbSession dbSession;
private DbClient dbClient = dbTester.getDbClient();
private Settings settings = new MapSettings();
- private IssueAuthorizationIndexer issueAuthorizationIndexer;
+ private AuthorizationIndexer issueAuthorizationIndexer;
private ApplyPermissionsStep step;
@Before
public void setUp() {
dbSession = dbClient.openSession(false);
- issueAuthorizationIndexer = new IssueAuthorizationIndexer(dbClient, esTester.client());
+ issueAuthorizationIndexer = new AuthorizationIndexer(dbClient, esTester.client());
step = new ApplyPermissionsStep(dbClient, dbIdsRepository, issueAuthorizationIndexer, new PermissionRepository(dbClient, settings), treeRootHolder);
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.issue.index;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.Iterables;
-import java.util.Collection;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbTester;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class IssueAuthorizationDaoTest {
-
- @Rule
- public DbTester dbTester = DbTester.create(System2.INSTANCE);
-
- private IssueAuthorizationDao dao = new IssueAuthorizationDao();
-
- @Test
- public void select_all() {
- dbTester.prepareDbUnit(getClass(), "shared.xml");
-
- Collection<IssueAuthorizationDao.Dto> dtos = dao.selectAfterDate(dbTester.getDbClient(), dbTester.getSession(), 0L);
- assertThat(dtos).hasSize(2);
-
- IssueAuthorizationDao.Dto abc = Iterables.find(dtos, new ProjectPredicate("ABC"));
- assertThat(abc.getGroups()).containsOnly("Anyone", "devs");
- assertThat(abc.getUsers()).containsOnly("user1");
- assertThat(abc.getUpdatedAt()).isNotNull();
-
- IssueAuthorizationDao.Dto def = Iterables.find(dtos, new ProjectPredicate("DEF"));
- assertThat(def.getGroups()).containsOnly("Anyone");
- assertThat(def.getUsers()).containsOnly("user1", "user2");
- assertThat(def.getUpdatedAt()).isNotNull();
- }
-
- @Test
- public void select_after_date() {
- dbTester.prepareDbUnit(getClass(), "shared.xml");
-
- Collection<IssueAuthorizationDao.Dto> dtos = dao.selectAfterDate(dbTester.getDbClient(), dbTester.getSession(), 1500000000L);
-
- // only project DEF was updated in this period
- assertThat(dtos).hasSize(1);
- IssueAuthorizationDao.Dto def = Iterables.find(dtos, new ProjectPredicate("DEF"));
- assertThat(def).isNotNull();
- assertThat(def.getGroups()).containsOnly("Anyone");
- assertThat(def.getUsers()).containsOnly("user1", "user2");
- }
-
- @Test
- public void no_authorization() {
- dbTester.prepareDbUnit(getClass(), "no_authorization.xml");
-
- Collection<IssueAuthorizationDao.Dto> dtos = dao.selectAfterDate(dbTester.getDbClient(), dbTester.getSession(), 0L);
-
- assertThat(dtos).hasSize(1);
- IssueAuthorizationDao.Dto abc = Iterables.find(dtos, new ProjectPredicate("ABC"));
- assertThat(abc.getGroups()).isEmpty();
- assertThat(abc.getUsers()).isEmpty();
- assertThat(abc.getUpdatedAt()).isNotNull();
- }
-
- private static class ProjectPredicate implements Predicate<IssueAuthorizationDao.Dto> {
-
- private final String projectUuid;
-
- ProjectPredicate(String projectUuid) {
- this.projectUuid = projectUuid;
- }
-
- @Override
- public boolean apply(IssueAuthorizationDao.Dto input) {
- return input.getProjectUuid().equals(projectUuid);
- }
-
- @Override
- public boolean equals(Object object) {
- return true;
- }
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.issue.index;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import org.elasticsearch.search.SearchHit;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.config.MapSettings;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbTester;
-import org.sonar.server.es.EsTester;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-
-public class IssueAuthorizationIndexerTest {
-
- @Rule
- public DbTester dbTester = DbTester.create(System2.INSTANCE);
-
- @Rule
- public EsTester esTester = new EsTester(new IssueIndexDefinition(new MapSettings()));
-
- @Test
- public void index_nothing() {
- IssueAuthorizationIndexer indexer = createIndexer();
- indexer.index();
-
- assertThat(esTester.countDocuments("issues", "authorization")).isZero();
- }
-
- @Test
- public void index() {
- dbTester.prepareDbUnit(getClass(), "index.xml");
-
- IssueAuthorizationIndexer indexer = createIndexer();
- indexer.doIndex(0L);
-
- List<SearchHit> docs = esTester.getDocuments("issues", "authorization");
- assertThat(docs).hasSize(1);
- SearchHit doc = docs.get(0);
- assertThat(doc.getSource().get("project")).isEqualTo("ABC");
- assertThat((Collection) doc.getSource().get("groups")).containsOnly("devs", "Anyone");
- assertThat((Collection) doc.getSource().get("users")).containsOnly("user1");
-
- // delete project
- indexer.deleteProject("ABC", true);
-
- assertThat(esTester.countDocuments("issues", "issueAuthorization")).isZero();
- }
-
- @Test
- public void do_not_fail_when_deleting_unindexed_project() {
- IssueAuthorizationIndexer indexer = createIndexer();
- indexer.deleteProject("UNKNOWN", true);
- assertThat(esTester.countDocuments("issues", "authorization")).isZero();
- }
-
- @Test
- public void delete_permissions() {
- IssueAuthorizationIndexer indexer = createIndexer();
- IssueAuthorizationDao.Dto authorization = new IssueAuthorizationDao.Dto("ABC", System.currentTimeMillis());
- authorization.addUser("guy");
- authorization.addGroup("dev");
- indexer.index(Arrays.asList(authorization));
-
- // has permissions
- assertThat(esTester.countDocuments("issues", "authorization")).isEqualTo(1);
-
- // remove permissions -> dto has no users nor groups
- authorization = new IssueAuthorizationDao.Dto("ABC", System.currentTimeMillis());
- indexer.index(Arrays.asList(authorization));
-
- List<SearchHit> docs = esTester.getDocuments("issues", "authorization");
- assertThat(docs).hasSize(1);
- assertThat((Collection)docs.get(0).sourceAsMap().get(IssueIndexDefinition.FIELD_AUTHORIZATION_USERS)).hasSize(0);
- assertThat((Collection)docs.get(0).sourceAsMap().get(IssueIndexDefinition.FIELD_AUTHORIZATION_GROUPS)).hasSize(0);
- }
-
- private IssueAuthorizationIndexer createIndexer() {
- return new IssueAuthorizationIndexer(new DbClient(dbTester.database(), dbTester.myBatis()), esTester.client());
- }
-}
import org.sonar.server.issue.IssueQuery;
import org.sonar.server.issue.IssueQuery.Builder;
import org.sonar.server.issue.IssueTesting;
+import org.sonar.server.permission.index.AuthorizationDao;
+import org.sonar.server.permission.index.AuthorizationIndexer;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.view.index.ViewIndexDefinition;
import org.sonar.server.view.index.ViewIndexer;
IssueIndex index;
IssueIndexer issueIndexer;
- IssueAuthorizationIndexer issueAuthorizationIndexer;
+ AuthorizationIndexer issueAuthorizationIndexer;
ViewIndexer viewIndexer;
@Before
public void setUp() {
issueIndexer = new IssueIndexer(null, tester.client());
- issueAuthorizationIndexer = new IssueAuthorizationIndexer(null, tester.client());
+ issueAuthorizationIndexer = new AuthorizationIndexer(null, tester.client());
viewIndexer = new ViewIndexer(null, tester.client());
System2 system = mock(System2.class);
when(system.getDefaultTimeZone()).thenReturn(TimeZone.getTimeZone("+01:00"));
}
private void addIssueAuthorization(String projectUuid, @Nullable String group, @Nullable String user) {
- issueAuthorizationIndexer.index(newArrayList(new IssueAuthorizationDao.Dto(projectUuid, 1).addGroup(group).addUser(user)));
+ issueAuthorizationIndexer.index(newArrayList(new AuthorizationDao.Dto(projectUuid, 1).addGroup(group).addUser(user)));
}
private Builder newQueryBuilder() {
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.issue.IssueQuery;
import org.sonar.server.issue.IssueTesting;
+import org.sonar.server.permission.index.AuthorizationDao;
+import org.sonar.server.permission.index.AuthorizationIndexer;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.view.index.ViewDoc;
import org.sonar.server.view.index.ViewIndexDefinition;
IssueIndex underTest;
IssueIndexer issueIndexer;
- IssueAuthorizationIndexer issueAuthorizationIndexer;
+ AuthorizationIndexer issueAuthorizationIndexer;
ViewIndexer viewIndexer;
@Before
public void setUp() {
issueIndexer = new IssueIndexer(null, tester.client());
- issueAuthorizationIndexer = new IssueAuthorizationIndexer(null, tester.client());
+ issueAuthorizationIndexer = new AuthorizationIndexer(null, tester.client());
viewIndexer = new ViewIndexer(null, tester.client());
System2 system = mock(System2.class);
when(system.getDefaultTimeZone()).thenReturn(TimeZone.getTimeZone("GMT-1:00"));
}
private void addIssueAuthorization(String projectUuid, @Nullable String group, @Nullable String user) {
- issueAuthorizationIndexer.index(newArrayList(new IssueAuthorizationDao.Dto(projectUuid, 1).addGroup(group).addUser(user)));
+ issueAuthorizationIndexer.index(newArrayList(new AuthorizationDao.Dto(projectUuid, 1).addGroup(group).addUser(user)));
}
private void indexView(String viewUuid, List<String> projects) {
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.permission.index;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import java.util.Collection;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class AuthorizationDaoTest {
+
+ @Rule
+ public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+ private AuthorizationDao dao = new AuthorizationDao();
+
+ @Test
+ public void select_all() {
+ dbTester.prepareDbUnit(getClass(), "shared.xml");
+
+ Collection<AuthorizationDao.Dto> dtos = dao.selectAfterDate(dbTester.getDbClient(), dbTester.getSession(), 0L);
+ assertThat(dtos).hasSize(2);
+
+ AuthorizationDao.Dto abc = Iterables.find(dtos, new ProjectPredicate("ABC"));
+ assertThat(abc.getGroups()).containsOnly("Anyone", "devs");
+ assertThat(abc.getUsers()).containsOnly("user1");
+ assertThat(abc.getUpdatedAt()).isNotNull();
+
+ AuthorizationDao.Dto def = Iterables.find(dtos, new ProjectPredicate("DEF"));
+ assertThat(def.getGroups()).containsOnly("Anyone");
+ assertThat(def.getUsers()).containsOnly("user1", "user2");
+ assertThat(def.getUpdatedAt()).isNotNull();
+ }
+
+ @Test
+ public void select_after_date() {
+ dbTester.prepareDbUnit(getClass(), "shared.xml");
+
+ Collection<AuthorizationDao.Dto> dtos = dao.selectAfterDate(dbTester.getDbClient(), dbTester.getSession(), 1500000000L);
+
+ // only project DEF was updated in this period
+ assertThat(dtos).hasSize(1);
+ AuthorizationDao.Dto def = Iterables.find(dtos, new ProjectPredicate("DEF"));
+ assertThat(def).isNotNull();
+ assertThat(def.getGroups()).containsOnly("Anyone");
+ assertThat(def.getUsers()).containsOnly("user1", "user2");
+ }
+
+ @Test
+ public void no_authorization() {
+ dbTester.prepareDbUnit(getClass(), "no_authorization.xml");
+
+ Collection<AuthorizationDao.Dto> dtos = dao.selectAfterDate(dbTester.getDbClient(), dbTester.getSession(), 0L);
+
+ assertThat(dtos).hasSize(1);
+ AuthorizationDao.Dto abc = Iterables.find(dtos, new ProjectPredicate("ABC"));
+ assertThat(abc.getGroups()).isEmpty();
+ assertThat(abc.getUsers()).isEmpty();
+ assertThat(abc.getUpdatedAt()).isNotNull();
+ }
+
+ private static class ProjectPredicate implements Predicate<AuthorizationDao.Dto> {
+
+ private final String projectUuid;
+
+ ProjectPredicate(String projectUuid) {
+ this.projectUuid = projectUuid;
+ }
+
+ @Override
+ public boolean apply(AuthorizationDao.Dto input) {
+ return input.getProjectUuid().equals(projectUuid);
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ return true;
+ }
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.permission.index;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import org.elasticsearch.search.SearchHit;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.config.MapSettings;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbTester;
+import org.sonar.server.es.EsTester;
+import org.sonar.server.issue.index.IssueIndexDefinition;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+
+public class AuthorizationIndexerTest {
+
+ @Rule
+ public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+ @Rule
+ public EsTester esTester = new EsTester(new IssueIndexDefinition(new MapSettings()));
+
+ @Test
+ public void index_nothing() {
+ AuthorizationIndexer indexer = createIndexer();
+ indexer.index();
+
+ assertThat(esTester.countDocuments("issues", "authorization")).isZero();
+ }
+
+ @Test
+ public void index() {
+ dbTester.prepareDbUnit(getClass(), "index.xml");
+
+ AuthorizationIndexer indexer = createIndexer();
+ indexer.doIndex(0L);
+
+ List<SearchHit> docs = esTester.getDocuments("issues", "authorization");
+ assertThat(docs).hasSize(1);
+ SearchHit doc = docs.get(0);
+ assertThat(doc.getSource().get("project")).isEqualTo("ABC");
+ assertThat((Collection) doc.getSource().get("groups")).containsOnly("devs", "Anyone");
+ assertThat((Collection) doc.getSource().get("users")).containsOnly("user1");
+
+ // delete project
+ indexer.deleteProject("ABC", true);
+
+ assertThat(esTester.countDocuments("issues", "issueAuthorization")).isZero();
+ }
+
+ @Test
+ public void do_not_fail_when_deleting_unindexed_project() {
+ AuthorizationIndexer indexer = createIndexer();
+ indexer.deleteProject("UNKNOWN", true);
+ assertThat(esTester.countDocuments("issues", "authorization")).isZero();
+ }
+
+ @Test
+ public void delete_permissions() {
+ AuthorizationIndexer indexer = createIndexer();
+ AuthorizationDao.Dto authorization = new AuthorizationDao.Dto("ABC", System.currentTimeMillis());
+ authorization.addUser("guy");
+ authorization.addGroup("dev");
+ indexer.index(Arrays.asList(authorization));
+
+ // has permissions
+ assertThat(esTester.countDocuments("issues", "authorization")).isEqualTo(1);
+
+ // remove permissions -> dto has no users nor groups
+ authorization = new AuthorizationDao.Dto("ABC", System.currentTimeMillis());
+ indexer.index(Arrays.asList(authorization));
+
+ List<SearchHit> docs = esTester.getDocuments("issues", "authorization");
+ assertThat(docs).hasSize(1);
+ assertThat((Collection)docs.get(0).sourceAsMap().get(IssueIndexDefinition.FIELD_AUTHORIZATION_USERS)).hasSize(0);
+ assertThat((Collection)docs.get(0).sourceAsMap().get(IssueIndexDefinition.FIELD_AUTHORIZATION_GROUPS)).hasSize(0);
+ }
+
+ private AuthorizationIndexer createIndexer() {
+ return new AuthorizationIndexer(new DbClient(dbTester.database(), dbTester.myBatis()), esTester.client());
+ }
+}
import org.sonar.db.permission.template.PermissionTemplateDto;
import org.sonar.db.permission.template.PermissionTemplateTesting;
import org.sonar.server.component.ComponentFinder;
-import org.sonar.server.issue.index.IssueAuthorizationIndexer;
import org.sonar.server.organization.TestDefaultOrganizationProvider;
import org.sonar.server.permission.GroupPermissionChanger;
import org.sonar.server.permission.PermissionUpdater;
import org.sonar.server.permission.UserPermissionChanger;
+import org.sonar.server.permission.index.AuthorizationIndexer;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.usergroups.ws.GroupWsSupport;
import org.sonar.server.ws.WsTester;
protected PermissionUpdater newPermissionUpdater() {
return new PermissionUpdater(db.getDbClient(),
- mock(IssueAuthorizationIndexer.class),
+ mock(AuthorizationIndexer.class),
new UserPermissionChanger(db.getDbClient(), defaultOrganizationProvider),
new GroupPermissionChanger(db.getDbClient(), defaultOrganizationProvider));
}
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.issue.index.IssueAuthorizationIndexer;
import org.sonar.server.permission.PermissionService;
+import org.sonar.server.permission.index.AuthorizationIndexer;
import org.sonar.server.permission.ws.BasePermissionWsTest;
import org.sonar.server.ws.WsTester;
private ComponentDto project;
private PermissionTemplateDto template1;
private PermissionTemplateDto template2;
- private IssueAuthorizationIndexer issueAuthorizationIndexer = mock(IssueAuthorizationIndexer.class);
+ private AuthorizationIndexer issueAuthorizationIndexer = mock(AuthorizationIndexer.class);
@Override
protected ApplyTemplateAction buildWsAction() {
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.i18n.I18nRule;
-import org.sonar.server.issue.index.IssueAuthorizationIndexer;
import org.sonar.server.permission.PermissionService;
+import org.sonar.server.permission.index.AuthorizationIndexer;
import org.sonar.server.permission.ws.BasePermissionWsTest;
import org.sonar.server.ws.WsTester;
private GroupDto group2;
private PermissionTemplateDto template1;
private PermissionTemplateDto template2;
- private IssueAuthorizationIndexer issueAuthorizationIndexer = mock(IssueAuthorizationIndexer.class);
+ private AuthorizationIndexer issueAuthorizationIndexer = mock(AuthorizationIndexer.class);
@Override
protected BulkApplyTemplateAction buildWsAction() {
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.issue.IssueTesting;
import org.sonar.server.issue.index.IssueAuthorizationDoc;
-import org.sonar.server.issue.index.IssueAuthorizationIndexer;
import org.sonar.server.issue.index.IssueIndexDefinition;
import org.sonar.server.issue.index.IssueIndexer;
+import org.sonar.server.permission.index.AuthorizationIndexer;
import org.sonar.server.component.es.ProjectMeasuresIndexer;
import org.sonar.server.test.index.TestDoc;
import org.sonar.server.test.index.TestIndexDefinition;
ws = new WsTester(new ProjectsWs(
new BulkDeleteAction(
new ComponentCleanerService(dbClient,
- new IssueAuthorizationIndexer(dbClient, es.client()),
+ new AuthorizationIndexer(dbClient, es.client()),
new IssueIndexer(dbClient, es.client()),
new TestIndexer(dbClient, es.client()),
new ProjectMeasuresIndexer(dbClient, es.client()),
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.issue.IssueTesting;
import org.sonar.server.issue.index.IssueAuthorizationDoc;
-import org.sonar.server.issue.index.IssueAuthorizationIndexer;
import org.sonar.server.issue.index.IssueIndexDefinition;
import org.sonar.server.issue.index.IssueIndexer;
+import org.sonar.server.permission.index.AuthorizationIndexer;
import org.sonar.server.component.es.ProjectMeasuresIndexer;
import org.sonar.server.test.index.TestDoc;
import org.sonar.server.test.index.TestIndexDefinition;
new DeleteAction(
new ComponentCleanerService(
dbClient,
- new IssueAuthorizationIndexer(dbClient, es.client()),
+ new AuthorizationIndexer(dbClient, es.client()),
new IssueIndexer(dbClient, es.client()),
new TestIndexer(dbClient, es.client()),
new ProjectMeasuresIndexer(dbClient, es.client()),
import org.sonar.server.es.SearchResult;
import org.sonar.server.issue.IssueQuery;
import org.sonar.server.issue.IssueTesting;
-import org.sonar.server.issue.index.IssueAuthorizationIndexer;
import org.sonar.server.issue.index.IssueDoc;
import org.sonar.server.issue.index.IssueIndex;
import org.sonar.server.issue.index.IssueIndexDefinition;
import org.sonar.server.issue.index.IssueIndexer;
+import org.sonar.server.permission.index.AuthorizationIndexer;
import org.sonar.server.tester.UserSessionRule;
import static com.google.common.collect.Lists.newArrayList;
public void clear_views_lookup_cache_on_index_view_uuid() {
IssueIndex issueIndex = new IssueIndex(esTester.client(), System2.INSTANCE, userSessionRule);
IssueIndexer issueIndexer = new IssueIndexer(dbClient, esTester.client());
- IssueAuthorizationIndexer issueAuthorizationIndexer = new IssueAuthorizationIndexer(dbClient, esTester.client());
+ AuthorizationIndexer issueAuthorizationIndexer = new AuthorizationIndexer(dbClient, esTester.client());
String viewUuid = "ABCD";
+++ /dev/null
-<dataset>
-
- <projects uuid="ABC"
- uuid_path="NOT_USED"
- project_uuid="ABC"
- module_uuid="[null]"
- module_uuid_path="."
- root_uuid="ABC"
- scope="PRJ"
- qualifier="TRK"
- kee="org.struts:struts"
- name="Struts"
- description="the description"
- long_name="Apache Struts"
- enabled="[true]"
- language="java"
- path="[null]"
- authorization_updated_at="123456789"
- id="1"/>
-
- <!-- no authorizations project ABC. -->
-
- <users id="10"
- login="user1"
- name="User 1"
- email="user1@company.net"
- active="[true]"
- is_root="[false]"/>
- <groups id="100"
- name="devs"
- organization_uuid="org1"/>
-
- <user_roles id="1"
- user_id="10"
- resource_id="2"
- role="user"
- organization_uuid="org1"/>
- <group_roles id="1"
- group_id="100"
- resource_id="2"
- role="admin"
- organization_uuid="org1"/>
-</dataset>
+++ /dev/null
-<dataset>
-
- <projects uuid="ABC"
- uuid_path="NOT_USED"
- project_uuid="ABC"
- module_uuid="[null]"
- module_uuid_path="."
- root_uuid="ABC"
- scope="PRJ"
- qualifier="TRK"
- kee="org.struts:struts"
- name="Struts"
- description="the description"
- long_name="Apache Struts"
- enabled="[true]"
- language="java"
- path="[null]"
- authorization_updated_at="1000000000"
- id="1"/>
-
- <projects uuid="DEF"
- uuid_path="NOT_USED"
- project_uuid="DEF"
- module_uuid="[null]"
- module_uuid_path="."
- root_uuid="ABC"
- scope="PRJ"
- qualifier="TRK"
- kee="org.sonar.sample"
- name="Sample"
- description="the description"
- long_name="Sample"
- enabled="[true]"
- language="java"
- path="[null]"
- authorization_updated_at="2000000000"
- id="2"/>
-
- <!-- user1 can access both projects -->
- <users id="10"
- login="user1"
- name="User 1"
- email="user1@company.net"
- active="[true]"
- is_root="[false]"/>
- <user_roles id="1"
- user_id="10"
- resource_id="1"
- role="user"
- organization_uuid="org1"/>
- <user_roles id="2"
- user_id="10"
- resource_id="1"
- role="admin"
- organization_uuid="org1"/>
- <user_roles id="3"
- user_id="10"
- resource_id="2"
- role="user"
- organization_uuid="org1"/>
-
- <!-- group devs has user access on ABC only -->
- <groups id="100"
- name="devs"
- organization_uuid="org1"/>
- <group_roles id="1"
- group_id="100"
- resource_id="1"
- role="user"
- organization_uuid="org1"/>
- <group_roles id="2"
- group_id="100"
- resource_id="1"
- role="admin"
- organization_uuid="org1"/>
-
- <!-- Anyone group has user access on both projects -->
- <group_roles id="4"
- group_id="[null]"
- resource_id="1"
- role="user"
- organization_uuid="org1"/>
- <group_roles id="5"
- group_id="[null]"
- resource_id="1"
- role="admin"
- organization_uuid="org1"/>
- <group_roles id="6"
- group_id="[null]"
- resource_id="2"
- role="user"
- organization_uuid="org1"/>
-
- <!-- user2 has user access on DEF only -->
- <users id="11"
- login="user2"
- name="User 2"
- email="user2@company.net"
- active="[true]"
- is_root="[false]"/>
- <user_roles id="4"
- user_id="11"
- resource_id="1"
- role="admin"
- organization_uuid="org1"/>
- <user_roles id="5"
- user_id="11"
- resource_id="2"
- role="user"
- organization_uuid="org1"/>
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <projects uuid="ABC"
- uuid_path="NOT_USED"
- project_uuid="ABC"
- module_uuid="[null]"
- module_uuid_path="."
- root_uuid="ABC"
- scope="PRJ"
- qualifier="TRK"
- kee="org.struts:struts"
- name="Struts"
- description="the description"
- long_name="Apache Struts"
- enabled="[true]"
- language="java"
- path="[null]"
- authorization_updated_at="123456789"
- id="1"/>
-
- <users id="10"
- login="user1"
- name="User 1"
- email="user1@company.net"
- active="[true]"
- is_root="[false]"/>
- <user_roles id="1"
- user_id="10"
- resource_id="1"
- role="user"
- organization_uuid="org1"/>
- <user_roles id="2"
- user_id="10"
- resource_id="1"
- role="admin"
- organization_uuid="org1"/>
- <user_roles id="3"
- user_id="10"
- resource_id="2"
- role="admin"
- organization_uuid="org1"/>
-
- <groups id="100"
- name="devs"
- organization_uuid="org1"/>
- <group_roles id="1"
- group_id="100"
- resource_id="1"
- role="user"
- organization_uuid="org1"/>
- <group_roles id="2"
- group_id="100"
- resource_id="2"
- role="admin"
- organization_uuid="org1"/>
-
- <!-- Anyone group -->
- <group_roles id="3"
- group_id="[null]"
- resource_id="1"
- role="user"
- organization_uuid="org1"/>
- <group_roles id="4"
- group_id="[null]"
- resource_id="2"
- role="admin"
- organization_uuid="org1"/>
-
-</dataset>
--- /dev/null
+<dataset>
+
+ <projects uuid="ABC"
+ uuid_path="NOT_USED"
+ project_uuid="ABC"
+ module_uuid="[null]"
+ module_uuid_path="."
+ root_uuid="ABC"
+ scope="PRJ"
+ qualifier="TRK"
+ kee="org.struts:struts"
+ name="Struts"
+ description="the description"
+ long_name="Apache Struts"
+ enabled="[true]"
+ language="java"
+ path="[null]"
+ authorization_updated_at="123456789"
+ id="1"/>
+
+ <!-- no authorizations project ABC. -->
+
+ <users id="10"
+ login="user1"
+ name="User 1"
+ email="user1@company.net"
+ active="[true]"
+ is_root="[false]"/>
+ <groups id="100"
+ name="devs"
+ organization_uuid="org1"/>
+
+ <user_roles id="1"
+ user_id="10"
+ resource_id="2"
+ role="user"
+ organization_uuid="org1"/>
+ <group_roles id="1"
+ group_id="100"
+ resource_id="2"
+ role="admin"
+ organization_uuid="org1"/>
+</dataset>
--- /dev/null
+<dataset>
+
+ <projects uuid="ABC"
+ uuid_path="NOT_USED"
+ project_uuid="ABC"
+ module_uuid="[null]"
+ module_uuid_path="."
+ root_uuid="ABC"
+ scope="PRJ"
+ qualifier="TRK"
+ kee="org.struts:struts"
+ name="Struts"
+ description="the description"
+ long_name="Apache Struts"
+ enabled="[true]"
+ language="java"
+ path="[null]"
+ authorization_updated_at="1000000000"
+ id="1"/>
+
+ <projects uuid="DEF"
+ uuid_path="NOT_USED"
+ project_uuid="DEF"
+ module_uuid="[null]"
+ module_uuid_path="."
+ root_uuid="ABC"
+ scope="PRJ"
+ qualifier="TRK"
+ kee="org.sonar.sample"
+ name="Sample"
+ description="the description"
+ long_name="Sample"
+ enabled="[true]"
+ language="java"
+ path="[null]"
+ authorization_updated_at="2000000000"
+ id="2"/>
+
+ <!-- user1 can access both projects -->
+ <users id="10"
+ login="user1"
+ name="User 1"
+ email="user1@company.net"
+ active="[true]"
+ is_root="[false]"/>
+ <user_roles id="1"
+ user_id="10"
+ resource_id="1"
+ role="user"
+ organization_uuid="org1"/>
+ <user_roles id="2"
+ user_id="10"
+ resource_id="1"
+ role="admin"
+ organization_uuid="org1"/>
+ <user_roles id="3"
+ user_id="10"
+ resource_id="2"
+ role="user"
+ organization_uuid="org1"/>
+
+ <!-- group devs has user access on ABC only -->
+ <groups id="100"
+ name="devs"
+ organization_uuid="org1"/>
+ <group_roles id="1"
+ group_id="100"
+ resource_id="1"
+ role="user"
+ organization_uuid="org1"/>
+ <group_roles id="2"
+ group_id="100"
+ resource_id="1"
+ role="admin"
+ organization_uuid="org1"/>
+
+ <!-- Anyone group has user access on both projects -->
+ <group_roles id="4"
+ group_id="[null]"
+ resource_id="1"
+ role="user"
+ organization_uuid="org1"/>
+ <group_roles id="5"
+ group_id="[null]"
+ resource_id="1"
+ role="admin"
+ organization_uuid="org1"/>
+ <group_roles id="6"
+ group_id="[null]"
+ resource_id="2"
+ role="user"
+ organization_uuid="org1"/>
+
+ <!-- user2 has user access on DEF only -->
+ <users id="11"
+ login="user2"
+ name="User 2"
+ email="user2@company.net"
+ active="[true]"
+ is_root="[false]"/>
+ <user_roles id="4"
+ user_id="11"
+ resource_id="1"
+ role="admin"
+ organization_uuid="org1"/>
+ <user_roles id="5"
+ user_id="11"
+ resource_id="2"
+ role="user"
+ organization_uuid="org1"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <projects uuid="ABC"
+ uuid_path="NOT_USED"
+ project_uuid="ABC"
+ module_uuid="[null]"
+ module_uuid_path="."
+ root_uuid="ABC"
+ scope="PRJ"
+ qualifier="TRK"
+ kee="org.struts:struts"
+ name="Struts"
+ description="the description"
+ long_name="Apache Struts"
+ enabled="[true]"
+ language="java"
+ path="[null]"
+ authorization_updated_at="123456789"
+ id="1"/>
+
+ <users id="10"
+ login="user1"
+ name="User 1"
+ email="user1@company.net"
+ active="[true]"
+ is_root="[false]"/>
+ <user_roles id="1"
+ user_id="10"
+ resource_id="1"
+ role="user"
+ organization_uuid="org1"/>
+ <user_roles id="2"
+ user_id="10"
+ resource_id="1"
+ role="admin"
+ organization_uuid="org1"/>
+ <user_roles id="3"
+ user_id="10"
+ resource_id="2"
+ role="admin"
+ organization_uuid="org1"/>
+
+ <groups id="100"
+ name="devs"
+ organization_uuid="org1"/>
+ <group_roles id="1"
+ group_id="100"
+ resource_id="1"
+ role="user"
+ organization_uuid="org1"/>
+ <group_roles id="2"
+ group_id="100"
+ resource_id="2"
+ role="admin"
+ organization_uuid="org1"/>
+
+ <!-- Anyone group -->
+ <group_roles id="3"
+ group_id="[null]"
+ resource_id="1"
+ role="user"
+ organization_uuid="org1"/>
+ <group_roles id="4"
+ group_id="[null]"
+ resource_id="2"
+ role="admin"
+ organization_uuid="org1"/>
+
+</dataset>