Allow admins to set/delete email even if email is not allowed

Administrators may generally disallow emails but then want to make
exceptions for a few service users. This is why they should always be
able to set/delete email addresses. Anyway they could use the normal
Gerrit core REST endpoints to do this.

Change-Id: Ifc1b06b261f5af0e888fcf063297d2a0c3db16bb
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutEmail.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutEmail.java
index d281105..5e1f2fe 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutEmail.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/PutEmail.java
@@ -24,6 +24,7 @@
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestModifyView;
+import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.account.CreateEmail;
 import com.google.gerrit.server.account.DeleteEmail;
 import com.google.gerrit.server.account.PutPreferred;
@@ -45,18 +46,21 @@
   private final Provider<CreateEmail.Factory> createEmailFactory;
   private final Provider<DeleteEmail> deleteEmail;
   private final Provider<PutPreferred> putPreferred;
+  private final Provider<CurrentUser> self;
 
   @Inject
   PutEmail(Provider<GetConfig> getConfig,
       Provider<GetEmail> getEmail,
       Provider<CreateEmail.Factory> createEmailFactory,
       Provider<DeleteEmail> deleteEmail,
-      Provider<PutPreferred> putPreferred) {
+      Provider<PutPreferred> putPreferred,
+      Provider<CurrentUser> self) {
     this.getConfig = getConfig;
     this.getEmail = getEmail;
     this.createEmailFactory = createEmailFactory;
     this.deleteEmail = deleteEmail;
     this.putPreferred = putPreferred;
+    this.self = self;
   }
 
   @Override
@@ -65,7 +69,8 @@
       ResourceConflictException, MethodNotAllowedException, OrmException,
       BadRequestException, EmailException {
     Boolean emailAllowed = getConfig.get().apply(new ConfigResource()).allowEmail;
-    if (emailAllowed == null || !emailAllowed) {
+    if ((emailAllowed == null || !emailAllowed)
+        && !self.get().getCapabilities().canAdministrateServer()) {
       throw new ResourceConflictException("setting email not allowed");
     }
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/AccountCapabilities.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/AccountCapabilities.java
new file mode 100644
index 0000000..c705d53
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/AccountCapabilities.java
@@ -0,0 +1,34 @@
+// Copyright (C) 2014 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.serviceuser.client;
+
+import com.google.gerrit.plugin.client.rpc.RestApi;
+import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+
+/** Capabilities the caller has from {@code /accounts/self/capabilities}.  */
+public class AccountCapabilities extends JavaScriptObject {
+  public static void all(AsyncCallback<AccountCapabilities> cb, String... filter) {
+    new RestApi("/accounts/self/capabilities")
+      .addParameter("q", filter)
+      .get(cb);
+  }
+
+  protected AccountCapabilities() {
+  }
+
+  public final native boolean canPerform(String name)
+  /*-{ return this[name] ? true : false; }-*/;
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ServiceUserScreen.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ServiceUserScreen.java
index d96c416..ea5c4fb 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ServiceUserScreen.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/client/ServiceUserScreen.java
@@ -48,8 +48,19 @@
                   .view(Plugin.get().getPluginName(), "config")
                   .get(new AsyncCallback<ConfigInfo>() {
                     @Override
-                    public void onSuccess(ConfigInfo configInfo) {
-                      display(serviceUserInfo, configInfo.getAllowEmail());
+                    public void onSuccess(final ConfigInfo configInfo) {
+                      AccountCapabilities.all(new AsyncCallback<AccountCapabilities>() {
+                        @Override
+                        public void onSuccess(AccountCapabilities ac) {
+                            display(serviceUserInfo, configInfo.getAllowEmail()
+                                || ac.canPerform("administrateServer"));
+                        }
+
+                        @Override
+                        public void onFailure(Throwable caught) {
+                          // never invoked
+                        }
+                      }, "administrateServer");
                     }
 
                     @Override