// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.server.account;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_GERRIT;
import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_GOOGLE_OAUTH;
import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_USERNAME;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.entities.AccessSection;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.Permission;
import com.google.gerrit.exceptions.NoSuchGroupException;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.client.AccountFieldName;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.Sequences;
import com.google.gerrit.server.ServerInitiated;
import com.google.gerrit.server.account.externalids.DuplicateExternalIdKeyException;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.account.externalids.ExternalIdFactory;
import com.google.gerrit.server.account.externalids.ExternalIdKeyFactory;
import com.google.gerrit.server.account.externalids.ExternalIds;
import com.google.gerrit.server.auth.NoSuchUserException;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.group.db.GroupDelta;
import com.google.gerrit.server.group.db.GroupsUpdate;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.ssh.SshKeyCache;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;

/** Tracks authentication related details for user accounts. */
@Singleton
public class AccountManager {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final Sequences sequences;
  private final Accounts accounts;
  private final Provider<AccountsUpdate> accountsUpdateProvider;
  private final AccountCache byIdCache;
  private final Realm realm;
  private final IdentifiedUser.GenericFactory userFactory;
  private final SshKeyCache sshKeyCache;
  private final ProjectCache projectCache;
  private final AtomicBoolean awaitsFirstAccountCheck;
  private final ExternalIds externalIds;
  private final GroupsUpdate.Factory groupsUpdateFactory;
  private final boolean autoUpdateAccountActiveStatus;
  private final SetInactiveFlag setInactiveFlag;
  private final ExternalIdFactory externalIdFactory;
  private final ExternalIdKeyFactory externalIdKeyFactory;

  @VisibleForTesting
  @Inject
  public AccountManager(
      Sequences sequences,
      @GerritServerConfig Config cfg,
      Accounts accounts,
      @ServerInitiated Provider<AccountsUpdate> accountsUpdateProvider,
      AccountCache byIdCache,
      Realm accountMapper,
      IdentifiedUser.GenericFactory userFactory,
      SshKeyCache sshKeyCache,
      ProjectCache projectCache,
      ExternalIds externalIds,
      GroupsUpdate.Factory groupsUpdateFactory,
      SetInactiveFlag setInactiveFlag,
      ExternalIdFactory externalIdFactory,
      ExternalIdKeyFactory externalIdKeyFactory) {
    this.sequences = sequences;
    this.accounts = accounts;
    this.accountsUpdateProvider = accountsUpdateProvider;
    this.byIdCache = byIdCache;
    this.realm = accountMapper;
    this.userFactory = userFactory;
    this.sshKeyCache = sshKeyCache;
    this.projectCache = projectCache;
    this.awaitsFirstAccountCheck =
        new AtomicBoolean(cfg.getBoolean("capability", "makeFirstUserAdmin", true));
    this.externalIds = externalIds;
    this.groupsUpdateFactory = groupsUpdateFactory;
    this.autoUpdateAccountActiveStatus =
        cfg.getBoolean("auth", "autoUpdateAccountActiveStatus", false);
    this.setInactiveFlag = setInactiveFlag;
    this.externalIdFactory = externalIdFactory;
    this.externalIdKeyFactory = externalIdKeyFactory;
  }

  /** Returns a user identified by this external identity string */
  public Optional<Account.Id> lookup(String externalId) throws AccountException {
    try {
      return externalIds.get(externalIdKeyFactory.parse(externalId)).map(ExternalId::accountId);
    } catch (IOException e) {
      throw new AccountException("Cannot lookup account " + externalId, e);
    }
  }

  /**
   * Authenticate the user, potentially creating a new account if they are new.
   *
   * @param who identity of the user, with any details we received about them.
   * @return the result of authenticating the user.
   * @throws AccountException the account does not exist, and cannot be created, or exists, but
   *     cannot be located, is unable to be activated or deactivated, or is inactive, or cannot be
   *     added to the admin group (only for the first account).
   */
  public AuthResult authenticate(AuthRequest who) throws AccountException, IOException {
    try {
      who = realm.authenticate(who);
    } catch (NoSuchUserException e) {
      deactivateAccountIfItExists(who);
      throw e;
    }
    try {
      Optional<ExternalId> optionalExtId = externalIds.get(who.getExternalIdKey());
      if (!optionalExtId.isPresent()) {
        return createOrLinkAccount(who);
      }

      ExternalId extId = optionalExtId.get();
      Optional<AccountState> accountState = byIdCache.get(extId.accountId());
      if (!accountState.isPresent()) {
        logger.atSevere().log(
            "Authentication with external ID %s failed. Account %s doesn't exist.",
            extId.key().get(), extId.accountId().get());
        throw new AccountException("Authentication error, account not found");
      }

      // Account exists
      Optional<Account> act = updateAccountActiveStatus(who, accountState.get().account());
      if (!act.isPresent()) {
        // The account was deleted since we checked for it last time. This should never happen
        // since we don't support deletion of accounts.
        throw new AccountException("Authentication error, account not found");
      }
      if (!act.get().isActive()) {
        throw new AccountException("Authentication error, account inactive");
      }

      // return the identity to the caller.
      update(who, extId);
      return new AuthResult(extId.accountId(), who.getExternalIdKey(), false);
    } catch (StorageException | ConfigInvalidException e) {
      throw new AccountException("Authentication error", e);
    }
  }

  /**
   * Determines if a new account should be created or if we should link to an existing account.
   *
   * @param who identity of the user, with any details we received about them.
   * @return the result of authenticating the user.
   * @throws AccountException the account does not exist, and cannot be created, or exists, but
   *     cannot be located, is unable to be activated or deactivated, or is inactive, or cannot be
   *     added to the admin group (only for the first account).
   */
  private AuthResult createOrLinkAccount(AuthRequest who)
      throws AccountException, IOException, ConfigInvalidException {
    // TODO: in case of extension of further migration paths this code should
    // probably be refactored out by creating an AccountMigrator extension point.
    if (who.getExternalIdKey().isScheme(SCHEME_GOOGLE_OAUTH)) {
      Optional<ExternalId> existingLDAPExtID = findLdapExternalId(who);
      if (existingLDAPExtID.isPresent()) {
        return migrateLdapAccountToOauth(who, existingLDAPExtID.get());
      }
    }
    logger.atFine().log(
        "External ID for account %s not found. A new account will be automatically created.",
        who.getEmailAddress());
    return create(who);
  }

  private AuthResult migrateLdapAccountToOauth(AuthRequest who, ExternalId ldapExternalId)
      throws AccountException, IOException, ConfigInvalidException {
    Account.Id extAccId = ldapExternalId.accountId();
    AuthResult res = link(extAccId, who);
    accountsUpdateProvider
        .get()
        .update(
            "remove existing LDAP externalId with matching e-mail",
            extAccId,
            u -> {
              u.deleteExternalId(ldapExternalId);
            });
    return res;
  }

  private void deactivateAccountIfItExists(AuthRequest authRequest) {
    if (!shouldUpdateActiveStatus(authRequest)) {
      return;
    }
    try {
      Optional<ExternalId> extId = externalIds.get(authRequest.getExternalIdKey());
      if (!extId.isPresent()) {
        return;
      }
      setInactiveFlag.deactivate(extId.get().accountId());
    } catch (Exception e) {
      logger.atSevere().withCause(e).log(
          "Unable to deactivate account %s",
          authRequest
              .getUserName()
              .orElse(" for external ID key " + authRequest.getExternalIdKey().get()));
    }
  }

  private Optional<Account> updateAccountActiveStatus(AuthRequest authRequest, Account account)
      throws AccountException {
    if (!shouldUpdateActiveStatus(authRequest) || authRequest.isActive() == account.isActive()) {
      return Optional.of(account);
    }

    if (authRequest.isActive()) {
      try {
        setInactiveFlag.activate(account.id());
      } catch (Exception e) {
        throw new AccountException("Unable to activate account " + account.id(), e);
      }
    } else {
      try {
        setInactiveFlag.deactivate(account.id());
      } catch (Exception e) {
        throw new AccountException("Unable to deactivate account " + account.id(), e);
      }
    }
    return byIdCache.get(account.id()).map(AccountState::account);
  }

  private boolean shouldUpdateActiveStatus(AuthRequest authRequest) {
    return autoUpdateAccountActiveStatus && authRequest.authProvidesAccountActiveStatus();
  }

  private void update(AuthRequest who, ExternalId extId)
      throws IOException, ConfigInvalidException, AccountException {
    IdentifiedUser user = userFactory.create(extId.accountId());
    List<Consumer<AccountDelta.Builder>> accountUpdates = new ArrayList<>();

    // If the email address was modified by the authentication provider,
    // update our records to match the changed email.
    //
    String newEmail = who.getEmailAddress();
    String oldEmail = extId.email();
    if (newEmail != null && !newEmail.equals(oldEmail)) {
      ExternalId extIdWithNewEmail =
          externalIdFactory.create(extId.key(), extId.accountId(), newEmail, extId.password());
      checkEmailNotUsed(extId.accountId(), extIdWithNewEmail);
      accountUpdates.add(u -> u.replaceExternalId(extId, extIdWithNewEmail));

      if (oldEmail != null && oldEmail.equals(user.getAccount().preferredEmail())) {
        accountUpdates.add(u -> u.setPreferredEmail(newEmail));
      }
    }

    if (!Strings.isNullOrEmpty(who.getDisplayName())
        && !Objects.equals(user.getAccount().fullName(), who.getDisplayName())) {
      accountUpdates.add(a -> a.setFullName(who.getDisplayName()));
    }

    if (!realm.allowsEdit(AccountFieldName.USER_NAME)
        && who.getUserName().isPresent()
        && !who.getUserName().equals(user.getUserName())) {
      if (user.getUserName().isPresent()) {
        logger.atWarning().log(
            "Not changing already set username %s to %s",
            user.getUserName().get(), who.getUserName().get());
      } else {
        logger.atWarning().log("Not setting username to %s", who.getUserName().get());
      }
    }

    if (!accountUpdates.isEmpty()) {
      Optional<AccountState> updatedAccount =
          accountsUpdateProvider
              .get()
              .update(
                  "Update Account on Login",
                  user.getAccountId(),
                  AccountsUpdate.joinConsumers(accountUpdates));
      if (!updatedAccount.isPresent()) {
        throw new StorageException("Account " + user.getAccountId() + " has been deleted");
      }
    }
  }

  private Optional<ExternalId> findLdapExternalId(AuthRequest who) throws IOException {
    String email = who.getEmailAddress();
    if (email == null || email.isEmpty()) {
      return Optional.empty();
    }

    Optional<ExternalId> ldapExternalId =
        externalIds.byEmail(email).stream().filter(a -> a.isScheme(SCHEME_GERRIT)).findFirst();
    return ldapExternalId;
  }

  private AuthResult create(AuthRequest who)
      throws AccountException, IOException, ConfigInvalidException {
    Account.Id newId = Account.id(sequences.nextAccountId());
    logger.atFine().log("Assigning new Id %s to account", newId);

    ExternalId extId =
        externalIdFactory.createWithEmail(who.getExternalIdKey(), newId, who.getEmailAddress());
    logger.atFine().log("Created external Id: %s", extId);
    checkEmailNotUsed(newId, extId);
    ExternalId userNameExtId =
        who.getUserName().isPresent() ? createUsername(newId, who.getUserName().get()) : null;

    boolean isFirstAccount = awaitsFirstAccountCheck.getAndSet(false) && !accounts.hasAnyAccount();

    AccountState accountState;
    try {
      accountState =
          accountsUpdateProvider
              .get()
              .insert(
                  "Create Account on First Login",
                  newId,
                  u -> {
                    u.setFullName(who.getDisplayName())
                        .setPreferredEmail(extId.email())
                        .addExternalId(extId);
                    if (userNameExtId != null) {
                      u.addExternalId(userNameExtId);
                    }
                  });
    } catch (DuplicateExternalIdKeyException e) {
      throw new AccountException(
          "Cannot assign external ID \""
              + e.getDuplicateKey().get()
              + "\" to account "
              + newId
              + "; external ID already in use.");
    } finally {
      // If adding the account failed, it may be that it actually was the
      // first account. So we reset the 'check for first account'-guard, as
      // otherwise the first account would not get administration permissions.
      awaitsFirstAccountCheck.set(isFirstAccount);
    }

    if (userNameExtId != null) {
      who.getUserName().ifPresent(sshKeyCache::evict);
    }

    IdentifiedUser user = userFactory.create(newId);

    if (isFirstAccount) {
      // This is the first user account on our site. Assume this user
      // is going to be the site's administrator and just make them that
      // to bootstrap the authentication database.
      //
      Permission admin =
          projectCache
              .getAllProjects()
              .getConfig()
              .getAccessSection(AccessSection.GLOBAL_CAPABILITIES)
              .orElseThrow(() -> new IllegalStateException("access section does not exist"))
              .getPermission(GlobalCapability.ADMINISTRATE_SERVER);

      AccountGroup.UUID adminGroupUuid = admin.getRules().get(0).getGroup().getUUID();
      addGroupMember(adminGroupUuid, user);
    }

    realm.onCreateAccount(who, accountState.account());
    return new AuthResult(newId, extId.key(), true);
  }

  private ExternalId createUsername(Account.Id accountId, String username)
      throws AccountUserNameException {
    checkArgument(!Strings.isNullOrEmpty(username));

    if (!ExternalId.isValidUsername(username)) {
      throw new AccountUserNameException(
          String.format(
              "Cannot assign user name \"%s\" to account %s; name does not conform.",
              username, accountId));
    }
    return externalIdFactory.create(SCHEME_USERNAME, username, accountId);
  }

  private void checkEmailNotUsed(Account.Id accountId, ExternalId extIdToBeCreated)
      throws IOException, AccountException {
    String email = extIdToBeCreated.email();
    if (email == null) {
      return;
    }

    Set<ExternalId> existingExtIdsWithEmail = externalIds.byEmail(email);
    if (existingExtIdsWithEmail.isEmpty()) {
      return;
    }

    for (ExternalId externalId : existingExtIdsWithEmail) {
      if (externalId.accountId().get() != accountId.get()) {
        logger.atWarning().log(
            "Email %s is already assigned to account %s;"
                + " cannot create external ID %s with the same email for account %s.",
            email,
            externalId.accountId().get(),
            extIdToBeCreated.key().get(),
            extIdToBeCreated.accountId().get());
        throw new AccountException("Email '" + email + "' in use by another account");
      }
    }
  }

  private void addGroupMember(AccountGroup.UUID groupUuid, IdentifiedUser user)
      throws IOException, ConfigInvalidException, AccountException {
    // The user initiated this request by logging in. -> Attribute all modifications to that user.
    GroupsUpdate groupsUpdate = groupsUpdateFactory.create(user);
    GroupDelta groupDelta =
        GroupDelta.builder()
            .setMemberModification(
                memberIds -> Sets.union(memberIds, ImmutableSet.of(user.getAccountId())))
            .build();
    try {
      groupsUpdate.updateGroup(groupUuid, groupDelta);
    } catch (NoSuchGroupException e) {
      throw new AccountException(String.format("Group %s not found", groupUuid), e);
    }
  }

  /**
   * Link another authentication identity to an existing account.
   *
   * @param to account to link the identity onto.
   * @param who the additional identity.
   * @return the result of linking the identity to the user.
   * @throws AccountException the identity belongs to a different account, or it cannot be linked at
   *     this time.
   */
  public AuthResult link(Account.Id to, AuthRequest who)
      throws AccountException, IOException, ConfigInvalidException {
    Optional<ExternalId> optionalExtId = externalIds.get(who.getExternalIdKey());
    if (optionalExtId.isPresent()) {
      ExternalId extId = optionalExtId.get();
      if (!extId.accountId().equals(to)) {
        throw new AccountException(
            "Identity '" + extId.key().get() + "' in use by another account");
      }
      update(who, extId);
    } else {
      ExternalId newExtId =
          externalIdFactory.createWithEmail(who.getExternalIdKey(), to, who.getEmailAddress());
      checkEmailNotUsed(to, newExtId);
      accountsUpdateProvider
          .get()
          .update(
              "Link External ID",
              to,
              (a, u) -> {
                u.addExternalId(newExtId);
                if (who.getEmailAddress() != null && a.account().preferredEmail() == null) {
                  u.setPreferredEmail(who.getEmailAddress());
                }
              });
    }
    return new AuthResult(to, who.getExternalIdKey(), false);
  }

  /**
   * Update the link to another unique authentication identity to an existing account.
   *
   * <p>Existing external identities with the same scheme will be removed and replaced with the new
   * one.
   *
   * @param to account to link the identity onto.
   * @param who the additional identity.
   * @return the result of linking the identity to the user.
   * @throws AccountException the identity belongs to a different account, or it cannot be linked at
   *     this time.
   */
  public AuthResult updateLink(Account.Id to, AuthRequest who)
      throws AccountException, IOException, ConfigInvalidException {
    accountsUpdateProvider
        .get()
        .update(
            "Delete External IDs on Update Link",
            to,
            (a, u) -> {
              Set<ExternalId> filteredExtIdsByScheme =
                  a.externalIds().stream()
                      .filter(e -> e.key().isScheme(who.getExternalIdKey().scheme()))
                      .collect(toImmutableSet());
              if (filteredExtIdsByScheme.isEmpty()) {
                return;
              }

              if (filteredExtIdsByScheme.size() > 1
                  || filteredExtIdsByScheme.stream()
                      .noneMatch(e -> e.key().equals(who.getExternalIdKey()))) {
                u.deleteExternalIds(filteredExtIdsByScheme);
              }
            });

    return link(to, who);
  }

  /**
   * Unlink an external identity from an existing account.
   *
   * @param from account to unlink the external identity from
   * @param extIdKey the key of the external ID that should be deleted
   * @throws AccountException the identity belongs to a different account, or the identity was not
   *     found
   */
  public void unlink(Account.Id from, ExternalId.Key extIdKey)
      throws AccountException, IOException, ConfigInvalidException {
    unlink(from, ImmutableList.of(extIdKey));
  }

  /**
   * Unlink an external identities from an existing account.
   *
   * @param from account to unlink the external identity from
   * @param extIdKeys the keys of the external IDs that should be deleted
   * @throws AccountException any of the identity belongs to a different account, or any of the
   *     identity was not found
   */
  public void unlink(Account.Id from, Collection<ExternalId.Key> extIdKeys)
      throws AccountException, IOException, ConfigInvalidException {
    if (extIdKeys.isEmpty()) {
      return;
    }

    List<ExternalId> extIds = new ArrayList<>(extIdKeys.size());
    for (ExternalId.Key extIdKey : extIdKeys) {
      Optional<ExternalId> extId = externalIds.get(extIdKey);
      if (extId.isPresent()) {
        if (!extId.get().accountId().equals(from)) {
          throw new AccountException("Identity '" + extIdKey.get() + "' in use by another account");
        }
        extIds.add(extId.get());
      } else {
        throw new AccountException("Identity '" + extIdKey.get() + "' not found");
      }
    }

    accountsUpdateProvider
        .get()
        .update(
            "Unlink External ID" + (extIds.size() > 1 ? "s" : ""),
            from,
            (a, u) -> {
              u.deleteExternalIds(extIds);
              if (a.account().preferredEmail() != null
                  && extIds.stream()
                      .anyMatch(e -> a.account().preferredEmail().equals(e.email()))) {
                u.setPreferredEmail(null);
              }
            });
  }
}
