package org.sonar.server.component;
import org.sonar.api.ServerSide;
+import org.sonar.api.resources.ResourceType;
+import org.sonar.api.resources.ResourceTypes;
import org.sonar.api.resources.Scopes;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
import org.sonar.core.purge.IdUuidPair;
-import org.sonar.core.purge.PurgeDao;
import org.sonar.server.db.DbClient;
import org.sonar.server.issue.index.IssueAuthorizationIndexer;
import org.sonar.server.issue.index.IssueIndexer;
import org.sonar.server.source.index.SourceLineIndexer;
import org.sonar.server.test.index.TestIndexer;
+import java.util.List;
+
@ServerSide
public class ComponentCleanerService {
private final DbClient dbClient;
- private final PurgeDao purgeDao;
private final IssueAuthorizationIndexer issueAuthorizationIndexer;
private final IssueIndexer issueIndexer;
private final SourceLineIndexer sourceLineIndexer;
private final TestIndexer testIndexer;
+ private final ResourceTypes resourceTypes;
- public ComponentCleanerService(DbClient dbClient, PurgeDao purgeDao, IssueAuthorizationIndexer issueAuthorizationIndexer, IssueIndexer issueIndexer,
- SourceLineIndexer sourceLineIndexer, TestIndexer testIndexer) {
+ public ComponentCleanerService(DbClient dbClient, IssueAuthorizationIndexer issueAuthorizationIndexer, IssueIndexer issueIndexer,
+ SourceLineIndexer sourceLineIndexer, TestIndexer testIndexer, ResourceTypes resourceTypes) {
this.dbClient = dbClient;
- this.purgeDao = purgeDao;
this.issueAuthorizationIndexer = issueAuthorizationIndexer;
this.issueIndexer = issueIndexer;
this.sourceLineIndexer = sourceLineIndexer;
this.testIndexer = testIndexer;
+ this.resourceTypes = resourceTypes;
+ }
+
+ public void delete(DbSession dbSession, List<ComponentDto> projects) {
+ for (ComponentDto project : projects) {
+ delete(dbSession, project);
+ }
}
public void delete(String projectKey) {
DbSession dbSession = dbClient.openSession(false);
try {
ComponentDto project = dbClient.componentDao().selectByKey(dbSession, projectKey);
- if (!Scopes.PROJECT.equals(project.scope())) {
- throw new IllegalArgumentException("Only projects can be deleted");
- }
- purgeDao.deleteResourceTree(new IdUuidPair(project.getId(), project.uuid()));
- dbSession.commit();
-
- deleteFromIndices(project.uuid());
+ delete(dbSession, project);
} finally {
MyBatis.closeQuietly(dbSession);
}
}
+ private void delete(DbSession dbSession, ComponentDto project) {
+ if (hasNotProjectScope(project) || isNotDeletable(project)) {
+ throw new IllegalArgumentException("Only projects can be deleted");
+ }
+ dbClient.purgeDao().deleteResourceTree(dbSession, new IdUuidPair(project.getId(), project.uuid()));
+ dbSession.commit();
+
+ deleteFromIndices(project.uuid());
+ }
+
private void deleteFromIndices(String projectUuid) {
// optimization : index "issues" is refreshed once at the end
issueAuthorizationIndexer.deleteProject(projectUuid, false);
testIndexer.deleteByProject(projectUuid);
}
+ private boolean hasNotProjectScope(ComponentDto project) {
+ return !Scopes.PROJECT.equals(project.scope());
+ }
+
+ private boolean isNotDeletable(ComponentDto project) {
+ ResourceType resourceType = resourceTypes.get(project.qualifier());
+ return resourceType == null || !resourceType.getBooleanProperty("deletable");
+ }
}
--- /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.component.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.server.component.ComponentCleanerService;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.user.UserSession;
+
+import javax.annotation.Nullable;
+
+import java.util.List;
+
+public class ProjectsDeleteAction implements ProjectsWsAction {
+ private static final String ACTION = "delete";
+ private static final String PARAM_UUIDS = "uuids";
+ private static final String PARAM_KEYS = "keys";
+
+ private final ComponentCleanerService componentCleanerService;
+ private final DbClient dbClient;
+ private final UserSession userSession;
+
+ public ProjectsDeleteAction(ComponentCleanerService componentCleanerService, DbClient dbClient, UserSession userSession) {
+ this.componentCleanerService = componentCleanerService;
+ this.dbClient = dbClient;
+ this.userSession = userSession;
+ }
+
+ @Override
+ public void define(WebService.NewController context) {
+ WebService.NewAction action = context
+ .createAction(ACTION)
+ .setDescription("Delete one or several projects.<br /> Requires Admin permission.")
+ .setSince("5.2")
+ .setHandler(this);
+
+ action
+ .createParam(PARAM_UUIDS)
+ .setDescription("List of project UUIDs to delete")
+ .setExampleValue("ce4c03d6-430f-40a9-b777-ad877c00aa4d,c526ef20-131b-4486-9357-063fa64b5079");
+
+ action
+ .createParam(PARAM_KEYS)
+ .setDescription("List of project keys to delete")
+ .setExampleValue("org.apache.hbas:hbase,com.microsoft.roslyn:roslyn");
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ userSession.checkGlobalPermission(UserRole.ADMIN);
+ List<String> uuids = request.paramAsStrings(PARAM_UUIDS);
+ List<String> keys = request.paramAsStrings(PARAM_KEYS);
+
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ List<ComponentDto> projects = searchProjects(dbSession, uuids, keys);
+ componentCleanerService.delete(dbSession, projects);
+ } finally {
+ MyBatis.closeQuietly(dbSession);
+ }
+
+ response.noContent();
+ }
+
+ private List<ComponentDto> searchProjects(DbSession dbSession, @Nullable List<String> uuids, @Nullable List<String> keys) {
+ if (uuids != null) {
+ return dbClient.componentDao().selectByUuids(dbSession, uuids);
+ }
+ if (keys != null) {
+ return dbClient.componentDao().selectByKeys(dbSession, keys);
+ }
+
+ throw new IllegalArgumentException("UUIDs or keys must be provided");
+ }
+}
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
import org.sonar.core.properties.PropertiesDao;
+import org.sonar.core.purge.PurgeDao;
import org.sonar.core.qualityprofile.db.QualityProfileDao;
import org.sonar.core.resource.ResourceDao;
import org.sonar.core.technicaldebt.db.CharacteristicDao;
private final ComponentLinkDao componentLinkDao;
private final EventDao eventDao;
private final FileDependencyDao fileDependencyDao;
+ private final PurgeDao purgeDao;
public DbClient(Database db, MyBatis myBatis, DaoComponent... daoComponents) {
this.db = db;
componentLinkDao = getDao(map, ComponentLinkDao.class);
eventDao = getDao(map, EventDao.class);
fileDependencyDao = getDao(map, FileDependencyDao.class);
+ purgeDao = getDao(map, PurgeDao.class);
}
public Database database() {
return fileDependencyDao;
}
+ public PurgeDao purgeDao() {
+ return purgeDao;
+ }
+
private <K> K getDao(Map<Class, DaoComponent> map, Class<K> clazz) {
return (K) map.get(clazz);
}
+++ /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.component;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.security.DefaultGroups;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.rule.RuleDto;
-import org.sonar.server.component.db.ComponentDao;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.es.EsClient;
-import org.sonar.server.issue.IssueTesting;
-import org.sonar.server.issue.db.IssueDao;
-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.InternalPermissionService;
-import org.sonar.server.permission.PermissionChange;
-import org.sonar.server.rule.RuleTesting;
-import org.sonar.server.rule.db.RuleDao;
-import org.sonar.server.search.IndexClient;
-import org.sonar.server.tester.ServerTester;
-import org.sonar.server.tester.UserSessionRule;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class ComponentCleanerServiceMediumTest {
-
- @ClassRule
- public static ServerTester tester = new ServerTester();
- @Rule
- public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester);
-
- DbClient db;
- IndexClient index;
- DbSession session;
-
- ComponentCleanerService service;
-
- @Before
- public void setUp() {
- tester.clearDbAndIndexes();
-
- db = tester.get(DbClient.class);
- index = tester.get(IndexClient.class);
- session = db.openSession(false);
- service = tester.get(ComponentCleanerService.class);
- }
-
- @After
- public void after() {
- session.close();
- }
-
- @Test
- public void delete_project() {
- ComponentDto project = ComponentTesting.newProjectDto();
- db.componentDao().insert(session, project);
- session.commit();
-
- service.delete(project.getKey());
-
- assertThat(db.componentDao().selectNullableByKey(session, project.key())).isNull();
- }
-
- @Test
- public void remove_issue_permission_index_when_deleting_a_project() {
- ComponentDto project = ComponentTesting.newProjectDto();
- db.componentDao().insert(session, project);
-
- // project can be seen by anyone
- session.commit();
- userSessionRule.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
- tester.get(InternalPermissionService.class).addPermission(new PermissionChange().setComponentKey(project.getKey()).setGroup(DefaultGroups.ANYONE).setPermission(UserRole.USER));
-
- assertThat(countIssueAuthorizationDocs()).isEqualTo(1);
-
- service.delete(project.getKey());
-
- assertThat(countIssueAuthorizationDocs()).isEqualTo(0);
- }
-
- @Test
- public void remove_issue_when_deleting_a_project() {
- // ARRANGE
- ComponentDto project = ComponentTesting.newProjectDto();
- db.componentDao().insert(session, project);
-
- RuleDto rule = RuleTesting.newXooX1();
- tester.get(RuleDao.class).insert(session, rule);
-
- ComponentDto file = ComponentTesting.newFileDto(project);
- tester.get(ComponentDao.class).insert(session, file);
-
- tester.get(IssueDao.class).insert(session, IssueTesting.newDto(rule, file, project));
- session.commit();
- tester.get(IssueIndexer.class).indexAll();
-
- assertThat(tester.get(IssueIndex.class).countAll()).isEqualTo(1);
-
- // ACT
- service.delete(project.getKey());
-
- assertThat(tester.get(IssueIndex.class).countAll()).isEqualTo(0);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void fail_to_delete_not_project() {
- ComponentDto project = ComponentTesting.newProjectDto();
- ComponentDto file = ComponentTesting.newFileDto(project);
- db.componentDao().insert(session, project, file);
- session.commit();
-
- service.delete(file.getKey());
- }
-
- private long countIssueAuthorizationDocs() {
- return tester.get(EsClient.class).prepareCount(IssueIndexDefinition.INDEX).setTypes(IssueIndexDefinition.TYPE_AUTHORIZATION).get().getCount();
- }
-}
--- /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.component.ws;
+
+import com.google.common.collect.ImmutableMap;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.config.Settings;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.ResourceType;
+import org.sonar.api.resources.ResourceTypes;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.utils.System2;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.component.SnapshotDto;
+import org.sonar.core.issue.db.IssueDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.core.purge.PurgeDao;
+import org.sonar.core.purge.PurgeProfiler;
+import org.sonar.core.resource.ResourceDao;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.server.component.ComponentCleanerService;
+import org.sonar.server.component.ComponentTesting;
+import org.sonar.server.component.SnapshotTesting;
+import org.sonar.server.component.db.ComponentDao;
+import org.sonar.server.component.db.SnapshotDao;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.es.EsTester;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.issue.IssueTesting;
+import org.sonar.server.issue.db.IssueDao;
+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.rule.RuleTesting;
+import org.sonar.server.rule.db.RuleDao;
+import org.sonar.server.source.index.SourceLineDoc;
+import org.sonar.server.source.index.SourceLineIndexDefinition;
+import org.sonar.server.source.index.SourceLineIndexer;
+import org.sonar.server.test.index.TestDoc;
+import org.sonar.server.test.index.TestIndexDefinition;
+import org.sonar.server.test.index.TestIndexer;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsTester;
+import org.sonar.test.DbTests;
+
+import java.util.Arrays;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@Category(DbTests.class)
+public class ProjectsDeleteActionTest {
+
+ @ClassRule
+ public static DbTester db = new DbTester();
+ @ClassRule
+ public static EsTester es = new EsTester().addDefinitions(new IssueIndexDefinition(new Settings()), new SourceLineIndexDefinition(new Settings()),
+ new TestIndexDefinition(new Settings()));
+ @Rule
+ public UserSessionRule userSessionRule = UserSessionRule.standalone();
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+ WsTester ws;
+ DbClient dbClient;
+ DbSession dbSession;
+ ResourceType resourceType;
+
+ @Before
+ public void setUp() throws Exception {
+ ComponentDao componentDao = new ComponentDao();
+ ResourceDao resourceDao = new ResourceDao(db.myBatis(), System2.INSTANCE);
+ PurgeDao purgeDao = new PurgeDao(db.myBatis(), resourceDao, new PurgeProfiler(), System2.INSTANCE);
+ dbClient = new DbClient(db.database(), db.myBatis(), componentDao, purgeDao, new RuleDao(System2.INSTANCE), new IssueDao(db.myBatis()), new SnapshotDao(System2.INSTANCE));
+ dbSession = dbClient.openSession(false);
+ resourceType = mock(ResourceType.class);
+ when(resourceType.getBooleanProperty(anyString())).thenReturn(true);
+ ResourceTypes mockResourceTypes = mock(ResourceTypes.class);
+ when(mockResourceTypes.get(anyString())).thenReturn(resourceType);
+ ws = new WsTester(new ProjectsWs(new ProjectsDeleteAction(new ComponentCleanerService(dbClient, new IssueAuthorizationIndexer(dbClient, es.client()), new IssueIndexer(
+ dbClient, es.client()), new SourceLineIndexer(dbClient, es.client()), new TestIndexer(dbClient, es.client()), mockResourceTypes), dbClient, userSessionRule)));
+ db.truncateTables();
+ es.truncateIndices();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ dbSession.close();
+ }
+
+ @Test
+ public void delete_projects_and_data_in_db_by_uuids() throws Exception {
+ userSessionRule.setGlobalPermissions(UserRole.ADMIN);
+ long snapshotId1 = insertNewProjectInDbAndReturnSnapshotId(1);
+ long snapshotId2 = insertNewProjectInDbAndReturnSnapshotId(2);
+ long snapshotId3 = insertNewProjectInDbAndReturnSnapshotId(3);
+ long snapshotId4 = insertNewProjectInDbAndReturnSnapshotId(4);
+
+ ws.newGetRequest("api/projects", "delete")
+ .setParam("uuids", "project-uuid-1, project-uuid-3, project-uuid-4").execute();
+ dbSession.commit();
+
+ assertThat(dbClient.componentDao().selectByUuids(dbSession, Arrays.asList("project-uuid-1", "project-uuid-3", "project-uuid-4"))).isEmpty();
+ assertThat(dbClient.componentDao().selectByUuid(dbSession, "project-uuid-2")).isNotNull();
+ assertThat(dbClient.snapshotDao().getNullableByKey(dbSession, snapshotId1)).isNull();
+ assertThat(dbClient.snapshotDao().getNullableByKey(dbSession, snapshotId3)).isNull();
+ assertThat(dbClient.snapshotDao().getNullableByKey(dbSession, snapshotId4)).isNull();
+ assertThat(dbClient.snapshotDao().getNullableByKey(dbSession, snapshotId2)).isNotNull();
+ assertThat(dbClient.issueDao().selectByKeys(dbSession, Arrays.asList("issue-key-1", "issue-key-3", "issue-key-4"))).isEmpty();
+ assertThat(dbClient.issueDao().selectByKey(dbSession, "issue-key-2")).isNotNull();
+ }
+
+ @Test
+ public void delete_projects_and_data_in_db_by_keys() throws Exception {
+ userSessionRule.setGlobalPermissions(UserRole.ADMIN);
+ insertNewProjectInDbAndReturnSnapshotId(1);
+ insertNewProjectInDbAndReturnSnapshotId(2);
+ insertNewProjectInDbAndReturnSnapshotId(3);
+ insertNewProjectInDbAndReturnSnapshotId(4);
+
+ ws.newGetRequest("api/projects", "delete")
+ .setParam("keys", "project-key-1, project-key-3, project-key-4").execute();
+ dbSession.commit();
+
+ assertThat(dbClient.componentDao().selectByUuids(dbSession, Arrays.asList("project-uuid-1", "project-uuid-3", "project-uuid-4"))).isEmpty();
+ assertThat(dbClient.componentDao().selectByUuid(dbSession, "project-uuid-2")).isNotNull();
+ }
+
+ @Test
+ public void delete_documents_indexes() throws Exception {
+ userSessionRule.setGlobalPermissions(UserRole.ADMIN);
+ insertNewProjectInIndexes(1);
+ insertNewProjectInIndexes(2);
+ insertNewProjectInIndexes(3);
+ insertNewProjectInIndexes(4);
+
+ ws.newGetRequest("api/projects", "delete")
+ .setParam("keys", "project-key-1, project-key-3, project-key-4").execute();
+
+ String remainingProjectUuid = "project-uuid-2";
+ assertThat(es.getDocumentFieldValues(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_ISSUE, IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID))
+ .containsOnly(remainingProjectUuid);
+ assertThat(es.getDocumentFieldValues(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION, IssueIndexDefinition.FIELD_AUTHORIZATION_PROJECT_UUID))
+ .containsOnly(remainingProjectUuid);
+ assertThat(es.getDocumentFieldValues(SourceLineIndexDefinition.INDEX, SourceLineIndexDefinition.TYPE, SourceLineIndexDefinition.FIELD_PROJECT_UUID))
+ .containsOnly(remainingProjectUuid);
+ assertThat(es.getDocumentFieldValues(TestIndexDefinition.INDEX, TestIndexDefinition.TYPE, TestIndexDefinition.FIELD_PROJECT_UUID))
+ .containsOnly(remainingProjectUuid);
+ }
+
+ @Test
+ public void web_service_returns_204() throws Exception {
+ userSessionRule.setGlobalPermissions(UserRole.ADMIN);
+ insertNewProjectInDbAndReturnSnapshotId(1);
+
+ WsTester.Result result = ws.newGetRequest("api/projects", "delete").setParam("uuids", "project-uuid-1").execute();
+
+ result.assertNoContent();
+ }
+
+ @Test
+ public void fail_if_insufficient_privileges() throws Exception {
+ userSessionRule.setGlobalPermissions(UserRole.CODEVIEWER, UserRole.ISSUE_ADMIN, UserRole.USER);
+ expectedException.expect(ForbiddenException.class);
+
+ ws.newGetRequest("api/projects", "delete").setParam("uuids", "whatever-the-uuid").execute();
+ }
+
+ @Test
+ public void fail_if_scope_is_not_project() throws Exception {
+ userSessionRule.setGlobalPermissions(UserRole.ADMIN);
+ expectedException.expect(IllegalArgumentException.class);
+ dbClient.componentDao().insert(dbSession, ComponentTesting.newFileDto(ComponentTesting.newProjectDto(), "file-uuid"));
+ dbSession.commit();
+
+ ws.newGetRequest("api/projects", "delete").setParam("uuids", "file-uuid").execute();
+ }
+
+ @Test
+ public void fail_if_qualifier_is_not_deletable() throws Exception {
+ userSessionRule.setGlobalPermissions(UserRole.ADMIN);
+ expectedException.expect(IllegalArgumentException.class);
+ dbClient.componentDao().insert(dbSession, ComponentTesting.newProjectDto("project-uuid").setQualifier(Qualifiers.FILE));
+ dbSession.commit();
+ when(resourceType.getBooleanProperty(anyString())).thenReturn(false);
+
+ ws.newGetRequest("api/projects", "delete").setParam("uuids", "project-uuid").execute();
+ }
+
+ private long insertNewProjectInDbAndReturnSnapshotId(int id) {
+ String suffix = String.valueOf(id);
+ ComponentDto project = ComponentTesting
+ .newProjectDto("project-uuid-" + suffix)
+ .setKey("project-key-" + suffix);
+ RuleDto rule = RuleTesting.newDto(RuleKey.of("sonarqube", "rule-" + suffix));
+ dbClient.ruleDao().insert(dbSession, rule);
+ IssueDto issue = IssueTesting.newDto(rule, project, project).setKee("issue-key-" + suffix);
+ dbClient.componentDao().insert(dbSession, project);
+ SnapshotDto snapshot = dbClient.snapshotDao().insert(dbSession, SnapshotTesting.createForProject(project));
+ dbClient.issueDao().insert(dbSession, issue);
+ dbSession.commit();
+
+ return snapshot.getId();
+ }
+
+ private void insertNewProjectInIndexes(int id) throws Exception {
+ String suffix = String.valueOf(id);
+ ComponentDto project = ComponentTesting
+ .newProjectDto("project-uuid-" + suffix)
+ .setKey("project-key-" + suffix);
+ dbClient.componentDao().insert(dbSession, project);
+ dbSession.commit();
+
+ es.putDocuments(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_ISSUE, IssueTesting.newDoc("issue-key-" + suffix, project));
+ SourceLineDoc sourceLineDoc = new SourceLineDoc()
+ .setProjectUuid(project.uuid())
+ .setFileUuid(project.uuid());
+ es.putDocuments(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION,
+ ImmutableMap.<String, Object>of(IssueIndexDefinition.FIELD_AUTHORIZATION_PROJECT_UUID, project.uuid()));
+
+ es.putDocuments(SourceLineIndexDefinition.INDEX, SourceLineIndexDefinition.TYPE, sourceLineDoc);
+ TestDoc testDoc = new TestDoc().setUuid("test-uuid-" + suffix).setProjectUuid(project.uuid()).setFileUuid(project.uuid());
+ es.putDocuments(TestIndexDefinition.INDEX, TestIndexDefinition.TYPE, testDoc);
+ }
+}
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.experimental.categories.Category;
import org.sonar.api.config.Settings;
import org.sonar.api.web.UserRole;
import org.sonar.core.component.ComponentDto;
import org.sonar.server.test.index.TestIndexDefinition;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.WsTester;
+import org.sonar.test.DbTests;
import java.util.Arrays;
import java.util.List;
+@Category(DbTests.class)
public class TestsListActionTest {
DbClient dbClient;
DbSession dbSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.utils.System2;
+import org.sonar.core.persistence.DaoComponent;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
import org.sonar.core.resource.ResourceDao;
/**
* @since 2.14
*/
-public class PurgeDao {
+public class PurgeDao implements DaoComponent {
private static final Logger LOG = LoggerFactory.getLogger(PurgeDao.class);
private final MyBatis mybatis;
private final ResourceDao resourceDao;
}
public List<PurgeableSnapshotDto> selectPurgeableSnapshots(long resourceId, DbSession session) {
- PurgeMapper mapper = session.getMapper(PurgeMapper.class);
List<PurgeableSnapshotDto> result = Lists.newArrayList();
- result.addAll(mapper.selectPurgeableSnapshotsWithEvents(resourceId));
- result.addAll(mapper.selectPurgeableSnapshotsWithoutEvents(resourceId));
+ result.addAll(mapper(session).selectPurgeableSnapshotsWithEvents(resourceId));
+ result.addAll(mapper(session).selectPurgeableSnapshotsWithoutEvents(resourceId));
// sort by date
Collections.sort(result);
return result;
}
public PurgeDao deleteResourceTree(IdUuidPair rootIdUuid) {
- final DbSession session = mybatis.openSession(true);
- final PurgeMapper mapper = session.getMapper(PurgeMapper.class);
+ DbSession session = mybatis.openSession(true);
try {
- deleteProject(rootIdUuid, mapper, new PurgeCommands(session, profiler));
- deleteFileSources(rootIdUuid.getUuid(), new PurgeCommands(session, profiler));
- return this;
+ return deleteResourceTree(session, rootIdUuid);
} finally {
MyBatis.closeQuietly(session);
}
}
+ public PurgeDao deleteResourceTree(DbSession session, IdUuidPair rootIdUuid) {
+ deleteProject(rootIdUuid, mapper(session), new PurgeCommands(session, profiler));
+ deleteFileSources(rootIdUuid.getUuid(), new PurgeCommands(session, profiler));
+ return this;
+ }
+
private void deleteFileSources(String rootUuid, PurgeCommands commands) {
commands.deleteFileSources(rootUuid);
}
}
public List<String> selectPurgeableFiles(DbSession dbSession, Long projectId) {
- PurgeMapper mapper = dbSession.getMapper(PurgeMapper.class);
- return mapper.selectPurgeableFileUuids(projectId);
+ return mapper(dbSession).selectPurgeableFileUuids(projectId);
+ }
+
+ private PurgeMapper mapper(DbSession session) {
+ return session.getMapper(PurgeMapper.class);
}
}