/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.sentry.provider.file;

import static org.apache.sentry.provider.file.PolicyFileConstants.DATABASES;
import static org.apache.sentry.provider.file.PolicyFileConstants.GROUPS;
import static org.apache.sentry.provider.file.PolicyFileConstants.ROLES;
import static org.apache.sentry.provider.file.PolicyFileConstants.ROLE_SPLITTER;
import static org.apache.sentry.provider.file.PolicyFileConstants.USERS;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URI;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;

import javax.annotation.Nullable;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.sentry.core.AccessURI;
import org.apache.sentry.core.Authorizable;
import org.apache.sentry.core.Database;
import org.apache.shiro.config.ConfigurationException;
import org.apache.shiro.config.Ini;
import org.apache.shiro.util.PermissionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;

public class SimplePolicyEngine implements PolicyEngine {

  private static final Logger LOGGER = LoggerFactory
      .getLogger(SimplePolicyEngine.class);



  private final FileSystem fileSystem;
  private final Path resourcePath;
  private final String serverName;
  private final List<Path> perDbResources = Lists.newArrayList();
  private final AtomicReference<Roles> rolesReference;
  public final static String ACCESS_ALLOW_URI_PER_DB_POLICYFILE = "sentry.allow.uri.db.policyfile";

  public SimplePolicyEngine(String resourcePath, String serverName) throws IOException {
    this(new Configuration(), new Path(resourcePath), serverName);
  }
  @VisibleForTesting
  public SimplePolicyEngine(Configuration conf, Path resourcePath, String serverName) throws IOException {
    this.resourcePath = resourcePath;
    this.serverName = serverName;
    this.fileSystem = resourcePath.getFileSystem(conf);
    this.rolesReference = new AtomicReference<Roles>();
    this.rolesReference.set(new Roles());
    parse();
  }

  /**
   * Parse the resource. Should not be used in the normal course
   */
  protected void parse() {
    LOGGER.info("Parsing " + resourcePath);
    Roles roles = new Roles();
    try {
      perDbResources.clear();
      Ini ini = PolicyFiles.loadFromPath(fileSystem, resourcePath);
      if(LOGGER.isDebugEnabled()) {
        for(String sectionName : ini.getSectionNames()) {
          LOGGER.debug("Section: " + sectionName);
          Ini.Section section = ini.get(sectionName);
          for(String key : section.keySet()) {
            String value = section.get(key);
            LOGGER.debug(key + " = " + value);
          }
        }
      }
      ImmutableSetMultimap<String, String> globalRoles;
      Map<String, ImmutableSetMultimap<String, String>> perDatabaseRoles = Maps.newHashMap();
      globalRoles = parseIni(null, ini);
      Ini.Section filesSection = ini.getSection(DATABASES);
      if(filesSection == null) {
        LOGGER.info("Section " + DATABASES + " needs no further processing");
      } else {
        for(Map.Entry<String, String> entry : filesSection.entrySet()) {
          String database = Strings.nullToEmpty(entry.getKey()).trim().toLowerCase();
          Path perDbPolicy = new Path(Strings.nullToEmpty(entry.getValue()).trim());
          if(isRelative(perDbPolicy)) {
            perDbPolicy = new Path(resourcePath.getParent(), perDbPolicy);
          }
          try {
            LOGGER.info("Parsing " + perDbPolicy);
            Ini perDbIni = PolicyFiles.loadFromPath(fileSystem, perDbPolicy);
            if(perDbIni.containsKey(USERS)) {
              throw new ConfigurationException("Per-db policy files cannot contain " + USERS + " section");
            }
            if(perDbIni.containsKey(DATABASES)) {
              throw new ConfigurationException("Per-db policy files cannot contain " + DATABASES + " section");
            }
            ImmutableSetMultimap<String, String> currentDbRoles = parseIni(database, perDbIni);
            perDatabaseRoles.put(database, currentDbRoles);
            perDbResources.add(perDbPolicy);
          } catch (Exception e) {
            LOGGER.error("Error processing key " + entry.getKey() + ", skipping " + entry.getValue(), e);
          }
        }
      }
      roles = new Roles(globalRoles, ImmutableMap.copyOf(perDatabaseRoles));
    } catch (Exception e) {
      LOGGER.error("Error processing file, ignoring " + resourcePath, e);
    }
    rolesReference.set(roles);
  }

  /**
   * Relative for our purposes is no scheme, no authority
   * and a non-absolute path portion.
   */
  private boolean isRelative(Path path) {
    URI uri = path.toUri();
    return uri.getAuthority() == null && uri.getScheme() == null && !path.isUriPathAbsolute();
  }

  protected long getModificationTime() throws IOException {
    // if resource path has been deleted, throw all exceptions
    long result = fileSystem.getFileStatus(resourcePath).getModificationTime();
    for(Path perDbPolicy : perDbResources) {
      try {
        result = Math.max(result, fileSystem.getFileStatus(perDbPolicy).getModificationTime());
      } catch (FileNotFoundException e) {
        // if a per-db file has been deleted, wait until the main
        // policy file has been updated before refreshing
      }
    }
    return result;
  }

  private ImmutableSetMultimap<String, String> parseIni(String database, Ini ini) {
    Ini.Section privilegesSection = ini.getSection(ROLES);
    boolean invalidConfiguration = false;
    if (privilegesSection == null) {
      LOGGER.warn("Section {} empty for {}", ROLES, resourcePath);
      invalidConfiguration = true;
    }
    Ini.Section groupsSection = ini.getSection(GROUPS);
    if (groupsSection == null) {
      LOGGER.warn("Section {} empty for {}", GROUPS, resourcePath);
      invalidConfiguration = true;
    }
    if (!invalidConfiguration) {
      return parsePermissions(database, privilegesSection, groupsSection);
    }
    return ImmutableSetMultimap.of();
  }

  private ImmutableSetMultimap<String, String> parsePermissions(@Nullable String database,
      Ini.Section rolesSection, Ini.Section groupsSection) {
    ImmutableSetMultimap.Builder<String, String> resultBuilder = ImmutableSetMultimap.builder();
    Multimap<String, String> roleNameToPrivilegeMap = HashMultimap
        .create();
    List<? extends RoleValidator> validators = Lists.newArrayList(
        new ServersAllIsInvalid(),
        new DatabaseMustMatch(),
        new DatabaseRequiredInRole(),
        new ServerNameMustMatch(serverName));
    for (Map.Entry<String, String> entry : rolesSection.entrySet()) {
      String roleName = Strings.nullToEmpty(entry.getKey()).trim();
      String roleValue = Strings.nullToEmpty(entry.getValue()).trim();
      boolean invalidConfiguration = false;
      if (roleName.isEmpty()) {
        LOGGER.warn("Empty role name encountered in {}", resourcePath);
        invalidConfiguration = true;
      }
      if (roleValue.isEmpty()) {
        LOGGER.warn("Empty role value encountered in {}", resourcePath);
        invalidConfiguration = true;
      }
      if (roleNameToPrivilegeMap.containsKey(roleName)) {
        LOGGER.warn("Role {} defined twice in {}", roleName,
            resourcePath);
      }
      Set<String> roles = PermissionUtils
          .toPermissionStrings(roleValue);
      if (!invalidConfiguration && roles != null) {
        for(String role : roles) {
          for(RoleValidator validator : validators) {
            validator.validate(database, role.trim());
          }
        }
        roleNameToPrivilegeMap.putAll(roleName, roles);
      }
    }
    Splitter roleSplitter = ROLE_SPLITTER.omitEmptyStrings().trimResults();
    for (Map.Entry<String, String> entry : groupsSection.entrySet()) {
      String groupName = Strings.nullToEmpty(entry.getKey()).trim();
      String groupPrivileges = Strings.nullToEmpty(entry.getValue()).trim();
      Collection<String> resolvedGroupPrivileges = Sets.newHashSet();
      for (String roleName : roleSplitter.split(groupPrivileges)) {
        if (roleNameToPrivilegeMap.containsKey(roleName)) {
          resolvedGroupPrivileges.addAll(roleNameToPrivilegeMap
              .get(roleName));
        } else {
          LOGGER.warn("Role {} for group {} does not exist in privileges section in {}",
              new Object[] { roleName, groupName, resourcePath });
        }
      }
      resultBuilder.putAll(groupName, resolvedGroupPrivileges);
    }
    return resultBuilder.build();
  }



  /**
   * {@inheritDoc}
   */
  @Override
  public ImmutableSetMultimap<String, String> getPermissions(List<Authorizable> authorizables, List<String> groups) {
    Roles roles = rolesReference.get();
    String database = null;
    Boolean isURI = false;
    for(Authorizable authorizable : authorizables) {
      if(authorizable instanceof Database) {
        database = authorizable.getName();
      }
      if (authorizable instanceof AccessURI) {
        isURI = true;
      }
    }

    if(LOGGER.isDebugEnabled()) {
      LOGGER.debug("Getting permissions for {} via {}", groups, database);
    }
    ImmutableSetMultimap.Builder<String, String> resultBuilder = ImmutableSetMultimap.builder();
    for(String group : groups) {
      resultBuilder.putAll(group, roles.getRoles(database, group, isURI));
    }
    ImmutableSetMultimap<String, String> result = resultBuilder.build();
    if(LOGGER.isDebugEnabled()) {
      LOGGER.debug("result = " + result);
    }
    return result;
  }
}
