LCOV - code coverage report
Current view: top level - acceptance/testsuite/account - AccountOperationsImpl.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 81 103 78.6 %
Date: 2022-11-19 15:00:39 Functions: 25 31 80.6 %

          Line data    Source code
       1             : // Copyright (C) 2018 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.acceptance.testsuite.account;
      16             : 
      17             : import static com.google.common.base.Preconditions.checkState;
      18             : import static com.google.common.collect.ImmutableSet.toImmutableSet;
      19             : 
      20             : import com.google.common.collect.ImmutableSet;
      21             : import com.google.common.collect.Sets;
      22             : import com.google.gerrit.entities.Account;
      23             : import com.google.gerrit.server.ServerInitiated;
      24             : import com.google.gerrit.server.account.AccountDelta;
      25             : import com.google.gerrit.server.account.AccountState;
      26             : import com.google.gerrit.server.account.Accounts;
      27             : import com.google.gerrit.server.account.AccountsUpdate;
      28             : import com.google.gerrit.server.account.AccountsUpdate.ConfigureDeltaFromState;
      29             : import com.google.gerrit.server.account.externalids.ExternalId;
      30             : import com.google.gerrit.server.account.externalids.ExternalIdFactory;
      31             : import com.google.gerrit.server.notedb.Sequences;
      32             : import com.google.inject.Inject;
      33             : import java.io.IOException;
      34             : import java.util.Optional;
      35             : import java.util.function.Consumer;
      36             : import org.eclipse.jgit.errors.ConfigInvalidException;
      37             : 
      38             : /**
      39             :  * The implementation of {@code AccountOperations}.
      40             :  *
      41             :  * <p>There is only one implementation of {@code AccountOperations}. Nevertheless, we keep the
      42             :  * separation between interface and implementation to enhance clarity.
      43             :  */
      44             : public class AccountOperationsImpl implements AccountOperations {
      45             :   private final Accounts accounts;
      46             :   private final AccountsUpdate accountsUpdate;
      47             :   private final Sequences seq;
      48             :   private final ExternalIdFactory externalIdFactory;
      49             : 
      50             :   @Inject
      51             :   public AccountOperationsImpl(
      52             :       Accounts accounts,
      53             :       @ServerInitiated AccountsUpdate accountsUpdate,
      54             :       Sequences seq,
      55         138 :       ExternalIdFactory externalIdFactory) {
      56         138 :     this.accounts = accounts;
      57         138 :     this.accountsUpdate = accountsUpdate;
      58         138 :     this.seq = seq;
      59         138 :     this.externalIdFactory = externalIdFactory;
      60         138 :   }
      61             : 
      62             :   @Override
      63             :   public PerAccountOperations account(Account.Id accountId) {
      64         132 :     return new PerAccountOperationsImpl(accountId);
      65             :   }
      66             : 
      67             :   @Override
      68             :   public TestAccountCreation.Builder newAccount() {
      69          11 :     return TestAccountCreation.builder(this::createAccount);
      70             :   }
      71             : 
      72             :   private Account.Id createAccount(TestAccountCreation testAccountCreation) throws Exception {
      73          11 :     Account.Id accountId = Account.id(seq.nextAccountId());
      74          11 :     Consumer<AccountDelta.Builder> accountCreation =
      75          11 :         deltaBuilder -> initAccountDelta(deltaBuilder, testAccountCreation, accountId);
      76          11 :     AccountState createdAccount =
      77          11 :         accountsUpdate.insert("Create Test Account", accountId, accountCreation);
      78          11 :     return createdAccount.account().id();
      79             :   }
      80             : 
      81             :   private void initAccountDelta(
      82             :       AccountDelta.Builder builder, TestAccountCreation accountCreation, Account.Id accountId) {
      83          11 :     accountCreation.fullname().ifPresent(builder::setFullName);
      84          11 :     accountCreation.preferredEmail().ifPresent(e -> setPreferredEmail(builder, accountId, e));
      85          11 :     String httpPassword = accountCreation.httpPassword().orElse(null);
      86          11 :     accountCreation.username().ifPresent(u -> setUsername(builder, accountId, u, httpPassword));
      87          11 :     accountCreation.status().ifPresent(builder::setStatus);
      88          11 :     accountCreation.active().ifPresent(builder::setActive);
      89          11 :     accountCreation
      90          11 :         .secondaryEmails()
      91          11 :         .forEach(
      92             :             secondaryEmail ->
      93           1 :                 builder.addExternalId(externalIdFactory.createEmail(accountId, secondaryEmail)));
      94          11 :   }
      95             : 
      96             :   private void setPreferredEmail(
      97             :       AccountDelta.Builder builder, Account.Id accountId, String preferredEmail) {
      98           4 :     builder
      99           4 :         .setPreferredEmail(preferredEmail)
     100           4 :         .addExternalId(externalIdFactory.createEmail(accountId, preferredEmail));
     101           4 :   }
     102             : 
     103             :   private void setUsername(
     104             :       AccountDelta.Builder builder, Account.Id accountId, String username, String httpPassword) {
     105           5 :     builder.addExternalId(externalIdFactory.createUsername(username, accountId, httpPassword));
     106           5 :   }
     107             : 
     108             :   private class PerAccountOperationsImpl implements PerAccountOperations {
     109             :     private final Account.Id accountId;
     110             : 
     111         132 :     PerAccountOperationsImpl(Account.Id accountId) {
     112         132 :       this.accountId = accountId;
     113         132 :     }
     114             : 
     115             :     @Override
     116             :     public boolean exists() {
     117           0 :       return getAccountState(accountId).isPresent();
     118             :     }
     119             : 
     120             :     @Override
     121             :     public TestAccount get() {
     122         132 :       AccountState account =
     123         132 :           getAccountState(accountId)
     124         132 :               .orElseThrow(
     125           1 :                   () -> new IllegalStateException("Tried to get non-existing test account"));
     126         132 :       return toTestAccount(account);
     127             :     }
     128             : 
     129             :     private Optional<AccountState> getAccountState(Account.Id accountId) {
     130             :       try {
     131         132 :         return accounts.get(accountId);
     132           0 :       } catch (IOException | ConfigInvalidException e) {
     133           0 :         throw new IllegalStateException(e);
     134             :       }
     135             :     }
     136             : 
     137             :     private TestAccount toTestAccount(AccountState accountState) {
     138         132 :       Account account = accountState.account();
     139         132 :       return TestAccount.builder()
     140         132 :           .accountId(account.id())
     141         132 :           .preferredEmail(Optional.ofNullable(account.preferredEmail()))
     142         132 :           .fullname(Optional.ofNullable(account.fullName()))
     143         132 :           .username(accountState.userName())
     144         132 :           .active(accountState.account().isActive())
     145         132 :           .emails(ExternalId.getEmails(accountState.externalIds()).collect(toImmutableSet()))
     146         132 :           .build();
     147             :     }
     148             : 
     149             :     @Override
     150             :     public TestAccountUpdate.Builder forUpdate() {
     151           3 :       return TestAccountUpdate.builder(this::updateAccount);
     152             :     }
     153             : 
     154             :     private void updateAccount(TestAccountUpdate accountUpdate)
     155             :         throws IOException, ConfigInvalidException {
     156           3 :       ConfigureDeltaFromState configureDeltaFromState =
     157           3 :           (accountState, deltaBuilder) -> fillBuilder(deltaBuilder, accountUpdate, accountState);
     158           3 :       Optional<AccountState> updatedAccount = updateAccount(configureDeltaFromState);
     159           3 :       checkState(updatedAccount.isPresent(), "Tried to update non-existing test account");
     160           3 :     }
     161             : 
     162             :     private Optional<AccountState> updateAccount(ConfigureDeltaFromState configureDeltaFromState)
     163             :         throws IOException, ConfigInvalidException {
     164           4 :       return accountsUpdate.update("Update Test Account", accountId, configureDeltaFromState);
     165             :     }
     166             : 
     167             :     private void fillBuilder(
     168             :         AccountDelta.Builder builder, TestAccountUpdate accountUpdate, AccountState accountState) {
     169           3 :       accountUpdate.fullname().ifPresent(builder::setFullName);
     170           3 :       accountUpdate.preferredEmail().ifPresent(e -> setPreferredEmail(builder, accountId, e));
     171           3 :       String httpPassword = accountUpdate.httpPassword().orElse(null);
     172           3 :       accountUpdate.username().ifPresent(u -> setUsername(builder, accountId, u, httpPassword));
     173           3 :       accountUpdate.status().ifPresent(builder::setStatus);
     174           3 :       accountUpdate.active().ifPresent(builder::setActive);
     175             : 
     176           3 :       ImmutableSet<String> secondaryEmails = getSecondaryEmails(accountUpdate, accountState);
     177           3 :       ImmutableSet<String> newSecondaryEmails =
     178           3 :           ImmutableSet.copyOf(accountUpdate.secondaryEmailsModification().apply(secondaryEmails));
     179           3 :       if (!secondaryEmails.equals(newSecondaryEmails)) {
     180           0 :         setSecondaryEmails(builder, accountUpdate, accountState, newSecondaryEmails);
     181             :       }
     182           3 :     }
     183             : 
     184             :     private ImmutableSet<String> getSecondaryEmails(
     185             :         TestAccountUpdate accountUpdate, AccountState accountState) {
     186           3 :       ImmutableSet<String> allEmails =
     187           3 :           ExternalId.getEmails(accountState.externalIds()).collect(toImmutableSet());
     188           3 :       if (accountUpdate.preferredEmail().isPresent()) {
     189           0 :         return ImmutableSet.copyOf(
     190           0 :             Sets.difference(allEmails, ImmutableSet.of(accountUpdate.preferredEmail().get())));
     191           3 :       } else if (accountState.account().preferredEmail() != null) {
     192           3 :         return ImmutableSet.copyOf(
     193           3 :             Sets.difference(allEmails, ImmutableSet.of(accountState.account().preferredEmail())));
     194             :       }
     195           0 :       return allEmails;
     196             :     }
     197             : 
     198             :     private void setSecondaryEmails(
     199             :         AccountDelta.Builder builder,
     200             :         TestAccountUpdate accountUpdate,
     201             :         AccountState accountState,
     202             :         ImmutableSet<String> newSecondaryEmails) {
     203             :       // delete all external IDs of SCHEME_MAILTO scheme, then add back SCHEME_MAILTO external IDs
     204             :       // for the new secondary emails and the preferred email
     205           0 :       builder.deleteExternalIds(
     206           0 :           accountState.externalIds().stream()
     207           0 :               .filter(e -> e.isScheme(ExternalId.SCHEME_MAILTO))
     208           0 :               .collect(toImmutableSet()));
     209           0 :       builder.addExternalIds(
     210           0 :           newSecondaryEmails.stream()
     211           0 :               .map(secondaryEmail -> externalIdFactory.createEmail(accountId, secondaryEmail))
     212           0 :               .collect(toImmutableSet()));
     213           0 :       if (accountUpdate.preferredEmail().isPresent()) {
     214           0 :         builder.addExternalId(
     215           0 :             externalIdFactory.createEmail(accountId, accountUpdate.preferredEmail().get()));
     216           0 :       } else if (accountState.account().preferredEmail() != null) {
     217           0 :         builder.addExternalId(
     218           0 :             externalIdFactory.createEmail(accountId, accountState.account().preferredEmail()));
     219             :       }
     220           0 :     }
     221             : 
     222             :     @Override
     223             :     public TestAccountInvalidation.Builder forInvalidation() {
     224           1 :       return TestAccountInvalidation.builder(this::invalidateAccount);
     225             :     }
     226             : 
     227             :     private void invalidateAccount(TestAccountInvalidation testAccountInvalidation)
     228             :         throws Exception {
     229           1 :       Optional<AccountState> accountState = getAccountState(accountId);
     230           1 :       checkState(accountState.isPresent(), "Tried to invalidate a non-existing test account");
     231             : 
     232           1 :       if (testAccountInvalidation.preferredEmailWithoutExternalId().isPresent()) {
     233           1 :         updateAccount(
     234             :             (account, deltaBuilder) ->
     235           1 :                 deltaBuilder.setPreferredEmail(
     236           1 :                     testAccountInvalidation.preferredEmailWithoutExternalId().get()));
     237             :       }
     238           1 :     }
     239             :   }
     240             : }

Generated by: LCOV version 1.16+git.20220603.dfeb750