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