Add global collectServerData permission extension

Allow to assign permissions to collect Gerrit Server Data through
a new plugin-provided permission 'collectServerData' at global
capability level.

Preserve backward compatibility using reflection.

Change-Id: I3f58d1f3dca1daed7696bb7badead4240e55f187
diff --git a/build.sbt b/build.sbt
index 5c2df1c..23def50 100644
--- a/build.sbt
+++ b/build.sbt
@@ -6,6 +6,8 @@
 
 scalaVersion := "2.11.8"
 
+val gerritVersion = "2.15-SNAPSHOT"
+
 val scalatraV = "2.4.+"
 
 resolvers += Resolver.mavenLocal
@@ -13,7 +15,7 @@
 libraryDependencies ++= Seq(
   // provided by gerrit
   "com.google.inject"     %   "guice"             % "3.0"       % Provided,
-  "com.google.gerrit"     %   "gerrit-plugin-api" % "2.11"      % Provided,
+  "com.google.gerrit"     %   "gerrit-plugin-api" % gerritVersion % Provided,
   "com.google.code.gson"  %   "gson"              % "2.7"       % Provided,
   "joda-time"             %   "joda-time"         % "2.9.4"     % Provided,
 
@@ -36,6 +38,7 @@
   Package.ManifestAttributes(
     "Gerrit-ApiType" -> "plugin",
     "Gerrit-PluginName" -> pluginName,
+    "Gerrit-Module" -> "com.googlesource.gerrit.plugins.support.Module",
     "Gerrit-HttpModule" -> "com.googlesource.gerrit.plugins.support.HttpModule"
   )
 }
diff --git a/src/main/resources/Documentation/rest-api.md b/src/main/resources/Documentation/rest-api.md
index 878787d..aa8101a 100644
--- a/src/main/resources/Documentation/rest-api.md
+++ b/src/main/resources/Documentation/rest-api.md
@@ -7,7 +7,7 @@
 
 SYNOPSIS
 --------
->     POST /plugins/gerrit-support/collect
+>     POST /a/plugins/gerrit-support/collect
 
 DESCRIPTION
 -----------
@@ -20,6 +20,9 @@
 - cpuInfo - JSON Object with all the CPU information collected by [jHardware](https://github.com/profesorfalken/jHardware)
 - memInfo - JSON Object with all the Memory information collected by [jHardware](https://github.com/profesorfalken/jHardware)
 
+NOTE: API must be authenticated with the credentials of a user with the
+'Collect Server Data' capability.
+
 EXAMPLES
 --------
 
@@ -27,7 +30,7 @@
 
 >     curl -v -H "Content-Type: application/json" \
 >        -d '{"gerritVersion": true,"cpuInfo": true, "memInfo": true }' \
->        http://host:port/plugins/gerrit-support/collect
+>        http://host:port/a/plugins/gerrit-support/collect
 
 ```
 < HTTP/1.1 201 Created
@@ -37,7 +40,10 @@
 < Content-Length: 2
 
 ```
-NOTE: Location header gives the name of the prepared file created on Gerrit server.
+NOTE: Location header gives the name of the prepared file created on Gerrit
+server. API must be authenticated with the credentials of a user with the
+'Collect Server Data' capability.
+
 
 NAME
 ----
@@ -45,7 +51,7 @@
 
 SYNOPSIS
 --------
->     GET /plugins/gerrit-support/collect/<zip file name>
+>     GET /a/plugins/gerrit-support/collect/<zip file name>
 
 DESCRIPTION
 -----------
@@ -56,6 +62,6 @@
 
 Download the .zip support file
 
->     curl http://host:port/plugins/gerrit-support/collect/20170405-005334-collect-b6d2bc6a-7f01-4b93-9f74-ad28b4a68e67.zip \
+>     curl http://host:port/a/plugins/gerrit-support/collect/20170405-005334-collect-b6d2bc6a-7f01-4b93-9f74-ad28b4a68e67.zip \
 >          -o received.zip
 
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/support/CollectServerDataCapability.scala b/src/main/scala/com/googlesource/gerrit/plugins/support/CollectServerDataCapability.scala
new file mode 100644
index 0000000..c85f461
--- /dev/null
+++ b/src/main/scala/com/googlesource/gerrit/plugins/support/CollectServerDataCapability.scala
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 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.support
+
+import com.google.gerrit.extensions.api.access.PluginPermission
+import com.google.gerrit.extensions.config.CapabilityDefinition
+import com.google.gerrit.server.account.CapabilityControl
+
+import scala.util.Try
+
+class CollectServerDataCapability extends CapabilityDefinition {
+  override def getDescription: String = "Collect Server Data"
+}
+
+object CollectServerDataCapability {
+  val COLLECT_SERVER_DATA = "collectServerData"
+
+  val pluginName = "gerrit-support"
+
+  implicit class PimpedCapabilityControl(val capabilityControl: CapabilityControl) extends AnyVal {
+
+    def legacyCanPerform(operation: String): Try[Boolean] = Try {
+      val canPerform = capabilityControl.getClass.getMethod("canPerform", classOf[String])
+      canPerform.invoke(capabilityControl, operation).asInstanceOf[Boolean]
+    }
+
+    implicit def stringToGlobalOrPluginPermissions(operation: String) = new PluginPermission(pluginName, operation)
+
+    def canDo(operation: String): Boolean =
+      legacyCanPerform(operation).getOrElse {
+        capabilityControl.doCanForDefaultPermissionBackend(operation)
+      }
+  }
+}
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/support/GerritSupportServlet.scala b/src/main/scala/com/googlesource/gerrit/plugins/support/GerritSupportServlet.scala
index 382c978..13621d6 100644
--- a/src/main/scala/com/googlesource/gerrit/plugins/support/GerritSupportServlet.scala
+++ b/src/main/scala/com/googlesource/gerrit/plugins/support/GerritSupportServlet.scala
@@ -18,9 +18,9 @@
 
 import java.io.{File, FileNotFoundException}
 
-import com.google.gerrit.extensions.annotations._
 import com.google.gerrit.server.CurrentUser
 import com.google.inject.{Inject, Provider, Singleton}
+import com.googlesource.gerrit.plugins.support.CollectServerDataCapability._
 import eu.medsea.mimeutil.detector.ExtensionMimeDetector
 import org.scalatra._
 import org.scalatra.util.Mimes
@@ -61,8 +61,8 @@
 
   private def requireAdministrateServerPermissions(block: => ActionResult) = {
     currentUserProvider.get match {
-      case user if user.isIdentifiedUser && user.getCapabilities.canAdministrateServer => block
-      case _ => Forbidden("ACCESS DENIED TO NON-ADMINS")
+      case user if user.isIdentifiedUser && user.getCapabilities.canDo(COLLECT_SERVER_DATA) => block
+      case _ => Forbidden("NOT ALLOWED to collect server data")
     }
   }
 
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/support/Module.scala b/src/main/scala/com/googlesource/gerrit/plugins/support/Module.scala
new file mode 100644
index 0000000..cc871e5
--- /dev/null
+++ b/src/main/scala/com/googlesource/gerrit/plugins/support/Module.scala
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2017 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.support
+
+import com.google.inject.AbstractModule
+import com.google.gerrit.extensions.annotations.Exports
+import com.google.gerrit.extensions.config.CapabilityDefinition
+import CollectServerDataCapability.COLLECT_SERVER_DATA
+
+class Module extends AbstractModule {
+  override def configure() {
+    bind(classOf[CapabilityDefinition]).annotatedWith(Exports.named(COLLECT_SERVER_DATA))
+      .to(classOf[CollectServerDataCapability])
+  }
+}