// Copyright (C) 2011 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.gerrit.entities.PermissionRule.Action.BLOCK;
import static com.google.gerrit.server.project.RefPattern.containsParameters;
import static com.google.gerrit.server.project.RefPattern.isRE;
import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.toList;

import com.google.auto.value.AutoValue;
import com.google.common.collect.Lists;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.AccessSection;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.Permission;
import com.google.gerrit.entities.PermissionRule;
import com.google.gerrit.entities.PermissionRule.Action;
import com.google.gerrit.entities.Project;
import com.google.gerrit.metrics.Description;
import com.google.gerrit.metrics.Description.Units;
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.metrics.Timer0;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.project.RefPattern;
import com.google.gerrit.server.project.RefPatternMatcher.ExpandParameters;
import com.google.gerrit.server.project.SectionMatcher;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Effective permissions applied to a reference in a project.
 *
 * <p>A collection may be user specific if a matching {@link AccessSection} uses "${username}" in
 * its name. The permissions granted in that section may only be granted to the username that
 * appears in the reference name, and also only if the user is a member of the relevant group.
 */
public class PermissionCollection {
  @Singleton
  public static class Factory {
    private final SectionSortCache sorter;
    // TODO(hiesel): Remove this once we got production data
    private final Timer0 filterLatency;

    @Inject
    Factory(SectionSortCache sorter, MetricMaker metricMaker) {
      this.sorter = sorter;
      this.filterLatency =
          metricMaker.newTimer(
              "permissions/permission_collection/filter_latency",
              new Description("Latency for access filter computations in PermissionCollection")
                  .setCumulative()
                  .setUnit(Units.NANOSECONDS));
    }

    /**
     * Drop the SectionMatchers that don't apply to the current ref. The user is only used for
     * expanding per-user ref patterns, and not for checking group memberships.
     *
     * @param matcherList the input sections.
     * @param ref the ref name for which to filter.
     * @param user Only used for expanding per-user ref patterns.
     * @param out the filtered sections.
     * @return true if the result is only valid for this user.
     */
    private static boolean filterRefMatchingSections(
        Iterable<SectionMatcher> matcherList,
        String ref,
        CurrentUser user,
        Map<AccessSection, Project.NameKey> out) {
      boolean perUser = false;
      for (SectionMatcher sm : matcherList) {
        // If the matcher has to expand parameters and its prefix matches the
        // reference there is a very good chance the reference is actually user
        // specific, even if the matcher does not match the reference. Since its
        // difficult to prove this is true all of the time, use an approximation
        // to prevent reuse of collections across users accessing the same
        // reference at the same time.
        //
        // This check usually gets caching right, as most per-user references
        // use a common prefix like "refs/sandbox/" or "refs/heads/users/"
        // that will never be shared with non-user references, and the per-user
        // references are usually less frequent than the non-user references.
        if (sm.getMatcher() instanceof ExpandParameters) {
          if (!((ExpandParameters) sm.getMatcher()).matchPrefix(ref)) {
            continue;
          }
          perUser = true;
          if (sm.match(ref, user)) {
            out.put(sm.getSection(), sm.getProject());
          }
        } else if (sm.match(ref, null)) {
          out.put(sm.getSection(), sm.getProject());
        }
      }
      return perUser;
    }

    /**
     * Get all permissions that apply to a reference. The user is only used for per-user ref names,
     * so the return value may include permissions for groups the user is not part of.
     *
     * @param matcherList collection of sections that should be considered, in priority order
     *     (project specific definitions must appear before inherited ones).
     * @param ref reference being accessed.
     * @param user if the reference is a per-user reference, e.g. access sections using the
     *     parameter variable "${username}" will have each username inserted into them to see if
     *     they apply to the reference named by {@code ref}.
     * @return map of permissions that apply to this reference, keyed by permission name.
     */
    PermissionCollection filter(
        Iterable<SectionMatcher> matcherList, String ref, CurrentUser user) {
      try (Timer0.Context ignored = filterLatency.start()) {
        if (isRE(ref)) {
          if (!containsParameters(ref)) {
            ref = RefPattern.shortestExample(ref);
          }
        } else if (ref.endsWith("/*")) {
          ref = ref.substring(0, ref.length() - 1);
        }

        // LinkedHashMap to maintain input ordering.
        Map<AccessSection, Project.NameKey> sectionToProject = new LinkedHashMap<>();
        boolean perUser = filterRefMatchingSections(matcherList, ref, user, sectionToProject);
        List<AccessSection> sections = Lists.newArrayList(sectionToProject.keySet());

        // Sort by ref pattern specificity. For equally specific patterns, the sections from the
        // project closer to the current one come first.
        sorter.sort(ref, sections);

        // For block permissions, we want a different order: first, we want to go from parent to
        // child.
        List<Map.Entry<AccessSection, Project.NameKey>> accessDescending =
            Lists.reverse(Lists.newArrayList(sectionToProject.entrySet()));

        Map<Project.NameKey, List<AccessSection>> accessByProject =
            accessDescending.stream()
                .collect(
                    Collectors.groupingBy(
                        Map.Entry::getValue,
                        LinkedHashMap::new,
                        mapping(Map.Entry::getKey, toList())));
        // Within each project, sort by ref specificity.
        for (List<AccessSection> secs : accessByProject.values()) {
          sorter.sort(ref, secs);
        }

        return new PermissionCollection(
            Lists.newArrayList(accessByProject.values()), sections, perUser);
      }
    }
  }

  /** Returns permissions in the right order for evaluating BLOCK status. */
  List<List<Permission>> getBlockRules(String perm) {
    List<List<Permission>> ps = blockPerProjectByPermission.get(perm);
    if (ps == null) {
      ps = calculateBlockRules(perm);
      blockPerProjectByPermission.put(perm, ps);
    }
    return ps;
  }

  /** Returns permissions in the right order for evaluating ALLOW/DENY status. */
  List<PermissionRule> getAllowRules(String perm) {
    List<PermissionRule> ps = rulesByPermission.get(perm);
    if (ps == null) {
      ps = calculateAllowRules(perm);
      rulesByPermission.put(perm, ps);
    }
    return ps;
  }

  /** calculates permissions for ALLOW processing. */
  private List<PermissionRule> calculateAllowRules(String permName) {
    Set<SeenRule> seen = new HashSet<>();

    List<PermissionRule> r = new ArrayList<>();
    for (AccessSection s : accessSectionsUpward) {
      Permission p = s.getPermission(permName);
      if (p == null) {
        continue;
      }
      for (PermissionRule pr : p.getRules()) {
        SeenRule sr = SeenRule.create(s, pr);
        if (seen.contains(sr)) {
          // We allow only one rule per (ref-pattern, group) tuple. This is used to implement DENY:
          // If we see a DENY before an ALLOW rule, that causes the ALLOW rule to be skipped here,
          // negating access.
          continue;
        }
        seen.add(sr);

        if (pr.getAction() == BLOCK) {
          // Block rules are handled elsewhere.
          continue;
        }

        if (pr.getAction() == PermissionRule.Action.DENY) {
          // DENY rules work by not adding ALLOW rules. Nothing else to do.
          continue;
        }
        r.add(pr);
      }
      if (p.getExclusiveGroup()) {
        // We found an exclusive permission, so no need to further go up the hierarchy.
        break;
      }
    }
    return r;
  }

  // Calculates the inputs for determining BLOCK status, grouped by project.
  private List<List<Permission>> calculateBlockRules(String permName) {
    List<List<Permission>> result = new ArrayList<>();
    for (List<AccessSection> secs : this.accessSectionsPerProjectDownward) {
      List<Permission> perms = new ArrayList<>();
      boolean blockFound = false;
      for (AccessSection sec : secs) {
        Permission p = sec.getPermission(permName);
        if (p == null) {
          continue;
        }
        for (PermissionRule pr : p.getRules()) {
          if (blockFound || pr.getAction() == Action.BLOCK) {
            blockFound = true;
            break;
          }
        }

        perms.add(p);
      }

      if (blockFound) {
        result.add(perms);
      }
    }
    return result;
  }

  private List<List<AccessSection>> accessSectionsPerProjectDownward;
  private List<AccessSection> accessSectionsUpward;

  private final Map<String, List<PermissionRule>> rulesByPermission;
  private final Map<String, List<List<Permission>>> blockPerProjectByPermission;
  private final boolean perUser;

  private PermissionCollection(
      List<List<AccessSection>> accessSectionsDownward,
      List<AccessSection> accessSectionsUpward,
      boolean perUser) {
    this.accessSectionsPerProjectDownward = accessSectionsDownward;
    this.accessSectionsUpward = accessSectionsUpward;
    this.rulesByPermission = new HashMap<>();
    this.blockPerProjectByPermission = new HashMap<>();
    this.perUser = perUser;
  }

  /**
   * Returns true if a "${username}" pattern might need to be expanded to build this collection,
   * making the results user specific.
   */
  public boolean isUserSpecific() {
    return perUser;
  }

  /** (ref, permission, group) tuple. */
  @AutoValue
  abstract static class SeenRule {
    public abstract String refPattern();

    @Nullable
    public abstract AccountGroup.UUID group();

    static SeenRule create(AccessSection section, @Nullable PermissionRule rule) {
      AccountGroup.UUID group =
          rule != null && rule.getGroup() != null ? rule.getGroup().getUUID() : null;
      return new AutoValue_PermissionCollection_SeenRule(section.getName(), group);
    }
  }
}
