Line data Source code
1 : // Copyright (C) 2013 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.server.restapi.account; 16 : 17 : import static java.util.stream.Collectors.toSet; 18 : 19 : import com.google.gerrit.entities.Account; 20 : import com.google.gerrit.extensions.client.AccountFieldName; 21 : import com.google.gerrit.extensions.client.AuthType; 22 : import com.google.gerrit.extensions.common.Input; 23 : import com.google.gerrit.extensions.restapi.AuthException; 24 : import com.google.gerrit.extensions.restapi.MethodNotAllowedException; 25 : import com.google.gerrit.extensions.restapi.ResourceConflictException; 26 : import com.google.gerrit.extensions.restapi.ResourceNotFoundException; 27 : import com.google.gerrit.extensions.restapi.Response; 28 : import com.google.gerrit.extensions.restapi.RestModifyView; 29 : import com.google.gerrit.server.CurrentUser; 30 : import com.google.gerrit.server.IdentifiedUser; 31 : import com.google.gerrit.server.account.AccountException; 32 : import com.google.gerrit.server.account.AccountManager; 33 : import com.google.gerrit.server.account.AccountResource; 34 : import com.google.gerrit.server.account.Realm; 35 : import com.google.gerrit.server.account.externalids.ExternalId; 36 : import com.google.gerrit.server.account.externalids.ExternalIds; 37 : import com.google.gerrit.server.config.AuthConfig; 38 : import com.google.gerrit.server.permissions.GlobalPermission; 39 : import com.google.gerrit.server.permissions.PermissionBackend; 40 : import com.google.gerrit.server.permissions.PermissionBackendException; 41 : import com.google.inject.Inject; 42 : import com.google.inject.Provider; 43 : import com.google.inject.Singleton; 44 : import java.io.IOException; 45 : import java.util.Set; 46 : import org.eclipse.jgit.errors.ConfigInvalidException; 47 : 48 : @Singleton 49 : public class DeleteEmail implements RestModifyView<AccountResource.Email, Input> { 50 : 51 : private final Provider<CurrentUser> self; 52 : private final Realm realm; 53 : private final PermissionBackend permissionBackend; 54 : private final AccountManager accountManager; 55 : private final ExternalIds externalIds; 56 : private final AuthType authType; 57 : 58 : @Inject 59 : DeleteEmail( 60 : Provider<CurrentUser> self, 61 : Realm realm, 62 : PermissionBackend permissionBackend, 63 : AccountManager accountManager, 64 : ExternalIds externalIds, 65 148 : AuthConfig authConfig) { 66 148 : this.self = self; 67 148 : this.realm = realm; 68 148 : this.permissionBackend = permissionBackend; 69 148 : this.accountManager = accountManager; 70 148 : this.externalIds = externalIds; 71 148 : this.authType = authConfig.getAuthType(); 72 148 : } 73 : 74 : @Override 75 : public Response<?> apply(AccountResource.Email rsrc, Input input) 76 : throws AuthException, ResourceNotFoundException, ResourceConflictException, 77 : MethodNotAllowedException, IOException, ConfigInvalidException, 78 : PermissionBackendException { 79 3 : if (!self.get().hasSameAccountId(rsrc.getUser())) { 80 1 : permissionBackend.currentUser().check(GlobalPermission.MODIFY_ACCOUNT); 81 : } 82 3 : return apply(rsrc.getUser(), rsrc.getEmail()); 83 : } 84 : 85 : public Response<?> apply(IdentifiedUser user, String email) 86 : throws ResourceNotFoundException, ResourceConflictException, MethodNotAllowedException, 87 : IOException, ConfigInvalidException { 88 3 : Account.Id accountId = user.getAccountId(); 89 3 : if (realm.accountBelongsToRealm(externalIds.byAccount(accountId)) 90 1 : && !realm.allowsEdit(AccountFieldName.REGISTER_NEW_EMAIL)) { 91 0 : throw new MethodNotAllowedException("realm does not allow deleting emails"); 92 : } 93 : 94 3 : Set<ExternalId> extIds = 95 3 : externalIds.byAccount(accountId).stream() 96 3 : .filter(e -> email.equals(e.email())) 97 3 : .collect(toSet()); 98 3 : if (extIds.isEmpty()) { 99 0 : throw new ResourceNotFoundException(email); 100 : } 101 : 102 3 : if (realm.accountBelongsToRealm(extIds)) { 103 1 : String errorMsg = 104 1 : String.format( 105 : "Cannot remove e-mail '%s' which is directly associated with %s authentication", 106 : email, authType); 107 1 : throw new ResourceConflictException(errorMsg); 108 : } 109 : 110 : try { 111 3 : accountManager.unlink( 112 3 : user.getAccountId(), extIds.stream().map(ExternalId::key).collect(toSet())); 113 0 : } catch (AccountException e) { 114 0 : throw new ResourceConflictException(e.getMessage()); 115 3 : } 116 3 : return Response.none(); 117 : } 118 : }