Line data Source code
1 : // Copyright (C) 2015 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.config; 16 : 17 : import com.google.gerrit.entities.Account; 18 : import com.google.gerrit.extensions.restapi.AuthException; 19 : import com.google.gerrit.extensions.restapi.DefaultInput; 20 : import com.google.gerrit.extensions.restapi.Response; 21 : import com.google.gerrit.extensions.restapi.RestModifyView; 22 : import com.google.gerrit.extensions.restapi.UnprocessableEntityException; 23 : import com.google.gerrit.server.CurrentUser; 24 : import com.google.gerrit.server.account.AccountException; 25 : import com.google.gerrit.server.account.AccountManager; 26 : import com.google.gerrit.server.config.ConfigResource; 27 : import com.google.gerrit.server.mail.EmailTokenVerifier; 28 : import com.google.gerrit.server.restapi.config.ConfirmEmail.Input; 29 : import com.google.inject.Inject; 30 : import com.google.inject.Provider; 31 : import com.google.inject.Singleton; 32 : import java.io.IOException; 33 : import org.eclipse.jgit.errors.ConfigInvalidException; 34 : 35 : /** 36 : * REST endpoint to confirm an email address for an account. 37 : * 38 : * <p>This REST endpoint handles {@code PUT /config/server/email.confirm} requests. 39 : * 40 : * <p>When a user registers a new email address for their account (see {@link 41 : * com.google.gerrit.server.restapi.account.CreateEmail}) an email with a confirmation link is sent 42 : * to that address. When the receiver confirms the email by clicking on the confirmation link, this 43 : * REST endpoint is invoked and the email address is added to the account. Confirming an email 44 : * address for an account creates an external ID that links the email address to the account. An 45 : * email address can only be added to an account if it is not assigned to any other account yet. 46 : */ 47 : @Singleton 48 : public class ConfirmEmail implements RestModifyView<ConfigResource, Input> { 49 2 : public static class Input { 50 : @DefaultInput public String token; 51 : } 52 : 53 : private final Provider<CurrentUser> self; 54 : private final EmailTokenVerifier emailTokenVerifier; 55 : private final AccountManager accountManager; 56 : 57 : @Inject 58 : public ConfirmEmail( 59 : Provider<CurrentUser> self, 60 : EmailTokenVerifier emailTokenVerifier, 61 138 : AccountManager accountManager) { 62 138 : this.self = self; 63 138 : this.emailTokenVerifier = emailTokenVerifier; 64 138 : this.accountManager = accountManager; 65 138 : } 66 : 67 : @Override 68 : public Response<?> apply(ConfigResource rsrc, Input input) 69 : throws AuthException, UnprocessableEntityException, IOException, ConfigInvalidException { 70 2 : CurrentUser user = self.get(); 71 2 : if (!user.isIdentifiedUser()) { 72 0 : throw new AuthException("Authentication required"); 73 : } 74 : 75 2 : if (input == null) { 76 0 : input = new Input(); 77 : } 78 2 : if (input.token == null) { 79 1 : throw new UnprocessableEntityException("missing token"); 80 : } 81 : 82 : try { 83 1 : EmailTokenVerifier.ParsedToken token = emailTokenVerifier.decode(input.token); 84 1 : Account.Id accId = user.getAccountId(); 85 1 : if (accId.equals(token.getAccountId())) { 86 1 : accountManager.link(accId, token.toAuthRequest()); 87 1 : return Response.none(); 88 : } 89 1 : throw new UnprocessableEntityException("invalid token"); 90 1 : } catch (EmailTokenVerifier.InvalidTokenException e) { 91 1 : throw new UnprocessableEntityException("invalid token", e); 92 1 : } catch (AccountException e) { 93 1 : throw new UnprocessableEntityException(e.getMessage()); 94 : } 95 : } 96 : }