// Copyright (C) 2014 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.acceptance.api.accounts;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.common.truth.Truth8.assertThat;
import static com.google.gerrit.acceptance.GitUtil.deleteRef;
import static com.google.gerrit.acceptance.GitUtil.fetch;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allow;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowCapability;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowLabel;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.block;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.deny;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.permissionKey;
import static com.google.gerrit.gpg.PublicKeyStore.REFS_GPG_KEYS;
import static com.google.gerrit.gpg.PublicKeyStore.keyToString;
import static com.google.gerrit.gpg.testing.TestKeys.allValidKeys;
import static com.google.gerrit.gpg.testing.TestKeys.validKeyWithExpiration;
import static com.google.gerrit.gpg.testing.TestKeys.validKeyWithSecondUserId;
import static com.google.gerrit.gpg.testing.TestKeys.validKeyWithoutExpiration;
import static com.google.gerrit.server.StarredChangesUtil.DEFAULT_LABEL;
import static com.google.gerrit.server.StarredChangesUtil.IGNORE_LABEL;
import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_GPGKEY;
import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static com.google.gerrit.truth.ConfigSubject.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.SECONDS;
import static java.util.stream.Collectors.toSet;
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;

import com.github.rholder.retry.StopStrategies;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Iterables;
import com.google.common.io.BaseEncoding;
import com.google.common.truth.Correspondence;
import com.google.common.util.concurrent.AtomicLongMap;
import com.google.common.util.concurrent.Runnables;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.ExtensionRegistry;
import com.google.gerrit.acceptance.ExtensionRegistry.Registration;
import com.google.gerrit.acceptance.GerritConfig;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.Sandboxed;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.UseClockStep;
import com.google.gerrit.acceptance.UseSsh;
import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
import com.google.gerrit.acceptance.testsuite.account.TestSshKeys;
import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.common.data.PermissionRule.Action;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.api.accounts.AccountInput;
import com.google.gerrit.extensions.api.accounts.DeleteDraftCommentsInput;
import com.google.gerrit.extensions.api.accounts.DeletedDraftCommentInfo;
import com.google.gerrit.extensions.api.accounts.EmailInput;
import com.google.gerrit.extensions.api.changes.AddReviewerInput;
import com.google.gerrit.extensions.api.changes.DraftInput;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.api.changes.StarsInput;
import com.google.gerrit.extensions.api.config.ConsistencyCheckInfo;
import com.google.gerrit.extensions.api.config.ConsistencyCheckInfo.ConsistencyProblemInfo;
import com.google.gerrit.extensions.api.config.ConsistencyCheckInput;
import com.google.gerrit.extensions.api.config.ConsistencyCheckInput.CheckAccountsInput;
import com.google.gerrit.extensions.common.AccountDetailInfo;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.extensions.common.EmailInfo;
import com.google.gerrit.extensions.common.GpgKeyInfo;
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.common.SshKeyInfo;
import com.google.gerrit.extensions.events.AccountIndexedListener;
import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.git.LockFailureException;
import com.google.gerrit.gpg.Fingerprint;
import com.google.gerrit.gpg.PublicKeyStore;
import com.google.gerrit.gpg.testing.TestKey;
import com.google.gerrit.mail.Address;
import com.google.gerrit.server.ServerInitiated;
import com.google.gerrit.server.account.AccountProperties;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.account.AccountsUpdate;
import com.google.gerrit.server.account.Emails;
import com.google.gerrit.server.account.ProjectWatches;
import com.google.gerrit.server.account.ProjectWatches.NotifyType;
import com.google.gerrit.server.account.VersionedAuthorizedKeys;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.account.externalids.ExternalIdNotes;
import com.google.gerrit.server.account.externalids.ExternalIds;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.index.account.AccountIndexer;
import com.google.gerrit.server.index.account.StalenessChecker;
import com.google.gerrit.server.notedb.Sequences;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackend.RefFilterOptions;
import com.google.gerrit.server.plugincontext.PluginContext.PluginMetrics;
import com.google.gerrit.server.plugincontext.PluginSetContext;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.project.RefPattern;
import com.google.gerrit.server.query.account.InternalAccountQuery;
import com.google.gerrit.server.update.RetryHelper;
import com.google.gerrit.server.util.MagicBranch;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.gerrit.server.validators.AccountActivationValidationListener;
import com.google.gerrit.server.validators.ValidationException;
import com.google.gerrit.testing.ConfigSuite;
import com.google.gerrit.testing.FakeEmailSender.Message;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.name.Named;
import com.jcraft.jsch.KeyPair;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.bouncycastle.bcpg.ArmoredOutputStream;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.eclipse.jgit.api.errors.TransportException;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.PushCertificateIdent;
import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.RemoteRefUpdate;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.junit.After;
import org.junit.Test;

public class AccountIT extends AbstractDaemonTest {
  @ConfigSuite.Default
  public static Config enableSignedPushConfig() {
    Config cfg = new Config();
    cfg.setBoolean("receive", null, "enableSignedPush", true);

    // Disable the staleness checker so that tests that verify the number of expected index events
    // are stable.
    cfg.setBoolean("index", null, "autoReindexIfStale", false);

    return cfg;
  }

  @Inject private @ServerInitiated Provider<AccountsUpdate> accountsUpdateProvider;
  @Inject private AccountIndexer accountIndexer;
  @Inject private ExternalIdNotes.Factory extIdNotesFactory;
  @Inject private ExternalIds externalIds;
  @Inject private GitReferenceUpdated gitReferenceUpdated;
  @Inject private ProjectOperations projectOperations;
  @Inject private Provider<InternalAccountQuery> accountQueryProvider;
  @Inject private Provider<MetaDataUpdate.InternalFactory> metaDataUpdateInternalFactory;
  @Inject private Provider<PublicKeyStore> publicKeyStoreProvider;
  @Inject private RequestScopeOperations requestScopeOperations;
  @Inject private RetryHelper.Metrics retryMetrics;
  @Inject private Sequences seq;
  @Inject private StalenessChecker stalenessChecker;
  @Inject private VersionedAuthorizedKeys.Accessor authorizedKeys;
  @Inject private PermissionBackend permissionBackend;
  @Inject private ExtensionRegistry extensionRegistry;

  @Inject protected Emails emails;

  @Inject
  @Named("accounts")
  private LoadingCache<Account.Id, AccountState> accountsCache;

  @Inject private AccountOperations accountOperations;

  @Inject protected GroupOperations groupOperations;

  @After
  public void clearPublicKeyStore() throws Exception {
    try (Repository repo = repoManager.openRepository(allUsers)) {
      Ref ref = repo.exactRef(REFS_GPG_KEYS);
      if (ref != null) {
        RefUpdate ru = repo.updateRef(REFS_GPG_KEYS);
        ru.setForceUpdate(true);
        assertThat(ru.delete()).isEqualTo(RefUpdate.Result.FORCED);
      }
    }
  }

  @After
  public void deleteGpgKeys() throws Exception {
    String ref = REFS_GPG_KEYS;
    try (Repository repo = repoManager.openRepository(allUsers)) {
      if (repo.getRefDatabase().exactRef(ref) != null) {
        RefUpdate ru = repo.updateRef(ref);
        ru.setForceUpdate(true);
        assertWithMessage("Failed to delete " + ref)
            .that(ru.delete())
            .isEqualTo(RefUpdate.Result.FORCED);
      }
    }
  }

  protected void assertLabelPermission(
      Project.NameKey project,
      GroupReference groupReference,
      String ref,
      boolean exclusive,
      String labelName,
      int min,
      int max)
      throws IOException {
    ProjectConfig cfg = projectCache.checkedGet(project).getConfig();
    AccessSection accessSection = cfg.getAccessSection(ref);
    assertThat(accessSection).isNotNull();

    String permissionName = Permission.LABEL + labelName;
    Permission permission = accessSection.getPermission(permissionName);
    assertPermission(permission, permissionName, exclusive, labelName);
    assertPermissionRule(
        permission.getRule(groupReference), groupReference, Action.ALLOW, false, min, max);
  }

  @Test
  public void createByAccountCreator() throws Exception {
    RefUpdateCounter refUpdateCounter = new RefUpdateCounter();
    try (Registration registration = extensionRegistry.newRegistration().add(refUpdateCounter)) {
      Account.Id accountId = createByAccountCreator(1);
      refUpdateCounter.assertRefUpdateFor(
          RefUpdateCounter.projectRef(allUsers, RefNames.refsUsers(accountId)),
          RefUpdateCounter.projectRef(allUsers, RefNames.REFS_EXTERNAL_IDS),
          RefUpdateCounter.projectRef(allUsers, RefNames.REFS_SEQUENCES + Sequences.NAME_ACCOUNTS));
    }
  }

  @Test
  public void createWithInvalidEmailAddress() throws Exception {
    AccountInput input = new AccountInput();
    input.username = name("test");
    input.email = "invalid email address";

    // Invalid email address should cause the creation to fail
    BadRequestException thrown =
        assertThrows(BadRequestException.class, () -> gApi.accounts().create(input));
    assertThat(thrown).hasMessageThat().isEqualTo("invalid email address");

    // The account should not have been created
    assertThrows(ResourceNotFoundException.class, () -> gApi.accounts().id(input.username).get());
  }

  private Account.Id createByAccountCreator(int expectedAccountReindexCalls) throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      String name = "foo";
      TestAccount foo = accountCreator.create(name);
      AccountInfo info = gApi.accounts().id(foo.id().get()).get();
      assertThat(info.username).isEqualTo(name);
      assertThat(info.name).isEqualTo(name);
      accountIndexedCounter.assertReindexOf(foo, expectedAccountReindexCalls);
      assertUserBranch(foo.id(), name, null);
      return foo.id();
    }
  }

  @Test
  public void createAnonymousCowardByAccountCreator() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      TestAccount anonymousCoward = accountCreator.create();
      accountIndexedCounter.assertReindexOf(anonymousCoward);
      assertUserBranchWithoutAccountConfig(anonymousCoward.id());
    }
  }

  @Test
  public void create() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      AccountInput input = new AccountInput();
      input.username = "foo";
      input.name = "Foo";
      input.email = "foo@example.com";
      AccountInfo accountInfo = gApi.accounts().create(input).get();
      assertThat(accountInfo._accountId).isNotNull();
      assertThat(accountInfo.username).isEqualTo(input.username);
      assertThat(accountInfo.name).isEqualTo(input.name);
      assertThat(accountInfo.email).isEqualTo(input.email);
      assertThat(accountInfo.status).isNull();

      Account.Id accountId = Account.id(accountInfo._accountId);
      accountIndexedCounter.assertReindexOf(accountId, 1);
      assertThat(externalIds.byAccount(accountId))
          .containsExactly(
              ExternalId.createUsername(input.username, accountId, null),
              ExternalId.createEmail(accountId, input.email));
    }
  }

  @Test
  public void createAccountUsernameAlreadyTaken() throws Exception {
    AccountInput input = new AccountInput();
    input.username = admin.username();

    ResourceConflictException thrown =
        assertThrows(ResourceConflictException.class, () -> gApi.accounts().create(input));
    assertThat(thrown)
        .hasMessageThat()
        .contains("username '" + admin.username() + "' already exists");
  }

  @Test
  public void createAccountEmailAlreadyTaken() throws Exception {
    AccountInput input = new AccountInput();
    input.username = "foo";
    input.email = admin.email();

    UnprocessableEntityException thrown =
        assertThrows(UnprocessableEntityException.class, () -> gApi.accounts().create(input));
    assertThat(thrown).hasMessageThat().contains("email '" + admin.email() + "' already exists");
  }

  @Test
  public void commitMessageOnAccountUpdates() throws Exception {
    AccountsUpdate au = accountsUpdateProvider.get();
    Account.Id accountId = Account.id(seq.nextAccountId());
    au.insert("Create Test Account", accountId, u -> {});
    assertLastCommitMessageOfUserBranch(accountId, "Create Test Account");

    au.update("Set Status", accountId, u -> u.setStatus("Foo"));
    assertLastCommitMessageOfUserBranch(accountId, "Set Status");
  }

  private void assertLastCommitMessageOfUserBranch(Account.Id accountId, String expectedMessage)
      throws Exception {
    try (Repository repo = repoManager.openRepository(allUsers);
        RevWalk rw = new RevWalk(repo)) {
      Ref exactRef = repo.exactRef(RefNames.refsUsers(accountId));
      assertThat(rw.parseCommit(exactRef.getObjectId()).getShortMessage())
          .isEqualTo(expectedMessage);
    }
  }

  @Test
  @UseClockStep
  public void createAtomically() throws Exception {
    Account.Id accountId = Account.id(seq.nextAccountId());
    String fullName = "Foo";
    ExternalId extId = ExternalId.createEmail(accountId, "foo@example.com");
    AccountState accountState =
        accountsUpdateProvider
            .get()
            .insert(
                "Create Account Atomically",
                accountId,
                u -> u.setFullName(fullName).addExternalId(extId));
    assertThat(accountState.account().fullName()).isEqualTo(fullName);

    AccountInfo info = gApi.accounts().id(accountId.get()).get();
    assertThat(info.name).isEqualTo(fullName);

    List<EmailInfo> emails = gApi.accounts().id(accountId.get()).getEmails();
    assertThat(emails.stream().map(e -> e.email).collect(toSet())).containsExactly(extId.email());

    RevCommit commitUserBranch =
        projectOperations.project(allUsers).getHead(RefNames.refsUsers(accountId));
    RevCommit commitRefsMetaExternalIds =
        projectOperations.project(allUsers).getHead(RefNames.REFS_EXTERNAL_IDS);
    assertThat(commitUserBranch.getCommitTime())
        .isEqualTo(commitRefsMetaExternalIds.getCommitTime());
  }

  @Test
  public void updateNonExistingAccount() throws Exception {
    Account.Id nonExistingAccountId = Account.id(999999);
    AtomicBoolean consumerCalled = new AtomicBoolean();
    Optional<AccountState> accountState =
        accountsUpdateProvider
            .get()
            .update(
                "Update Non-Existing Account", nonExistingAccountId, a -> consumerCalled.set(true));
    assertThat(accountState).isEmpty();
    assertThat(consumerCalled.get()).isFalse();
  }

  @Test
  public void updateAccountWithoutAccountConfigNoteDb() throws Exception {
    TestAccount anonymousCoward = accountCreator.create();
    assertUserBranchWithoutAccountConfig(anonymousCoward.id());

    String status = "OOO";
    Optional<AccountState> accountState =
        accountsUpdateProvider
            .get()
            .update("Set status", anonymousCoward.id(), u -> u.setStatus(status));
    assertThat(accountState).isPresent();
    Account account = accountState.get().account();
    assertThat(account.fullName()).isNull();
    assertThat(account.status()).isEqualTo(status);
    assertUserBranch(anonymousCoward.id(), null, status);
  }

  private void assertUserBranchWithoutAccountConfig(Account.Id accountId) throws Exception {
    assertUserBranch(accountId, null, null);
  }

  private void assertUserBranch(
      Account.Id accountId, @Nullable String name, @Nullable String status) throws Exception {
    try (Repository repo = repoManager.openRepository(allUsers);
        RevWalk rw = new RevWalk(repo);
        ObjectReader or = repo.newObjectReader()) {
      Ref ref = repo.exactRef(RefNames.refsUsers(accountId));
      assertThat(ref).isNotNull();
      RevCommit c = rw.parseCommit(ref.getObjectId());
      long timestampDiffMs =
          Math.abs(c.getCommitTime() * 1000L - getAccount(accountId).registeredOn().getTime());
      assertThat(timestampDiffMs).isAtMost(SECONDS.toMillis(1));

      // Check the 'account.config' file.
      try (TreeWalk tw = TreeWalk.forPath(or, AccountProperties.ACCOUNT_CONFIG, c.getTree())) {
        if (name != null || status != null) {
          assertThat(tw).isNotNull();
          Config cfg = new Config();
          cfg.fromText(new String(or.open(tw.getObjectId(0), OBJ_BLOB).getBytes(), UTF_8));
          assertThat(cfg)
              .stringValue(AccountProperties.ACCOUNT, null, AccountProperties.KEY_FULL_NAME)
              .isEqualTo(name);
          assertThat(cfg)
              .stringValue(AccountProperties.ACCOUNT, null, AccountProperties.KEY_STATUS)
              .isEqualTo(status);
        } else {
          // No account properties were set, hence an 'account.config' file was not created.
          assertThat(tw).isNull();
        }
      }
    }
  }

  @Test
  public void get() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      AccountInfo info = gApi.accounts().id("admin").get();
      assertThat(info.name).isEqualTo("Administrator");
      assertThat(info.email).isEqualTo("admin@example.com");
      assertThat(info.username).isEqualTo("admin");
      accountIndexedCounter.assertNoReindex();
    }
  }

  @Test
  public void getByIntId() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      AccountInfo info = gApi.accounts().id("admin").get();
      AccountInfo infoByIntId = gApi.accounts().id(info._accountId).get();
      assertThat(info.name).isEqualTo(infoByIntId.name);
      accountIndexedCounter.assertNoReindex();
    }
  }

  @Test
  public void self() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      AccountInfo info = gApi.accounts().self().get();
      assertUser(info, admin);

      info = gApi.accounts().id("self").get();
      assertUser(info, admin);
      accountIndexedCounter.assertNoReindex();
    }
  }

  @Test
  public void active() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      int id = gApi.accounts().id("user").get()._accountId;
      assertThat(gApi.accounts().id("user").getActive()).isTrue();
      gApi.accounts().id("user").setActive(false);
      accountIndexedCounter.assertReindexOf(user);

      // Inactive users may only be resolved by ID.
      ResourceNotFoundException thrown =
          assertThrows(ResourceNotFoundException.class, () -> gApi.accounts().id("user"));
      assertThat(thrown)
          .hasMessageThat()
          .isEqualTo(
              "Account 'user' only matches inactive accounts. To use an inactive account, retry"
                  + " with one of the following exact account IDs:\n"
                  + id
                  + ": User <user@example.com>");
      assertThat(gApi.accounts().id(id).getActive()).isFalse();

      gApi.accounts().id(id).setActive(true);
      assertThat(gApi.accounts().id("user").getActive()).isTrue();
      accountIndexedCounter.assertReindexOf(user);
    }
  }

  @Test
  public void shouldAllowQueryByEmailForInactiveUser() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      Account.Id activatableAccountId =
          accountOperations.newAccount().inactive().preferredEmail("foo@activatable.com").create();
      accountIndexedCounter.assertReindexOf(activatableAccountId, 1);
    }

    gApi.changes().query("owner:foo@activatable.com").get();
  }

  @Test
  public void shouldAllowQueryByUserNameForInactiveUser() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      Account.Id activatableAccountId =
          accountOperations.newAccount().inactive().username("foo").create();
      accountIndexedCounter.assertReindexOf(activatableAccountId, 1);
    }

    gApi.changes().query("owner:foo").get();
  }

  @Test
  public void validateAccountActivation() throws Exception {
    Account.Id activatableAccountId =
        accountOperations.newAccount().inactive().preferredEmail("foo@activatable.com").create();
    Account.Id deactivatableAccountId =
        accountOperations.newAccount().preferredEmail("foo@deactivatable.com").create();

    AccountActivationValidationListener listener =
        new AccountActivationValidationListener() {
          @Override
          public void validateActivation(AccountState account) throws ValidationException {
            String preferredEmail = account.account().preferredEmail();
            if (preferredEmail == null || !preferredEmail.endsWith("@activatable.com")) {
              throw new ValidationException("not allowed to active account");
            }
          }

          @Override
          public void validateDeactivation(AccountState account) throws ValidationException {
            String preferredEmail = account.account().preferredEmail();
            if (preferredEmail == null || !preferredEmail.endsWith("@deactivatable.com")) {
              throw new ValidationException("not allowed to deactive account");
            }
          }
        };
    try (Registration registration = extensionRegistry.newRegistration().add(listener)) {
      /* Test account that can be activated, but not deactivated */
      // Deactivate account that is already inactive
      ResourceConflictException thrown =
          assertThrows(
              ResourceConflictException.class,
              () -> gApi.accounts().id(activatableAccountId.get()).setActive(false));
      assertThat(thrown).hasMessageThat().isEqualTo("account not active");
      assertThat(accountOperations.account(activatableAccountId).get().active()).isFalse();

      // Activate account that can be activated
      gApi.accounts().id(activatableAccountId.get()).setActive(true);
      assertThat(accountOperations.account(activatableAccountId).get().active()).isTrue();

      // Activate account that is already active
      gApi.accounts().id(activatableAccountId.get()).setActive(true);
      assertThat(accountOperations.account(activatableAccountId).get().active()).isTrue();

      // Try deactivating account that cannot be deactivated
      thrown =
          assertThrows(
              ResourceConflictException.class,
              () -> gApi.accounts().id(activatableAccountId.get()).setActive(false));
      assertThat(thrown).hasMessageThat().isEqualTo("not allowed to deactive account");
      assertThat(accountOperations.account(activatableAccountId).get().active()).isTrue();

      /* Test account that can be deactivated, but not activated */
      // Activate account that is already inactive
      gApi.accounts().id(deactivatableAccountId.get()).setActive(true);
      assertThat(accountOperations.account(deactivatableAccountId).get().active()).isTrue();

      // Deactivate account that can be deactivated
      gApi.accounts().id(deactivatableAccountId.get()).setActive(false);
      assertThat(accountOperations.account(deactivatableAccountId).get().active()).isFalse();

      // Deactivate account that is already inactive
      thrown =
          assertThrows(
              ResourceConflictException.class,
              () -> gApi.accounts().id(deactivatableAccountId.get()).setActive(false));
      assertThat(thrown).hasMessageThat().isEqualTo("account not active");
      assertThat(accountOperations.account(deactivatableAccountId).get().active()).isFalse();

      // Try activating account that cannot be activated
      thrown =
          assertThrows(
              ResourceConflictException.class,
              () -> gApi.accounts().id(deactivatableAccountId.get()).setActive(true));
      assertThat(thrown).hasMessageThat().isEqualTo("not allowed to active account");
      assertThat(accountOperations.account(deactivatableAccountId).get().active()).isFalse();
    }
  }

  @Test
  public void deactivateSelf() throws Exception {
    ResourceConflictException thrown =
        assertThrows(
            ResourceConflictException.class, () -> gApi.accounts().self().setActive(false));
    assertThat(thrown).hasMessageThat().contains("cannot deactivate own account");
  }

  @Test
  public void deactivateNotActive() throws Exception {
    int id = gApi.accounts().id("user").get()._accountId;
    assertThat(gApi.accounts().id("user").getActive()).isTrue();
    gApi.accounts().id("user").setActive(false);
    assertThat(gApi.accounts().id(id).getActive()).isFalse();
    ResourceConflictException thrown =
        assertThrows(
            ResourceConflictException.class, () -> gApi.accounts().id(id).setActive(false));
    assertThat(thrown).hasMessageThat().isEqualTo("account not active");
    gApi.accounts().id(id).setActive(true);
  }

  @Test
  public void starUnstarChange() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    RefUpdateCounter refUpdateCounter = new RefUpdateCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter).add(refUpdateCounter)) {
      PushOneCommit.Result r = createChange();
      String triplet = project.get() + "~master~" + r.getChangeId();
      refUpdateCounter.clear();

      gApi.accounts().self().starChange(triplet);
      ChangeInfo change = info(triplet);
      assertThat(change.starred).isTrue();
      assertThat(change.stars).contains(DEFAULT_LABEL);
      refUpdateCounter.assertRefUpdateFor(
          RefUpdateCounter.projectRef(
              allUsers, RefNames.refsStarredChanges(Change.id(change._number), admin.id())));

      gApi.accounts().self().unstarChange(triplet);
      change = info(triplet);
      assertThat(change.starred).isNull();
      assertThat(change.stars).isNull();
      refUpdateCounter.assertRefUpdateFor(
          RefUpdateCounter.projectRef(
              allUsers, RefNames.refsStarredChanges(Change.id(change._number), admin.id())));

      accountIndexedCounter.assertNoReindex();
    }
  }

  @Test
  public void starUnstarChangeWithLabels() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    RefUpdateCounter refUpdateCounter = new RefUpdateCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter).add(refUpdateCounter)) {
      PushOneCommit.Result r = createChange();
      String triplet = project.get() + "~master~" + r.getChangeId();
      refUpdateCounter.clear();

      assertThat(gApi.accounts().self().getStars(triplet)).isEmpty();
      assertThat(gApi.accounts().self().getStarredChanges()).isEmpty();

      gApi.accounts()
          .self()
          .setStars(triplet, new StarsInput(ImmutableSet.of(DEFAULT_LABEL, "red", "blue")));
      ChangeInfo change = info(triplet);
      assertThat(change.starred).isTrue();
      assertThat(change.stars).containsExactly("blue", "red", DEFAULT_LABEL).inOrder();
      assertThat(gApi.accounts().self().getStars(triplet))
          .containsExactly("blue", "red", DEFAULT_LABEL)
          .inOrder();
      List<ChangeInfo> starredChanges = gApi.accounts().self().getStarredChanges();
      assertThat(starredChanges).hasSize(1);
      ChangeInfo starredChange = starredChanges.get(0);
      assertThat(starredChange._number).isEqualTo(r.getChange().getId().get());
      assertThat(starredChange.starred).isTrue();
      assertThat(starredChange.stars).containsExactly("blue", "red", DEFAULT_LABEL).inOrder();
      refUpdateCounter.assertRefUpdateFor(
          RefUpdateCounter.projectRef(
              allUsers, RefNames.refsStarredChanges(Change.id(change._number), admin.id())));

      gApi.accounts()
          .self()
          .setStars(
              triplet,
              new StarsInput(ImmutableSet.of("yellow"), ImmutableSet.of(DEFAULT_LABEL, "blue")));
      change = info(triplet);
      assertThat(change.starred).isNull();
      assertThat(change.stars).containsExactly("red", "yellow").inOrder();
      assertThat(gApi.accounts().self().getStars(triplet))
          .containsExactly("red", "yellow")
          .inOrder();
      starredChanges = gApi.accounts().self().getStarredChanges();
      assertThat(starredChanges).hasSize(1);
      starredChange = starredChanges.get(0);
      assertThat(starredChange._number).isEqualTo(r.getChange().getId().get());
      assertThat(starredChange.starred).isNull();
      assertThat(starredChange.stars).containsExactly("red", "yellow").inOrder();
      refUpdateCounter.assertRefUpdateFor(
          RefUpdateCounter.projectRef(
              allUsers, RefNames.refsStarredChanges(Change.id(change._number), admin.id())));

      accountIndexedCounter.assertNoReindex();

      requestScopeOperations.setApiUser(user.id());
      AuthException thrown =
          assertThrows(
              AuthException.class,
              () -> gApi.accounts().id(Integer.toString((admin.id().get()))).getStars(triplet));
      assertThat(thrown).hasMessageThat().contains("not allowed to get stars of another account");
    }
  }

  @Test
  public void starWithInvalidLabels() throws Exception {
    PushOneCommit.Result r = createChange();
    String triplet = project.get() + "~master~" + r.getChangeId();
    BadRequestException thrown =
        assertThrows(
            BadRequestException.class,
            () ->
                gApi.accounts()
                    .self()
                    .setStars(
                        triplet,
                        new StarsInput(
                            ImmutableSet.of(
                                DEFAULT_LABEL, "invalid label", "blue", "another invalid label"))));
    assertThat(thrown)
        .hasMessageThat()
        .contains("invalid labels: another invalid label, invalid label");
  }

  @Test
  public void deleteStarLabelsFromChangeWithoutStarLabels() throws Exception {
    PushOneCommit.Result r = createChange();
    String triplet = project.get() + "~master~" + r.getChangeId();
    assertThat(gApi.accounts().self().getStars(triplet)).isEmpty();

    gApi.accounts().self().setStars(triplet, new StarsInput());

    assertThat(gApi.accounts().self().getStars(triplet)).isEmpty();
  }

  @Test
  public void starWithDefaultAndIgnoreLabel() throws Exception {
    PushOneCommit.Result r = createChange();
    String triplet = project.get() + "~master~" + r.getChangeId();
    BadRequestException thrown =
        assertThrows(
            BadRequestException.class,
            () ->
                gApi.accounts()
                    .self()
                    .setStars(
                        triplet,
                        new StarsInput(ImmutableSet.of(DEFAULT_LABEL, "blue", IGNORE_LABEL))));
    assertThat(thrown)
        .hasMessageThat()
        .contains(
            "The labels "
                + DEFAULT_LABEL
                + " and "
                + IGNORE_LABEL
                + " are mutually exclusive."
                + " Only one of them can be set.");
  }

  @Test
  public void ignoreChangeBySetStars() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      TestAccount user2 = accountCreator.user2();
      accountIndexedCounter.clear();

      PushOneCommit.Result r = createChange();

      AddReviewerInput in = new AddReviewerInput();
      in.reviewer = user.email();
      gApi.changes().id(r.getChangeId()).addReviewer(in);

      in = new AddReviewerInput();
      in.reviewer = user2.email();
      gApi.changes().id(r.getChangeId()).addReviewer(in);

      requestScopeOperations.setApiUser(user.id());
      gApi.accounts()
          .self()
          .setStars(r.getChangeId(), new StarsInput(ImmutableSet.of(IGNORE_LABEL)));

      sender.clear();
      requestScopeOperations.setApiUser(admin.id());
      gApi.changes().id(r.getChangeId()).abandon();
      List<Message> messages = sender.getMessages();
      assertThat(messages).hasSize(1);
      assertThat(messages.get(0).rcpt()).containsExactly(user2.getEmailAddress());
      accountIndexedCounter.assertNoReindex();
    }
  }

  @Test
  public void addReviewerToIgnoredChange() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      PushOneCommit.Result r = createChange();

      requestScopeOperations.setApiUser(user.id());
      gApi.accounts()
          .self()
          .setStars(r.getChangeId(), new StarsInput(ImmutableSet.of(IGNORE_LABEL)));

      sender.clear();
      requestScopeOperations.setApiUser(admin.id());

      AddReviewerInput in = new AddReviewerInput();
      in.reviewer = user.email();
      gApi.changes().id(r.getChangeId()).addReviewer(in);
      List<Message> messages = sender.getMessages();
      assertThat(messages).hasSize(1);
      Message message = messages.get(0);
      assertThat(message.rcpt()).containsExactly(user.getEmailAddress());
      assertMailReplyTo(message, admin.email());
      accountIndexedCounter.assertNoReindex();
    }
  }

  @Test
  public void suggestAccounts() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      String adminUsername = "admin";
      List<AccountInfo> result = gApi.accounts().suggestAccounts().withQuery(adminUsername).get();
      assertThat(result).hasSize(1);
      assertThat(result.get(0).username).isEqualTo(adminUsername);

      List<AccountInfo> resultShortcutApi = gApi.accounts().suggestAccounts(adminUsername).get();
      assertThat(resultShortcutApi).hasSize(result.size());

      List<AccountInfo> emptyResult = gApi.accounts().suggestAccounts("unknown").get();
      assertThat(emptyResult).isEmpty();
      accountIndexedCounter.assertNoReindex();
    }
  }

  @Test
  public void getOwnDetail() throws Exception {
    String email = "preferred@example.com";
    String name = "Foo";
    String username = name("foo");
    TestAccount foo = accountCreator.create(username, email, name);
    String secondaryEmail = "secondary@example.com";
    EmailInput input = newEmailInput(secondaryEmail);
    gApi.accounts().id(foo.id().get()).addEmail(input);

    String status = "OOO";
    gApi.accounts().id(foo.id().get()).setStatus(status);

    requestScopeOperations.setApiUser(foo.id());
    AccountDetailInfo detail = gApi.accounts().id(foo.id().get()).detail();
    assertThat(detail._accountId).isEqualTo(foo.id().get());
    assertThat(detail.name).isEqualTo(name);
    assertThat(detail.username).isEqualTo(username);
    assertThat(detail.email).isEqualTo(email);
    assertThat(detail.secondaryEmails).containsExactly(secondaryEmail);
    assertThat(detail.status).isEqualTo(status);
    assertThat(detail.registeredOn).isEqualTo(getAccount(foo.id()).registeredOn());
    assertThat(detail.inactive).isNull();
    assertThat(detail._moreAccounts).isNull();
  }

  @Test
  public void detailOfOtherAccountDoesntIncludeSecondaryEmailsWithoutModifyAccount()
      throws Exception {
    String email = "preferred@example.com";
    TestAccount foo = accountCreator.create(name("foo"), email, "Foo");
    String secondaryEmail = "secondary@example.com";
    EmailInput input = newEmailInput(secondaryEmail);
    gApi.accounts().id(foo.id().get()).addEmail(input);

    requestScopeOperations.setApiUser(user.id());
    AccountDetailInfo detail = gApi.accounts().id(foo.id().get()).detail();
    assertThat(detail.secondaryEmails).isNull();
  }

  @Test
  public void detailOfOtherAccountIncludeSecondaryEmailsWithModifyAccount() throws Exception {
    String email = "preferred@example.com";
    TestAccount foo = accountCreator.create(name("foo"), email, "Foo");
    String secondaryEmail = "secondary@example.com";
    EmailInput input = newEmailInput(secondaryEmail);
    gApi.accounts().id(foo.id().get()).addEmail(input);

    AccountDetailInfo detail = gApi.accounts().id(foo.id().get()).detail();
    assertThat(detail.secondaryEmails).containsExactly(secondaryEmail);
  }

  @Test
  public void getOwnEmails() throws Exception {
    String email = "preferred@example.com";
    TestAccount foo = accountCreator.create(name("foo"), email, "Foo");

    requestScopeOperations.setApiUser(foo.id());
    assertThat(getEmails()).containsExactly(email);

    requestScopeOperations.setApiUser(admin.id());
    String secondaryEmail = "secondary@example.com";
    EmailInput input = newEmailInput(secondaryEmail);
    gApi.accounts().id(foo.id().get()).addEmail(input);

    requestScopeOperations.setApiUser(foo.id());
    assertThat(getEmails()).containsExactly(email, secondaryEmail);
  }

  @Test
  public void cannotGetEmailsOfOtherAccountWithoutModifyAccount() throws Exception {
    String email = "preferred2@example.com";
    TestAccount foo = accountCreator.create(name("foo"), email, "Foo");

    requestScopeOperations.setApiUser(user.id());
    AuthException thrown =
        assertThrows(AuthException.class, () -> gApi.accounts().id(foo.id().get()).getEmails());
    assertThat(thrown).hasMessageThat().contains("modify account not permitted");
  }

  @Test
  public void getEmailsOfOtherAccount() throws Exception {
    String email = "preferred3@example.com";
    String secondaryEmail = "secondary3@example.com";
    TestAccount foo = accountCreator.create(name("foo"), email, "Foo");
    EmailInput input = newEmailInput(secondaryEmail);
    gApi.accounts().id(foo.id().get()).addEmail(input);

    assertThat(
            gApi.accounts().id(foo.id().get()).getEmails().stream()
                .map(e -> e.email)
                .collect(toSet()))
        .containsExactly(email, secondaryEmail);
  }

  @Test
  public void addEmail() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      List<String> emails = ImmutableList.of("new.email@example.com", "new.email@example.systems");
      Set<String> currentEmails = getEmails();
      for (String email : emails) {
        assertThat(currentEmails).doesNotContain(email);
        EmailInput input = newEmailInput(email);
        gApi.accounts().self().addEmail(input);
        accountIndexedCounter.assertReindexOf(admin);
      }

      requestScopeOperations.resetCurrentApiUser();
      assertThat(getEmails()).containsAtLeastElementsIn(emails);
    }
  }

  @Test
  public void addInvalidEmail() throws Exception {
    List<String> emails =
        ImmutableList.of(
            // Missing domain part
            "new.email",

            // Missing domain part
            "new.email@",

            // Missing user part
            "@example.com",

            // Non-supported TLD  (see tlds-alpha-by-domain.txt)
            "new.email@example.africa");
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      for (String email : emails) {
        EmailInput input = newEmailInput(email);
        BadRequestException thrown =
            assertThrows(BadRequestException.class, () -> gApi.accounts().self().addEmail(input));
        assertWithMessage(email).that(thrown).hasMessageThat().isEqualTo("invalid email address");
      }
      accountIndexedCounter.assertNoReindex();
    }
  }

  @Test
  public void cannotAddNonConfirmedEmailWithoutModifyAccountPermission() throws Exception {
    TestAccount account = accountCreator.create(name("user"));
    EmailInput input = newEmailInput("test@test.com");
    requestScopeOperations.setApiUser(user.id());
    assertThrows(AuthException.class, () -> gApi.accounts().id(account.username()).addEmail(input));
  }

  @Test
  public void cannotAddEmailAddressUsedByAnotherAccount() throws Exception {
    String email = "new.email@example.com";
    EmailInput input = newEmailInput(email);
    gApi.accounts().self().addEmail(input);
    ResourceConflictException thrown =
        assertThrows(
            ResourceConflictException.class,
            () -> gApi.accounts().id(user.username()).addEmail(input));
    assertThat(thrown)
        .hasMessageThat()
        .contains("Identity 'mailto:" + email + "' in use by another account");
  }

  @Test
  @GerritConfig(
      name = "auth.registerEmailPrivateKey",
      value = "HsOc6l+2lhS9G7sE/RsnS7Z6GJjdRDX14co=")
  public void addEmailSendsConfirmationEmail() throws Exception {
    String email = "new.email@example.com";
    EmailInput input = newEmailInput(email, false);
    gApi.accounts().self().addEmail(input);

    assertThat(sender.getMessages()).hasSize(1);
    Message m = sender.getMessages().get(0);
    assertThat(m.rcpt()).containsExactly(new Address(email));
  }

  @Test
  @GerritConfig(
      name = "auth.registerEmailPrivateKey",
      value = "HsOc6l+2lhS9G7sE/RsnS7Z6GJjdRDX14co=")
  public void addEmailToBeConfirmedToOwnAccount() throws Exception {
    TestAccount user = accountCreator.create();
    requestScopeOperations.setApiUser(user.id());

    String email = "self@example.com";
    EmailInput input = newEmailInput(email, false);
    gApi.accounts().self().addEmail(input);
  }

  @Test
  public void cannotAddEmailToBeConfirmedToOtherAccountWithoutModifyAccountPermission()
      throws Exception {
    TestAccount user = accountCreator.create();
    requestScopeOperations.setApiUser(user.id());

    AuthException thrown =
        assertThrows(
            AuthException.class,
            () ->
                gApi.accounts()
                    .id(admin.id().get())
                    .addEmail(newEmailInput("foo@example.com", false)));
    assertThat(thrown).hasMessageThat().contains("modify account not permitted");
  }

  @Test
  @GerritConfig(
      name = "auth.registerEmailPrivateKey",
      value = "HsOc6l+2lhS9G7sE/RsnS7Z6GJjdRDX14co=")
  public void addEmailToBeConfirmedToOtherAccount() throws Exception {
    TestAccount user = accountCreator.create();
    String email = "me@example.com";
    gApi.accounts().id(user.id().get()).addEmail(newEmailInput(email, false));
  }

  @Test
  public void addEmailAndSetPreferred() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      String email = "foo.bar@example.com";
      EmailInput input = new EmailInput();
      input.email = email;
      input.noConfirmation = true;
      input.preferred = true;
      gApi.accounts().self().addEmail(input);

      // Account is reindexed twice; once on adding the new email,
      // and then again on setting the email preferred.
      accountIndexedCounter.assertReindexOf(admin, 2);

      String preferred = gApi.accounts().self().get().email;
      assertThat(preferred).isEqualTo(email);
    }
  }

  @Test
  public void deleteEmail() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      String email = "foo.bar@example.com";
      EmailInput input = newEmailInput(email);
      gApi.accounts().self().addEmail(input);

      requestScopeOperations.resetCurrentApiUser();
      assertThat(getEmails()).contains(email);

      accountIndexedCounter.clear();
      gApi.accounts().self().deleteEmail(input.email);
      accountIndexedCounter.assertReindexOf(admin);

      requestScopeOperations.resetCurrentApiUser();
      assertThat(getEmails()).doesNotContain(email);
    }
  }

  @Test
  public void deletePreferredEmail() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      String previous = gApi.accounts().self().get().email;
      String email = "foo.bar.baz@example.com";
      EmailInput input = new EmailInput();
      input.email = email;
      input.noConfirmation = true;
      input.preferred = true;
      gApi.accounts().self().addEmail(input);

      // Account is reindexed twice; once on adding the new email,
      // and then again on setting the email preferred.
      accountIndexedCounter.assertReindexOf(admin, 2);

      // The new preferred email is set
      assertThat(gApi.accounts().self().get().email).isEqualTo(email);

      accountIndexedCounter.clear();
      gApi.accounts().self().deleteEmail(input.email);
      accountIndexedCounter.assertReindexOf(admin);

      requestScopeOperations.resetCurrentApiUser();
      assertThat(getEmails()).containsExactly(previous);
      assertThat(gApi.accounts().self().get().email).isNull();
    }
  }

  @Test
  @Sandboxed
  public void deleteAllEmails() throws Exception {
    EmailInput input = new EmailInput();
    input.email = "foo.bar@example.com";
    input.noConfirmation = true;
    gApi.accounts().self().addEmail(input);

    requestScopeOperations.resetCurrentApiUser();
    Set<String> allEmails = getEmails();
    assertThat(allEmails).hasSize(2);

    for (String email : allEmails) {
      gApi.accounts().self().deleteEmail(email);
    }

    requestScopeOperations.resetCurrentApiUser();
    assertThat(getEmails()).isEmpty();
    assertThat(gApi.accounts().self().get().email).isNull();
  }

  @Test
  public void deleteEmailFromCustomExternalIdSchemes() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      String email = "foo.bar@example.com";
      String extId1 = "foo:bar";
      String extId2 = "foo:baz";
      accountsUpdateProvider
          .get()
          .update(
              "Add External IDs",
              admin.id(),
              u ->
                  u.addExternalId(
                          ExternalId.createWithEmail(
                              ExternalId.Key.parse(extId1), admin.id(), email))
                      .addExternalId(
                          ExternalId.createWithEmail(
                              ExternalId.Key.parse(extId2), admin.id(), email)));
      accountIndexedCounter.assertReindexOf(admin);
      assertThat(
              gApi.accounts().self().getExternalIds().stream()
                  .map(e -> e.identity)
                  .collect(toSet()))
          .containsAtLeast(extId1, extId2);

      requestScopeOperations.resetCurrentApiUser();
      assertThat(getEmails()).contains(email);

      gApi.accounts().self().deleteEmail(email);
      accountIndexedCounter.assertReindexOf(admin);

      requestScopeOperations.resetCurrentApiUser();
      assertThat(getEmails()).doesNotContain(email);
      assertThat(
              gApi.accounts().self().getExternalIds().stream()
                  .map(e -> e.identity)
                  .collect(toSet()))
          .containsNoneOf(extId1, extId2);
    }
  }

  @Test
  public void deleteEmailOfOtherUser() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      String email = "foo.bar@example.com";
      EmailInput input = new EmailInput();
      input.email = email;
      input.noConfirmation = true;
      gApi.accounts().id(user.id().get()).addEmail(input);
      accountIndexedCounter.assertReindexOf(user);

      requestScopeOperations.setApiUser(user.id());
      assertThat(getEmails()).contains(email);

      // admin can delete email of user
      requestScopeOperations.setApiUser(admin.id());
      gApi.accounts().id(user.id().get()).deleteEmail(email);
      accountIndexedCounter.assertReindexOf(user);

      requestScopeOperations.setApiUser(user.id());
      assertThat(getEmails()).doesNotContain(email);

      // user cannot delete email of admin
      AuthException thrown =
          assertThrows(
              AuthException.class,
              () -> gApi.accounts().id(admin.id().get()).deleteEmail(admin.email()));
      assertThat(thrown).hasMessageThat().contains("modify account not permitted");
    }
  }

  @Test
  public void lookUpByEmail() throws Exception {
    // exact match with scheme "mailto:"
    assertEmail(emails.getAccountFor(admin.email()), admin);

    // exact match with other scheme
    String email = "foo.bar@example.com";
    accountsUpdateProvider
        .get()
        .update(
            "Add Email",
            admin.id(),
            u ->
                u.addExternalId(
                    ExternalId.createWithEmail(
                        ExternalId.Key.parse("foo:bar"), admin.id(), email)));
    assertEmail(emails.getAccountFor(email), admin);

    // wrong case doesn't match
    assertThat(emails.getAccountFor(admin.email().toUpperCase(Locale.US))).isEmpty();

    // prefix doesn't match
    assertThat(emails.getAccountFor(admin.email().substring(0, admin.email().indexOf('@'))))
        .isEmpty();

    // non-existing doesn't match
    assertThat(emails.getAccountFor("non-existing@example.com")).isEmpty();

    // lookup several accounts by email at once
    ImmutableSetMultimap<String, Account.Id> byEmails =
        emails.getAccountsFor(admin.email(), user.email());
    assertEmail(byEmails.get(admin.email()), admin);
    assertEmail(byEmails.get(user.email()), user);
  }

  @Test
  public void lookUpByPreferredEmail() throws Exception {
    // create an inconsistent account that has a preferred email without external ID
    String prefix = "foo.preferred";
    String prefEmail = prefix + "@example.com";
    TestAccount foo = accountCreator.create(name("foo"));
    accountsUpdateProvider
        .get()
        .update("Set Preferred Email", foo.id(), u -> u.setPreferredEmail(prefEmail));

    // verify that the account is still found when using the preferred email to lookup the account
    ImmutableSet<Account.Id> accountsByPrefEmail = emails.getAccountFor(prefEmail);
    assertThat(accountsByPrefEmail).hasSize(1);
    assertThat(Iterables.getOnlyElement(accountsByPrefEmail)).isEqualTo(foo.id());

    // look up by email prefix doesn't find the account
    accountsByPrefEmail = emails.getAccountFor(prefix);
    assertThat(accountsByPrefEmail).isEmpty();

    // look up by other case doesn't find the account
    accountsByPrefEmail = emails.getAccountFor(prefEmail.toUpperCase(Locale.US));
    assertThat(accountsByPrefEmail).isEmpty();
  }

  @Test
  public void putStatus() throws Exception {
    List<String> statuses = ImmutableList.of("OOO", "Busy");
    AccountInfo info;
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      for (String status : statuses) {
        gApi.accounts().self().setStatus(status);
        info = gApi.accounts().self().get();
        assertUser(info, admin, status);
        accountIndexedCounter.assertReindexOf(admin);
      }

      gApi.accounts().self().setStatus(null);
      info = gApi.accounts().self().get();
      assertUser(info, admin);
      accountIndexedCounter.assertReindexOf(admin);
    }
  }

  @Test
  public void setName() throws Exception {
    gApi.accounts().self().setName("Admin McAdminface");
    assertThat(gApi.accounts().self().get().name).isEqualTo("Admin McAdminface");
  }

  @Test
  public void adminCanSetNameOfOtherUser() throws Exception {
    gApi.accounts().id(user.username()).setName("User McUserface");
    assertThat(gApi.accounts().id(user.username()).get().name).isEqualTo("User McUserface");
  }

  @Test
  public void userCannotSetNameOfOtherUser() throws Exception {
    requestScopeOperations.setApiUser(user.id());
    assertThrows(
        AuthException.class,
        () -> gApi.accounts().id(admin.username()).setName("Admin McAdminface"));
  }

  @Test
  @Sandboxed
  public void userCanSetNameOfOtherUserWithModifyAccountPermission() throws Exception {
    projectOperations
        .allProjectsForUpdate()
        .add(allowCapability(GlobalCapability.MODIFY_ACCOUNT).group(REGISTERED_USERS))
        .update();
    gApi.accounts().id(admin.username()).setName("Admin McAdminface");
    assertThat(gApi.accounts().id(admin.username()).get().name).isEqualTo("Admin McAdminface");
  }

  @Test
  public void fetchUserBranch() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      requestScopeOperations.setApiUser(user.id());

      TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers, user);
      String userRefName = RefNames.refsUsers(user.id());

      // remove default READ permissions
      try (ProjectConfigUpdate u = updateProject(allUsers)) {
        u.getConfig()
            .getAccessSection(RefNames.REFS_USERS + "${" + RefPattern.USERID_SHARDED + "}", true)
            .remove(new Permission(Permission.READ));
        u.save();
      }

      // deny READ permission that is inherited from All-Projects
      projectOperations
          .project(allUsers)
          .forUpdate()
          .add(deny(Permission.READ).ref(RefNames.REFS + "*").group(ANONYMOUS_USERS))
          .update();

      // fetching user branch without READ permission fails
      assertThrows(TransportException.class, () -> fetch(allUsersRepo, userRefName + ":userRef"));

      // allow each user to read its own user branch
      projectOperations
          .project(allUsers)
          .forUpdate()
          .add(
              allow(Permission.READ)
                  .ref(RefNames.REFS_USERS + "${" + RefPattern.USERID_SHARDED + "}")
                  .group(REGISTERED_USERS))
          .update();

      // fetch user branch using refs/users/YY/XXXXXXX
      fetch(allUsersRepo, userRefName + ":userRef");
      Ref userRef = allUsersRepo.getRepository().exactRef("userRef");
      assertThat(userRef).isNotNull();

      // fetch user branch using refs/users/self
      fetch(allUsersRepo, RefNames.REFS_USERS_SELF + ":userSelfRef");
      Ref userSelfRef = allUsersRepo.getRepository().getRefDatabase().exactRef("userSelfRef");
      assertThat(userSelfRef).isNotNull();
      assertThat(userSelfRef.getObjectId()).isEqualTo(userRef.getObjectId());

      accountIndexedCounter.assertNoReindex();

      // fetching user branch of another user fails
      String otherUserRefName = RefNames.refsUsers(admin.id());
      TransportException thrown =
          assertThrows(
              TransportException.class,
              () -> fetch(allUsersRepo, otherUserRefName + ":otherUserRef"));
      assertThat(thrown)
          .hasMessageThat()
          .contains("Remote does not have " + otherUserRefName + " available for fetch.");
    }
  }

  @Test
  public void refsUsersSelfIsAdvertised() throws Exception {
    try (Repository allUsersRepo = repoManager.openRepository(allUsers)) {
      assertThat(
              permissionBackend
                  .currentUser()
                  .project(allUsers)
                  .filter(ImmutableList.of(), allUsersRepo, RefFilterOptions.defaults())
                  .keySet())
          .containsExactly(RefNames.REFS_USERS_SELF);
    }
  }

  @Test
  public void pushToUserBranch() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
      fetch(allUsersRepo, RefNames.refsUsers(admin.id()) + ":userRef");
      allUsersRepo.reset("userRef");
      PushOneCommit push = pushFactory.create(admin.newIdent(), allUsersRepo);
      push.to(RefNames.refsUsers(admin.id())).assertOkStatus();
      accountIndexedCounter.assertReindexOf(admin);

      push = pushFactory.create(admin.newIdent(), allUsersRepo);
      push.to(RefNames.REFS_USERS_SELF).assertOkStatus();
      accountIndexedCounter.assertReindexOf(admin);
    }
  }

  @Test
  public void pushToUserBranchForReview() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      String userRefName = RefNames.refsUsers(admin.id());
      TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
      fetch(allUsersRepo, userRefName + ":userRef");
      allUsersRepo.reset("userRef");
      PushOneCommit push = pushFactory.create(admin.newIdent(), allUsersRepo);
      PushOneCommit.Result r = push.to(MagicBranch.NEW_CHANGE + userRefName);
      r.assertOkStatus();
      accountIndexedCounter.assertNoReindex();
      assertThat(r.getChange().change().getDest().branch()).isEqualTo(userRefName);
      gApi.changes().id(r.getChangeId()).current().review(ReviewInput.approve());
      gApi.changes().id(r.getChangeId()).current().submit();
      accountIndexedCounter.assertReindexOf(admin);

      push = pushFactory.create(admin.newIdent(), allUsersRepo);
      r = push.to(MagicBranch.NEW_CHANGE + RefNames.REFS_USERS_SELF);
      r.assertOkStatus();
      accountIndexedCounter.assertNoReindex();
      assertThat(r.getChange().change().getDest().branch()).isEqualTo(userRefName);
      gApi.changes().id(r.getChangeId()).current().review(ReviewInput.approve());
      gApi.changes().id(r.getChangeId()).current().submit();
      accountIndexedCounter.assertReindexOf(admin);
    }
  }

  @Test
  public void pushAccountConfigToUserBranchForReviewAndSubmit() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      String userRef = RefNames.refsUsers(admin.id());
      TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
      fetch(allUsersRepo, userRef + ":userRef");
      allUsersRepo.reset("userRef");

      Config ac = getAccountConfig(allUsersRepo);
      ac.setString(AccountProperties.ACCOUNT, null, AccountProperties.KEY_STATUS, "out-of-office");

      PushOneCommit.Result r =
          pushFactory
              .create(
                  admin.newIdent(),
                  allUsersRepo,
                  "Update account config",
                  AccountProperties.ACCOUNT_CONFIG,
                  ac.toText())
              .to(MagicBranch.NEW_CHANGE + userRef);
      r.assertOkStatus();
      accountIndexedCounter.assertNoReindex();
      assertThat(r.getChange().change().getDest().branch()).isEqualTo(userRef);

      gApi.changes().id(r.getChangeId()).current().review(ReviewInput.approve());
      gApi.changes().id(r.getChangeId()).current().submit();
      accountIndexedCounter.assertReindexOf(admin);

      AccountInfo info = gApi.accounts().self().get();
      assertThat(info.email).isEqualTo(admin.email());
      assertThat(info.name).isEqualTo(admin.fullName());
      assertThat(info.status).isEqualTo("out-of-office");
    }
  }

  @Test
  public void pushAccountConfigWithPrefEmailThatDoesNotExistAsExtIdToUserBranchForReviewAndSubmit()
      throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      TestAccount foo = accountCreator.create(name("foo"), name("foo") + "@example.com", "Foo");
      String userRef = RefNames.refsUsers(foo.id());
      accountIndexedCounter.clear();

      TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers, foo);
      fetch(allUsersRepo, userRef + ":userRef");
      allUsersRepo.reset("userRef");

      String email = "some.email@example.com";
      Config ac = getAccountConfig(allUsersRepo);
      ac.setString(AccountProperties.ACCOUNT, null, AccountProperties.KEY_PREFERRED_EMAIL, email);

      PushOneCommit.Result r =
          pushFactory
              .create(
                  foo.newIdent(),
                  allUsersRepo,
                  "Update account config",
                  AccountProperties.ACCOUNT_CONFIG,
                  ac.toText())
              .to(MagicBranch.NEW_CHANGE + userRef);
      r.assertOkStatus();
      accountIndexedCounter.assertNoReindex();
      assertThat(r.getChange().change().getDest().branch()).isEqualTo(userRef);

      requestScopeOperations.setApiUser(foo.id());
      gApi.changes().id(r.getChangeId()).current().review(ReviewInput.approve());
      gApi.changes().id(r.getChangeId()).current().submit();

      accountIndexedCounter.assertReindexOf(foo);

      AccountInfo info = gApi.accounts().self().get();
      assertThat(info.email).isEqualTo(email);
      assertThat(info.name).isEqualTo(foo.fullName());
    }
  }

  @Test
  public void pushAccountConfigToUserBranchForReviewIsRejectedOnSubmitIfConfigIsInvalid()
      throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      String userRef = RefNames.refsUsers(admin.id());
      TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
      fetch(allUsersRepo, userRef + ":userRef");
      allUsersRepo.reset("userRef");

      PushOneCommit.Result r =
          pushFactory
              .create(
                  admin.newIdent(),
                  allUsersRepo,
                  "Update account config",
                  AccountProperties.ACCOUNT_CONFIG,
                  "invalid config")
              .to(MagicBranch.NEW_CHANGE + userRef);
      r.assertOkStatus();
      accountIndexedCounter.assertNoReindex();
      assertThat(r.getChange().change().getDest().branch()).isEqualTo(userRef);

      gApi.changes().id(r.getChangeId()).current().review(ReviewInput.approve());
      ResourceConflictException thrown =
          assertThrows(
              ResourceConflictException.class,
              () -> gApi.changes().id(r.getChangeId()).current().submit());
      assertThat(thrown)
          .hasMessageThat()
          .contains(
              String.format(
                  "invalid account configuration: commit '%s' has an invalid '%s' file for account"
                      + " '%s': Invalid config file %s in commit %s",
                  r.getCommit().name(),
                  AccountProperties.ACCOUNT_CONFIG,
                  admin.id(),
                  AccountProperties.ACCOUNT_CONFIG,
                  r.getCommit().name()));
    }
  }

  @Test
  public void pushAccountConfigToUserBranchForReviewIsRejectedOnSubmitIfPreferredEmailIsInvalid()
      throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      String userRef = RefNames.refsUsers(admin.id());
      TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
      fetch(allUsersRepo, userRef + ":userRef");
      allUsersRepo.reset("userRef");

      String noEmail = "no.email";
      Config ac = getAccountConfig(allUsersRepo);
      ac.setString(AccountProperties.ACCOUNT, null, AccountProperties.KEY_PREFERRED_EMAIL, noEmail);

      PushOneCommit.Result r =
          pushFactory
              .create(
                  admin.newIdent(),
                  allUsersRepo,
                  "Update account config",
                  AccountProperties.ACCOUNT_CONFIG,
                  ac.toText())
              .to(MagicBranch.NEW_CHANGE + userRef);
      r.assertOkStatus();
      accountIndexedCounter.assertNoReindex();
      assertThat(r.getChange().change().getDest().branch()).isEqualTo(userRef);

      gApi.changes().id(r.getChangeId()).current().review(ReviewInput.approve());
      ResourceConflictException thrown =
          assertThrows(
              ResourceConflictException.class,
              () -> gApi.changes().id(r.getChangeId()).current().submit());
      assertThat(thrown)
          .hasMessageThat()
          .contains(
              String.format(
                  "invalid account configuration: invalid preferred email '%s' for account '%s'",
                  noEmail, admin.id()));
    }
  }

  @Test
  public void pushAccountConfigToUserBranchForReviewIsRejectedOnSubmitIfOwnAccountIsDeactivated()
      throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      String userRef = RefNames.refsUsers(admin.id());
      TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
      fetch(allUsersRepo, userRef + ":userRef");
      allUsersRepo.reset("userRef");

      Config ac = getAccountConfig(allUsersRepo);
      ac.setBoolean(AccountProperties.ACCOUNT, null, AccountProperties.KEY_ACTIVE, false);

      PushOneCommit.Result r =
          pushFactory
              .create(
                  admin.newIdent(),
                  allUsersRepo,
                  "Update account config",
                  AccountProperties.ACCOUNT_CONFIG,
                  ac.toText())
              .to(MagicBranch.NEW_CHANGE + userRef);
      r.assertOkStatus();
      accountIndexedCounter.assertNoReindex();
      assertThat(r.getChange().change().getDest().branch()).isEqualTo(userRef);

      gApi.changes().id(r.getChangeId()).current().review(ReviewInput.approve());
      ResourceConflictException thrown =
          assertThrows(
              ResourceConflictException.class,
              () -> gApi.changes().id(r.getChangeId()).current().submit());
      assertThat(thrown)
          .hasMessageThat()
          .contains("invalid account configuration: cannot deactivate own account");
    }
  }

  @Test
  public void pushAccountConfigToUserBranchForReviewDeactivateOtherAccount() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      projectOperations
          .allProjectsForUpdate()
          .add(allowCapability(GlobalCapability.ACCESS_DATABASE).group(REGISTERED_USERS))
          .update();

      TestAccount foo = accountCreator.create(name("foo"));
      assertThat(gApi.accounts().id(foo.id().get()).getActive()).isTrue();
      String userRef = RefNames.refsUsers(foo.id());
      accountIndexedCounter.clear();

      projectOperations
          .project(allUsers)
          .forUpdate()
          .add(allow(Permission.PUSH).ref(userRef).group(adminGroupUuid()))
          .add(allowLabel("Code-Review").ref(userRef).group(adminGroupUuid()).range(-2, 2))
          .add(allow(Permission.SUBMIT).ref(userRef).group(adminGroupUuid()))
          .update();

      TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
      fetch(allUsersRepo, userRef + ":userRef");
      allUsersRepo.reset("userRef");

      Config ac = getAccountConfig(allUsersRepo);
      ac.setBoolean(AccountProperties.ACCOUNT, null, AccountProperties.KEY_ACTIVE, false);

      PushOneCommit.Result r =
          pushFactory
              .create(
                  admin.newIdent(),
                  allUsersRepo,
                  "Update account config",
                  AccountProperties.ACCOUNT_CONFIG,
                  ac.toText())
              .to(MagicBranch.NEW_CHANGE + userRef);
      r.assertOkStatus();
      accountIndexedCounter.assertNoReindex();
      assertThat(r.getChange().change().getDest().branch()).isEqualTo(userRef);

      gApi.changes().id(r.getChangeId()).current().review(ReviewInput.approve());
      gApi.changes().id(r.getChangeId()).current().submit();
      accountIndexedCounter.assertReindexOf(foo);

      assertThat(gApi.accounts().id(foo.id().get()).getActive()).isFalse();
    }
  }

  @Test
  public void pushWatchConfigToUserBranch() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
      fetch(allUsersRepo, RefNames.refsUsers(admin.id()) + ":userRef");
      allUsersRepo.reset("userRef");

      Config wc = new Config();
      wc.setString(
          ProjectWatches.PROJECT,
          project.get(),
          ProjectWatches.KEY_NOTIFY,
          ProjectWatches.NotifyValue.create(null, EnumSet.of(NotifyType.ALL_COMMENTS)).toString());
      PushOneCommit push =
          pushFactory.create(
              admin.newIdent(),
              allUsersRepo,
              "Add project watch",
              ProjectWatches.WATCH_CONFIG,
              wc.toText());
      push.to(RefNames.REFS_USERS_SELF).assertOkStatus();
      accountIndexedCounter.assertReindexOf(admin);

      String invalidNotifyValue = "]invalid[";
      wc.setString(
          ProjectWatches.PROJECT, project.get(), ProjectWatches.KEY_NOTIFY, invalidNotifyValue);
      push =
          pushFactory.create(
              admin.newIdent(),
              allUsersRepo,
              "Add invalid project watch",
              ProjectWatches.WATCH_CONFIG,
              wc.toText());
      PushOneCommit.Result r = push.to(RefNames.REFS_USERS_SELF);
      r.assertErrorStatus("invalid account configuration");
      r.assertMessage(
          String.format(
              "%s: Invalid project watch of account %d for project %s: %s",
              ProjectWatches.WATCH_CONFIG, admin.id().get(), project.get(), invalidNotifyValue));
    }
  }

  @Test
  public void pushAccountConfigToUserBranch() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      TestAccount oooUser = accountCreator.create("away", "away@mail.invalid", "Ambrose Way");
      requestScopeOperations.setApiUser(oooUser.id());

      // Must clone as oooUser to ensure the push is allowed.
      TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers, oooUser);
      fetch(allUsersRepo, RefNames.refsUsers(oooUser.id()) + ":userRef");
      allUsersRepo.reset("userRef");

      Config ac = getAccountConfig(allUsersRepo);
      ac.setString(AccountProperties.ACCOUNT, null, AccountProperties.KEY_STATUS, "out-of-office");

      accountIndexedCounter.clear();
      pushFactory
          .create(
              oooUser.newIdent(),
              allUsersRepo,
              "Update account config",
              AccountProperties.ACCOUNT_CONFIG,
              ac.toText())
          .to(RefNames.refsUsers(oooUser.id()))
          .assertOkStatus();

      accountIndexedCounter.assertReindexOf(oooUser);

      AccountInfo info = gApi.accounts().self().get();
      assertThat(info.email).isEqualTo(oooUser.email());
      assertThat(info.name).isEqualTo(oooUser.fullName());
      assertThat(info.status).isEqualTo("out-of-office");
    }
  }

  @Test
  public void pushAccountConfigToUserBranchIsRejectedIfConfigIsInvalid() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
      fetch(allUsersRepo, RefNames.refsUsers(admin.id()) + ":userRef");
      allUsersRepo.reset("userRef");

      PushOneCommit.Result r =
          pushFactory
              .create(
                  admin.newIdent(),
                  allUsersRepo,
                  "Update account config",
                  AccountProperties.ACCOUNT_CONFIG,
                  "invalid config")
              .to(RefNames.REFS_USERS_SELF);
      r.assertErrorStatus("invalid account configuration");
      r.assertMessage(
          String.format(
              "commit '%s' has an invalid '%s' file for account '%s':"
                  + " Invalid config file %s in commit %s",
              r.getCommit().name(),
              AccountProperties.ACCOUNT_CONFIG,
              admin.id(),
              AccountProperties.ACCOUNT_CONFIG,
              r.getCommit().name()));
      accountIndexedCounter.assertNoReindex();
    }
  }

  @Test
  public void pushAccountConfigToUserBranchIsRejectedIfPreferredEmailIsInvalid() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
      fetch(allUsersRepo, RefNames.refsUsers(admin.id()) + ":userRef");
      allUsersRepo.reset("userRef");

      String noEmail = "no.email";
      Config ac = getAccountConfig(allUsersRepo);
      ac.setString(AccountProperties.ACCOUNT, null, AccountProperties.KEY_PREFERRED_EMAIL, noEmail);

      PushOneCommit.Result r =
          pushFactory
              .create(
                  admin.newIdent(),
                  allUsersRepo,
                  "Update account config",
                  AccountProperties.ACCOUNT_CONFIG,
                  ac.toText())
              .to(RefNames.REFS_USERS_SELF);
      r.assertErrorStatus("invalid account configuration");
      r.assertMessage(
          String.format("invalid preferred email '%s' for account '%s'", noEmail, admin.id()));
      accountIndexedCounter.assertNoReindex();
    }
  }

  @Test
  public void pushAccountConfigToUserBranchInvalidPreferredEmailButNotChanged() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      TestAccount foo = accountCreator.create(name("foo"), name("foo") + "@example.com", "Foo");
      String userRef = RefNames.refsUsers(foo.id());

      String noEmail = "no.email";
      accountsUpdateProvider
          .get()
          .update("Set Preferred Email", foo.id(), u -> u.setPreferredEmail(noEmail));
      accountIndexedCounter.clear();

      projectOperations
          .project(allUsers)
          .forUpdate()
          .add(allow(Permission.PUSH).ref(userRef).group(REGISTERED_USERS))
          .update();
      TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers, foo);
      fetch(allUsersRepo, userRef + ":userRef");
      allUsersRepo.reset("userRef");

      String status = "in vacation";
      Config ac = getAccountConfig(allUsersRepo);
      ac.setString(AccountProperties.ACCOUNT, null, AccountProperties.KEY_STATUS, status);

      pushFactory
          .create(
              foo.newIdent(),
              allUsersRepo,
              "Update account config",
              AccountProperties.ACCOUNT_CONFIG,
              ac.toText())
          .to(userRef)
          .assertOkStatus();
      accountIndexedCounter.assertReindexOf(foo);

      AccountInfo info = gApi.accounts().id(foo.id().get()).get();
      assertThat(info.email).isEqualTo(noEmail);
      assertThat(info.name).isEqualTo(foo.fullName());
      assertThat(info.status).isEqualTo(status);
    }
  }

  @Test
  public void pushAccountConfigToUserBranchIfPreferredEmailDoesNotExistAsExtId() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      TestAccount foo = accountCreator.create(name("foo"), name("foo") + "@example.com", "Foo");
      String userRef = RefNames.refsUsers(foo.id());
      accountIndexedCounter.clear();

      projectOperations
          .project(allUsers)
          .forUpdate()
          .add(allow(Permission.PUSH).ref(userRef).group(adminGroupUuid()))
          .update();

      TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers, foo);
      fetch(allUsersRepo, userRef + ":userRef");
      allUsersRepo.reset("userRef");

      String email = "some.email@example.com";
      Config ac = getAccountConfig(allUsersRepo);
      ac.setString(AccountProperties.ACCOUNT, null, AccountProperties.KEY_PREFERRED_EMAIL, email);

      pushFactory
          .create(
              foo.newIdent(),
              allUsersRepo,
              "Update account config",
              AccountProperties.ACCOUNT_CONFIG,
              ac.toText())
          .to(userRef)
          .assertOkStatus();
      accountIndexedCounter.assertReindexOf(foo);

      AccountInfo info = gApi.accounts().id(foo.id().get()).get();
      assertThat(info.email).isEqualTo(email);
      assertThat(info.name).isEqualTo(foo.fullName());
    }
  }

  @Test
  public void pushAccountConfigToUserBranchIsRejectedIfOwnAccountIsDeactivated() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
      fetch(allUsersRepo, RefNames.refsUsers(admin.id()) + ":userRef");
      allUsersRepo.reset("userRef");

      Config ac = getAccountConfig(allUsersRepo);
      ac.setBoolean(AccountProperties.ACCOUNT, null, AccountProperties.KEY_ACTIVE, false);

      PushOneCommit.Result r =
          pushFactory
              .create(
                  admin.newIdent(),
                  allUsersRepo,
                  "Update account config",
                  AccountProperties.ACCOUNT_CONFIG,
                  ac.toText())
              .to(RefNames.REFS_USERS_SELF);
      r.assertErrorStatus("invalid account configuration");
      r.assertMessage("cannot deactivate own account");
      accountIndexedCounter.assertNoReindex();
    }
  }

  @Test
  public void pushAccountConfigToUserBranchDeactivateOtherAccount() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      projectOperations
          .allProjectsForUpdate()
          .add(allowCapability(GlobalCapability.ACCESS_DATABASE).group(REGISTERED_USERS))
          .update();

      TestAccount foo = accountCreator.create(name("foo"));
      assertThat(gApi.accounts().id(foo.id().get()).getActive()).isTrue();
      String userRef = RefNames.refsUsers(foo.id());
      accountIndexedCounter.clear();

      projectOperations
          .project(allUsers)
          .forUpdate()
          .add(allow(Permission.PUSH).ref(userRef).group(adminGroupUuid()))
          .update();

      TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
      fetch(allUsersRepo, userRef + ":userRef");
      allUsersRepo.reset("userRef");

      Config ac = getAccountConfig(allUsersRepo);
      ac.setBoolean(AccountProperties.ACCOUNT, null, AccountProperties.KEY_ACTIVE, false);

      pushFactory
          .create(
              admin.newIdent(),
              allUsersRepo,
              "Update account config",
              AccountProperties.ACCOUNT_CONFIG,
              ac.toText())
          .to(userRef)
          .assertOkStatus();
      accountIndexedCounter.assertReindexOf(foo);

      assertThat(gApi.accounts().id(foo.id().get()).getActive()).isFalse();
    }
  }

  @Test
  public void cannotCreateUserBranch() throws Exception {
    projectOperations
        .project(allUsers)
        .forUpdate()
        .add(allow(Permission.CREATE).ref(RefNames.REFS_USERS + "*").group(adminGroupUuid()))
        .add(allow(Permission.PUSH).ref(RefNames.REFS_USERS + "*").group(adminGroupUuid()))
        .update();

    String userRef = RefNames.refsUsers(Account.id(seq.nextAccountId()));
    TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
    PushOneCommit.Result r = pushFactory.create(admin.newIdent(), allUsersRepo).to(userRef);
    r.assertErrorStatus();
    assertThat(r.getMessage()).contains("Not allowed to create user branch.");

    try (Repository repo = repoManager.openRepository(allUsers)) {
      assertThat(repo.exactRef(userRef)).isNull();
    }
  }

  @Test
  public void createUserBranchWithAccessDatabaseCapability() throws Exception {
    projectOperations
        .allProjectsForUpdate()
        .add(allowCapability(GlobalCapability.ACCESS_DATABASE).group(REGISTERED_USERS))
        .update();
    projectOperations
        .project(allUsers)
        .forUpdate()
        .add(allow(Permission.CREATE).ref(RefNames.REFS_USERS + "*").group(adminGroupUuid()))
        .add(allow(Permission.PUSH).ref(RefNames.REFS_USERS + "*").group(adminGroupUuid()))
        .update();

    String userRef = RefNames.refsUsers(Account.id(seq.nextAccountId()));
    TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
    pushFactory.create(admin.newIdent(), allUsersRepo).to(userRef).assertOkStatus();

    try (Repository repo = repoManager.openRepository(allUsers)) {
      assertThat(repo.exactRef(userRef)).isNotNull();
    }
  }

  @Test
  public void cannotCreateNonUserBranchUnderRefsUsersWithAccessDatabaseCapability()
      throws Exception {
    projectOperations
        .allProjectsForUpdate()
        .add(allowCapability(GlobalCapability.ACCESS_DATABASE).group(REGISTERED_USERS))
        .update();
    projectOperations
        .project(allUsers)
        .forUpdate()
        .add(allow(Permission.CREATE).ref(RefNames.REFS_USERS + "*").group(adminGroupUuid()))
        .add(allow(Permission.PUSH).ref(RefNames.REFS_USERS + "*").group(adminGroupUuid()))
        .update();

    String userRef = RefNames.REFS_USERS + "foo";
    TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
    PushOneCommit.Result r = pushFactory.create(admin.newIdent(), allUsersRepo).to(userRef);
    r.assertErrorStatus();
    assertThat(r.getMessage()).contains("Not allowed to create non-user branch under refs/users/.");

    try (Repository repo = repoManager.openRepository(allUsers)) {
      assertThat(repo.exactRef(userRef)).isNull();
    }
  }

  @Test
  public void createDefaultUserBranch() throws Exception {
    try (Repository repo = repoManager.openRepository(allUsers)) {
      assertThat(repo.exactRef(RefNames.REFS_USERS_DEFAULT)).isNull();
    }

    projectOperations
        .project(allUsers)
        .forUpdate()
        .add(allow(Permission.CREATE).ref(RefNames.REFS_USERS_DEFAULT).group(adminGroupUuid()))
        .add(allow(Permission.PUSH).ref(RefNames.REFS_USERS_DEFAULT).group(adminGroupUuid()))
        .update();

    TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
    pushFactory
        .create(admin.newIdent(), allUsersRepo)
        .to(RefNames.REFS_USERS_DEFAULT)
        .assertOkStatus();

    try (Repository repo = repoManager.openRepository(allUsers)) {
      assertThat(repo.exactRef(RefNames.REFS_USERS_DEFAULT)).isNotNull();
    }
  }

  @Test
  public void cannotDeleteUserBranch() throws Exception {
    projectOperations
        .project(allUsers)
        .forUpdate()
        .add(
            allow(Permission.DELETE)
                .ref(RefNames.REFS_USERS + "${" + RefPattern.USERID_SHARDED + "}")
                .group(REGISTERED_USERS)
                .force(true))
        .update();

    TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
    String userRef = RefNames.refsUsers(admin.id());
    PushResult r = deleteRef(allUsersRepo, userRef);
    RemoteRefUpdate refUpdate = r.getRemoteUpdate(userRef);
    assertThat(refUpdate.getStatus()).isEqualTo(RemoteRefUpdate.Status.REJECTED_OTHER_REASON);
    assertThat(refUpdate.getMessage()).contains("Not allowed to delete user branch.");

    try (Repository repo = repoManager.openRepository(allUsers)) {
      assertThat(repo.exactRef(userRef)).isNotNull();
    }
  }

  @Test
  public void deleteUserBranchWithAccessDatabaseCapability() throws Exception {
    projectOperations
        .allProjectsForUpdate()
        .add(allowCapability(GlobalCapability.ACCESS_DATABASE).group(REGISTERED_USERS))
        .update();
    projectOperations
        .project(allUsers)
        .forUpdate()
        .add(
            allow(Permission.DELETE)
                .ref(RefNames.REFS_USERS + "${" + RefPattern.USERID_SHARDED + "}")
                .group(REGISTERED_USERS)
                .force(true))
        .update();

    TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
    String userRef = RefNames.refsUsers(admin.id());
    PushResult r = deleteRef(allUsersRepo, userRef);
    RemoteRefUpdate refUpdate = r.getRemoteUpdate(userRef);
    assertThat(refUpdate.getStatus()).isEqualTo(RemoteRefUpdate.Status.OK);

    try (Repository repo = repoManager.openRepository(allUsers)) {
      assertThat(repo.exactRef(userRef)).isNull();
    }

    assertThat(accountCache.get(admin.id())).isEmpty();
    assertThat(accountQueryProvider.get().byDefault(admin.id().toString())).isEmpty();
  }

  @Test
  public void addGpgKey() throws Exception {
    TestKey key = validKeyWithoutExpiration();
    String id = key.getKeyIdString();
    addExternalIdEmail(admin, "test1@example.com");

    sender.clear();
    assertKeyMapContains(key, addGpgKey(key.getPublicKeyArmored()));
    assertKeys(key);
    assertThat(sender.getMessages()).hasSize(1);
    assertThat(sender.getMessages().get(0).body()).contains("new GPG keys have been added");

    requestScopeOperations.setApiUser(user.id());
    ResourceNotFoundException thrown =
        assertThrows(
            ResourceNotFoundException.class, () -> gApi.accounts().self().gpgKey(id).get());
    assertThat(thrown).hasMessageThat().contains(id);
  }

  @Test
  public void adminCannotAddGpgKeyToOtherAccount() throws Exception {
    TestKey key = validKeyWithoutExpiration();
    addExternalIdEmail(user, "test1@example.com");

    sender.clear();
    requestScopeOperations.setApiUser(admin.id());
    assertThrows(ResourceNotFoundException.class, () -> addGpgKey(user, key.getPublicKeyArmored()));
  }

  @Test
  public void reAddExistingGpgKey() throws Exception {
    addExternalIdEmail(admin, "test5@example.com");
    TestKey key = validKeyWithSecondUserId();
    String id = key.getKeyIdString();
    PGPPublicKey pk = key.getPublicKey();

    sender.clear();
    GpgKeyInfo info = addGpgKey(armor(pk)).get(id);
    assertThat(info.userIds).hasSize(2);
    assertIteratorSize(2, getOnlyKeyFromStore(key).getUserIDs());
    assertThat(sender.getMessages()).hasSize(1);
    assertThat(sender.getMessages().get(0).body()).contains("new GPG keys have been added");

    pk = PGPPublicKey.removeCertification(pk, "foo:myId");
    sender.clear();
    info = addGpgKeyNoReindex(armor(pk)).get(id);
    assertThat(info.userIds).hasSize(1);
    assertIteratorSize(1, getOnlyKeyFromStore(key).getUserIDs());
    // TODO: Issue 10769: Adding an already existing key should not result in a notification email
    assertThat(sender.getMessages()).hasSize(1);
    assertThat(sender.getMessages().get(0).body()).contains("new GPG keys have been added");
  }

  @Test
  public void addOtherUsersGpgKey_Conflict() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      // Both users have a matching external ID for this key.
      addExternalIdEmail(admin, "test5@example.com");
      accountIndexedCounter.clear();
      accountsUpdateProvider
          .get()
          .update(
              "Add External ID",
              user.id(),
              u -> u.addExternalId(ExternalId.create("foo", "myId", user.id())));
      accountIndexedCounter.assertReindexOf(user);

      TestKey key = validKeyWithSecondUserId();
      addGpgKey(key.getPublicKeyArmored());
      requestScopeOperations.setApiUser(user.id());

      ResourceConflictException thrown =
          assertThrows(
              ResourceConflictException.class, () -> addGpgKey(user, key.getPublicKeyArmored()));
      assertThat(thrown)
          .hasMessageThat()
          .contains("GPG key already associated with another account");
    }
  }

  @Test
  public void listGpgKeys() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      List<TestKey> keys = allValidKeys();
      List<String> toAdd = new ArrayList<>(keys.size());
      for (TestKey key : keys) {
        addExternalIdEmail(
            admin, PushCertificateIdent.parse(key.getFirstUserId()).getEmailAddress());
        toAdd.add(key.getPublicKeyArmored());
      }
      accountIndexedCounter.clear();
      gApi.accounts().self().putGpgKeys(toAdd, ImmutableList.of());
      assertKeys(keys);
      accountIndexedCounter.assertReindexOf(admin);
    }
  }

  @Test
  public void deleteGpgKey() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      TestKey key = validKeyWithoutExpiration();
      String id = key.getKeyIdString();
      addExternalIdEmail(admin, "test1@example.com");
      addGpgKey(key.getPublicKeyArmored());
      assertKeys(key);
      accountIndexedCounter.clear();

      sender.clear();
      gApi.accounts().self().gpgKey(id).delete();
      accountIndexedCounter.assertReindexOf(admin);
      assertKeys();
      assertThat(sender.getMessages()).hasSize(1);
      assertThat(sender.getMessages().get(0).body()).contains("GPG keys have been deleted");

      ResourceNotFoundException thrown =
          assertThrows(
              ResourceNotFoundException.class, () -> gApi.accounts().self().gpgKey(id).get());
      assertThat(thrown).hasMessageThat().contains(id);
    }
  }

  @Test
  public void addAndRemoveGpgKeys() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      for (TestKey key : allValidKeys()) {
        addExternalIdEmail(
            admin, PushCertificateIdent.parse(key.getFirstUserId()).getEmailAddress());
      }
      accountIndexedCounter.clear();
      TestKey key1 = validKeyWithoutExpiration();
      TestKey key2 = validKeyWithExpiration();
      TestKey key5 = validKeyWithSecondUserId();

      Map<String, GpgKeyInfo> infos =
          gApi.accounts()
              .self()
              .putGpgKeys(
                  ImmutableList.of(key1.getPublicKeyArmored(), key2.getPublicKeyArmored()),
                  ImmutableList.of(key5.getKeyIdString()));
      assertThat(infos.keySet()).containsExactly(key1.getKeyIdString(), key2.getKeyIdString());
      assertKeys(key1, key2);
      accountIndexedCounter.assertReindexOf(admin);

      infos =
          gApi.accounts()
              .self()
              .putGpgKeys(
                  ImmutableList.of(key5.getPublicKeyArmored()),
                  ImmutableList.of(key1.getKeyIdString()));
      assertThat(infos.keySet()).containsExactly(key1.getKeyIdString(), key5.getKeyIdString());
      assertKeyMapContains(key5, infos);
      assertThat(infos.get(key1.getKeyIdString()).key).isNull();
      assertKeys(key2, key5);
      accountIndexedCounter.assertReindexOf(admin);

      BadRequestException thrown =
          assertThrows(
              BadRequestException.class,
              () ->
                  gApi.accounts()
                      .self()
                      .putGpgKeys(
                          ImmutableList.of(key2.getPublicKeyArmored()),
                          ImmutableList.of(key2.getKeyIdString())));
      assertThat(thrown)
          .hasMessageThat()
          .contains("Cannot both add and delete key: " + keyToString(key2.getPublicKey()));
    }
  }

  @Test
  public void addMalformedGpgKey() throws Exception {
    String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\ntest\n-----END PGP PUBLIC KEY BLOCK-----";
    BadRequestException thrown = assertThrows(BadRequestException.class, () -> addGpgKey(key));
    assertThat(thrown).hasMessageThat().contains("Failed to parse GPG keys");
  }

  @Test
  @UseSsh
  public void sshKeys() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      // The test account should initially have exactly one ssh key
      List<SshKeyInfo> info = gApi.accounts().self().listSshKeys();
      assertThat(info).hasSize(1);
      assertSequenceNumbers(info);
      SshKeyInfo key = info.get(0);
      KeyPair keyPair = sshKeys.getKeyPair(admin);
      String initial = TestSshKeys.publicKey(keyPair, admin.email());
      assertThat(key.sshPublicKey).isEqualTo(initial);
      accountIndexedCounter.assertNoReindex();

      // Add a new key
      sender.clear();
      String newKey = TestSshKeys.publicKey(TestSshKeys.genSshKey(), admin.email());
      gApi.accounts().self().addSshKey(newKey);
      info = gApi.accounts().self().listSshKeys();
      assertThat(info).hasSize(2);
      assertSequenceNumbers(info);
      accountIndexedCounter.assertReindexOf(admin);
      assertThat(sender.getMessages()).hasSize(1);
      assertThat(sender.getMessages().get(0).body()).contains("new SSH keys have been added");

      // Add an existing key (the request succeeds, but the key isn't added again)
      sender.clear();
      gApi.accounts().self().addSshKey(initial);
      info = gApi.accounts().self().listSshKeys();
      assertThat(info).hasSize(2);
      assertSequenceNumbers(info);
      accountIndexedCounter.assertNoReindex();
      // TODO: Issue 10769: Adding an already existing key should not result in a notification email
      assertThat(sender.getMessages()).hasSize(1);
      assertThat(sender.getMessages().get(0).body()).contains("new SSH keys have been added");

      // Add another new key
      sender.clear();
      String newKey2 = TestSshKeys.publicKey(TestSshKeys.genSshKey(), admin.email());
      gApi.accounts().self().addSshKey(newKey2);
      info = gApi.accounts().self().listSshKeys();
      assertThat(info).hasSize(3);
      assertSequenceNumbers(info);
      accountIndexedCounter.assertReindexOf(admin);
      assertThat(sender.getMessages()).hasSize(1);
      assertThat(sender.getMessages().get(0).body()).contains("new SSH keys have been added");

      // Delete second key
      sender.clear();
      gApi.accounts().self().deleteSshKey(2);
      info = gApi.accounts().self().listSshKeys();
      assertThat(info).hasSize(2);
      assertThat(info.get(0).seq).isEqualTo(1);
      assertThat(info.get(1).seq).isEqualTo(3);
      accountIndexedCounter.assertReindexOf(admin);

      assertThat(sender.getMessages()).hasSize(1);
      assertThat(sender.getMessages().get(0).body()).contains("SSH keys have been deleted");

      // Mark first key as invalid
      assertThat(info.get(0).valid).isTrue();
      authorizedKeys.markKeyInvalid(admin.id(), 1);
      info = gApi.accounts().self().listSshKeys();
      assertThat(info).hasSize(2);
      assertThat(info.get(0).seq).isEqualTo(1);
      assertThat(info.get(0).valid).isFalse();
      assertThat(info.get(1).seq).isEqualTo(3);
      accountIndexedCounter.assertReindexOf(admin);
    }
  }

  @Test
  @UseSsh
  public void adminCanAddOrRemoveSshKeyOnOtherAccount() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      // The test account should initially have exactly one ssh key
      List<SshKeyInfo> info = gApi.accounts().self().listSshKeys();
      assertThat(info).hasSize(1);
      assertSequenceNumbers(info);
      SshKeyInfo key = info.get(0);
      KeyPair keyPair = sshKeys.getKeyPair(admin);
      String initial = TestSshKeys.publicKey(keyPair, admin.email());
      assertThat(key.sshPublicKey).isEqualTo(initial);
      accountIndexedCounter.assertNoReindex();

      // Add a new key
      sender.clear();
      String newKey = TestSshKeys.publicKey(TestSshKeys.genSshKey(), user.email());
      gApi.accounts().id(user.username()).addSshKey(newKey);
      info = gApi.accounts().id(user.username()).listSshKeys();
      assertThat(info).hasSize(2);
      assertSequenceNumbers(info);
      accountIndexedCounter.assertReindexOf(user);

      assertThat(sender.getMessages()).hasSize(1);
      Message message = sender.getMessages().get(0);
      assertThat(message.rcpt()).containsExactly(user.getEmailAddress());
      assertThat(message.body()).contains("new SSH keys have been added");

      // Delete key
      sender.clear();
      gApi.accounts().id(user.username()).deleteSshKey(1);
      info = gApi.accounts().id(user.username()).listSshKeys();
      assertThat(info).hasSize(1);
      accountIndexedCounter.assertReindexOf(user);

      assertThat(sender.getMessages()).hasSize(1);
      message = sender.getMessages().get(0);
      assertThat(message.rcpt()).containsExactly(user.getEmailAddress());
      assertThat(message.body()).contains("SSH keys have been deleted");
    }
  }

  @Test
  @UseSsh
  public void userCannotAddSshKeyToOtherAccount() throws Exception {
    String newKey = TestSshKeys.publicKey(TestSshKeys.genSshKey(), admin.email());
    requestScopeOperations.setApiUser(user.id());
    assertThrows(AuthException.class, () -> gApi.accounts().id(admin.username()).addSshKey(newKey));
  }

  @Test
  @UseSsh
  public void userCannotDeleteSshKeyOfOtherAccount() throws Exception {
    requestScopeOperations.setApiUser(user.id());
    assertThrows(
        ResourceNotFoundException.class,
        () -> gApi.accounts().id(admin.username()).deleteSshKey(0));
  }

  // reindex is tested by {@link AbstractQueryAccountsTest#reindex}
  @Test
  public void reindexPermissions() throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      // admin can reindex any account
      requestScopeOperations.setApiUser(admin.id());
      gApi.accounts().id(user.username()).index();
      accountIndexedCounter.assertReindexOf(user);

      // user can reindex own account
      requestScopeOperations.setApiUser(user.id());
      gApi.accounts().self().index();
      accountIndexedCounter.assertReindexOf(user);

      // user cannot reindex any account
      AuthException thrown =
          assertThrows(AuthException.class, () -> gApi.accounts().id(admin.username()).index());
      assertThat(thrown).hasMessageThat().contains("modify account not permitted");
    }
  }

  @Test
  public void checkConsistency() throws Exception {
    projectOperations
        .allProjectsForUpdate()
        .add(allowCapability(GlobalCapability.ACCESS_DATABASE).group(REGISTERED_USERS))
        .update();
    requestScopeOperations.resetCurrentApiUser();

    // Create an account with a preferred email.
    String username = name("foo");
    String email = username + "@example.com";
    TestAccount account = accountCreator.create(username, email, "Foo Bar");

    ConsistencyCheckInput input = new ConsistencyCheckInput();
    input.checkAccounts = new CheckAccountsInput();
    ConsistencyCheckInfo checkInfo = gApi.config().server().checkConsistency(input);
    assertThat(checkInfo.checkAccountsResult.problems).isEmpty();

    Set<ConsistencyProblemInfo> expectedProblems = new HashSet<>();

    // Delete the external ID for the preferred email. This makes the account inconsistent since it
    // now doesn't have an external ID for its preferred email.
    accountsUpdateProvider
        .get()
        .update(
            "Delete External ID",
            account.id(),
            u -> u.deleteExternalId(ExternalId.createEmail(account.id(), email)));
    expectedProblems.add(
        new ConsistencyProblemInfo(
            ConsistencyProblemInfo.Status.ERROR,
            "Account '"
                + account.id().get()
                + "' has no external ID for its preferred email '"
                + email
                + "'"));

    checkInfo = gApi.config().server().checkConsistency(input);
    assertThat(checkInfo.checkAccountsResult.problems).hasSize(expectedProblems.size());
    assertThat(checkInfo.checkAccountsResult.problems).containsExactlyElementsIn(expectedProblems);
  }

  @Test
  public void internalQueryFindActiveAndInactiveAccounts() throws Exception {
    String name = name("foo");
    assertThat(accountQueryProvider.get().byDefault(name)).isEmpty();

    TestAccount foo1 = accountCreator.create(name + "-1");
    assertThat(gApi.accounts().id(foo1.username()).getActive()).isTrue();

    TestAccount foo2 = accountCreator.create(name + "-2");
    gApi.accounts().id(foo2.username()).setActive(false);
    assertThat(gApi.accounts().id(foo2.id().get()).getActive()).isFalse();

    assertThat(accountQueryProvider.get().byDefault(name)).hasSize(2);
  }

  @Test
  public void checkMetaId() throws Exception {
    // metaId is set when account is loaded
    assertThat(accounts.get(admin.id()).get().account().metaId()).isEqualTo(getMetaId(admin.id()));

    // metaId is set when account is created
    AccountsUpdate au = accountsUpdateProvider.get();
    Account.Id accountId = Account.id(seq.nextAccountId());
    AccountState accountState = au.insert("Create Test Account", accountId, u -> {});
    assertThat(accountState.account().metaId()).isEqualTo(getMetaId(accountId));

    // metaId is set when account is updated
    Optional<AccountState> updatedAccountState =
        au.update("Set Full Name", accountId, u -> u.setFullName("foo"));
    assertThat(updatedAccountState).isPresent();
    Account updatedAccount = updatedAccountState.get().account();
    assertThat(accountState.account().metaId()).isNotEqualTo(updatedAccount.metaId());
    assertThat(updatedAccount.metaId()).isEqualTo(getMetaId(accountId));
  }

  private EmailInput newEmailInput(String email, boolean noConfirmation) {
    EmailInput input = new EmailInput();
    input.email = email;
    input.noConfirmation = noConfirmation;
    return input;
  }

  private EmailInput newEmailInput(String email) {
    return newEmailInput(email, true);
  }

  private String getMetaId(Account.Id accountId) throws IOException {
    try (Repository repo = repoManager.openRepository(allUsers);
        RevWalk rw = new RevWalk(repo);
        ObjectReader or = repo.newObjectReader()) {
      Ref ref = repo.exactRef(RefNames.refsUsers(accountId));
      return ref != null ? ref.getObjectId().name() : null;
    }
  }

  @Test
  public void allGroupsForAnAdminAccountCanBeRetrieved() throws Exception {
    List<GroupInfo> groups = gApi.accounts().id(admin.username()).getGroups();
    assertThat(groups)
        .comparingElementsUsing(getGroupToNameCorrespondence())
        .containsExactly("Anonymous Users", "Registered Users", "Administrators");
  }

  @Test
  public void createUserWithValidUsername() throws Exception {
    ImmutableList<String> names =
        ImmutableList.of(
            "user@domain",
            "user-name",
            "user_name",
            "1234",
            "user1234",
            "1234@domain",
            "user!+alias{*}#$%&’^=~|@domain");
    for (String name : names) {
      gApi.accounts().create(name);
    }
  }

  @Test
  public void createUserWithInvalidUsername() throws Exception {
    ImmutableList<String> invalidNames =
        ImmutableList.of(
            "@", "@foo", "-", "-foo", "_", "_foo", "!", "+", "{", "}", "*", "%", "#", "$", "&", "’",
            "^", "=", "~");
    for (String name : invalidNames) {
      BadRequestException thrown =
          assertThrows(BadRequestException.class, () -> gApi.accounts().create(name));
      assertThat(thrown).hasMessageThat().isEqualTo(String.format("Invalid username '%s'", name));
    }
  }

  @Test
  public void allGroupsForAUserAccountCanBeRetrieved() throws Exception {
    String username = name("user1");
    accountOperations.newAccount().username(username).create();
    AccountGroup.UUID groupID = groupOperations.newGroup().name("group").create();
    String group = groupOperations.group(groupID).get().name();

    gApi.groups().id(group).addMembers(username);

    List<GroupInfo> allGroups = gApi.accounts().id(username).getGroups();
    assertThat(allGroups)
        .comparingElementsUsing(getGroupToNameCorrespondence())
        .containsExactly("Anonymous Users", "Registered Users", group);
  }

  @Test
  public void defaultPermissionsOnUserBranches() throws Exception {
    String userRef = RefNames.REFS_USERS + "${" + RefPattern.USERID_SHARDED + "}";
    assertPermissions(
        allUsers,
        groupRef(REGISTERED_USERS),
        userRef,
        true,
        Permission.READ,
        Permission.PUSH,
        Permission.SUBMIT);

    assertLabelPermission(
        allUsers, groupRef(REGISTERED_USERS), userRef, true, "Code-Review", -2, 2);

    assertPermissions(
        allUsers,
        adminGroupRef(),
        RefNames.REFS_USERS_DEFAULT,
        true,
        Permission.READ,
        Permission.PUSH,
        Permission.CREATE);
  }

  @Test
  public void retryOnLockFailure() throws Exception {
    String status = "happy";
    String fullName = "Foo";
    AtomicBoolean doneBgUpdate = new AtomicBoolean(false);
    PersonIdent ident = serverIdent.get();
    AccountsUpdate update =
        new AccountsUpdate(
            repoManager,
            gitReferenceUpdated,
            Optional.empty(),
            allUsers,
            externalIds,
            metaDataUpdateInternalFactory,
            new RetryHelper(
                cfg,
                retryMetrics,
                null,
                new PluginSetContext<>(DynamicSet.emptySet(), PluginMetrics.DISABLED_INSTANCE),
                r -> r.withBlockStrategy(noSleepBlockStrategy)),
            extIdNotesFactory,
            ident,
            ident,
            () -> {
              if (!doneBgUpdate.getAndSet(true)) {
                try {
                  accountsUpdateProvider
                      .get()
                      .update("Set Status", admin.id(), u -> u.setStatus(status));
                } catch (IOException | ConfigInvalidException | StorageException e) {
                  // Ignore, the successful update of the account is asserted later
                }
              }
            },
            Runnables.doNothing());
    assertThat(doneBgUpdate.get()).isFalse();
    AccountInfo accountInfo = gApi.accounts().id(admin.id().get()).get();
    assertThat(accountInfo.status).isNull();
    assertThat(accountInfo.name).isNotEqualTo(fullName);

    Optional<AccountState> updatedAccountState =
        update.update("Set Full Name", admin.id(), u -> u.setFullName(fullName));
    assertThat(doneBgUpdate.get()).isTrue();

    assertThat(updatedAccountState).isPresent();
    Account updatedAccount = updatedAccountState.get().account();
    assertThat(updatedAccount.status()).isEqualTo(status);
    assertThat(updatedAccount.fullName()).isEqualTo(fullName);

    accountInfo = gApi.accounts().id(admin.id().get()).get();
    assertThat(accountInfo.status).isEqualTo(status);
    assertThat(accountInfo.name).isEqualTo(fullName);
  }

  @Test
  public void failAfterRetryerGivesUp() throws Exception {
    List<String> status = ImmutableList.of("foo", "bar", "baz");
    String fullName = "Foo";
    AtomicInteger bgCounter = new AtomicInteger(0);
    PersonIdent ident = serverIdent.get();
    AccountsUpdate update =
        new AccountsUpdate(
            repoManager,
            gitReferenceUpdated,
            Optional.empty(),
            allUsers,
            externalIds,
            metaDataUpdateInternalFactory,
            new RetryHelper(
                cfg,
                retryMetrics,
                null,
                new PluginSetContext<>(DynamicSet.emptySet(), PluginMetrics.DISABLED_INSTANCE),
                r ->
                    r.withStopStrategy(StopStrategies.stopAfterAttempt(status.size()))
                        .withBlockStrategy(noSleepBlockStrategy)),
            extIdNotesFactory,
            ident,
            ident,
            () -> {
              try {
                accountsUpdateProvider
                    .get()
                    .update(
                        "Set Status",
                        admin.id(),
                        u -> u.setStatus(status.get(bgCounter.getAndAdd(1))));
              } catch (IOException | ConfigInvalidException | StorageException e) {
                // Ignore, the expected exception is asserted later
              }
            },
            Runnables.doNothing());
    assertThat(bgCounter.get()).isEqualTo(0);
    AccountInfo accountInfo = gApi.accounts().id(admin.id().get()).get();
    assertThat(accountInfo.status).isNull();
    assertThat(accountInfo.name).isNotEqualTo(fullName);

    assertThrows(
        LockFailureException.class,
        () -> update.update("Set Full Name", admin.id(), u -> u.setFullName(fullName)));
    assertThat(bgCounter.get()).isEqualTo(status.size());

    Account updatedAccount = accounts.get(admin.id()).get().account();
    assertThat(updatedAccount.status()).isEqualTo(Iterables.getLast(status));
    assertThat(updatedAccount.fullName()).isEqualTo(admin.fullName());

    accountInfo = gApi.accounts().id(admin.id().get()).get();
    assertThat(accountInfo.status).isEqualTo(Iterables.getLast(status));
    assertThat(accountInfo.name).isEqualTo(admin.fullName());
  }

  @Test
  public void atomicReadMofifyWrite() throws Exception {
    gApi.accounts().id(admin.id().get()).setStatus("A-1");

    AtomicInteger bgCounterA1 = new AtomicInteger(0);
    AtomicInteger bgCounterA2 = new AtomicInteger(0);
    PersonIdent ident = serverIdent.get();
    AccountsUpdate update =
        new AccountsUpdate(
            repoManager,
            gitReferenceUpdated,
            Optional.empty(),
            allUsers,
            externalIds,
            metaDataUpdateInternalFactory,
            new RetryHelper(
                cfg,
                retryMetrics,
                null,
                new PluginSetContext<>(DynamicSet.emptySet(), PluginMetrics.DISABLED_INSTANCE),
                r -> r.withBlockStrategy(noSleepBlockStrategy)),
            extIdNotesFactory,
            ident,
            ident,
            Runnables.doNothing(),
            () -> {
              try {
                accountsUpdateProvider
                    .get()
                    .update("Set Status", admin.id(), u -> u.setStatus("A-2"));
              } catch (IOException | ConfigInvalidException | StorageException e) {
                // Ignore, the expected exception is asserted later
              }
            });
    assertThat(bgCounterA1.get()).isEqualTo(0);
    assertThat(bgCounterA2.get()).isEqualTo(0);
    assertThat(gApi.accounts().id(admin.id().get()).get().status).isEqualTo("A-1");

    Optional<AccountState> updatedAccountState =
        update.update(
            "Set Status",
            admin.id(),
            (a, u) -> {
              if ("A-1".equals(a.account().status())) {
                bgCounterA1.getAndIncrement();
                u.setStatus("B-1");
              }

              if ("A-2".equals(a.account().status())) {
                bgCounterA2.getAndIncrement();
                u.setStatus("B-2");
              }
            });

    assertThat(bgCounterA1.get()).isEqualTo(1);
    assertThat(bgCounterA2.get()).isEqualTo(1);

    assertThat(updatedAccountState).isPresent();
    assertThat(updatedAccountState.get().account().status()).isEqualTo("B-2");
    assertThat(accounts.get(admin.id()).get().account().status()).isEqualTo("B-2");
    assertThat(gApi.accounts().id(admin.id().get()).get().status).isEqualTo("B-2");
  }

  @Test
  public void atomicReadMofifyWriteExternalIds() throws Exception {
    projectOperations
        .allProjectsForUpdate()
        .add(allowCapability(GlobalCapability.ACCESS_DATABASE).group(REGISTERED_USERS))
        .update();

    Account.Id accountId = Account.id(seq.nextAccountId());
    ExternalId extIdA1 = ExternalId.create("foo", "A-1", accountId);
    accountsUpdateProvider
        .get()
        .insert("Create Test Account", accountId, u -> u.addExternalId(extIdA1));

    AtomicInteger bgCounterA1 = new AtomicInteger(0);
    AtomicInteger bgCounterA2 = new AtomicInteger(0);
    PersonIdent ident = serverIdent.get();
    ExternalId extIdA2 = ExternalId.create("foo", "A-2", accountId);
    AccountsUpdate update =
        new AccountsUpdate(
            repoManager,
            gitReferenceUpdated,
            Optional.empty(),
            allUsers,
            externalIds,
            metaDataUpdateInternalFactory,
            new RetryHelper(
                cfg,
                retryMetrics,
                null,
                new PluginSetContext<>(DynamicSet.emptySet(), PluginMetrics.DISABLED_INSTANCE),
                r -> r.withBlockStrategy(noSleepBlockStrategy)),
            extIdNotesFactory,
            ident,
            ident,
            Runnables.doNothing(),
            () -> {
              try {
                accountsUpdateProvider
                    .get()
                    .update(
                        "Update External ID",
                        accountId,
                        u -> u.replaceExternalId(extIdA1, extIdA2));
              } catch (IOException | ConfigInvalidException | StorageException e) {
                // Ignore, the expected exception is asserted later
              }
            });
    assertThat(bgCounterA1.get()).isEqualTo(0);
    assertThat(bgCounterA2.get()).isEqualTo(0);
    assertThat(
            gApi.accounts().id(accountId.get()).getExternalIds().stream()
                .map(i -> i.identity)
                .collect(toSet()))
        .containsExactly(extIdA1.key().get());

    ExternalId extIdB1 = ExternalId.create("foo", "B-1", accountId);
    ExternalId extIdB2 = ExternalId.create("foo", "B-2", accountId);
    Optional<AccountState> updatedAccount =
        update.update(
            "Update External ID",
            accountId,
            (a, u) -> {
              if (a.externalIds().contains(extIdA1)) {
                bgCounterA1.getAndIncrement();
                u.replaceExternalId(extIdA1, extIdB1);
              }

              if (a.externalIds().contains(extIdA2)) {
                bgCounterA2.getAndIncrement();
                u.replaceExternalId(extIdA2, extIdB2);
              }
            });

    assertThat(bgCounterA1.get()).isEqualTo(1);
    assertThat(bgCounterA2.get()).isEqualTo(1);

    assertThat(updatedAccount).isPresent();
    assertThat(updatedAccount.get().externalIds()).containsExactly(extIdB2);
    assertThat(accounts.get(accountId).get().externalIds()).containsExactly(extIdB2);
    assertThat(
            gApi.accounts().id(accountId.get()).getExternalIds().stream()
                .map(i -> i.identity)
                .collect(toSet()))
        .containsExactly(extIdB2.key().get());
  }

  @Test
  public void stalenessChecker() throws Exception {
    // Newly created account is not stale.
    AccountInfo accountInfo = gApi.accounts().create(name("foo")).get();
    Account.Id accountId = Account.id(accountInfo._accountId);
    assertThat(stalenessChecker.isStale(accountId)).isFalse();

    // Manually updating the user ref makes the index document stale.
    String userRef = RefNames.refsUsers(accountId);
    try (Repository repo = repoManager.openRepository(allUsers);
        ObjectInserter oi = repo.newObjectInserter();
        RevWalk rw = new RevWalk(repo)) {
      RevCommit commit = rw.parseCommit(repo.exactRef(userRef).getObjectId());

      PersonIdent ident = new PersonIdent(serverIdent.get(), TimeUtil.nowTs());
      CommitBuilder cb = new CommitBuilder();
      cb.setTreeId(commit.getTree());
      cb.setCommitter(ident);
      cb.setAuthor(ident);
      cb.setMessage(commit.getFullMessage());
      ObjectId emptyCommit = oi.insert(cb);
      oi.flush();

      RefUpdate updateRef = repo.updateRef(userRef);
      updateRef.setExpectedOldObjectId(commit.toObjectId());
      updateRef.setNewObjectId(emptyCommit);
      assertThat(updateRef.forceUpdate()).isEqualTo(RefUpdate.Result.FORCED);
    }
    assertStaleAccountAndReindex(accountId);

    // Manually inserting/updating/deleting an external ID of the user makes the index document
    // stale.
    try (Repository repo = repoManager.openRepository(allUsers)) {
      ExternalIdNotes extIdNotes = ExternalIdNotes.loadNoCacheUpdate(allUsers, repo);

      ExternalId.Key key = ExternalId.Key.create("foo", "foo");
      extIdNotes.insert(ExternalId.create(key, accountId));
      try (MetaDataUpdate update = metaDataUpdateFactory.create(allUsers)) {
        extIdNotes.commit(update);
      }
      assertStaleAccountAndReindex(accountId);

      extIdNotes.upsert(ExternalId.createWithEmail(key, accountId, "foo@example.com"));
      try (MetaDataUpdate update = metaDataUpdateFactory.create(allUsers)) {
        extIdNotes.commit(update);
      }
      assertStaleAccountAndReindex(accountId);

      extIdNotes.delete(accountId, key);
      try (MetaDataUpdate update = metaDataUpdateFactory.create(allUsers)) {
        extIdNotes.commit(update);
      }
      assertStaleAccountAndReindex(accountId);
    }

    // Manually delete account
    try (Repository repo = repoManager.openRepository(allUsers);
        RevWalk rw = new RevWalk(repo)) {
      RevCommit commit = rw.parseCommit(repo.exactRef(userRef).getObjectId());
      RefUpdate updateRef = repo.updateRef(userRef);
      updateRef.setExpectedOldObjectId(commit.toObjectId());
      updateRef.setNewObjectId(ObjectId.zeroId());
      updateRef.setForceUpdate(true);
      assertThat(updateRef.delete()).isEqualTo(RefUpdate.Result.FORCED);
    }
    assertStaleAccountAndReindex(accountId);
  }

  private void assertStaleAccountAndReindex(Account.Id accountId) throws IOException {
    // Evict account from cache to be sure that we use the index state for staleness checks. This
    // has to happen directly on the accounts cache because AccountCacheImpl triggers a reindex for
    // the account.
    accountsCache.invalidate(accountId);
    assertThat(stalenessChecker.isStale(accountId)).isTrue();

    // Reindex fixes staleness
    accountIndexer.index(accountId);
    assertThat(stalenessChecker.isStale(accountId)).isFalse();
  }

  @Test
  @UseClockStep
  public void deleteAllDraftComments() throws Exception {
    try {
      Project.NameKey project2 = projectOperations.newProject().create();
      PushOneCommit.Result r1 = createChange();

      TestRepository<?> tr2 = cloneProject(project2);
      PushOneCommit.Result r2 =
          createChange(
              tr2,
              "refs/heads/master",
              "Change in project2",
              PushOneCommit.FILE_NAME,
              "content2",
              null);

      // Create 2 drafts each on both changes for user.
      requestScopeOperations.setApiUser(user.id());
      createDraft(r1, PushOneCommit.FILE_NAME, "draft 1a");
      createDraft(r1, PushOneCommit.FILE_NAME, "draft 1b");
      createDraft(r2, PushOneCommit.FILE_NAME, "draft 2a");
      createDraft(r2, PushOneCommit.FILE_NAME, "draft 2b");
      assertThat(gApi.changes().id(r1.getChangeId()).current().draftsAsList()).hasSize(2);
      assertThat(gApi.changes().id(r2.getChangeId()).current().draftsAsList()).hasSize(2);

      // Create 1 draft on first change for admin.
      requestScopeOperations.setApiUser(admin.id());
      createDraft(r1, PushOneCommit.FILE_NAME, "admin draft");
      assertThat(gApi.changes().id(r1.getChangeId()).current().draftsAsList()).hasSize(1);

      // Delete user's draft comments; leave admin's alone.
      requestScopeOperations.setApiUser(user.id());
      List<DeletedDraftCommentInfo> result =
          gApi.accounts().self().deleteDraftComments(new DeleteDraftCommentsInput());

      // Results are ordered according to the change search, most recently updated first.
      assertThat(result).hasSize(2);
      DeletedDraftCommentInfo del2 = result.get(0);
      assertThat(del2.change.changeId).isEqualTo(r2.getChangeId());
      assertThat(del2.deleted.stream().map(c -> c.message)).containsExactly("draft 2a", "draft 2b");
      DeletedDraftCommentInfo del1 = result.get(1);
      assertThat(del1.change.changeId).isEqualTo(r1.getChangeId());
      assertThat(del1.deleted.stream().map(c -> c.message)).containsExactly("draft 1a", "draft 1b");

      assertThat(gApi.changes().id(r1.getChangeId()).current().draftsAsList()).isEmpty();
      assertThat(gApi.changes().id(r2.getChangeId()).current().draftsAsList()).isEmpty();

      requestScopeOperations.setApiUser(admin.id());
      assertThat(gApi.changes().id(r1.getChangeId()).current().draftsAsList()).hasSize(1);
    } finally {
      cleanUpDrafts();
    }
  }

  @Test
  public void deleteDraftCommentsByQuery() throws Exception {
    try {
      PushOneCommit.Result r1 = createChange();
      PushOneCommit.Result r2 = createChange();

      createDraft(r1, PushOneCommit.FILE_NAME, "draft a");
      createDraft(r2, PushOneCommit.FILE_NAME, "draft b");
      assertThat(gApi.changes().id(r1.getChangeId()).current().draftsAsList()).hasSize(1);
      assertThat(gApi.changes().id(r2.getChangeId()).current().draftsAsList()).hasSize(1);

      List<DeletedDraftCommentInfo> result =
          gApi.accounts()
              .self()
              .deleteDraftComments(new DeleteDraftCommentsInput("change:" + r1.getChangeId()));
      assertThat(result).hasSize(1);
      assertThat(result.get(0).change.changeId).isEqualTo(r1.getChangeId());
      assertThat(result.get(0).deleted.stream().map(c -> c.message)).containsExactly("draft a");

      assertThat(gApi.changes().id(r1.getChangeId()).current().draftsAsList()).isEmpty();
      assertThat(gApi.changes().id(r2.getChangeId()).current().draftsAsList()).hasSize(1);
    } finally {
      cleanUpDrafts();
    }
  }

  @Test
  public void deleteOtherUsersDraftCommentsDisallowed() throws Exception {
    try {
      PushOneCommit.Result r = createChange();
      requestScopeOperations.setApiUser(user.id());
      createDraft(r, PushOneCommit.FILE_NAME, "draft");
      requestScopeOperations.setApiUser(admin.id());
      AuthException thrown =
          assertThrows(
              AuthException.class,
              () ->
                  gApi.accounts()
                      .id(user.id().get())
                      .deleteDraftComments(new DeleteDraftCommentsInput()));
      assertThat(thrown).hasMessageThat().isEqualTo("Cannot delete drafts of other user");
    } finally {
      cleanUpDrafts();
    }
  }

  @Test
  public void deleteDraftCommentsSkipsInvisibleChanges() throws Exception {
    try {
      createBranch(BranchNameKey.create(project, "secret"));
      PushOneCommit.Result r1 = createChange();
      PushOneCommit.Result r2 = createChange("refs/for/secret");

      requestScopeOperations.setApiUser(user.id());
      createDraft(r1, PushOneCommit.FILE_NAME, "draft a");
      createDraft(r2, PushOneCommit.FILE_NAME, "draft b");
      assertThat(gApi.changes().id(r1.getChangeId()).current().draftsAsList()).hasSize(1);
      assertThat(gApi.changes().id(r2.getChangeId()).current().draftsAsList()).hasSize(1);

      projectOperations
          .project(project)
          .forUpdate()
          .add(block(Permission.READ).ref("refs/heads/secret").group(REGISTERED_USERS))
          .update();
      List<DeletedDraftCommentInfo> result =
          gApi.accounts().self().deleteDraftComments(new DeleteDraftCommentsInput());
      assertThat(result).hasSize(1);
      assertThat(result.get(0).change.changeId).isEqualTo(r1.getChangeId());
      assertThat(result.get(0).deleted.stream().map(c -> c.message)).containsExactly("draft a");

      projectOperations
          .project(project)
          .forUpdate()
          .remove(permissionKey(Permission.READ).ref("refs/heads/secret"))
          .update();
      assertThat(gApi.changes().id(r1.getChangeId()).current().draftsAsList()).isEmpty();
      // Draft still exists since change wasn't visible when drafts where deleted.
      assertThat(gApi.changes().id(r2.getChangeId()).current().draftsAsList()).hasSize(1);
    } finally {
      cleanUpDrafts();
    }
  }

  @Test
  public void userCanGenerateNewHttpPassword() throws Exception {
    sender.clear();
    String newPassword = gApi.accounts().self().generateHttpPassword();
    assertThat(newPassword).isNotNull();
    assertThat(sender.getMessages()).hasSize(1);
    assertThat(sender.getMessages().get(0).body()).contains("HTTP password was added or updated");
  }

  @Test
  public void adminCanGenerateNewHttpPasswordForUser() throws Exception {
    requestScopeOperations.setApiUser(admin.id());
    sender.clear();
    String newPassword = gApi.accounts().id(user.username()).generateHttpPassword();
    assertThat(newPassword).isNotNull();
    assertThat(sender.getMessages()).hasSize(1);
    assertThat(sender.getMessages().get(0).body()).contains("HTTP password was added or updated");
  }

  @Test
  public void userCannotGenerateNewHttpPasswordForOtherUser() throws Exception {
    requestScopeOperations.setApiUser(user.id());
    assertThrows(
        AuthException.class, () -> gApi.accounts().id(admin.username()).generateHttpPassword());
  }

  @Test
  public void userCannotExplicitlySetHttpPassword() throws Exception {
    requestScopeOperations.setApiUser(user.id());
    assertThrows(
        AuthException.class, () -> gApi.accounts().self().setHttpPassword("my-new-password"));
  }

  @Test
  public void userCannotExplicitlySetHttpPasswordForOtherUser() throws Exception {
    requestScopeOperations.setApiUser(user.id());
    assertThrows(
        AuthException.class,
        () -> gApi.accounts().id(admin.username()).setHttpPassword("my-new-password"));
  }

  @Test
  public void userCanRemoveHttpPassword() throws Exception {
    requestScopeOperations.setApiUser(user.id());
    sender.clear();
    assertThat(gApi.accounts().self().setHttpPassword(null)).isNull();
    assertThat(sender.getMessages()).hasSize(1);
    assertThat(sender.getMessages().get(0).body()).contains("HTTP password was deleted");
  }

  @Test
  public void userCannotRemoveHttpPasswordForOtherUser() throws Exception {
    requestScopeOperations.setApiUser(user.id());
    assertThrows(
        AuthException.class, () -> gApi.accounts().id(admin.username()).setHttpPassword(null));
  }

  @Test
  public void adminCanExplicitlySetHttpPasswordForUser() throws Exception {
    requestScopeOperations.setApiUser(admin.id());
    String httpPassword = "new-password-for-user";
    sender.clear();
    assertThat(gApi.accounts().id(user.username()).setHttpPassword(httpPassword))
        .isEqualTo(httpPassword);
    assertThat(sender.getMessages()).hasSize(1);
    assertThat(sender.getMessages().get(0).body()).contains("HTTP password was added or updated");
  }

  @Test
  public void adminCanRemoveHttpPasswordForUser() throws Exception {
    requestScopeOperations.setApiUser(admin.id());
    sender.clear();
    assertThat(gApi.accounts().id(user.username()).setHttpPassword(null)).isNull();
    assertThat(sender.getMessages()).hasSize(1);
    assertThat(sender.getMessages().get(0).body()).contains("HTTP password was deleted");
  }

  @Test
  public void cannotGenerateHttpPasswordWhenUsernameIsNotSet() throws Exception {
    requestScopeOperations.setApiUser(admin.id());
    int userId = accountCreator.create().id().get();
    assertThat(gApi.accounts().id(userId).get().username).isNull();
    ResourceConflictException thrown =
        assertThrows(
            ResourceConflictException.class,
            () -> gApi.accounts().id(userId).generateHttpPassword());
    assertThat(thrown).hasMessageThat().contains("username");
  }

  private void createDraft(PushOneCommit.Result r, String path, String message) throws Exception {
    DraftInput in = new DraftInput();
    in.path = path;
    in.line = 1;
    in.message = message;
    gApi.changes().id(r.getChangeId()).current().createDraft(in);
  }

  private void cleanUpDrafts() throws Exception {
    for (TestAccount testAccount : accountCreator.getAll()) {
      requestScopeOperations.setApiUser(testAccount.id());
      for (ChangeInfo changeInfo : gApi.changes().query("has:draft").get()) {
        for (CommentInfo c :
            gApi.changes().id(changeInfo.id).drafts().values().stream()
                .flatMap(List::stream)
                .collect(toImmutableList())) {
          gApi.changes().id(changeInfo.id).revision(c.patchSet).draft(c.id).delete();
        }
      }
    }
  }

  private static Correspondence<GroupInfo, String> getGroupToNameCorrespondence() {
    return Correspondence.from(
        (actualGroup, expectedName) -> {
          String groupName = actualGroup == null ? null : actualGroup.name;
          return Objects.equals(groupName, expectedName);
        },
        "has name");
  }

  private void assertSequenceNumbers(List<SshKeyInfo> sshKeys) {
    int seq = 1;
    for (SshKeyInfo key : sshKeys) {
      assertThat(key.seq).isEqualTo(seq++);
    }
  }

  private PGPPublicKey getOnlyKeyFromStore(TestKey key) throws Exception {
    try (PublicKeyStore store = publicKeyStoreProvider.get()) {
      Iterable<PGPPublicKeyRing> keys = store.get(key.getKeyId());
      assertThat(keys).hasSize(1);
      return keys.iterator().next().getPublicKey();
    }
  }

  private static String armor(PGPPublicKey key) throws Exception {
    ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
    try (ArmoredOutputStream aout = new ArmoredOutputStream(out)) {
      key.encode(aout);
    }
    return new String(out.toByteArray(), UTF_8);
  }

  private static void assertIteratorSize(int size, Iterator<?> it) {
    List<?> lst = ImmutableList.copyOf(it);
    assertThat(lst).hasSize(size);
  }

  private static void assertKeyMapContains(TestKey expected, Map<String, GpgKeyInfo> actualMap) {
    GpgKeyInfo actual = actualMap.get(expected.getKeyIdString());
    assertThat(actual).isNotNull();
    assertThat(actual.id).isNull();
    actual.id = expected.getKeyIdString();
    assertKeyEquals(expected, actual);
  }

  private void assertKeys(TestKey... expectedKeys) throws Exception {
    assertKeys(Arrays.asList(expectedKeys));
  }

  private void assertKeys(Iterable<TestKey> expectedKeys) throws Exception {
    // Check via API.
    FluentIterable<TestKey> expected = FluentIterable.from(expectedKeys);
    Map<String, GpgKeyInfo> keyMap = gApi.accounts().self().listGpgKeys();
    assertWithMessage("keys returned by listGpgKeys()")
        .that(keyMap.keySet())
        .containsExactlyElementsIn(expected.transform(TestKey::getKeyIdString));

    for (TestKey key : expected) {
      assertKeyEquals(key, gApi.accounts().self().gpgKey(key.getKeyIdString()).get());
      assertKeyEquals(
          key,
          gApi.accounts()
              .self()
              .gpgKey(Fingerprint.toString(key.getPublicKey().getFingerprint()))
              .get());
      assertKeyMapContains(key, keyMap);
    }

    // Check raw external IDs.
    Account.Id currAccountId = atrScope.get().getUser().getAccountId();
    Iterable<String> expectedFps =
        expected.transform(k -> BaseEncoding.base16().encode(k.getPublicKey().getFingerprint()));
    Iterable<String> actualFps =
        externalIds.byAccount(currAccountId, SCHEME_GPGKEY).stream()
            .map(e -> e.key().id())
            .collect(toSet());
    assertWithMessage("external IDs in database")
        .that(actualFps)
        .containsExactlyElementsIn(expectedFps);

    // Check raw stored keys.
    for (TestKey key : expected) {
      getOnlyKeyFromStore(key);
    }
  }

  private static void assertKeyEquals(TestKey expected, GpgKeyInfo actual) {
    String id = expected.getKeyIdString();
    assertWithMessage(id).that(actual.id).isEqualTo(id);
    assertWithMessage(id)
        .that(actual.fingerprint)
        .isEqualTo(Fingerprint.toString(expected.getPublicKey().getFingerprint()));
    List<String> userIds = ImmutableList.copyOf(expected.getPublicKey().getUserIDs());
    assertWithMessage(id).that(actual.userIds).containsExactlyElementsIn(userIds);
    String key = actual.key;
    assertWithMessage(id).that(key).startsWith("-----BEGIN PGP PUBLIC KEY BLOCK-----\n");
    assertWithMessage(id).that(key).endsWith("-----END PGP PUBLIC KEY BLOCK-----\n");
    assertThat(actual.status).isEqualTo(GpgKeyInfo.Status.TRUSTED);
    assertThat(actual.problems).isEmpty();
  }

  private void addExternalIdEmail(TestAccount account, String email) throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      requireNonNull(email);
      accountsUpdateProvider
          .get()
          .update(
              "Add Email",
              account.id(),
              u ->
                  u.addExternalId(
                      ExternalId.createWithEmail(name("test"), email, account.id(), email)));
      accountIndexedCounter.assertReindexOf(account);
      requestScopeOperations.setApiUser(account.id());
    }
  }

  private Map<String, GpgKeyInfo> addGpgKey(String armored) throws Exception {
    return addGpgKey(admin, armored);
  }

  private Map<String, GpgKeyInfo> addGpgKey(TestAccount account, String armored) throws Exception {
    AccountIndexedCounter accountIndexedCounter = new AccountIndexedCounter();
    try (Registration registration =
        extensionRegistry.newRegistration().add(accountIndexedCounter)) {
      Map<String, GpgKeyInfo> gpgKeys =
          gApi.accounts()
              .id(account.username())
              .putGpgKeys(ImmutableList.of(armored), ImmutableList.<String>of());
      accountIndexedCounter.assertReindexOf(gApi.accounts().id(account.username()).get());
      return gpgKeys;
    }
  }

  private Map<String, GpgKeyInfo> addGpgKeyNoReindex(String armored) throws Exception {
    return gApi.accounts().self().putGpgKeys(ImmutableList.of(armored), ImmutableList.of());
  }

  private void assertUser(AccountInfo info, TestAccount account) throws Exception {
    assertUser(info, account, null);
  }

  private void assertUser(AccountInfo info, TestAccount account, @Nullable String expectedStatus)
      throws Exception {
    assertThat(info.name).isEqualTo(account.fullName());
    assertThat(info.email).isEqualTo(account.email());
    assertThat(info.username).isEqualTo(account.username());
    assertThat(info.status).isEqualTo(expectedStatus);
  }

  private Set<String> getEmails() throws RestApiException {
    return gApi.accounts().self().getEmails().stream().map(e -> e.email).collect(toSet());
  }

  private void assertEmail(Set<Account.Id> accounts, TestAccount expectedAccount) {
    assertThat(accounts).hasSize(1);
    assertThat(Iterables.getOnlyElement(accounts)).isEqualTo(expectedAccount.id());
  }

  private Config getAccountConfig(TestRepository<?> allUsersRepo) throws Exception {
    Config ac = new Config();
    try (TreeWalk tw =
        TreeWalk.forPath(
            allUsersRepo.getRepository(),
            AccountProperties.ACCOUNT_CONFIG,
            getHead(allUsersRepo.getRepository(), "HEAD").getTree())) {
      assertThat(tw).isNotNull();
      ac.fromText(
          new String(
              allUsersRepo
                  .getRevWalk()
                  .getObjectReader()
                  .open(tw.getObjectId(0), OBJ_BLOB)
                  .getBytes(),
              UTF_8));
    }
    return ac;
  }

  /** Checks if an account is indexed the correct number of times. */
  private static class AccountIndexedCounter implements AccountIndexedListener {
    private final AtomicLongMap<Integer> countsByAccount = AtomicLongMap.create();

    @Override
    public void onAccountIndexed(int id) {
      countsByAccount.incrementAndGet(id);
    }

    void clear() {
      countsByAccount.clear();
    }

    void assertReindexOf(TestAccount testAccount) {
      assertReindexOf(testAccount, 1);
    }

    void assertReindexOf(AccountInfo accountInfo) {
      assertReindexOf(Account.id(accountInfo._accountId), 1);
    }

    void assertReindexOf(TestAccount testAccount, long expectedCount) {
      assertThat(countsByAccount.asMap()).containsExactly(testAccount.id().get(), expectedCount);
      clear();
    }

    void assertReindexOf(Account.Id accountId, long expectedCount) {
      assertThat(countsByAccount.asMap()).containsEntry(accountId.get(), expectedCount);
      countsByAccount.remove(accountId.get());
    }

    void assertNoReindex() {
      assertThat(countsByAccount.asMap()).isEmpty();
    }
  }

  private static class RefUpdateCounter implements GitReferenceUpdatedListener {
    private final AtomicLongMap<String> countsByProjectRefs = AtomicLongMap.create();

    static String projectRef(Project.NameKey project, String ref) {
      return projectRef(project.get(), ref);
    }

    static String projectRef(String project, String ref) {
      return project + ":" + ref;
    }

    @Override
    public void onGitReferenceUpdated(Event event) {
      countsByProjectRefs.incrementAndGet(projectRef(event.getProjectName(), event.getRefName()));
    }

    void clear() {
      countsByProjectRefs.clear();
    }

    void assertRefUpdateFor(String... projectRefs) {
      Map<String, Long> expectedRefUpdateCounts = new HashMap<>();
      for (String projectRef : projectRefs) {
        expectedRefUpdateCounts.put(projectRef, 1L);
      }
      assertRefUpdateFor(expectedRefUpdateCounts);
    }

    void assertRefUpdateFor(Map<String, Long> expectedProjectRefUpdateCounts) {
      assertThat(countsByProjectRefs.asMap())
          .containsExactlyEntriesIn(expectedProjectRefUpdateCounts);
      clear();
    }
  }
}
