/*
 * 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.jackrabbit.oak.security.authorization.accesscontrol;

import java.security.Principal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.security.AccessControlEntry;
import javax.jcr.security.AccessControlException;
import javax.jcr.security.AccessControlManager;
import javax.jcr.security.AccessControlPolicy;
import javax.jcr.security.Privilege;

import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
import org.apache.jackrabbit.api.security.principal.PrincipalManager;
import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager;
import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
import org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants;
import org.apache.jackrabbit.oak.spi.security.principal.PrincipalConfiguration;
import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
import org.apache.jackrabbit.oak.spi.xml.ImportBehavior;
import org.apache.jackrabbit.oak.spi.xml.NodeInfo;
import org.apache.jackrabbit.oak.spi.xml.PropInfo;
import org.apache.jackrabbit.oak.spi.xml.ProtectedNodeImporter;
import org.apache.jackrabbit.oak.spi.xml.ReferenceChangeTracker;
import org.apache.jackrabbit.oak.spi.xml.TextValue;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * {@link ProtectedNodeImporter} implementation that handles access control lists,
 * entries and restrictions.
 */
public class AccessControlImporter implements ProtectedNodeImporter, AccessControlConstants {

    private static final Logger log = LoggerFactory.getLogger(AccessControlImporter.class);

    private static final int CHILD_STATUS_UNDEFINED = 0;
    private static final int CHILD_STATUS_ACE = 1;
    private static final int CHILD_STATUS_RESTRICTION = 2;

    private AccessControlManager acMgr;
    private PrincipalManager principalManager;
    private ReadOnlyNodeTypeManager ntMgr;

    private boolean initialized = false;
    private int childStatus;

    private JackrabbitAccessControlList acl;
    private MutableEntry entry;

    private int importBehavior;

    //----------------------------------------------< ProtectedItemImporter >---

    @Override
    public boolean init(@NotNull Session session, @NotNull Root root, @NotNull NamePathMapper namePathMapper,
            boolean isWorkspaceImport, int uuidBehavior,
            @NotNull ReferenceChangeTracker referenceTracker, @NotNull SecurityProvider securityProvider) {
        if (initialized) {
            throw new IllegalStateException("Already initialized");
        }
        if (!(session instanceof JackrabbitSession)) {
            return false;
        }
        try {
            AuthorizationConfiguration config = securityProvider.getConfiguration(AuthorizationConfiguration.class);
            importBehavior = Util.getImportBehavior(config);

            if (isWorkspaceImport) {
                acMgr = config.getAccessControlManager(root, namePathMapper);
                PrincipalConfiguration pConfig = securityProvider.getConfiguration(PrincipalConfiguration.class);
                principalManager = pConfig.getPrincipalManager(root, namePathMapper);
            } else {
                acMgr = session.getAccessControlManager();
                principalManager = ((JackrabbitSession) session).getPrincipalManager();
            }
            ntMgr = ReadOnlyNodeTypeManager.getInstance(root, namePathMapper);
            initialized = true;
        } catch (RepositoryException e) {
            log.warn("Error while initializing access control importer", e);
        }
        return initialized;
    }

    @Override
    public void processReferences() throws RepositoryException {
        // nothing to do.
    }

    //----------------------------------------------< ProtectedNodeImporter >---

    @Override
    public boolean start(@NotNull Tree protectedParent) throws RepositoryException {
        checkInitialized();

        // the acl node must have been added during the regular import before
        // this importer is only successfully started if an valid ACL was created.
        acl = getACL(protectedParent);
        return acl != null;
    }

    @Override
    public void end(@NotNull Tree protectedParent) throws RepositoryException {
        if (acl != null) {
            acMgr.setPolicy(acl.getPath(), acl);
            acl = null;
        } else {
            throw new IllegalStateException("End reached without ACL to write back.");
        }
    }

    @Override
    public void startChildInfo(@NotNull NodeInfo childInfo, @NotNull List<PropInfo> propInfos) throws RepositoryException {
        checkInitialized();
        String ntName = childInfo.getPrimaryTypeName();
        if (NT_REP_GRANT_ACE.equals(ntName) || NT_REP_DENY_ACE.equals(ntName)) {
            if (entry != null) {
                throw new ConstraintViolationException("Invalid child node sequence: ACEs may not be nested.");
            }
            entry = new MutableEntry(NT_REP_GRANT_ACE.equals(ntName));
            for (PropInfo prop : propInfos) {
                String name = prop.getName();
                if (REP_PRINCIPAL_NAME.equals(name)) {
                    entry.setPrincipal(prop.getTextValue());
                } else if (REP_PRIVILEGES.equals(name)) {
                    entry.setPrivilegeNames(prop.getTextValues());
                } else {
                    entry.addRestriction(prop);
                }
            }
            childStatus = CHILD_STATUS_ACE;
        } else if (NT_REP_RESTRICTIONS.equals(ntName)) {
            if (entry == null) {
                throw new ConstraintViolationException("Invalid child node sequence: Restriction must be associated with an ACE");
            }
            entry.addRestrictions(propInfos);
            childStatus = CHILD_STATUS_RESTRICTION;
        } else {
            throw new ConstraintViolationException("Invalid child node with type " + ntName);
        }
    }

    @Override
    public void endChildInfo() throws RepositoryException {
        checkInitialized();
        switch (childStatus) {
            case CHILD_STATUS_ACE:
                // write the ace to the policy
                entry.applyTo(acl);
                entry = null;
                childStatus = CHILD_STATUS_UNDEFINED;
                break;
            case CHILD_STATUS_RESTRICTION:
                // back to ace status
                childStatus = CHILD_STATUS_ACE;
                break;
            default:
                throw new ConstraintViolationException("Invalid child node sequence.");
        }
    }

    //------------------------------------------------------------< private >---
    private void checkInitialized() {
        if (!initialized) {
            throw new IllegalStateException("Not initialized");
        }
    }

    @Nullable
    private JackrabbitAccessControlList getACL(Tree tree) throws RepositoryException {
        String nodeName = tree.getName();

        JackrabbitAccessControlList acList = null;
        if (!tree.isRoot()) {
            Tree parent = tree.getParent();
            if (AccessControlConstants.REP_POLICY.equals(nodeName)
                    && ntMgr.isNodeType(tree, AccessControlConstants.NT_REP_ACL)) {
                String path = parent.getPath();
                acList = getACL(path);
            } else if (AccessControlConstants.REP_REPO_POLICY.equals(nodeName)
                    && ntMgr.isNodeType(tree, AccessControlConstants.NT_REP_ACL)
                    && parent.isRoot()) {
                acList = getACL((String) null);
            }
        }

        if (acList != null) {
            // clear all existing entries
            for (AccessControlEntry ace: acList.getAccessControlEntries()) {
                acList.removeAccessControlEntry(ace);
            }
        }

        return acList;
    }

    @Nullable
    private JackrabbitAccessControlList getACL(@Nullable String path) throws RepositoryException {
        JackrabbitAccessControlList acList = null;
        for (AccessControlPolicy p : acMgr.getPolicies(path)) {
            if (p instanceof JackrabbitAccessControlList) {
                acList = (JackrabbitAccessControlList) p;
                break;
            }
        }
        return acList;
    }

    //--------------------------------------------------------------------------
    private final class MutableEntry {

        private final boolean isAllow;

        private Principal principal;
        private List<Privilege> privileges = new ArrayList();
        private Map<String, Value> restrictions = new HashMap();
        private Map<String, Value[]> mvRestrictions = new HashMap();

        private boolean ignore;

        private MutableEntry(boolean isAllow) {
            this.isAllow = isAllow;
        }

        private void setPrincipal(TextValue txtValue) throws AccessControlException {
            String principalName = txtValue.getString();
            principal = principalManager.getPrincipal(principalName);
            if (principal == null) {
                switch (importBehavior) {
                    case ImportBehavior.IGNORE:
                        log.debug("Unknown principal " + principalName + " -> Ignoring this ACE.");
                        ignore = true;
                        break;
                    case ImportBehavior.ABORT:
                        throw new AccessControlException("Unknown principal " + principalName);
                    case ImportBehavior.BESTEFFORT:
                        principal = new PrincipalImpl(principalName);
                }
            }
        }

        private void setPrivilegeNames(List<? extends TextValue> txtValues) throws RepositoryException {
            for (TextValue value : txtValues) {
                Value privilegeName = value.getValue(PropertyType.NAME);
                privileges.add(acMgr.privilegeFromName(privilegeName.getString()));
            }
        }

        private void addRestriction(PropInfo propInfo) throws RepositoryException {
            String restrictionName = propInfo.getName();
            int targetType = acl.getRestrictionType(restrictionName);
            List<Value> values = propInfo.getValues(targetType);
            if (values.size() == 1) {
                restrictions.put(propInfo.getName(), values.get(0));
            } else {
                mvRestrictions.put(propInfo.getName(), values.toArray(new Value[values.size()]));
            }
        }

        private void addRestrictions(List<PropInfo> propInfos) throws RepositoryException {
            for (PropInfo prop : propInfos) {
                addRestriction(prop);
            }
        }

        private void applyTo(JackrabbitAccessControlList acl) throws RepositoryException {
            checkNotNull(acl);
            if (!ignore) {
                acl.addEntry(principal, privileges.toArray(new Privilege[privileges.size()]), isAllow, restrictions, mvRestrictions);
            } else {
                log.debug("Unknown principal: Ignore ACE based on ImportBehavior.IGNORE configuration.");
            }
        }
    }
}
