// Copyright (C) 2010 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 com.google.common.base.Preconditions.checkArgument;

import com.google.common.collect.ImmutableList;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Permission;
import com.google.gerrit.entities.PermissionRange;
import com.google.gerrit.entities.PermissionRule;
import com.google.gerrit.entities.PermissionRule.Action;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.conditions.BooleanCondition;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.logging.CallerFinder;
import com.google.gerrit.server.logging.LoggingContext;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.permissions.PermissionBackend.ForChange;
import com.google.gerrit.server.permissions.PermissionBackend.ForRef;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.util.MagicBranch;
import java.io.IOException;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;

/** Manages access control for Git references (aka branches, tags). */
class RefControl {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final ChangeData.Factory changeDataFactory;
  private final RefVisibilityControl refVisibilityControl;
  private final ProjectControl projectControl;
  private final GitRepositoryManager repositoryManager;
  private final String refName;

  /** All permissions that apply to this reference. */
  private final PermissionCollection relevant;

  private final CallerFinder callerFinder;

  // The next 4 members are cached canPerform() permissions.

  private Boolean owner;
  private Boolean canForgeAuthor;
  private Boolean canForgeCommitter;
  private Boolean hasReadPermissionOnRef;

  RefControl(
      ChangeData.Factory changeDataFactory,
      RefVisibilityControl refVisibilityControl,
      ProjectControl projectControl,
      GitRepositoryManager repositoryManager,
      String ref,
      PermissionCollection relevant) {
    this.changeDataFactory = changeDataFactory;
    this.refVisibilityControl = refVisibilityControl;
    this.projectControl = projectControl;
    this.repositoryManager = repositoryManager;
    this.refName = ref;
    this.relevant = relevant;
    this.callerFinder =
        CallerFinder.builder()
            .addTarget(PermissionBackend.class)
            .matchSubClasses(true)
            .matchInnerClasses(true)
            .skip(1)
            .build();
  }

  ProjectControl getProjectControl() {
    return projectControl;
  }

  CurrentUser getUser() {
    return projectControl.getUser();
  }

  /** Is this user a ref owner? */
  boolean isOwner() {
    if (owner == null) {
      if (canPerform(Permission.OWNER)) {
        owner = true;

      } else {
        owner = projectControl.isOwner();
      }
    }
    return owner;
  }

  /**
   * Returns {@code true} if the user has permission to read the ref. This method evaluates {@link
   * RefPermission#READ} only. Hence, it is not authoritative. For example, it does not tell if the
   * user can see NoteDb refs such as {@code refs/meta/external-ids} which requires {@link
   * GlobalPermission#ACCESS_DATABASE} and deny access in this case.
   */
  boolean hasReadPermissionOnRef(boolean allowNoteDbRefs) {
    // Don't allow checking for NoteDb refs unless instructed otherwise.
    if (!allowNoteDbRefs
        && (refName.startsWith(Constants.R_TAGS) || RefNames.isGerritRef(refName))) {
      logger.atWarning().atMostEvery(30, TimeUnit.SECONDS).log(
          "%s: Can't determine visibility of %s in RefControl. Denying access. "
              + "This case should have been handled before.",
          projectControl.getProject().getName(), refName);
      return false;
    }

    if (hasReadPermissionOnRef == null) {
      hasReadPermissionOnRef = getUser().isInternalUser() || canPerform(Permission.READ);
    }
    return hasReadPermissionOnRef;
  }

  /** Returns true if this user can add a new patch set to this ref */
  boolean canAddPatchSet() {
    return projectControl
        .controlForRef(MagicBranch.NEW_CHANGE + refName)
        .canPerform(Permission.ADD_PATCH_SET);
  }

  /** Returns true if this user can rebase changes on this ref */
  boolean canRebase() {
    return canPerform(Permission.REBASE);
  }

  /** Returns true if this user can submit patch sets to this ref */
  boolean canSubmit(boolean isChangeOwner) {
    if (RefNames.REFS_CONFIG.equals(refName)) {
      // Always allow project owners to submit configuration changes.
      // Submitting configuration changes modifies the access control
      // rules. Allowing this to be done by a non-project-owner opens
      // a security hole enabling editing of access rules, and thus
      // granting of powers beyond submitting to the configuration.
      return projectControl.isOwner();
    }
    return canPerform(Permission.SUBMIT, isChangeOwner, false);
  }

  /** Returns true if this user can force edit topic names. */
  boolean canForceEditTopicName(boolean isChangeOwner) {
    return canPerform(Permission.EDIT_TOPIC_NAME, isChangeOwner, true);
  }

  /** Returns true if this user can delete changes. */
  boolean canDeleteChanges(boolean isChangeOwner) {
    return canPerform(Permission.DELETE_CHANGES)
        || (isChangeOwner && canPerform(Permission.DELETE_OWN_CHANGES, isChangeOwner, false));
  }

  /** The range of permitted values associated with a label permission. */
  PermissionRange getRange(String permission) {
    return getRange(permission, false);
  }

  /** The range of permitted values associated with a label permission. */
  @Nullable
  PermissionRange getRange(String permission, boolean isChangeOwner) {
    if (Permission.hasRange(permission)) {
      return toRange(permission, isChangeOwner);
    }
    return null;
  }

  /** True if the user has this permission. Works only for non labels. */
  boolean canPerform(String permissionName) {
    return canPerform(permissionName, false, false);
  }

  ForRef asForRef() {
    return new ForRefImpl();
  }

  private boolean canUpload() {
    return projectControl.controlForRef("refs/for/" + refName).canPerform(Permission.PUSH);
  }

  boolean canRevert() {
    return canPerform(Permission.REVERT);
  }

  /** Returns true if this user can submit merge patch sets to this ref */
  private boolean canUploadMerges() {
    return projectControl.controlForRef("refs/for/" + refName).canPerform(Permission.PUSH_MERGE);
  }

  /** Returns true if the user can update the reference as a fast-forward. */
  private boolean canUpdate() {
    if (RefNames.REFS_CONFIG.equals(refName) && !projectControl.isOwner()) {
      // Pushing requires being at least project owner, in addition to push.
      // Pushing configuration changes modifies the access control
      // rules. Allowing this to be done by a non-project-owner opens
      // a security hole enabling editing of access rules, and thus
      // granting of powers beyond pushing to the configuration.

      // On the AllProjects project the owner access right cannot be assigned,
      // this why for the AllProjects project we allow administrators to push
      // configuration changes if they have push without being project owner.
      if (!(projectControl.getProjectState().isAllProjects() && projectControl.isAdmin())) {
        return false;
      }
    }
    return canPerform(Permission.PUSH);
  }

  /** Returns true if the user can rewind (force push) the reference. */
  private boolean canForceUpdate() {
    if (canPushWithForce()) {
      return true;
    }

    switch (getUser().getAccessPath()) {
      case GIT:
        return false;

      case REST_API:
      case SSH_COMMAND:
      case UNKNOWN:
      case WEB_BROWSER:
      default:
        return (isOwner() && !isBlocked(Permission.PUSH, false, true)) || projectControl.isAdmin();
    }
  }

  private boolean canPushWithForce() {
    if (RefNames.REFS_CONFIG.equals(refName) && !projectControl.isOwner()) {
      // Pushing requires being at least project owner, in addition to push.
      // Pushing configuration changes modifies the access control
      // rules. Allowing this to be done by a non-project-owner opens
      // a security hole enabling editing of access rules, and thus
      // granting of powers beyond pushing to the configuration.
      return false;
    }
    return canPerform(Permission.PUSH, false, true);
  }

  /**
   * Determines whether the user can delete the Git ref controlled by this object.
   *
   * @return {@code true} if the user specified can delete a Git ref.
   */
  private boolean canDelete() {
    switch (getUser().getAccessPath()) {
      case GIT:
        return canPushWithForce() || canPerform(Permission.DELETE);

      case REST_API:
      case SSH_COMMAND:
      case UNKNOWN:
      case WEB_BROWSER:
      default:
        return canPushWithForce() || canPerform(Permission.DELETE) || projectControl.isAdmin();
    }
  }

  /** Returns true if this user can forge the author line in a commit. */
  private boolean canForgeAuthor() {
    if (canForgeAuthor == null) {
      canForgeAuthor = canPerform(Permission.FORGE_AUTHOR);
    }
    return canForgeAuthor;
  }

  /** Returns true if this user can forge the committer line in a commit. */
  private boolean canForgeCommitter() {
    if (canForgeCommitter == null) {
      canForgeCommitter = canPerform(Permission.FORGE_COMMITTER);
    }
    return canForgeCommitter;
  }

  /** Returns true if this user can forge the server on the committer line. */
  private boolean canForgeGerritServerIdentity() {
    return canPerform(Permission.FORGE_SERVER);
  }

  private static boolean isAllow(PermissionRule pr, boolean withForce) {
    return pr.getAction() == Action.ALLOW && (pr.getForce() || !withForce);
  }

  private static boolean isBlock(PermissionRule pr, boolean withForce) {
    // BLOCK with force specified is a weaker rule than without.
    return pr.getAction() == Action.BLOCK && (!pr.getForce() || withForce);
  }

  private PermissionRange toRange(String permissionName, boolean isChangeOwner) {
    int blockAllowMin = Integer.MIN_VALUE, blockAllowMax = Integer.MAX_VALUE;

    projectLoop:
    for (List<Permission> ps : relevant.getBlockRules(permissionName)) {
      boolean blockFound = false;
      int projectBlockAllowMin = Integer.MIN_VALUE, projectBlockAllowMax = Integer.MAX_VALUE;

      for (Permission p : ps) {
        if (p.getExclusiveGroup()) {
          for (PermissionRule pr : p.getRules()) {
            if (pr.getAction() == Action.ALLOW && projectControl.match(pr, isChangeOwner)) {
              // exclusive override, usually for a more specific ref.
              continue projectLoop;
            }
          }
        }

        for (PermissionRule pr : p.getRules()) {
          if (pr.getAction() == Action.BLOCK && projectControl.match(pr, isChangeOwner)) {
            projectBlockAllowMin = pr.getMin() + 1;
            projectBlockAllowMax = pr.getMax() - 1;
            blockFound = true;
          }
        }

        if (blockFound) {
          for (PermissionRule pr : p.getRules()) {
            if (pr.getAction() == Action.ALLOW && projectControl.match(pr, isChangeOwner)) {
              projectBlockAllowMin = pr.getMin();
              projectBlockAllowMax = pr.getMax();
              break;
            }
          }
          break;
        }
      }

      blockAllowMin = Math.max(projectBlockAllowMin, blockAllowMin);
      blockAllowMax = Math.min(projectBlockAllowMax, blockAllowMax);
    }

    int voteMin = 0, voteMax = 0;
    for (PermissionRule pr : relevant.getAllowRules(permissionName)) {
      if (pr.getAction() == PermissionRule.Action.ALLOW
          && projectControl.match(pr, isChangeOwner)) {
        // For votes, contrary to normal permissions, we aggregate all applicable rules.
        voteMin = Math.min(voteMin, pr.getMin());
        voteMax = Math.max(voteMax, pr.getMax());
      }
    }

    return new PermissionRange(
        permissionName,
        /* min= */ Math.max(voteMin, blockAllowMin),
        /* max= */ Math.min(voteMax, blockAllowMax));
  }

  private boolean isBlocked(String permissionName, boolean isChangeOwner, boolean withForce) {
    // Permissions are ordered by (more general project, more specific ref). Because Permission
    // does not have back pointers, we can't tell what ref-pattern or project each permission comes
    // from.
    List<List<Permission>> downwardPerProject = relevant.getBlockRules(permissionName);

    projectLoop:
    for (List<Permission> projectRules : downwardPerProject) {
      boolean overrideFound = false;
      for (Permission p : projectRules) {
        // If this is an exclusive ALLOW, then block rules from the same project are ignored.
        if (p.getExclusiveGroup()) {
          for (PermissionRule pr : p.getRules()) {
            if (isAllow(pr, withForce) && projectControl.match(pr, isChangeOwner)) {
              overrideFound = true;
              break;
            }
          }
        }
        if (overrideFound) {
          // Found an exclusive override, nothing further to do in this project.
          continue projectLoop;
        }

        boolean blocked = false;
        for (PermissionRule pr : p.getRules()) {
          if (!withForce && pr.getForce()) {
            // force on block rule only applies to withForce permission.
            continue;
          }

          if (isBlock(pr, withForce) && projectControl.match(pr, isChangeOwner)) {
            blocked = true;
            break;
          }
        }

        if (blocked) {
          // ALLOW in the same AccessSection (ie. in the same Permission) overrides the BLOCK.
          for (PermissionRule pr : p.getRules()) {
            if (isAllow(pr, withForce) && projectControl.match(pr, isChangeOwner)) {
              blocked = false;
              break;
            }
          }
        }

        if (blocked) {
          return true;
        }
      }
    }

    return false;
  }

  /** True if the user has this permission. */
  private boolean canPerform(String permissionName, boolean isChangeOwner, boolean withForce) {
    if (isBlocked(permissionName, isChangeOwner, withForce)) {
      if (logger.atFine().isEnabled() || LoggingContext.getInstance().isAclLogging()) {
        String logMessage =
            String.format(
                "'%s' cannot perform '%s' with force=%s on project '%s' for ref '%s'"
                    + " because this permission is blocked",
                getUser().getLoggableName(),
                permissionName,
                withForce,
                projectControl.getProject().getName(),
                refName);
        LoggingContext.getInstance().addAclLogRecord(logMessage);
        logger.atFine().log("%s (caller: %s)", logMessage, callerFinder.findCallerLazy());
      }
      return false;
    }

    for (PermissionRule pr : relevant.getAllowRules(permissionName)) {
      if (isAllow(pr, withForce) && projectControl.match(pr, isChangeOwner)) {
        if (logger.atFine().isEnabled() || LoggingContext.getInstance().isAclLogging()) {
          String logMessage =
              String.format(
                  "'%s' can perform '%s' with force=%s on project '%s' for ref '%s'"
                      + " (allowed for group '%s' by rule '%s')",
                  getUser().getLoggableName(),
                  permissionName,
                  withForce,
                  projectControl.getProject().getName(),
                  refName,
                  pr.getGroup().getUUID().get(),
                  pr);
          LoggingContext.getInstance().addAclLogRecord(logMessage);
          logger.atFine().log("%s (caller: %s)", logMessage, callerFinder.findCallerLazy());
        }
        return true;
      }
    }

    if (logger.atFine().isEnabled() || LoggingContext.getInstance().isAclLogging()) {
      String logMessage =
          String.format(
              "'%s' cannot perform '%s' with force=%s on project '%s' for ref '%s'",
              getUser().getLoggableName(),
              permissionName,
              withForce,
              projectControl.getProject().getName(),
              refName);
      LoggingContext.getInstance().addAclLogRecord(logMessage);
      logger.atFine().log("%s (caller: %s)", logMessage, callerFinder.findCallerLazy());
    }
    return false;
  }

  private class ForRefImpl extends ForRef {
    private String resourcePath;

    @Override
    public String resourcePath() {
      if (resourcePath == null) {
        resourcePath =
            String.format(
                "/projects/%s/+refs/%s", getProjectControl().getProjectState().getName(), refName);
      }
      return resourcePath;
    }

    @Override
    public ForChange change(ChangeData cd) {
      try {
        return getProjectControl().controlFor(cd).asForChange();
      } catch (StorageException e) {
        return FailedPermissionBackend.change("unavailable", e);
      }
    }

    @Override
    public ForChange change(ChangeNotes notes) {
      Project.NameKey project = getProjectControl().getProject().getNameKey();
      Change change = notes.getChange();
      checkArgument(
          project.equals(change.getProject()),
          "expected change in project %s, not %s",
          project,
          change.getProject());
      // Having ChangeNotes means it's OK to load values from NoteDb if needed.
      // ChangeData.Factory will allow lazyLoading
      return getProjectControl().controlFor(changeDataFactory.create(notes)).asForChange();
    }

    @Override
    public void check(RefPermission perm) throws AuthException, PermissionBackendException {
      if (!can(perm)) {
        PermissionDeniedException pde = new PermissionDeniedException(perm, refName);
        switch (perm) {
          case UPDATE:
            if (refName.equals(RefNames.REFS_CONFIG)) {
              pde.setAdvice(
                  "Configuration changes can only be pushed by project owners\n"
                      + "who also have 'Push' rights on "
                      + RefNames.REFS_CONFIG);
            } else {
              pde.setAdvice(
                  "Push to refs/for/"
                      + RefNames.shortName(refName)
                      + " to create a review, or get 'Push' rights to update the branch.");
            }
            break;
          case DELETE:
            pde.setAdvice(
                "You need 'Delete Reference' rights or 'Push' rights with the \n"
                    + "'Force Push' flag set to delete references.");
            break;
          case CREATE_CHANGE:
            // This is misleading in the default permission backend, since "create change" on a
            // branch is encoded as "push" on refs/for/DESTINATION.
            pde.setAdvice(
                "You need 'Create Change' rights to upload code review requests.\n"
                    + "Verify that you are pushing to the right branch.");
            break;
          case CREATE:
            pde.setAdvice("You need 'Create' rights to create new references.");
            break;
          case CREATE_SIGNED_TAG:
            pde.setAdvice("You need 'Create Signed Tag' rights to push a signed tag.");
            break;
          case CREATE_TAG:
            pde.setAdvice("You need 'Create Tag' rights to push a normal tag.");
            break;
          case FORCE_UPDATE:
            pde.setAdvice(
                "You need 'Push' rights with 'Force' flag set to do a non-fastforward push.");
            break;
          case FORGE_AUTHOR:
            pde.setAdvice(
                "You need 'Forge Author' rights to push commits with another user as author.");
            break;
          case FORGE_COMMITTER:
            pde.setAdvice(
                "You need 'Forge Committer' rights to push commits with another user as"
                    + " committer.");
            break;
          case FORGE_SERVER:
            pde.setAdvice(
                "You need 'Forge Server' rights to push merge commits authored by the server.");
            break;
          case MERGE:
            pde.setAdvice(
                "You need 'Push Merge' in addition to 'Push' rights to push merge commits.");
            break;

          case READ:
            pde.setAdvice("You need 'Read' rights to fetch or clone this ref.");
            break;

          case READ_CONFIG:
            pde.setAdvice("You need 'Read' rights on refs/meta/config to see the configuration.");
            break;
          case READ_PRIVATE_CHANGES:
            pde.setAdvice("You need 'Read Private Changes' to see private changes.");
            break;
          case SET_HEAD:
            pde.setAdvice("You need 'Set HEAD' rights to set the default branch.");
            break;
          case SKIP_VALIDATION:
            pde.setAdvice(
                "You need 'Forge Author', 'Forge Server', 'Forge Committer'\n"
                    + "and 'Push Merge' rights to skip validation.");
            break;
          case UPDATE_BY_SUBMIT:
            pde.setAdvice(
                "You need 'Submit' rights on refs/for/ to submit changes during change upload.");
            break;

          case WRITE_CONFIG:
            pde.setAdvice("You need 'Write' rights on refs/meta/config.");
            break;
        }
        throw pde;
      }
    }

    @Override
    public Set<RefPermission> test(Collection<RefPermission> permSet)
        throws PermissionBackendException {
      EnumSet<RefPermission> ok = EnumSet.noneOf(RefPermission.class);
      for (RefPermission perm : permSet) {
        if (can(perm)) {
          ok.add(perm);
        }
      }
      return ok;
    }

    @Override
    public BooleanCondition testCond(RefPermission perm) {
      return new PermissionBackendCondition.ForRef(this, perm, getUser());
    }

    private boolean can(RefPermission perm) throws PermissionBackendException {
      switch (perm) {
        case READ:
          /* Internal users such as plugin users should be able to read all refs. */
          if (getUser().isInternalUser()) {
            return true;
          }
          if (refName.startsWith(Constants.R_TAGS)) {
            return isTagVisible();
          }
          return refVisibilityControl.isVisible(projectControl, refName);
        case CREATE:
          // TODO This isn't an accurate test.
          return canPerform(refPermissionName(perm));
        case DELETE:
          return canDelete();
        case UPDATE:
          return canUpdate();
        case FORCE_UPDATE:
          return canForceUpdate();
        case SET_HEAD:
          return projectControl.isOwner();

        case FORGE_AUTHOR:
          return canForgeAuthor();
        case FORGE_COMMITTER:
          return canForgeCommitter();
        case FORGE_SERVER:
          return canForgeGerritServerIdentity();
        case MERGE:
          return canUploadMerges();

        case CREATE_CHANGE:
          return canUpload();

        case CREATE_TAG:
        case CREATE_SIGNED_TAG:
          return canPerform(refPermissionName(perm));

        case UPDATE_BY_SUBMIT:
          return projectControl.controlForRef(MagicBranch.NEW_CHANGE + refName).canSubmit(true);

        case READ_PRIVATE_CHANGES:
          return canPerform(Permission.VIEW_PRIVATE_CHANGES);

        case READ_CONFIG:
          return projectControl
              .controlForRef(RefNames.REFS_CONFIG)
              .canPerform(RefPermission.READ.name());
        case WRITE_CONFIG:
          return isOwner();

        case SKIP_VALIDATION:
          return canForgeAuthor()
              && canForgeCommitter()
              && canForgeGerritServerIdentity()
              && canUploadMerges();
      }
      throw new PermissionBackendException(perm + " unsupported");
    }

    private boolean isTagVisible() throws PermissionBackendException {
      if (projectControl.asForProject().test(ProjectPermission.READ)) {
        // The user has READ on refs/* with no effective block permission. This is the broadest
        // permission one can assign. There is no way to grant access to (specific) tags in Gerrit,
        // so we have to assume that these users can see all tags because there could be tags that
        // aren't reachable by any visible ref while the user can see all non-Gerrit refs. This
        // matches Gerrit's historic behavior.
        // This makes it so that these users could see commits that they can't see otherwise
        // (e.g. a private change ref) if a tag was attached to it. Tags are meant to be used on
        // the regular Git tree that users interact with, not on any of the Gerrit trees, so this
        // is a negligible risk.
        return true;
      }

      try (Repository repo =
          repositoryManager.openRepository(projectControl.getProject().getNameKey())) {
        // Tag visibility requires going through RefFilter because it entails loading all taggable
        // refs and filtering them all by visibility.
        Ref resolvedRef = repo.getRefDatabase().exactRef(refName);
        if (resolvedRef == null) {
          return false;
        }
        return projectControl.asForProject()
            .filter(
                ImmutableList.of(resolvedRef), repo, PermissionBackend.RefFilterOptions.defaults())
            .stream()
            .anyMatch(r -> refName.equals(r.getName()));
      } catch (IOException e) {
        throw new PermissionBackendException(e);
      }
    }
  }

  private static String refPermissionName(RefPermission refPermission) {
    // Within this class, it's programmer error to call this method on a
    // RefPermission that isn't associated with a permission name.
    return DefaultPermissionMappings.refPermissionName(refPermission)
        .orElseThrow(() -> new IllegalStateException("no name for " + refPermission));
  }
}
