Support deletion of email address via REST
Change-Id: I3637a7f4497ddc2f88523728e5315ff56da92b8f
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
diff --git a/Documentation/rest-api-accounts.txt b/Documentation/rest-api-accounts.txt
index a78385a..075826b 100644
--- a/Documentation/rest-api-accounts.txt
+++ b/Documentation/rest-api-accounts.txt
@@ -267,6 +267,24 @@
}
----
+[[delete-account-email]]
+Delete Account Email
+~~~~~~~~~~~~~~~~~~~~
+[verse]
+'DELETE /accounts/link:#account-id[\{account-id\}]/emails/link:#email-id[\{email-id\}]'
+
+Deletes an email address of an account.
+
+.Request
+----
+ DELETE /accounts/self/emails/john.doe@example.com HTTP/1.0
+----
+
+.Response
+----
+ HTTP/1.1 204 No Content
+----
+
[[set-preferred-email]]
Set Preferred Email
~~~~~~~~~~~~~~~~~~~
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java
index c21d375..10b34ac 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java
@@ -435,42 +435,38 @@
* cannot be unlinked at this time.
*/
public AuthResult unlink(final Account.Id from, AuthRequest who)
- throws AccountException {
+ throws AccountException, OrmException {
+ final ReviewDb db = schema.open();
try {
- final ReviewDb db = schema.open();
- try {
- who = realm.unlink(db, from, who);
+ who = realm.unlink(db, from, who);
- final AccountExternalId.Key key = id(who);
- AccountExternalId extId = db.accountExternalIds().get(key);
- if (extId != null) {
- if (!extId.getAccountId().equals(from)) {
- throw new AccountException("Identity in use by another account");
+ final AccountExternalId.Key key = id(who);
+ AccountExternalId extId = db.accountExternalIds().get(key);
+ if (extId != null) {
+ if (!extId.getAccountId().equals(from)) {
+ throw new AccountException("Identity in use by another account");
+ }
+ db.accountExternalIds().delete(Collections.singleton(extId));
+
+ if (who.getEmailAddress() != null) {
+ final Account a = db.accounts().get(from);
+ if (a.getPreferredEmail() != null
+ && a.getPreferredEmail().equals(who.getEmailAddress())) {
+ a.setPreferredEmail(null);
+ db.accounts().update(Collections.singleton(a));
}
- db.accountExternalIds().delete(Collections.singleton(extId));
-
- if (who.getEmailAddress() != null) {
- final Account a = db.accounts().get(from);
- if (a.getPreferredEmail() != null
- && a.getPreferredEmail().equals(who.getEmailAddress())) {
- a.setPreferredEmail(null);
- db.accounts().update(Collections.singleton(a));
- }
- byEmailCache.evict(who.getEmailAddress());
- byIdCache.evict(from);
- }
-
- } else {
- throw new AccountException("Identity not found");
+ byEmailCache.evict(who.getEmailAddress());
+ byIdCache.evict(from);
}
- return new AuthResult(from, key, false);
-
- } finally {
- db.close();
+ } else {
+ throw new AccountException("Identity not found");
}
- } catch (OrmException e) {
- throw new AccountException("Cannot unlink identity", e);
+
+ return new AuthResult(from, key, false);
+
+ } finally {
+ db.close();
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/DeleteEmail.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/DeleteEmail.java
new file mode 100644
index 0000000..67bb968
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/DeleteEmail.java
@@ -0,0 +1,75 @@
+// Copyright (C) 2013 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.server.account;
+
+import com.google.gerrit.extensions.restapi.AuthException;
+import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
+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.Account.FieldName;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.account.DeleteEmail.Input;
+import com.google.gwtorm.server.OrmException;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+public class DeleteEmail implements RestModifyView<AccountResource.Email, Input> {
+ static class Input {
+ }
+
+ private final Provider<CurrentUser> self;
+ private final Realm realm;
+ private final Provider<ReviewDb> dbProvider;
+ private final AccountManager accountManager;
+
+ @Inject
+ DeleteEmail(Provider<CurrentUser> self, Realm realm,
+ Provider<ReviewDb> dbProvider, AccountManager accountManager) {
+ this.self = self;
+ this.realm = realm;
+ this.dbProvider = dbProvider;
+ this.accountManager = accountManager;
+ }
+
+ @Override
+ public Object apply(AccountResource.Email rsrc, Input input)
+ throws AuthException, ResourceNotFoundException,
+ ResourceConflictException, MethodNotAllowedException, OrmException {
+ if (self.get() != rsrc.getUser()
+ && !self.get().getCapabilities().canAdministrateServer()) {
+ throw new AuthException("not allowed to delete email address");
+ }
+ if (!realm.allowsEdit(FieldName.REGISTER_NEW_EMAIL)) {
+ throw new MethodNotAllowedException("realm does not allow deleting emails");
+ }
+ AccountExternalId.Key key = new AccountExternalId.Key(
+ AccountExternalId.SCHEME_MAILTO, rsrc.getEmail());
+ AccountExternalId extId = dbProvider.get().accountExternalIds().get(key);
+ if (extId == null) {
+ throw new ResourceNotFoundException(rsrc.getEmail());
+ }
+ try {
+ accountManager.unlink(rsrc.getUser().getAccountId(),
+ AuthRequest.forEmail(rsrc.getEmail()));
+ } catch (AccountException e) {
+ throw new ResourceConflictException(e.getMessage());
+ }
+ return Response.none();
+ }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/Module.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/Module.java
index 860a96e..4215cf2 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/Module.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/Module.java
@@ -40,6 +40,7 @@
child(ACCOUNT_KIND, "emails").to(Emails.class);
get(EMAIL_KIND).to(GetEmail.class);
put(EMAIL_KIND).to(PutEmail.class);
+ delete(EMAIL_KIND).to(DeleteEmail.class);
put(EMAIL_KIND, "preferred").to(PutPreferred.class);
get(ACCOUNT_KIND, "avatar").to(GetAvatar.class);
get(ACCOUNT_KIND, "avatar.change.url").to(GetAvatarChangeUrl.class);
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 4c23833..8d24757 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
@@ -260,6 +260,8 @@
manager.unlink(id, AuthRequest.forEmail(mailAddress));
} catch (AccountException ex) {
throw die(ex.getMessage());
+ } catch (OrmException ex) {
+ throw die(ex.getMessage());
}
}