/*
 * 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.sling.jcr.jackrabbit.accessmanager.post;

import java.security.Principal;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.security.AccessControlEntry;
import javax.jcr.security.AccessControlManager;
import javax.jcr.security.AccessControlPolicy;
import javax.servlet.Servlet;

import org.apache.jackrabbit.api.security.JackrabbitAccessControlEntry;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager;
import org.apache.jackrabbit.api.security.authorization.PrincipalAccessControlList;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
import org.apache.sling.jcr.jackrabbit.accessmanager.LocalPrivilege;
import org.apache.sling.jcr.jackrabbit.accessmanager.LocalRestriction;
import org.apache.sling.jcr.jackrabbit.accessmanager.ModifyPrincipalAce;
import org.apache.sling.jcr.jackrabbit.accessmanager.impl.PrincipalAceHelper;
import org.apache.sling.servlets.post.PostResponseCreator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicyOption;

/**
 * <p>
 * Sling Post Servlet implementation for modifying the principalbased ACE for a principal on a JCR
 * resource.
 * </p>
 * <h2>Rest Service Description</h2>
 * <p>
 * Modify a principal's ACEs for the node identified as a resource by the request
 * URL &gt;resource&lt;.modifyPAce.html
 * </p>
 * <h3>Transport Details:</h3>
 * <h4>Methods</h4>
 * <ul>
 * <li>POST</li>
 * </ul>
 * <h4>Post Parameters</h4>
 * <dl>
 * <dt>principalId</dt>
 * <dd>The principal of the ACEs to modify in the ACL specified by the path.</dd>
 * <dt>privilege@[privilege_name]</dt>
 * <dd>One or more privileges which will be applied to the ACE. Any permissions that are present in an
 * existing ACE for the principal but not in the request are left untouched. The parameter value must be either 'allow' or 'all'. 
 * For backward compatibility, 'granted' may also be used for the parameter value as an alias for 'allow'.</dd>
 * <dt>restriction@[restriction_name]</dt>
 * <dd>One or more restrictions which will be applied to the ACE. The value is the target value of the restriction to be set.</dd>
 * <dt>restriction@[restriction_name]@Delete</dt>
 * <dd>One or more restrictions which will be removed from the ACE</dd>
 * <dt>privilege@[privilege_name]@Delete</dt>
 * <dd>One param for each privilege to delete. The parameter value must be either 'allow' or 'all' to specify which state to delete from</dd>
 * <dt>restriction@[privilege_name]@[restriction_name]@Allow</dt>
 * <dt>restriction@[privilege_name]@[restriction_name]@Deny</dt>
 * <dd>One param for each restriction value. The same parameter name may be used again for multi-value restrictions. The @Allow suffix 
 *     specifies whether to apply the restriction to the 'allow' privilege.  The value is the target value of the restriction to be set.</dd>
 * <dt>restriction@[privilege_name]@[restriction_name]@Delete</dt>
 * <dd>One param for each restriction to delete. The parameter value must be either 'allow' or 'all' to specify which state to delete from.</dd>
 * </dl>
 *
 * <h4>Response</h4>
 * <dl>
 * <dt>200</dt>
 * <dd>Success.</dd>
 * <dt>404</dt>
 * <dd>The resource was not found.</dd>
 * <dt>500</dt>
 * <dd>Failure. HTML explains the failure.</dd>
 * </dl>
 *
 * <h4>Notes</h4>
 * <p>
 * The principalId is assumed to refer directly to an Authorizable, that comes direct from
 * the UserManager. This can be a group or a user, but if its a group, denied permissions
 * will not be added to the group. The group will only contain granted privileges.
 * </p>
 */
@Component(service = {Servlet.class, ModifyPrincipalAce.class},
property= {
        "sling.servlet.resourceTypes=sling/servlet/default",
        "sling.servlet.methods=POST",
        "sling.servlet.selectors=modifyPAce",
        "sling.servlet.prefix:Integer=-1"
},
reference = {
        @Reference(name="RestrictionProvider",
                bind = "bindRestrictionProvider",
                service = RestrictionProvider.class),
        @Reference(name = "PostResponseCreator",
                bind = "bindPostResponseCreator",
                cardinality = ReferenceCardinality.MULTIPLE,
                policyOption = ReferencePolicyOption.GREEDY,
                service = PostResponseCreator.class)
})
@SuppressWarnings("java:S110")
public class ModifyPrincipalAceServlet extends ModifyAceServlet implements ModifyPrincipalAce {

    private static final long serialVersionUID = -4152308935573740745L;

    @Override
    protected boolean allowNonExistingPaths() {
        return true;
    }

    @Override
    public void modifyPrincipalAce(Session jcrSession, String resourcePath, String principalId,
            Map<String, String> privileges, boolean autoSave) throws RepositoryException {
        modifyPrincipalAce(jcrSession, resourcePath, principalId, privileges,
                null, null, null, autoSave);
    }

    @Override
    public void modifyPrincipalAce(Session jcrSession, String resourcePath, String principalId,
            Map<String, String> privileges, Map<String, Value> restrictions,
            Map<String, Value[]> mvRestrictions, Set<String> removeRestrictionNames, boolean autoSave)
            throws RepositoryException {
        modifyAce(jcrSession, resourcePath, principalId, privileges, null,
                restrictions, mvRestrictions, removeRestrictionNames, autoSave, null);
    }

    @Override
    public void modifyPrincipalAce(Session jcrSession, String resourcePath, String principalId,
            Collection<LocalPrivilege> localPrivileges, boolean autoSave) throws RepositoryException {
        modifyAce(jcrSession, resourcePath, principalId,
                localPrivileges, null,
                autoSave, null);
    }

    /**
     * Override to ensure that we get the policy that implements {@link PrincipalAccessControlList}
     */
    @Override
    protected JackrabbitAccessControlList getAcl(@NotNull AccessControlManager acm, String resourcePath, Principal principal)
            throws RepositoryException {
        JackrabbitAccessControlList acl = null;
        if (acm instanceof JackrabbitAccessControlManager) {
            JackrabbitAccessControlManager jacm = (JackrabbitAccessControlManager)acm;
            AccessControlPolicy[] policies = jacm.getPolicies(principal);
            for (AccessControlPolicy policy : policies) {
                if (policy instanceof PrincipalAccessControlList) {
                    acl = (PrincipalAccessControlList) policy;
                    break;
                }
            }
            if (acl == null) {
                AccessControlPolicy[]  applicablePolicies = jacm.getApplicablePolicies(principal);
                for (AccessControlPolicy policy : applicablePolicies) {
                    if (policy instanceof PrincipalAccessControlList) {
                        acl = (PrincipalAccessControlList) policy;
                        break;
                    }
                }
            }
        }
        return acl;
    }

    /**
     * Override to ensure that we only remove the entries that have an effectivePath that matches
     * the current resourcePath
     */
    @Override
    protected String removeAces(@NotNull String resourcePath, @Nullable String order, @NotNull Principal principal,
            @NotNull JackrabbitAccessControlList acl) throws RepositoryException {
        AccessControlEntry[] existingAccessControlEntries = acl.getAccessControlEntries();
        for (int j = 0; j < existingAccessControlEntries.length; j++) {
            AccessControlEntry ace = existingAccessControlEntries[j];
            @Nullable
            JackrabbitAccessControlEntry jrEntry = getJackrabbitAccessControlEntry(ace, resourcePath, principal);
            if (jrEntry != null) {
                if (order == null || order.length() == 0) {
                    //order not specified, so keep track of the original ACE position.
                    order = String.valueOf(j);
                }

                acl.removeAccessControlEntry(ace);
            }
        }
        return order;
    }

    /**
     * Override to ensure we do not add enty that denies privileges which is not allowed in a principal ACE
     */
    @Override
    protected void addAces(@NotNull String resourcePath, @NotNull Principal principal,
            @NotNull Map<Set<LocalRestriction>, List<LocalPrivilege>> restrictionsToLocalPrivilegesMap, boolean isAllow,
            @NotNull JackrabbitAccessControlList acl) throws RepositoryException {
        if (!isAllow && !restrictionsToLocalPrivilegesMap.isEmpty()) {
            // deny privileges not allowed in a principal ACE
            throw new IllegalArgumentException("Deny privileges are not allowed in a principal ACE");
        }
        super.addAces(resourcePath, principal, restrictionsToLocalPrivilegesMap, isAllow, acl);
    }

    /**
     * Override to ensure that we only return the entries that have an effectivePath that matches
     * the current resourcePath
     */
    @Override
    protected @Nullable JackrabbitAccessControlEntry getJackrabbitAccessControlEntry(@NotNull AccessControlEntry entry, @NotNull String resourcePath,
            @NotNull Principal forPrincipal) {
        JackrabbitAccessControlEntry jrEntry = null;
        if (entry instanceof PrincipalAccessControlList.Entry &&
                entry.getPrincipal().equals(forPrincipal) &&
                PrincipalAceHelper.matchesResourcePath(resourcePath, entry)) {
            jrEntry = (JackrabbitAccessControlEntry)entry;
        }
        return jrEntry;
    }

}
