// 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.toMap;
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.data.LabelType;
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.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.CurrentUser;
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.Map;
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.CurrentUser.PropertyKey}.
 * {@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. 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 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(Branch.NameKey ref) {
      return project(ref.getParentKey()).ref(ref.get());
    }

    /** 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);
    }

    /**
     * Returns an instance scoped for the change loaded from index, and its destination ref and
     * project. This method should only be used when database access is harmful and potentially
     * stale data from the index is acceptable.
     */
    public ForChange indexedChange(ChangeData cd, ChangeNotes notes) {
      return ref(notes.getChange().getDest()).indexedChange(cd, notes);
    }

    /** Verify scoped user can {@code perm}, throwing if denied. */
    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 {
          project(project).check(perm);
          allowed.add(project);
        } catch (AuthException e) {
          // Do not include this project in allowed.
        } 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;
    }
  }

  /** 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.change().getDest().get()).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().get()).change(notes);
    }

    /**
     * Returns an instance scoped for the change loaded from index, and its destination ref and
     * project. This method should only be used when database access is harmful and potentially
     * stale data from the index is acceptable.
     */
    public ForChange indexedChange(ChangeData cd, ChangeNotes notes) {
      return ref(notes.getChange().getDest().get()).indexedChange(cd, notes);
    }

    /** Verify scoped user can {@code perm}, throwing if denied. */
    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 map of references by visibility.
     *
     * @param refs a map 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 Map<String, Ref> filter(
        Map<String, Ref> refs, Repository repo, RefFilterOptions opts)
        throws PermissionBackendException;

    /**
     * Filter a list of references by visibility.
     *
     * @param refs a list 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 Map<String, Ref> filter(List<Ref> refs, Repository repo, RefFilterOptions opts)
        throws PermissionBackendException {
      return filter(refs.stream().collect(toMap(Ref::getName, r -> r, (a, b) -> b)), repo, opts);
    }
  }

  /** 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);

    /**
     * @return instance scoped to change loaded from index. This method should only be used when
     *     database access is harmful and potentially stale data from the index is acceptable.
     */
    public abstract ForChange indexedChange(ChangeData cd, ChangeNotes notes);

    /** Verify scoped user can {@code perm}, throwing if denied. */
    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. */
    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 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()));
    }

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