Restrict endpoints to change health status to admins

Change-Id: I01aca30a9b08ab14c770fb2e7e1afd3ef8507efc
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/health/HealthServlet.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/health/HealthServlet.java
index a121a89..bfdcc12 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/health/HealthServlet.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/health/HealthServlet.java
@@ -14,10 +14,14 @@
 
 package com.ericsson.gerrit.plugins.highavailability.health;
 
+import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
 import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
 import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
 import static javax.servlet.http.HttpServletResponse.SC_SERVICE_UNAVAILABLE;
 
+import com.google.gerrit.server.CurrentUser;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
 import com.google.inject.Singleton;
 import java.io.IOException;
 import javax.servlet.http.HttpServlet;
@@ -31,20 +35,31 @@
   private static final Logger log = LoggerFactory.getLogger(HealthServlet.class);
   private static final long serialVersionUID = -1L;
 
+  private final Provider<CurrentUser> currentUserProvider;
   private boolean healthy;
 
-  HealthServlet() {
+  @Inject
+  HealthServlet(Provider<CurrentUser> currentUserProvider) {
+    this.currentUserProvider = currentUserProvider;
     this.healthy = true;
   }
 
   @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse rsp) {
+    if (!currentUserProvider.get().getCapabilities().canAdministrateServer()) {
+      sendError(rsp, SC_FORBIDDEN);
+      return;
+    }
     this.healthy = true;
     rsp.setStatus(SC_NO_CONTENT);
   }
 
   @Override
   protected void doDelete(HttpServletRequest req, HttpServletResponse rsp) {
+    if (!currentUserProvider.get().getCapabilities().canAdministrateServer()) {
+      sendError(rsp, SC_FORBIDDEN);
+      return;
+    }
     this.healthy = false;
     rsp.setStatus(SC_NO_CONTENT);
   }
@@ -54,12 +69,16 @@
     if (healthy) {
       rsp.setStatus(SC_NO_CONTENT);
     } else {
-      try {
-        rsp.sendError(SC_SERVICE_UNAVAILABLE);
-      } catch (IOException e) {
-        rsp.setStatus(SC_INTERNAL_SERVER_ERROR);
-        log.error("Failed to send error response", e);
-      }
+      sendError(rsp, SC_SERVICE_UNAVAILABLE);
+    }
+  }
+
+  private void sendError(HttpServletResponse rsp, int statusCode) {
+    try {
+      rsp.sendError(statusCode);
+    } catch (IOException e) {
+      rsp.setStatus(SC_INTERNAL_SERVER_ERROR);
+      log.error("Failed to send error response", e);
     }
   }
 }
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/health/HealthServletTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/health/HealthServletTest.java
index 343df09..9d1bf2b 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/health/HealthServletTest.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/health/HealthServletTest.java
@@ -14,25 +14,41 @@
 
 package com.ericsson.gerrit.plugins.highavailability.health;
 
+import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
 import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
 import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
 import static javax.servlet.http.HttpServletResponse.SC_SERVICE_UNAVAILABLE;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
+import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.account.CapabilityControl;
+import com.google.inject.Provider;
 import java.io.IOException;
 import javax.servlet.http.HttpServletResponse;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
 
+@RunWith(MockitoJUnitRunner.class)
 public class HealthServletTest {
 
+  @Mock private Provider<CurrentUser> currentUserProviderMock;
+  @Mock private CurrentUser currentUserMock;
+  @Mock private CapabilityControl capabilityControlMock;
+
   private HealthServlet servlet;
 
   @Before
   public void setUp() throws Exception {
-    servlet = new HealthServlet();
+    when(currentUserProviderMock.get()).thenReturn(currentUserMock);
+    when(currentUserMock.getCapabilities()).thenReturn(capabilityControlMock);
+    when(capabilityControlMock.canAdministrateServer()).thenReturn(true);
+    servlet = new HealthServlet(currentUserProviderMock);
   }
 
   @Test
@@ -58,6 +74,17 @@
   }
 
   @Test
+  public void testTransitionToUnhealthyByNonAdmins() throws IOException {
+    assertIsHealthy();
+
+    when(capabilityControlMock.canAdministrateServer()).thenReturn(false);
+    HttpServletResponse responseMock = mock(HttpServletResponse.class);
+    servlet.doDelete(null, responseMock);
+    verify(responseMock).sendError(SC_FORBIDDEN);
+    assertIsHealthy();
+  }
+
+  @Test
   public void testTransitionToHealty() throws IOException {
     // first, mark as unhealthy
     servlet.doDelete(null, mock(HttpServletResponse.class));
@@ -77,6 +104,19 @@
   }
 
   @Test
+  public void testTransitionToHealthyByNonAdmins() throws IOException {
+    // first, mark as unhealthy
+    servlet.doDelete(null, mock(HttpServletResponse.class));
+    assertIsUnhealthy();
+
+    when(capabilityControlMock.canAdministrateServer()).thenReturn(false);
+    HttpServletResponse responseMock = mock(HttpServletResponse.class);
+    servlet.doPost(null, responseMock);
+    verify(responseMock).sendError(SC_FORBIDDEN);
+    assertIsUnhealthy();
+  }
+
+  @Test
   public void testErrorWhileSendingUnhealthyResponse() throws IOException {
     HttpServletResponse responseMock = mock(HttpServletResponse.class);
     servlet.doDelete(null, responseMock);