// Copyright (C) 2017 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.permissions;

import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toSet;

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.UsedAt;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.LabelType;
import com.google.gerrit.entities.Project;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.api.access.CoreOrPluginProjectPermission;
import com.google.gerrit.extensions.api.access.GlobalOrPluginPermission;
import com.google.gerrit.extensions.conditions.BooleanCondition;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser.ImpersonationPermissionMode;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.inject.ImplementedBy;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;

/**
 * Checks authorization to perform an action on a project, reference, or change.
 *
 * <p>{@code check} methods should be used during action handlers to verify the user is allowed to
 * exercise the specified permission. For convenience in implementation {@code check} methods throw
 * {@link AuthException} if the permission is denied.
 *
 * <p>{@code test} methods should be used when constructing replies to the client and the result
 * object needs to include a true/false hint indicating the user's ability to exercise the
 * permission. This is suitable for configuring UI button state, but should not be relied upon to
 * guard handlers before making state changes.
 *
 * <p>{@code PermissionBackend} is a singleton for the server, acting as a factory for lightweight
 * request instances. Implementation classes may cache supporting data inside of {@link WithUser},
 * {@link ForProject}, {@link ForRef}, and {@link ForChange} instances, in addition to storing
 * within {@link CurrentUser} using a {@link com.google.gerrit.server.PropertyMap.Key}. {@link
 * GlobalPermission} caching for {@link WithUser} may best cached inside {@link CurrentUser} as
 * {@link WithUser} instances are frequently created.
 *
 * <p>Example use:
 *
 * <pre>
 *   private final PermissionBackend permissions;
 *   private final Provider<CurrentUser> user;
 *
 *   {@literal @}Inject
 *   Foo(PermissionBackend permissions, Provider<CurrentUser> user) {
 *     this.permissions = permissions;
 *     this.user = user;
 *   }
 *
 *   public void apply(...) {
 *     permissions.user(user).change(cd).check(ChangePermission.SUBMIT);
 *   }
 *
 *   public UiAction.Description getDescription(ChangeResource rsrc) {
 *     return new UiAction.Description()
 *       .setLabel("Submit")
 *       .setVisible(rsrc.permissions().testCond(ChangePermission.SUBMIT));
 * }
 * </pre>
 */
@ImplementedBy(DefaultPermissionBackend.class)
public abstract class PermissionBackend {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  /** Returns an instance scoped to the current user. */
  public abstract WithUser currentUser();

  /**
   * Returns an instance scoped to the specified user. Should be used in cases where the user could
   * either be the issuer of the current request or an impersonated user. Uses {@link
   * CurrentUser#getUserForPermission()} to determine permissions of which user should be used in
   * case of impersonation. PermissionBackends that do not support impersonation can fail with an
   * {@code IllegalStateException}.
   *
   * <p>If an instance scoped to the current user is desired, use {@code currentUser()} instead.
   */
  public abstract WithUser user(CurrentUser user);

  /**
   * Returns an instance scoped to the specified user. Should be used in cases where the user could
   * either be the issuer of the current request or an impersonated user. Uses {@code
   * permissionMode} argument to determine permissions of which user should be used in case of
   * impersonation. PermissionBackends that do not support impersonation can fail with an {@code
   * IllegalStateException}.
   */
  public abstract WithUser user(CurrentUser user, ImpersonationPermissionMode permissionMode);

  /**
   * For calls internal to permission evaluation logic, uses specified user without attempting to
   * resolve impersonation.
   */
  public abstract WithUser exactUser(CurrentUser user);

  /**
   * Returns an instance scoped to the provided user. Should be used in cases where the caller wants
   * to check the permissions of a user who is not the issuer of the current request and not the
   * target of impersonation.
   *
   * <p>Usage should be very limited as this can expose a group-oracle.
   */
  public abstract WithUser absentUser(Account.Id id);

  /**
   * Check whether this {@code PermissionBackend} respects the same global capabilities as the
   * {@link DefaultPermissionBackend}.
   *
   * <p>If true, then it makes sense for downstream callers to refer to built-in Gerrit capability
   * names in user-facing error messages, for example.
   *
   * @return whether this is the default permission backend.
   */
  public boolean usesDefaultCapabilities() {
    return false;
  }

  /**
   * Throw {@link ResourceNotFoundException} if this backend does not use the default global
   * capabilities.
   */
  public void checkUsesDefaultCapabilities() throws ResourceNotFoundException {
    if (!usesDefaultCapabilities()) {
      throw new ResourceNotFoundException("Gerrit capabilities not used on this server");
    }
  }

  /**
   * Bulk evaluate a set of {@link PermissionBackendCondition} for view handling.
   *
   * <p>Overridden implementations should call {@link PermissionBackendCondition#set(boolean)} to
   * cache the result of {@code testOrFalse} in the condition for later evaluation. Caching the
   * result will bypass the usual invocation of {@code testOrFalse}.
   *
   * @param conds conditions to consider.
   */
  public void bulkEvaluateTest(Set<PermissionBackendCondition> conds) {
    // Do nothing by default. The default implementation of PermissionBackendCondition
    // delegates to the appropriate testOrFalse method in PermissionBackend.
  }

  /** PermissionBackend scoped to a specific user. */
  public abstract static class WithUser {
    /** Returns an instance scoped for the specified project. */
    public abstract ForProject project(Project.NameKey project);

    /** Returns an instance scoped for the {@code ref}, and its parent project. */
    public ForRef ref(BranchNameKey ref) {
      return project(ref.project()).ref(ref.branch());
    }

    /** Returns an instance scoped for the change, and its destination ref and project. */
    public ForChange change(ChangeData cd) {
      try {
        return ref(cd.change().getDest()).change(cd);
      } catch (StorageException e) {
        return FailedPermissionBackend.change("unavailable", e);
      }
    }

    /** Returns an instance scoped for the change, and its destination ref and project. */
    public ForChange change(ChangeNotes notes) {
      return ref(notes.getChange().getDest()).change(notes);
    }

    /**
     * Verify scoped user can {@code perm}, throwing if denied.
     *
     * <p>Should be used in REST API handlers where the thrown {@link AuthException} can be
     * propagated. In business logic, where the exception would have to be caught, prefer using
     * {@link #test(GlobalOrPluginPermission)}.
     */
    public abstract void check(GlobalOrPluginPermission perm)
        throws AuthException, PermissionBackendException;

    /**
     * Verify scoped user can perform at least one listed permission.
     *
     * <p>If {@code any} is empty, the method completes normally and allows the caller to continue.
     * Since no permissions were supplied to check, its assumed no permissions are necessary to
     * continue with the caller's operation.
     *
     * <p>If the user has at least one of the permissions in {@code any}, the method completes
     * normally, possibly without checking all listed permissions.
     *
     * <p>If {@code any} is non-empty and the user has none, {@link AuthException} is thrown for one
     * of the failed permissions.
     *
     * @param any set of permissions to check.
     */
    public void checkAny(Set<GlobalOrPluginPermission> any)
        throws PermissionBackendException, AuthException {
      for (Iterator<GlobalOrPluginPermission> itr = any.iterator(); itr.hasNext(); ) {
        try {
          check(itr.next());
          return;
        } catch (AuthException err) {
          if (!itr.hasNext()) {
            throw err;
          }
        }
      }
    }

    /** Filter {@code permSet} to permissions scoped user might be able to perform. */
    public abstract <T extends GlobalOrPluginPermission> Set<T> test(Collection<T> permSet)
        throws PermissionBackendException;

    public boolean test(GlobalOrPluginPermission perm) throws PermissionBackendException {
      return test(Collections.singleton(perm)).contains(perm);
    }

    public boolean testOrFalse(GlobalOrPluginPermission perm) {
      try {
        return test(perm);
      } catch (PermissionBackendException e) {
        logger.atWarning().withCause(e).log("Cannot test %s; assuming false", perm);
        return false;
      }
    }

    public abstract BooleanCondition testCond(GlobalOrPluginPermission perm);

    /**
     * Filter a set of projects using {@code check(perm)}.
     *
     * @param perm required permission in a project to be included in result.
     * @param projects candidate set of projects; may be empty.
     * @return filtered set of {@code projects} where {@code check(perm)} was successful.
     * @throws PermissionBackendException backend cannot access its internal state.
     */
    public Set<Project.NameKey> filter(ProjectPermission perm, Collection<Project.NameKey> projects)
        throws PermissionBackendException {
      requireNonNull(perm, "ProjectPermission");
      requireNonNull(projects, "projects");
      Set<Project.NameKey> allowed = Sets.newHashSetWithExpectedSize(projects.size());
      for (Project.NameKey project : projects) {
        try {
          if (project(project).test(perm)) {
            allowed.add(project);
          }
        } catch (PermissionBackendException e) {
          if (e.getCause() instanceof RepositoryNotFoundException) {
            logger.atWarning().withCause(e).log(
                "Could not find repository of the project %s", project.get());
            // Do not include this project because doesn't exist
          } else {
            throw e;
          }
        }
      }
      return allowed;
    }

    /**
     * Additional filter for changes query for reducing the cardinality of the results for current
     * user.
     *
     * @return additional query filter to add to all user's change queries, null if no filters are
     *     required.
     * @since 3.11
     */
    @UsedAt(UsedAt.Project.MODULE_VIRTUALHOST)
    public @Nullable String filterQueryChanges() {
      return null;
    }
  }

  /** PermissionBackend scoped to a user and project. */
  public abstract static class ForProject {
    /** Returns the fully qualified resource path that this instance is scoped to. */
    public abstract String resourcePath();

    /** Returns an instance scoped for {@code ref} in this project. */
    public abstract ForRef ref(String ref);

    /** Returns an instance scoped for the change, and its destination ref and project. */
    public ForChange change(ChangeData cd) {
      try {
        return ref(cd.branchOrThrow().branch()).change(cd);
      } catch (StorageException e) {
        return FailedPermissionBackend.change("unavailable", e);
      }
    }

    /** Returns an instance scoped for the change, and its destination ref and project. */
    public ForChange change(ChangeNotes notes) {
      return ref(notes.getChange().getDest().branch()).change(notes);
    }

    /**
     * Verify scoped user can {@code perm}, throwing if denied.
     *
     * <p>Should be used in REST API handlers where the thrown {@link AuthException} can be
     * propagated. In business logic, where the exception would have to be caught, prefer using
     * {@link #test(CoreOrPluginProjectPermission)}.
     */
    public abstract void check(CoreOrPluginProjectPermission perm)
        throws AuthException, PermissionBackendException;

    /** Filter {@code permSet} to permissions scoped user might be able to perform. */
    public abstract <T extends CoreOrPluginProjectPermission> Set<T> test(Collection<T> permSet)
        throws PermissionBackendException;

    public boolean test(CoreOrPluginProjectPermission perm) throws PermissionBackendException {
      if (perm instanceof ProjectPermission) {
        return test(EnumSet.of((ProjectPermission) perm)).contains(perm);
      }

      // TODO(xchangcheng): implement for plugin defined project permissions.
      return false;
    }

    public boolean testOrFalse(CoreOrPluginProjectPermission perm) {
      try {
        return test(perm);
      } catch (PermissionBackendException e) {
        logger.atWarning().withCause(e).log("Cannot test %s; assuming false", perm);
        return false;
      }
    }

    public abstract BooleanCondition testCond(CoreOrPluginProjectPermission perm);

    /**
     * Filter a list of references by visibility.
     *
     * @param refs a collection of references to filter.
     * @param repo an open {@link Repository} handle for this instance's project
     * @param opts further options for filtering.
     * @return a partition of the provided refs that are visible to the user that this instance is
     *     scoped to.
     * @throws PermissionBackendException if failure consulting backend configuration.
     */
    public abstract Collection<Ref> filter(
        Collection<Ref> refs, Repository repo, RefFilterOptions opts)
        throws PermissionBackendException;
  }

  /** Options for filtering refs using {@link ForProject}. */
  @AutoValue
  public abstract static class RefFilterOptions {
    /** Remove all NoteDb refs (refs/changes/*, refs/users/*, edit refs) from the result. */
    public abstract boolean filterMeta();

    /**
     * Select only refs with names matching prefixes per {@link
     * org.eclipse.jgit.lib.RefDatabase#getRefsByPrefix}.
     */
    public abstract ImmutableList<String> prefixes();

    public abstract Builder toBuilder();

    public static Builder builder() {
      return new AutoValue_PermissionBackend_RefFilterOptions.Builder()
          .setFilterMeta(false)
          .setPrefixes(Collections.singletonList(""));
    }

    @AutoValue.Builder
    public abstract static class Builder {
      public abstract Builder setFilterMeta(boolean val);

      public abstract Builder setPrefixes(List<String> prefixes);

      public abstract RefFilterOptions build();
    }

    public static RefFilterOptions defaults() {
      return builder().build();
    }
  }

  /** PermissionBackend scoped to a user, project and reference. */
  public abstract static class ForRef {
    /** Returns a fully qualified resource path that this instance is scoped to. */
    public abstract String resourcePath();

    /** Returns an instance scoped to change. */
    public abstract ForChange change(ChangeData cd);

    /** Returns an instance scoped to change. */
    public abstract ForChange change(ChangeNotes notes);

    /** Returns an instance scoped to change that has not been created yet. */
    public abstract ForChange changeToBeCreated(boolean isOwner);

    /**
     * Verify scoped user can {@code perm}, throwing if denied.
     *
     * <p>Should be used in REST API handlers where the thrown {@link AuthException} can be
     * propagated. In business logic, where the exception would have to be caught, prefer using
     * {@link #test(RefPermission)}.
     */
    public abstract void check(RefPermission perm) throws AuthException, PermissionBackendException;

    /** Filter {@code permSet} to permissions scoped user might be able to perform. */
    public abstract Set<RefPermission> test(Collection<RefPermission> permSet)
        throws PermissionBackendException;

    public boolean test(RefPermission perm) throws PermissionBackendException {
      return test(EnumSet.of(perm)).contains(perm);
    }

    /**
     * Test if user may be able to perform the permission.
     *
     * <p>Similar to {@link #test(RefPermission)} except this method returns {@code false} instead
     * of throwing an exception.
     *
     * @param perm the permission to test.
     * @return true if the user might be able to perform the permission; false if the user may be
     *     missing the necessary grants or state, or if the backend threw an exception.
     */
    public boolean testOrFalse(RefPermission perm) {
      try {
        return test(perm);
      } catch (PermissionBackendException e) {
        logger.atWarning().withCause(e).log("Cannot test %s; assuming false", perm);
        return false;
      }
    }

    public abstract BooleanCondition testCond(RefPermission perm);
  }

  /** PermissionBackend scoped to a user, project, reference and change. */
  public abstract static class ForChange {
    /** Returns the fully qualified resource path that this instance is scoped to. */
    public abstract String resourcePath();

    /**
     * Verify scoped user can {@code perm}, throwing if denied.
     *
     * <p>Should be used in REST API handlers where the thrown {@link AuthException} can be
     * propagated. In business logic, where the exception would have to be caught, prefer using
     * {@link #test(ChangePermissionOrLabel)}.
     */
    public abstract void check(ChangePermissionOrLabel perm)
        throws AuthException, PermissionBackendException;

    /** Filter {@code permSet} to permissions scoped user might be able to perform. */
    public abstract <T extends ChangePermissionOrLabel> Set<T> test(Collection<T> permSet)
        throws PermissionBackendException;

    public boolean test(ChangePermissionOrLabel perm) throws PermissionBackendException {
      return test(Collections.singleton(perm)).contains(perm);
    }

    /**
     * Test if user may be able to perform the permission.
     *
     * <p>Similar to {@link #test(ChangePermissionOrLabel)} except this method returns {@code false}
     * instead of throwing an exception.
     *
     * @param perm the permission to test.
     * @return true if the user might be able to perform the permission; false if the user may be
     *     missing the necessary grants or state, or if the backend threw an exception.
     */
    public boolean testOrFalse(ChangePermissionOrLabel perm) {
      try {
        return test(perm);
      } catch (PermissionBackendException e) {
        logger.atWarning().withCause(e).log("Cannot test %s; assuming false", perm);
        return false;
      }
    }

    public abstract BooleanCondition testCond(ChangePermissionOrLabel perm);

    /**
     * Test which values of a label the user may be able to set.
     *
     * @param label definition of the label to test values of.
     * @return set containing values the user may be able to use; may be empty if none.
     * @throws PermissionBackendException if failure consulting backend configuration.
     */
    public Set<LabelPermission.WithValue> test(LabelType label) throws PermissionBackendException {
      return test(valuesOf(requireNonNull(label, "LabelType")));
    }

    /**
     * Test which values of a label the user may be able to remove.
     *
     * @param label definition of the label to test values of.
     * @return set containing values the user may be able to use; may be empty if none.
     * @throws PermissionBackendException if failure consulting backend configuration.
     */
    public Set<LabelRemovalPermission.WithValue> testRemoval(LabelType label)
        throws PermissionBackendException {
      return test(removalValuesOf(requireNonNull(label, "LabelType")));
    }

    /**
     * Test which values of a group of labels the user may be able to set.
     *
     * @param types definition of the labels to test values of.
     * @return set containing values the user may be able to use; may be empty if none.
     * @throws PermissionBackendException if failure consulting backend configuration.
     */
    public Set<LabelPermission.WithValue> testLabels(Collection<LabelType> types)
        throws PermissionBackendException {
      requireNonNull(types, "LabelType");
      return test(types.stream().flatMap(t -> valuesOf(t).stream()).collect(toSet()));
    }

    /**
     * Test which values of a group of labels the user may be able to remove.
     *
     * @param types definition of the labels to test values of.
     * @return set containing values the user may be able to use; may be empty if none.
     * @throws PermissionBackendException if failure consulting backend configuration.
     */
    public Set<LabelRemovalPermission.WithValue> testLabelRemovals(Collection<LabelType> types)
        throws PermissionBackendException {
      requireNonNull(types, "LabelType");
      return test(types.stream().flatMap(t -> removalValuesOf(t).stream()).collect(toSet()));
    }

    private static Set<LabelPermission.WithValue> valuesOf(LabelType label) {
      return label.getValues().stream()
          .map(v -> new LabelPermission.WithValue(label, v))
          .collect(toSet());
    }

    private static Set<LabelRemovalPermission.WithValue> removalValuesOf(LabelType label) {
      return label.getValues().stream()
          .map(v -> new LabelRemovalPermission.WithValue(label, v))
          .collect(toSet());
    }
  }
}
