Add REST API for deleting webhooks

Change-Id: If630c38496d0918f8b7597742cb001b4d3db8883
diff --git a/src/main/java/com/googlesource/gerrit/plugins/webhooks/WebhooksConfig.java b/src/main/java/com/googlesource/gerrit/plugins/webhooks/WebhooksConfig.java
index 59ff1b9..88bb951 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/webhooks/WebhooksConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/webhooks/WebhooksConfig.java
@@ -110,4 +110,8 @@
       cfg.setBoolean(REMOTE, remoteName, key, value);
     }
   }
+
+  public void deleteRemote(String remoteName) {
+    cfg.unsetSection(REMOTE, remoteName);
+  }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/webhooks/rest/DeleteRemote.java b/src/main/java/com/googlesource/gerrit/plugins/webhooks/rest/DeleteRemote.java
new file mode 100644
index 0000000..ebb8c4e
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/webhooks/rest/DeleteRemote.java
@@ -0,0 +1,68 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.googlesource.gerrit.plugins.webhooks.rest;
+
+import com.google.gerrit.extensions.restapi.Response;
+import com.google.gerrit.extensions.restapi.RestModifyView;
+import com.google.gerrit.server.auth.AuthException;
+import com.google.gerrit.server.git.MetaDataUpdate;
+import com.google.gerrit.server.project.ProjectCache;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.googlesource.gerrit.plugins.webhooks.WebhooksConfig;
+import com.googlesource.gerrit.plugins.webhooks.rest.DeleteRemote.Input;
+import java.io.IOException;
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.errors.RepositoryNotFoundException;
+
+public class DeleteRemote implements RestModifyView<RemoteResource, Input> {
+  public static class Input {}
+
+  private final Provider<WebhooksConfig> webhooksConfig;
+  private final Provider<MetaDataUpdate.User> metaDataUpdateFactory;
+  private final ProjectCache projectCache;
+  private final Permissions permissions;
+
+  @Inject
+  DeleteRemote(
+      Provider<WebhooksConfig> webhooksConfig,
+      Provider<MetaDataUpdate.User> metaDataUpdateFactory,
+      ProjectCache projectCache,
+      Permissions permissions) {
+    this.metaDataUpdateFactory = metaDataUpdateFactory;
+    this.webhooksConfig = webhooksConfig;
+    this.projectCache = projectCache;
+    this.permissions = permissions;
+  }
+
+  @Override
+  public Object apply(RemoteResource rsrc, Input input)
+      throws RepositoryNotFoundException, IOException, ConfigInvalidException, AuthException {
+    if (!permissions.canUpdate(rsrc.getProject())) {
+      throw new AuthException("not allowed to update webhooks");
+    }
+
+    try (MetaDataUpdate md = metaDataUpdateFactory.get().create(rsrc.getProject())) {
+      WebhooksConfig wh = webhooksConfig.get();
+      wh.load(md);
+      wh.deleteRemote(rsrc.getRemoteConfig().getName());
+      wh.commit(md);
+    }
+
+    projectCache.evict(rsrc.getProject());
+
+    return Response.none();
+  }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/webhooks/rest/WebhooksRestModule.java b/src/main/java/com/googlesource/gerrit/plugins/webhooks/rest/WebhooksRestModule.java
index fa57700..6ab24a4 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/webhooks/rest/WebhooksRestModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/webhooks/rest/WebhooksRestModule.java
@@ -33,6 +33,7 @@
     child(PROJECT_WEBHOOK_KIND, "remotes").to(RemotesCollection.class);
     get(REMOTE_KIND).to(GetRemote.class);
     put(REMOTE_KIND).to(UpsertRemote.Updater.class);
+    delete(REMOTE_KIND).to(DeleteRemote.class);
 
     bind(Permissions.class).to(PermissionsImpl.class);
 
diff --git a/src/main/resources/Documentation/rest-api-config.md b/src/main/resources/Documentation/rest-api-config.md
index 856770c..7267f99 100644
--- a/src/main/resources/Documentation/rest-api-config.md
+++ b/src/main/resources/Documentation/rest-api-config.md
@@ -123,6 +123,23 @@
   }
 ```
 
+### <a id="delete-webhook"> Delete webhook
+_DELETE /config/server/@PLUGIN@~projects/[\{project-name\}](../../../Documentation/rest-api-projects.html#project-name)/remotes/[\{remote-name\}]_
+
+Delete a webhook for a project.
+
+### Request
+
+```
+  DELETE /config/server/@PLUGIN@~projects/myProject/remotes/foo
+```
+
+### Response
+
+```
+  HTTP/1.1 204 No Content
+```
+
 ### <a id="remote-info"> RemoteInfo
 The `RemoteInfo` contains information about a remote section in a `webhooks.config` file.
 
diff --git a/src/test/java/com/googlesource/gerrit/plugins/webhooks/rest/UpdateRemoteIT.java b/src/test/java/com/googlesource/gerrit/plugins/webhooks/rest/UpdateRemoteIT.java
index eb1f97e..2960d7e 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/webhooks/rest/UpdateRemoteIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/webhooks/rest/UpdateRemoteIT.java
@@ -19,8 +19,10 @@
 import static com.googlesource.gerrit.plugins.webhooks.Configuration.DEFAULT_RETRY_INTERVAL;
 import static com.googlesource.gerrit.plugins.webhooks.Configuration.DEFAULT_SSL_VERIFY;
 import static com.googlesource.gerrit.plugins.webhooks.Configuration.DEFAULT_TIMEOUT_MS;
+import static com.googlesource.gerrit.plugins.webhooks.rest.GetRemoteIT.asMap;
 import static com.googlesource.gerrit.plugins.webhooks.rest.GetRemoteIT.asRemoteInfo;
 import static javax.servlet.http.HttpServletResponse.SC_CREATED;
+import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
 import static javax.servlet.http.HttpServletResponse.SC_OK;
 
 import com.google.common.collect.ImmutableList;
@@ -33,18 +35,18 @@
 @TestPlugin(name = "webhooks", sysModule = "com.googlesource.gerrit.plugins.webhooks.Module")
 public class UpdateRemoteIT extends LightweightPluginDaemonTest {
 
-  private String putFoo;
+  private String fooEndpoint;
 
   @Before
   public void setUp() throws Exception {
     super.setUp();
-    putFoo = String.format("/config/server/webhooks~projects/%s/remotes/foo", project.get());
+    fooEndpoint = String.format("/config/server/webhooks~projects/%s/remotes/foo", project.get());
   }
 
   @Test
   public void createWebhook() throws Exception {
     RemoteInfo info = newRemoteInfo("https://foo.org/");
-    RestResponse res = adminRestSession.put(putFoo, info);
+    RestResponse res = adminRestSession.put(fooEndpoint, info);
     assertThat(res.getStatusCode()).isEqualTo(SC_CREATED);
     assertThat(info).isEqualTo(asRemoteInfo(res.getEntityContent()));
   }
@@ -53,11 +55,24 @@
   public void updateWebhook() throws Exception {
     createWebhook();
     RemoteInfo info = newRemoteInfo("https://foo.org/gerrit-events");
-    RestResponse res = adminRestSession.put(putFoo, info);
+    RestResponse res = adminRestSession.put(fooEndpoint, info);
     assertThat(res.getStatusCode()).isEqualTo(SC_OK);
     assertThat(info).isEqualTo(asRemoteInfo(res.getEntityContent()));
   }
 
+  @Test
+  public void deleteRemote() throws Exception {
+    createWebhook();
+    RestResponse res = adminRestSession.delete(fooEndpoint);
+    assertThat(res.getStatusCode()).isEqualTo(SC_NO_CONTENT);
+
+    RestResponse response =
+        adminRestSession.get(
+            String.format("/config/server/webhooks~projects/%s/remotes/", project.get()));
+    assertThat(response.getStatusCode()).isEqualTo(200);
+    assertThat(asMap(response.getEntityContent()).size()).isEqualTo(0);
+  }
+
   private RemoteInfo newRemoteInfo(String url) {
     RemoteInfo info = new RemoteInfo();
     info.url = url;