Add project delete REST API endpoint
Replace direct call to the delete-project plugin REST API endpoint with
the call to the pull-replication REST API. This allows to add some
custom logic before triggering project deletion.
Bug: Issue 15392
Change-Id: I26f080004c37c959abe487fbc50a561d5b24a8b0
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationApiModule.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationApiModule.java
index f94f49b..8dc0f0f 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationApiModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationApiModule.java
@@ -27,8 +27,10 @@
protected void configure() {
bind(FetchAction.class).in(Scopes.SINGLETON);
bind(ApplyObjectAction.class).in(Scopes.SINGLETON);
+ bind(ProjectDeletionAction.class).in(Scopes.SINGLETON);
post(PROJECT_KIND, "fetch").to(FetchAction.class);
post(PROJECT_KIND, "apply-object").to(ApplyObjectAction.class);
+ delete(PROJECT_KIND, "delete-project").to(ProjectDeletionAction.class);
bind(FetchPreconditions.class).in(Scopes.SINGLETON);
bind(CapabilityDefinition.class)
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilter.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilter.java
index 44dd3bb..4af2bf7 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilter.java
@@ -27,6 +27,7 @@
import com.google.common.base.Splitter;
import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.api.projects.HeadInput;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
@@ -80,6 +81,7 @@
private ProjectsCollection projectsCollection;
private Gson gson;
private Provider<CurrentUser> userProvider;
+ private String pluginName;
@Inject
public PullReplicationFilter(
@@ -89,7 +91,8 @@
UpdateHeadAction updateHEADAction,
ProjectDeletionAction projectDeletionAction,
ProjectsCollection projectsCollection,
- Provider<CurrentUser> userProvider) {
+ Provider<CurrentUser> userProvider,
+ @PluginName String pluginName) {
this.fetchAction = fetchAction;
this.applyObjectAction = applyObjectAction;
this.projectInitializationAction = projectInitializationAction;
@@ -97,6 +100,7 @@
this.projectDeletionAction = projectDeletionAction;
this.projectsCollection = projectsCollection;
this.userProvider = userProvider;
+ this.pluginName = pluginName;
this.gson = OutputFormat.JSON.newGsonBuilder().create();
}
@@ -303,7 +307,7 @@
}
private boolean isDeleteProjectAction(HttpServletRequest httpRequest) {
- return httpRequest.getRequestURI().matches("(/a)?/projects/[^/]+$")
+ return httpRequest.getRequestURI().endsWith(String.format("%s~delete-project", pluginName))
&& "DELETE".equals(httpRequest.getMethod());
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClient.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClient.java
index df97609..a7e71af 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClient.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClient.java
@@ -190,7 +190,7 @@
}
String getProjectDeletionUrl(String projectName) {
- return String.format("a/projects/%s", Url.encode(projectName));
+ return String.format("a/projects/%s/%s~delete-project", Url.encode(projectName), pluginName);
}
String getProjectUpdateHeadUrl(String projectName) {
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationIT.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationIT.java
index c2335e8..c5b1790 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationIT.java
@@ -15,7 +15,6 @@
package com.googlesource.gerrit.plugins.replication.pull;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.gerrit.server.project.ProjectResource.PROJECT_KIND;
import static java.util.stream.Collectors.toList;
import com.google.common.flogger.FluentLogger;
@@ -38,11 +37,9 @@
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestApiModule;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.project.ProjectResource;
-import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.googlesource.gerrit.plugins.replication.AutoReloadConfigDecorator;
@@ -83,28 +80,10 @@
private FileBasedConfig config;
private FileBasedConfig secureConfig;
- static FakeDeleteProjectPlugin fakeDeleteProjectPlugin;
-
- static class FakeDeleteModule extends AbstractModule {
-
- @Override
- public void configure() {
- install(
- new RestApiModule() {
- @Override
- public void configure() {
- fakeDeleteProjectPlugin = new FakeDeleteProjectPlugin();
- delete(PROJECT_KIND).toInstance(fakeDeleteProjectPlugin);
- }
- });
- }
- }
-
@Override
public void setUpTestPlugin() throws Exception {
gitPath = sitePaths.site_path.resolve("git");
- installPlugin("fakeDeleteProjectPlugin", FakeDeleteModule.class, null, null);
config =
new FileBasedConfig(sitePaths.etc_dir.resolve("replication.config").toFile(), FS.DETECTED);
setReplicationSource(
@@ -278,12 +257,11 @@
return NotifyHandling.NONE;
}
};
-
for (ProjectDeletedListener l : deletedListeners) {
l.onProjectDeleted(event);
}
- waitUntil(() -> fakeDeleteProjectPlugin.getDeleteEndpointCalls() == 1);
+ waitUntil(() -> !repoManager.list().contains(project));
}
@Test
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ActionITBase.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ActionITBase.java
index 343ce66..34aaf8b 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ActionITBase.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ActionITBase.java
@@ -127,7 +127,6 @@
protected HttpDelete createDeleteRequest() {
HttpDelete delete = new HttpDelete(url);
- delete.addHeader(new BasicHeader("Content-Type", "application/json"));
return delete;
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectDeletionActionIT.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectDeletionActionIT.java
index 4c09266..f5c8d4c 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectDeletionActionIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectDeletionActionIT.java
@@ -31,6 +31,64 @@
@Inject private ProjectOperations projectOperations;
@Test
+ public void shouldReturnUnauthorizedForUserWithoutPermissions() throws Exception {
+ httpClientFactory
+ .create(source)
+ .execute(
+ createDeleteRequest(),
+ assertHttpResponseCode(HttpServletResponse.SC_UNAUTHORIZED),
+ getAnonymousContext());
+ }
+
+ @Test
+ public void shouldDeleteRepositoryWhenUserHasProjectDeletionCapabilities() throws Exception {
+ String testProjectName = project.get();
+ url = getURL(testProjectName);
+ httpClientFactory
+ .create(source)
+ .execute(
+ createDeleteRequest(),
+ assertHttpResponseCode(HttpServletResponse.SC_FORBIDDEN),
+ getUserContext());
+
+ projectOperations
+ .project(allProjects)
+ .forUpdate()
+ .add(allowCapability(DELETE_PROJECT_PERMISSION).group(SystemGroupBackend.REGISTERED_USERS))
+ .update();
+
+ httpClientFactory
+ .create(source)
+ .execute(
+ createDeleteRequest(),
+ assertHttpResponseCode(HttpServletResponse.SC_OK),
+ getUserContext());
+ }
+
+ @Test
+ public void shouldReturnOKWhenProjectIsDeleted() throws Exception {
+ String testProjectName = project.get();
+ url = getURL(testProjectName);
+
+ httpClientFactory
+ .create(source)
+ .execute(
+ createDeleteRequest(), assertHttpResponseCode(HttpServletResponse.SC_OK), getContext());
+ }
+
+ @Test
+ public void shouldReturnInternalServerErrorIfProjectCannotBeDeleted() throws Exception {
+ url = getURL(INVALID_TEST_PROJECT_NAME);
+
+ httpClientFactory
+ .create(source)
+ .execute(
+ createDeleteRequest(),
+ assertHttpResponseCode(HttpServletResponse.SC_INTERNAL_SERVER_ERROR),
+ getContext());
+ }
+
+ @Test
@GerritConfig(name = "container.replica", value = "true")
public void shouldReturnUnauthorizedForUserWithoutPermissionsOnReplica() throws Exception {
httpClientFactory
@@ -96,6 +154,8 @@
@Override
protected String getURL(String projectName) {
- return String.format("%s/a/projects/%s", adminRestSession.url(), Url.encode(projectName));
+ return String.format(
+ "%s/a/projects/%s/pull-replication~delete-project",
+ adminRestSession.url(), Url.encode(projectName));
}
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientTest.java
index ed1eef4..17df2df 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientTest.java
@@ -376,7 +376,8 @@
HttpDelete httpDelete = httpDeleteCaptor.getValue();
assertThat(httpDelete.getURI().getHost()).isEqualTo("gerrit-host");
- assertThat(httpDelete.getURI().getPath()).isEqualTo("/a/projects/test_repo");
+ assertThat(httpDelete.getURI().getPath())
+ .isEqualTo("/a/projects/test_repo/pull-replication~delete-project");
}
@Test