/**
 * 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
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * 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 permission and
 * limitations under the License.
 */
package org.apache.sentry.hdfs;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import org.apache.hadoop.conf.Configurable;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.permission.*;
import org.apache.hadoop.hdfs.DFSConfigKeys;
import org.apache.hadoop.hdfs.DFSUtil;

import org.apache.hadoop.hdfs.server.namenode.AclEntryStatusFormat;
import org.apache.hadoop.hdfs.server.namenode.AclFeature;
import org.apache.hadoop.hdfs.server.namenode.INodeAttributeProvider;
import org.apache.hadoop.hdfs.server.namenode.INodeAttributes;
import org.apache.hadoop.hdfs.server.namenode.INode;
import org.apache.hadoop.hdfs.server.namenode.INodeDirectory;
import org.apache.hadoop.hdfs.server.namenode.XAttrFeature;
import org.apache.hadoop.security.AccessControlException;
import org.apache.hadoop.security.UserGroupInformation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

public class SentryINodeAttributesProvider extends INodeAttributeProvider
        implements Configurable {

  private static Logger LOG =
          LoggerFactory.getLogger(SentryINodeAttributesProvider.class);

  static class SentryAclFeature extends AclFeature {
    public SentryAclFeature(ImmutableList<AclEntry> entries) {
      super(AclEntryStatusFormat.toInt(entries));
    }
  }

  class SentryPermissionEnforcer implements AccessControlEnforcer {
    private final AccessControlEnforcer ace;

    SentryPermissionEnforcer(INodeAttributeProvider.AccessControlEnforcer ace) {
      this.ace = ace;
    }

    @Override
    public void checkPermission(String fsOwner, String supergroup,
                                UserGroupInformation callerUgi,
                                INodeAttributes[] inodeAttrs,
                                INode[] inodes, byte[][] pathByNameArr,
                                int snapshotId, String path,
                                int ancestorIndex, boolean doCheckOwner,
                                FsAction ancestorAccess,
                                FsAction parentAccess, FsAction access,
                                FsAction subAccess,
                                boolean ignoreEmptyDir) throws
            AccessControlException {
      String[] pathElems = getPathElems(pathByNameArr);
      if (pathElems != null && (pathElems.length > 1) && ("".equals(pathElems[0]))) {
        pathElems = Arrays.copyOfRange(pathElems, 1, pathElems.length);
      }
      if (LOG.isDebugEnabled()) {
        LOG.debug("Enforcing Permission : + " + Lists
              .newArrayList(fsOwner, supergroup, callerUgi.getShortUserName(),
                      Arrays.toString(callerUgi.getGroupNames()),
                      Arrays.toString(pathElems), ancestorAccess,
                      parentAccess, access, subAccess, ignoreEmptyDir));
      }
      ace.checkPermission(fsOwner, supergroup, callerUgi,
              inodeAttrs, inodes,
              pathByNameArr, snapshotId, path, ancestorIndex,
              doCheckOwner,
              ancestorAccess, parentAccess, access, subAccess,
              ignoreEmptyDir);
    }

    private String[] getPathElems(byte[][] pathByName) {
      String[] retVal = new String[pathByName.length];
      for (int i = 0; i < pathByName.length; i++) {
        retVal[i] = (pathByName[i] != null) ? DFSUtil.bytes2String
                (pathByName[i]) : "";
      }
      return retVal;
    }
  }

  public class SentryINodeAttributes implements INodeAttributes {

    private final INodeAttributes defaultAttributes;
    private final String[] pathElements;

    public SentryINodeAttributes(INodeAttributes defaultAttributes, String[]
            pathElements) {
      this.defaultAttributes = defaultAttributes;
      this.pathElements = pathElements;
    }

    @Override
    public boolean isDirectory() {
      return defaultAttributes.isDirectory();
    }

    @Override
    public byte[] getLocalNameBytes() {
      return defaultAttributes.getLocalNameBytes();
    }

    @Override
    public String getUserName() {
      return isSentryManaged(pathElements)?
          SentryINodeAttributesProvider.this.user : defaultAttributes.getUserName();
    }

    @Override
    public String getGroupName() {
      return isSentryManaged(pathElements)?
          SentryINodeAttributesProvider.this.group : defaultAttributes.getGroupName();
    }

    @Override
    public FsPermission getFsPermission() {
      FsPermission permission;

      if (!isSentryManaged(pathElements)) {
        permission = defaultAttributes.getFsPermission();
      } else {
        FsPermission returnPerm = SentryINodeAttributesProvider.this.permission;
        // Handle case when prefix directory is itself associated with an
        // authorizable object (default db directory in hive)
        // An executable permission needs to be set on the the prefix directory
        // in this case.. else, subdirectories (which map to other dbs) will
        // not be travesible.
        for (String [] prefixPath : authzInfo.getPathPrefixes()) {
          if (Arrays.equals(prefixPath, pathElements)) {
            returnPerm = FsPermission.createImmutable((short)(returnPerm.toShort() | 0x01));
            break;
          }
        }
        permission = returnPerm;
      }
      return permission;
    }

    @Override
    public short getFsPermissionShort() {
      return getFsPermission().toShort();
    }

    @Override
    public long getPermissionLong() {
      PermissionStatus permissionStatus = new PermissionStatus(getUserName(),
              getGroupName(), getFsPermission());
      // No other way to get the long permission currently
      return new INodeDirectory(0L, null, permissionStatus, 0L)
              .getPermissionLong();
    }

    /**
     * Returns hadoop acls if
     *  - Not managed
     *  - Not stale and not an auth obj
     * Returns hive:hive
     *  - If stale
     * Returns sentry acls
     *  - Otherwise, if not stale and auth obj
     **/
    @Override
    public AclFeature getAclFeature() {
      AclFeature aclFeature;
      String p = Arrays.toString(pathElements);
      boolean isPrefixed = false;
      boolean isStale = false;
      boolean hasAuthzObj = false;
      Map<String, AclEntry> aclMap = null;

      // If path is not under prefix, return hadoop acls.
      if (!authzInfo.isUnderPrefix(pathElements)) {
        isPrefixed = false;
        aclFeature = defaultAttributes.getAclFeature();
      } else if (!authzInfo.doesBelongToAuthzObject(pathElements)) {
        // If path is not managed, return hadoop acls.
        isPrefixed = true;
        aclFeature = defaultAttributes.getAclFeature();
      } else {
        // If path is managed, add original hadoop permission if originalAuthzAsAcl true.
        isPrefixed = true;
        hasAuthzObj = true;
        aclMap = new HashMap<String, AclEntry>();
        if (originalAuthzAsAcl) {
          String user = defaultAttributes.getUserName();
          String group = defaultAttributes.getGroupName();
          FsPermission perm = defaultAttributes.getFsPermission();
          addToACLMap(aclMap, createAclEntries(user, group, perm));
        } else {
          // else add hive:hive
          addToACLMap(aclMap, createAclEntries(user, group, permission));
        }
        if (!authzInfo.isStale()) {
          // if not stale return sentry acls.
          isStale = false;
          addToACLMap(aclMap, authzInfo.getAclEntries(pathElements));
          aclFeature = new SentryAclFeature(ImmutableList.copyOf(aclMap.values()));
        } else {
          // if stale return hive:hive
          isStale = true;
          aclFeature = new SentryAclFeature(ImmutableList.copyOf(aclMap.values()));
        }
      }
      if (LOG.isDebugEnabled()) {
        LOG.debug("### getAclEntry \n[" + (p == null ? "null" : p) + "] : ["
            + "isPreifxed=" + isPrefixed
            + ", isStale=" + isStale
            + ", hasAuthzObj=" + hasAuthzObj
            + ", origAuthzAsAcl=" + originalAuthzAsAcl + "]\n"
            + "[" + (aclMap == null ? "null" : aclMap) + "]\n");
      }
      return aclFeature;
    }

    @Override
    public XAttrFeature getXAttrFeature() {
      return defaultAttributes.getXAttrFeature();
    }

    @Override
    public long getModificationTime() {
      return defaultAttributes.getModificationTime();
    }

    @Override
    public long getAccessTime() {
      return defaultAttributes.getAccessTime();
    }
  }

  private boolean started;
  private SentryAuthorizationInfo authzInfo;
  private String user;
  private String group;
  private FsPermission permission;
  private boolean originalAuthzAsAcl;
  private Configuration conf;

  public SentryINodeAttributesProvider() {
  }

  private boolean isSentryManaged(final String[] pathElements) {
    return authzInfo.isSentryManaged(pathElements);
  }

  @VisibleForTesting
  SentryINodeAttributesProvider(SentryAuthorizationInfo authzInfo) {
    this.authzInfo = authzInfo;
  }

  @Override
  public void setConf(Configuration conf) {
    this.conf = conf;
  }

  @Override
  public Configuration getConf() {
    return conf;
  }


  @Override
  public void start() {
    if (started) {
      throw new IllegalStateException("Provider already started");
    }
    started = true;
    try {
      if (!conf.getBoolean(DFSConfigKeys.DFS_NAMENODE_ACLS_ENABLED_KEY,
              false)) {
        throw new RuntimeException("HDFS ACLs must be enabled");
      }
      Configuration conf = new Configuration(this.conf);
      conf.addResource(SentryAuthorizationConstants.CONFIG_FILE, true);
      user = conf.get(SentryAuthorizationConstants.HDFS_USER_KEY,
              SentryAuthorizationConstants.HDFS_USER_DEFAULT);
      group = conf.get(SentryAuthorizationConstants.HDFS_GROUP_KEY,
              SentryAuthorizationConstants.HDFS_GROUP_DEFAULT);
      permission = FsPermission.createImmutable(
              (short) conf.getLong(SentryAuthorizationConstants
                              .HDFS_PERMISSION_KEY,
                      SentryAuthorizationConstants.HDFS_PERMISSION_DEFAULT)
      );
      originalAuthzAsAcl = conf.getBoolean(
              SentryAuthorizationConstants.INCLUDE_HDFS_AUTHZ_AS_ACL_KEY,
              SentryAuthorizationConstants.INCLUDE_HDFS_AUTHZ_AS_ACL_DEFAULT);

      LOG.info("Starting");
      LOG.info("Config: hdfs-user[{}] hdfs-group[{}] hdfs-permission[{}] " +
              "include-hdfs-authz-as-acl[{}]", new Object[]
              {user, group, permission, originalAuthzAsAcl});

      if (authzInfo == null) {
        authzInfo = new SentryAuthorizationInfo(conf);
      }
      authzInfo.start();
    } catch (Exception ex) {
      throw new RuntimeException(ex);
    }
  }

  @Override
  public void stop() {
    LOG.debug(getClass().getSimpleName() + ": Stopping");
    authzInfo.stop();
  }

  @Override
  public INodeAttributes getAttributes(String[] pathElements,
                                       INodeAttributes inode) {
    Preconditions.checkNotNull(pathElements);
    
    if (pathElements.length == 0) {
      return inode;
    }

    pathElements = "".equals(pathElements[0]) && pathElements.length > 1 ?
            Arrays.copyOfRange(pathElements, 1, pathElements.length) :
            pathElements;
    return isSentryManaged(pathElements) ? new SentryINodeAttributes
            (inode, pathElements) : inode;
  }

  @Override
  public AccessControlEnforcer getExternalAccessControlEnforcer
          (AccessControlEnforcer defaultEnforcer) {
    return new SentryPermissionEnforcer(defaultEnforcer);
  }

  private static void addToACLMap(Map<String, AclEntry> map,
                                  Collection<AclEntry> entries) {
    for (AclEntry ent : entries) {
      String key = (ent.getName() == null ? "" : ent.getName())
              + ent.getScope() + ent.getType();
      AclEntry aclEntry = map.get(key);
      if (aclEntry == null) {
        map.put(key, ent);
      } else {
        map.put(key,
                new AclEntry.Builder().
                        setName(ent.getName()).
                        setScope(ent.getScope()).
                        setType(ent.getType()).
                        setPermission(ent.getPermission().or(aclEntry
                                .getPermission())).
                        build());
      }
    }
  }

  private static List<AclEntry> createAclEntries(String user, String group,
                                                 FsPermission permission) {
    List<AclEntry> list = new ArrayList<AclEntry>();
    AclEntry.Builder builder = new AclEntry.Builder();
    FsPermission fsPerm = new FsPermission(permission);
    builder.setName(user);
    builder.setType(AclEntryType.USER);
    builder.setScope(AclEntryScope.ACCESS);
    builder.setPermission(fsPerm.getUserAction());
    list.add(builder.build());
    builder.setName(group);
    builder.setType(AclEntryType.GROUP);
    builder.setScope(AclEntryScope.ACCESS);
    builder.setPermission(fsPerm.getGroupAction());
    list.add(builder.build());
    builder.setName(null);
    return list;
  }
}
