// 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.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 com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
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).
 *
 * <p>Do not use this class directly - instead use {@link ProjectControl} class. This class is
 * public only because it is extended in google-owned implementation.
 */
public class RefControl {
  public interface Factory {
    RefControl create(ProjectControl projectControl, String ref, PermissionCollection relevant);
  }

  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;

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

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

  @Inject
  protected RefControl(
      ChangeData.Factory changeDataFactory,
      RefVisibilityControl refVisibilityControl,
      GitRepositoryManager repositoryManager,
      @Assisted ProjectControl projectControl,
      @Assisted String ref,
      @Assisted PermissionCollection relevant) {
    this.changeDataFactory = changeDataFactory;
    this.refVisibilityControl = refVisibilityControl;
    this.repositoryManager = repositoryManager;
    this.projectControl = projectControl;
    this.refName = ref;
    this.relevant = relevant;
  }

  protected ProjectControl getProjectControl() {
    return projectControl;
  }

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

  protected String getRefName() {
    return refName;
  }

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

  protected 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.
          logger.atFine().log(
              "Exclusive override found for permission %s and user %s",
              permissionName, getUser().getLoggableName());
          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)) {
            logger.atFine().log(
                "Block rule found for permission %s and user %s",
                permissionName, getUser().getLoggableName());
            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)) {
              logger.atFine().log(
                  "Allow rule found in the same access section which overrides the BLOCK for"
                      + " permission %s and user %s",
                  permissionName, getUser().getLoggableName());
              blocked = false;
              break;
            }
          }
        }

        if (blocked) {
          logger.atFine().log(
              "Permission %s is blocked for user %s", permissionName, getUser().getLoggableName());
          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);
      }
      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", logMessage);
        }
        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", logMessage);
    }
    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 ForChange changeToBeCreated(boolean isOwner) {
      return getProjectControl()
          .controlForChangeToBeCreated(RefControl.this, isOwner)
          .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.");
            }
          }
          case DELETE ->
              pde.setAdvice(
                  "You need 'Delete Reference' rights or 'Push' rights with the \n"
                      + "'Force Push' flag set to delete references.");
          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.");
          case CREATE -> pde.setAdvice("You need 'Create' rights to create new references.");
          case CREATE_SIGNED_TAG ->
              pde.setAdvice("You need 'Create Signed Tag' rights to push a signed tag.");
          case CREATE_TAG -> pde.setAdvice("You need 'Create Tag' rights to push a normal tag.");
          case FORCE_UPDATE ->
              pde.setAdvice(
                  "You need 'Push' rights with 'Force' flag set to do a non-fastforward push.");
          case FORGE_AUTHOR ->
              pde.setAdvice(
                  "You need 'Forge Author' rights to push commits with another user as author.");
          case FORGE_COMMITTER ->
              pde.setAdvice(
                  "You need 'Forge Committer' rights to push commits with another user as"
                      + " committer.");
          case FORGE_SERVER ->
              pde.setAdvice(
                  "You need 'Forge Server' rights to push merge commits authored by the server.");
          case MERGE ->
              pde.setAdvice(
                  "You need 'Push Merge' in addition to 'Push' rights to push merge commits.");
          case READ -> pde.setAdvice("You need 'Read' rights to fetch or clone this ref.");
          case READ_CONFIG ->
              pde.setAdvice("You need 'Read' rights on refs/meta/config to see the configuration.");
          case READ_PRIVATE_CHANGES ->
              pde.setAdvice("You need 'Read Private Changes' to see private changes.");
          case SET_HEAD -> pde.setAdvice("You need 'Set HEAD' rights to set the default branch.");
          case SKIP_VALIDATION ->
              pde.setAdvice(
                  "You need 'Forge Author', 'Forge Server', 'Forge Committer'\n"
                      + "and 'Push Merge' rights to skip validation.");
          case UPDATE_BY_SUBMIT ->
              pde.setAdvice(
                  "You need 'Submit' rights on refs/for/ to submit changes during change upload.");
          case WRITE_CONFIG -> pde.setAdvice("You need 'Write' rights on refs/meta/config.");
        }
        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());
    }
  }

  protected 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;
        }

        /* Admins should be able to read all branches and tags refs (including 'refs/meta/config'). */
        if (projectControl.isAdmin()
            && (refName.equals(RefNames.REFS_CONFIG)
                || refName.startsWith(Constants.R_HEADS)
                || refName.startsWith(Constants.R_TAGS))) {
          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, CREATE_SIGNED_TAG -> {
        return canPerform(refPermissionName(perm));
      }
      case UPDATE_BY_SUBMIT -> {
        return projectControl.controlForRef(MagicBranch.NEW_CHANGE + refName).canSubmit(true);
      }
      case READ_PRIVATE_CHANGES -> {
        // Admins should be able to see all changes.
        return projectControl.isAdmin() || 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));
  }
}
