Support to set an email address as preferred upon creation via REST

Change-Id: Ifc3aeb489fa6e45d816c73216f912ff731db30de
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
diff --git a/Documentation/rest-api-accounts.txt b/Documentation/rest-api-accounts.txt
index 9794666..0c9df42 100644
--- a/Documentation/rest-api-accounts.txt
+++ b/Documentation/rest-api-accounts.txt
@@ -236,9 +236,17 @@
 For the development mode email addresses are directly added without
 confirmation.
 
+In the request body additional data for the email address can be
+provided as link:#email-input[EmailInput].
+
 .Request
 ----
   PUT /accounts/self/emails/john.doe@example.com HTTP/1.0
+  Content-Type: application/json;charset=UTF-8
+
+  {
+    "preferred": true
+  }
 ----
 
 As response the new email address is returned as
@@ -252,7 +260,8 @@
 
   )]}'
   {
-    "email": "john.doe@example.com"
+    "email": "john.doe@example.com",
+    "preferred": true
   }
 ----
 
@@ -853,6 +862,23 @@
 Whether this is the preferred email address of the user.
 |========================
 
+[[email-input]]
+EmailInput
+~~~~~~~~~~
+The `EmailInput` entity contains information for registering a new
+email address.
+
+[options="header",width="50%",cols="1,^1,5"]
+|========================
+|Field Name ||Description
+|`email`    ||
+The email address. If provided, must match the email address from the
+URL.
+|`preferred`|`false` if not set|
+Whether the new email address should become the preferred email address
+of the user.
+|========================
+
 [[query-limit-info]]
 QueryLimitInfo
 ~~~~~~~~~~~~~~
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 a2c71da..28f8547 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
@@ -16,7 +16,10 @@
 
 import com.google.gerrit.common.errors.EmailException;
 import com.google.gerrit.extensions.restapi.AuthException;
+import com.google.gerrit.extensions.restapi.BadRequestException;
+import com.google.gerrit.extensions.restapi.DefaultInput;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
+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.reviewdb.client.AuthType;
@@ -38,6 +41,9 @@
   private final Logger log = LoggerFactory.getLogger(getClass());
 
   static class Input {
+    @DefaultInput
+    String email;
+    boolean preferred;
   }
 
   static interface Factory {
@@ -48,28 +54,38 @@
   private final AuthConfig authConfig;
   private final AccountManager accountManager;
   private final RegisterNewEmailSender.Factory registerNewEmailFactory;
+  private final Provider<PutPreferred> putPreferredProvider;
   private final String email;
 
   @Inject
   CreateEmail(Provider<CurrentUser> self, AuthConfig authConfig,
       AccountManager accountManager,
       RegisterNewEmailSender.Factory registerNewEmailFactory,
-      @Assisted String email) {
+      Provider<PutPreferred> putPreferredProvider, @Assisted String email) {
     this.self = self;
     this.authConfig = authConfig;
     this.accountManager = accountManager;
     this.registerNewEmailFactory = registerNewEmailFactory;
+    this.putPreferredProvider = putPreferredProvider;
     this.email = email;
   }
 
   @Override
   public Object apply(AccountResource rsrc, Input input) throws AuthException,
-      ResourceConflictException, OrmException, EmailException {
+      BadRequestException, ResourceConflictException,
+      ResourceNotFoundException, OrmException, EmailException {
     IdentifiedUser s = (IdentifiedUser) self.get();
     if (s.getAccountId().get() != rsrc.getUser().getAccountId().get()
         && !self.get().getCapabilities().canAdministrateServer()) {
       throw new AuthException("not allowed to add email address");
     }
+    if (input == null) {
+      input = new Input();
+    }
+    if (input.email != null && !email.equals(input.email)) {
+      throw new BadRequestException("email address must match URL");
+    }
+
     if (authConfig.getAuthType() == AuthType.DEVELOPMENT_BECOME_ANY_ACCOUNT) {
       try {
         accountManager.link(rsrc.getUser().getAccountId(),
@@ -91,6 +107,11 @@
     }
     EmailInfo e = new EmailInfo();
     e.email = email;
+    if (input.preferred) {
+      putPreferredProvider.get().apply(
+          new AccountResource.Email(rsrc.getUser(), email), null);
+      e.setPreferred(true);
+    }
     return Response.created(e);
   }
 }