<commit_before>/*
 * 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;

import java.util.Map;
import javax.jcr.security.AccessControlException;

import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.spi.commit.Validator;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeDefinition;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.oak.util.NodeUtil;

/**
 * AccessControlValidator... TODO
 */
class AccessControlValidator implements Validator, AccessControlConstants {

    private final NodeUtil parentBefore;
    private final NodeUtil parentAfter;
    private final Map<String, PrivilegeDefinition> privilegeDefinitions;
    private final RestrictionProvider restrictionProvider;

    AccessControlValidator(NodeUtil parentBefore, NodeUtil parentAfter,
                           Map<String, PrivilegeDefinition> privilegeDefinitions,
                           RestrictionProvider restrictionProvider) {
        this.parentBefore = parentBefore;
        this.parentAfter = parentAfter;
        this.privilegeDefinitions = privilegeDefinitions;
        this.restrictionProvider = restrictionProvider;
    }

    //----------------------------------------------------------< Validator >---
    @Override
    public void propertyAdded(PropertyState after) throws CommitFailedException {
        // TODO: validate access control property
    }

    @Override
    public void propertyChanged(PropertyState before, PropertyState after) throws CommitFailedException {
        // TODO: validate access control property
    }

    @Override
    public void propertyDeleted(PropertyState before) throws CommitFailedException {
        // nothing to do: mandatory properties will be enforced by node type validator
    }

    @Override
    public Validator childNodeAdded(String name, NodeState after) throws CommitFailedException {
        NodeUtil node = parentAfter.getChild(name);
        if (isAccessControlEntry(node)) {
            checkValidAccessControlEntry(node);
            return null;
        } else {
            return new AccessControlValidator(null, node, privilegeDefinitions, restrictionProvider);
        }
    }

    @Override
    public Validator childNodeChanged(String name, NodeState before, NodeState after) throws CommitFailedException {
        NodeUtil nodeBefore = parentBefore.getChild(name);
        NodeUtil nodeAfter = parentAfter.getChild(name);
        if (isAccessControlEntry(nodeAfter)) {
            checkValidAccessControlEntry(nodeAfter);
            return null;
        } else {
            return new AccessControlValidator(nodeBefore, nodeAfter, privilegeDefinitions, restrictionProvider);
        }
    }

    @Override
    public Validator childNodeDeleted(String name, NodeState before) throws CommitFailedException {
        // TODO validate acl / ace / restriction removal
        return null;
    }

    //------------------------------------------------------------< private >---
    private boolean isAccessControlEntry(NodeUtil node) {
        String ntName = node.getPrimaryNodeTypeName();
        return NT_REP_DENY_ACE.equals(ntName) || NT_REP_GRANT_ACE.equals(ntName);
    }

    private void checkValidAccessControlEntry(NodeUtil aceNode) throws CommitFailedException {
        checkValidPrincipal(aceNode.getString(REP_PRINCIPAL_NAME, null));
        checkValidPrivileges(aceNode.getNames(REP_PRIVILEGES));
        checkValidRestrictions(aceNode);
    }

    private void checkValidPrincipal(String principalName) throws CommitFailedException {
        if (principalName == null || principalName.isEmpty()) {
            fail("Missing principal name.");
        }
        // TODO
        // if (!principalMgr.hasPrincipal(principal.getName())) {
        //     throw new AccessControlException("Principal " + principal.getName() + " does not exist.");
        // }
    }

    private void checkValidPrivileges(String[] privilegeNames) throws CommitFailedException {
        if (privilegeNames == null || privilegeNames.length == 0) {
            fail("Missing privileges.");
        }
        for (String privilegeName : privilegeNames) {
            if (!privilegeDefinitions.containsKey(privilegeName)) {
                fail("Unknown privilege " + privilegeName);
            }

            PrivilegeDefinition def = privilegeDefinitions.get(privilegeName);
            if (def.isAbstract()) {
                fail("Abstract privilege " + privilegeName);
            }
        }
    }

    private void checkValidRestrictions(NodeUtil aceNode) throws CommitFailedException {
        try {
            String path = null; // TODO
            restrictionProvider.validateRestrictions(path, aceNode.getTree());
        } catch (AccessControlException e) {
            throw new CommitFailedException(e);
        }
    }

    private static void fail(String msg) throws CommitFailedException {
        throw new CommitFailedException(new AccessControlException(msg));
    }
}
<commit_msg>OAK-51 : Implement JCR Access Control Management (WIP)<commit_after>/*
 * 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;

import java.util.Map;
import javax.jcr.security.AccessControlException;

import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.spi.commit.Validator;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeDefinition;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.oak.util.NodeUtil;

/**
 * AccessControlValidator... TODO
 */
class AccessControlValidator implements Validator, AccessControlConstants {

    private final NodeUtil parentBefore;
    private final NodeUtil parentAfter;
    private final Map<String, PrivilegeDefinition> privilegeDefinitions;
    private final RestrictionProvider restrictionProvider;

    AccessControlValidator(NodeUtil parentBefore, NodeUtil parentAfter,
                           Map<String, PrivilegeDefinition> privilegeDefinitions,
                           RestrictionProvider restrictionProvider) {
        this.parentBefore = parentBefore;
        this.parentAfter = parentAfter;
        this.privilegeDefinitions = privilegeDefinitions;
        this.restrictionProvider = restrictionProvider;
    }

    //----------------------------------------------------------< Validator >---
    @Override
    public void propertyAdded(PropertyState after) throws CommitFailedException {
        if (isAccessControlEntry(parentAfter)) {
            checkValidAccessControlEntry(parentAfter);
        }
    }

    @Override
    public void propertyChanged(PropertyState before, PropertyState after) throws CommitFailedException {
        if (isAccessControlEntry(parentAfter)) {
            checkValidAccessControlEntry(parentAfter);
        }
    }

    @Override
    public void propertyDeleted(PropertyState before) throws CommitFailedException {
        // nothing to do: mandatory properties will be enforced by node type validator
    }

    @Override
    public Validator childNodeAdded(String name, NodeState after) throws CommitFailedException {
        NodeUtil node = parentAfter.getChild(name);
        if (isAccessControlEntry(node)) {
            checkValidAccessControlEntry(node);
            return null;
        } else {
            return new AccessControlValidator(null, node, privilegeDefinitions, restrictionProvider);
        }
    }

    @Override
    public Validator childNodeChanged(String name, NodeState before, NodeState after) throws CommitFailedException {
        NodeUtil nodeBefore = parentBefore.getChild(name);
        NodeUtil nodeAfter = parentAfter.getChild(name);
        if (isAccessControlEntry(nodeAfter)) {
            checkValidAccessControlEntry(nodeAfter);
            return null;
        } else {
            return new AccessControlValidator(nodeBefore, nodeAfter, privilegeDefinitions, restrictionProvider);
        }
    }

    @Override
    public Validator childNodeDeleted(String name, NodeState before) throws CommitFailedException {
        // TODO validate acl / ace / restriction removal
        return null;
    }

    //------------------------------------------------------------< private >---
    private boolean isAccessControlEntry(NodeUtil node) {
        String ntName = node.getPrimaryNodeTypeName();
        return NT_REP_DENY_ACE.equals(ntName) || NT_REP_GRANT_ACE.equals(ntName);
    }

    private void checkValidAccessControlEntry(NodeUtil aceNode) throws CommitFailedException {
        checkValidPrincipal(aceNode.getString(REP_PRINCIPAL_NAME, null));
        checkValidPrivileges(aceNode.getNames(REP_PRIVILEGES));
        checkValidRestrictions(aceNode);
    }

    private void checkValidPrincipal(String principalName) throws CommitFailedException {
        if (principalName == null || principalName.isEmpty()) {
            fail("Missing principal name.");
        }
        // TODO
        // if (!principalMgr.hasPrincipal(principal.getName())) {
        //     throw new AccessControlException("Principal " + principal.getName() + " does not exist.");
        // }
    }

    private void checkValidPrivileges(String[] privilegeNames) throws CommitFailedException {
        if (privilegeNames == null || privilegeNames.length == 0) {
            fail("Missing privileges.");
        }
        for (String privilegeName : privilegeNames) {
            if (!privilegeDefinitions.containsKey(privilegeName)) {
                fail("Unknown privilege " + privilegeName);
            }

            PrivilegeDefinition def = privilegeDefinitions.get(privilegeName);
            if (def.isAbstract()) {
                fail("Abstract privilege " + privilegeName);
            }
        }
    }

    private void checkValidRestrictions(NodeUtil aceNode) throws CommitFailedException {
        try {
            String path = null; // TODO
            restrictionProvider.validateRestrictions(path, aceNode.getTree());
        } catch (AccessControlException e) {
            throw new CommitFailedException(e);
        }
    }

    private static void fail(String msg) throws CommitFailedException {
        throw new CommitFailedException(new AccessControlException(msg));
    }
}

{'fraction_non_alphanumeric': 0.09511250309074425, 'fraction_numerical': 0.0009890381603890218, 'mean_word_length': 2.930677032717849, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3442102', 'n_tokens_mistral': 2958, 'n_tokens_neox': 2868, 'n_words': 790}