Merge "AccountApi: Add methods to get emails and delete email"
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java
index 130eb23..11b452e 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java
@@ -29,6 +29,7 @@
 import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
 import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
 import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.util.stream.Collectors.toSet;
 import static org.junit.Assert.fail;
 
 import com.google.common.collect.FluentIterable;
@@ -54,6 +55,7 @@
 import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
+import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.gpg.Fingerprint;
 import com.google.gerrit.gpg.PublicKeyStore;
 import com.google.gerrit.gpg.server.GpgKeys;
@@ -80,6 +82,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import org.bouncycastle.bcpg.ArmoredOutputStream;
 import org.bouncycastle.openpgp.PGPPublicKey;
 import org.bouncycastle.openpgp.PGPPublicKeyRing;
@@ -374,24 +377,19 @@
 
             // Not in the list of TLDs but added to override in OutgoingEmailValidator
             "new.email@example.local");
+    Set<String> currentEmails = getEmails();
     for (String email : emails) {
+      assertThat(currentEmails).doesNotContain(email);
       EmailInput input = new EmailInput();
       input.email = email;
       input.noConfirmation = true;
       gApi.accounts().self().addEmail(input);
     }
-  }
 
-  @Test
-  public void putStatus() throws Exception {
-    List<String> statuses = ImmutableList.of("OOO", "Busy");
-    AccountInfo info;
-    for (String status : statuses) {
-      gApi.accounts().self().setStatus(status);
-      admin.status = status;
-      info = gApi.accounts().self().get();
-      assertUser(info, admin);
-    }
+    // enforce a new request context so that emails that are cached in
+    // IdentifiedUser are reloaded
+    setApiUser(admin);
+    assertThat(getEmails()).containsAllIn(emails);
   }
 
   @Test
@@ -423,6 +421,39 @@
   }
 
   @Test
+  public void deleteEmail() throws Exception {
+    String email = "foo.bar@example.com";
+    EmailInput input = new EmailInput();
+    input.email = email;
+    input.noConfirmation = true;
+    gApi.accounts().self().addEmail(input);
+
+    // enforce a new request context so that emails that are cached in
+    // IdentifiedUser are reloaded
+    setApiUser(admin);
+    assertThat(getEmails()).contains(email);
+
+    gApi.accounts().self().deleteEmail(input.email);
+
+    // enforce a new request context so that emails that are cached in
+    // IdentifiedUser are reloaded
+    setApiUser(admin);
+    assertThat(getEmails()).doesNotContain(email);
+  }
+
+  @Test
+  public void putStatus() throws Exception {
+    List<String> statuses = ImmutableList.of("OOO", "Busy");
+    AccountInfo info;
+    for (String status : statuses) {
+      gApi.accounts().self().setStatus(status);
+      admin.status = status;
+      info = gApi.accounts().self().get();
+      assertUser(info, admin);
+    }
+  }
+
+  @Test
   public void fetchUserBranch() throws Exception {
     // change something in the user preferences to ensure that the user branch
     // is created
@@ -851,4 +882,8 @@
     assertThat(info.username).isEqualTo(account.username);
     assertThat(info.status).isEqualTo(account.status);
   }
+
+  private Set<String> getEmails() throws RestApiException {
+    return gApi.accounts().self().getEmails().stream().map(e -> e.email).collect(toSet());
+  }
 }
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/AccountApi.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/AccountApi.java
index 025ac30..876f85a 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/AccountApi.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/AccountApi.java
@@ -23,6 +23,7 @@
 import com.google.gerrit.extensions.common.AccountInfo;
 import com.google.gerrit.extensions.common.AgreementInfo;
 import com.google.gerrit.extensions.common.ChangeInfo;
+import com.google.gerrit.extensions.common.EmailInfo;
 import com.google.gerrit.extensions.common.GpgKeyInfo;
 import com.google.gerrit.extensions.common.SshKeyInfo;
 import com.google.gerrit.extensions.restapi.NotImplementedException;
@@ -68,8 +69,12 @@
 
   List<ChangeInfo> getStarredChanges() throws RestApiException;
 
+  List<EmailInfo> getEmails() throws RestApiException;
+
   void addEmail(EmailInput input) throws RestApiException;
 
+  void deleteEmail(String email) throws RestApiException;
+
   void setStatus(String status) throws RestApiException;
 
   List<SshKeyInfo> listSshKeys() throws RestApiException;
@@ -190,11 +195,21 @@
     }
 
     @Override
+    public List<EmailInfo> getEmails() {
+      throw new NotImplementedException();
+    }
+
+    @Override
     public void addEmail(EmailInput input) {
       throw new NotImplementedException();
     }
 
     @Override
+    public void deleteEmail(String email) {
+      throw new NotImplementedException();
+    }
+
+    @Override
     public void setStatus(String status) {
       throw new NotImplementedException();
     }
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/common/EmailInfo.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/common/EmailInfo.java
new file mode 100644
index 0000000..184a89f
--- /dev/null
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/common/EmailInfo.java
@@ -0,0 +1,25 @@
+// 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.google.gerrit.extensions.common;
+
+public class EmailInfo {
+  public String email;
+  public Boolean preferred;
+  public Boolean pendingConfirmation;
+
+  public void preferred(String e) {
+    this.preferred = e != null && e.equals(email) ? true : null;
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/CreateEmail.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/CreateEmail.java
index 8aa356f..005630c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/CreateEmail.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/CreateEmail.java
@@ -19,6 +19,7 @@
 import com.google.gerrit.common.errors.EmailException;
 import com.google.gerrit.extensions.api.accounts.EmailInput;
 import com.google.gerrit.extensions.client.AccountFieldName;
+import com.google.gerrit.extensions.common.EmailInfo;
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
@@ -28,7 +29,6 @@
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
-import com.google.gerrit.server.account.GetEmails.EmailInfo;
 import com.google.gerrit.server.config.AuthConfig;
 import com.google.gerrit.server.mail.send.OutgoingEmailValidator;
 import com.google.gerrit.server.mail.send.RegisterNewEmailSender;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GetEmail.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GetEmail.java
index edc2592..82e0944 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GetEmail.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GetEmail.java
@@ -14,8 +14,8 @@
 
 package com.google.gerrit.server.account;
 
+import com.google.gerrit.extensions.common.EmailInfo;
 import com.google.gerrit.extensions.restapi.RestReadView;
-import com.google.gerrit.server.account.GetEmails.EmailInfo;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GetEmails.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GetEmails.java
index 5d4fd9d..184780f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GetEmails.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GetEmails.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.server.account;
 
+import com.google.gerrit.extensions.common.EmailInfo;
 import com.google.gerrit.extensions.restapi.RestReadView;
 import com.google.inject.Singleton;
 import java.util.ArrayList;
@@ -45,14 +46,4 @@
         });
     return emails;
   }
-
-  public static class EmailInfo {
-    public String email;
-    public Boolean preferred;
-    public Boolean pendingConfirmation;
-
-    void preferred(String e) {
-      this.preferred = e != null && e.equals(email) ? true : null;
-    }
-  }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountApiImpl.java
index e1eb119..7b8637c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountApiImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountApiImpl.java
@@ -31,6 +31,7 @@
 import com.google.gerrit.extensions.common.AgreementInfo;
 import com.google.gerrit.extensions.common.AgreementInput;
 import com.google.gerrit.extensions.common.ChangeInfo;
+import com.google.gerrit.extensions.common.EmailInfo;
 import com.google.gerrit.extensions.common.GpgKeyInfo;
 import com.google.gerrit.extensions.common.SshKeyInfo;
 import com.google.gerrit.extensions.restapi.IdString;
@@ -43,6 +44,7 @@
 import com.google.gerrit.server.account.AddSshKey;
 import com.google.gerrit.server.account.CreateEmail;
 import com.google.gerrit.server.account.DeleteActive;
+import com.google.gerrit.server.account.DeleteEmail;
 import com.google.gerrit.server.account.DeleteExternalIds;
 import com.google.gerrit.server.account.DeleteSshKey;
 import com.google.gerrit.server.account.DeleteWatchedProjects;
@@ -51,6 +53,7 @@
 import com.google.gerrit.server.account.GetAvatar;
 import com.google.gerrit.server.account.GetDiffPreferences;
 import com.google.gerrit.server.account.GetEditPreferences;
+import com.google.gerrit.server.account.GetEmails;
 import com.google.gerrit.server.account.GetExternalIds;
 import com.google.gerrit.server.account.GetPreferences;
 import com.google.gerrit.server.account.GetSshKeys;
@@ -100,7 +103,9 @@
   private final Stars stars;
   private final Stars.Get starsGet;
   private final Stars.Post starsPost;
+  private final GetEmails getEmails;
   private final CreateEmail.Factory createEmailFactory;
+  private final DeleteEmail deleteEmail;
   private final GpgApiAdapter gpgApiAdapter;
   private final GetSshKeys getSshKeys;
   private final AddSshKey addSshKey;
@@ -135,7 +140,9 @@
       Stars stars,
       Stars.Get starsGet,
       Stars.Post starsPost,
+      GetEmails getEmails,
       CreateEmail.Factory createEmailFactory,
+      DeleteEmail deleteEmail,
       GpgApiAdapter gpgApiAdapter,
       GetSshKeys getSshKeys,
       AddSshKey addSshKey,
@@ -169,7 +176,9 @@
     this.stars = stars;
     this.starsGet = starsGet;
     this.starsPost = starsPost;
+    this.getEmails = getEmails;
     this.createEmailFactory = createEmailFactory;
+    this.deleteEmail = deleteEmail;
     this.getSshKeys = getSshKeys;
     this.addSshKey = addSshKey;
     this.deleteSshKey = deleteSshKey;
@@ -354,6 +363,11 @@
   }
 
   @Override
+  public List<EmailInfo> getEmails() {
+    return getEmails.apply(account);
+  }
+
+  @Override
   public void addEmail(EmailInput input) throws RestApiException {
     AccountResource.Email rsrc = new AccountResource.Email(account.getUser(), input.email);
     try {
@@ -364,6 +378,16 @@
   }
 
   @Override
+  public void deleteEmail(String email) throws RestApiException {
+    AccountResource.Email rsrc = new AccountResource.Email(account.getUser(), email);
+    try {
+      deleteEmail.apply(rsrc, null);
+    } catch (OrmException | IOException e) {
+      throw new RestApiException("Cannot delete email", e);
+    }
+  }
+
+  @Override
   public void setStatus(String status) throws RestApiException {
     PutStatus.Input in = new PutStatus.Input(status);
     try {
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetAccountCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetAccountCommand.java
index 7f3a90f..ce58921 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetAccountCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetAccountCommand.java
@@ -22,6 +22,7 @@
 import com.google.gerrit.common.errors.EmailException;
 import com.google.gerrit.extensions.annotations.RequiresCapability;
 import com.google.gerrit.extensions.api.accounts.EmailInput;
+import com.google.gerrit.extensions.common.EmailInfo;
 import com.google.gerrit.extensions.common.SshKeyInfo;
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
@@ -36,7 +37,6 @@
 import com.google.gerrit.server.account.DeleteEmail;
 import com.google.gerrit.server.account.DeleteSshKey;
 import com.google.gerrit.server.account.GetEmails;
-import com.google.gerrit.server.account.GetEmails.EmailInfo;
 import com.google.gerrit.server.account.GetSshKeys;
 import com.google.gerrit.server.account.PutActive;
 import com.google.gerrit.server.account.PutHttpPassword;