Author: angela
Date: Thu Nov 14 15:28:17 2013
New Revision: 1541930

URL: http://svn.apache.org/r1541930
Log:
OAK-527: permissions (wip)

Added:
    
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/AbstractAutoCreatedPropertyTest.java
    
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/MixCreatedTest.java
    
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/MixReferenceableTest.java
Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidator.java

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidator.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidator.java?rev=1541930&r1=1541929&r2=1541930&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidator.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidator.java
 Thu Nov 14 15:28:17 2013
@@ -58,42 +58,54 @@ class PermissionValidator extends Defaul
     PermissionValidator(Tree parentBefore, Tree parentAfter,
                         PermissionProvider permissionProvider,
                         PermissionValidatorProvider provider) {
-        this(parentBefore, parentAfter,
-                permissionProvider.getTreePermission(parentBefore, 
TreePermission.EMPTY),
-                permissionProvider, provider, Permissions.NO_PERMISSION);
+        this.parentBefore = parentBefore;
+        this.parentAfter = parentAfter;
+        this.parentPermission = 
permissionProvider.getTreePermission(parentBefore, TreePermission.EMPTY);
+
+        this.permissionProvider = permissionProvider;
+        this.provider = provider;
+
+        permission = Permissions.getPermission(getPath(parentBefore, 
parentAfter), Permissions.NO_PERMISSION);
     }
 
     private PermissionValidator(Tree parentBefore, Tree parentAfter,
                         @Nullable TreePermission parentPermission,
-                        PermissionProvider permissionProvider,
-                        PermissionValidatorProvider provider,
-                        long permission) {
-        this.permissionProvider = permissionProvider;
-        this.provider = provider;
+                        @Nonnull PermissionValidator parentValidator) {
         this.parentBefore = parentBefore;
         this.parentAfter = parentAfter;
         this.parentPermission = parentPermission;
-        if (Permissions.NO_PERMISSION == permission) {
+
+        permissionProvider = parentValidator.permissionProvider;
+        provider = parentValidator.provider;
+
+        if (Permissions.NO_PERMISSION == parentValidator.permission) {
             this.permission = Permissions.getPermission(getPath(parentBefore, 
parentAfter), Permissions.NO_PERMISSION);
         } else {
-            this.permission = permission;
+            this.permission = parentValidator.permission;
         }
     }
 
     //----------------------------------------------------------< Validator 
>---
     @Override
     public void propertyAdded(PropertyState after) throws 
CommitFailedException {
-        checkPermissions(parentAfter, after, Permissions.ADD_PROPERTY);
+        String name = after.getName();
+        if (!AbstractTree.OAK_CHILD_ORDER.equals(name)) {
+            checkPermissions(parentAfter, after, Permissions.ADD_PROPERTY);
+        }
     }
 
     @Override
     public void propertyChanged(PropertyState before, PropertyState after) 
throws CommitFailedException {
-        if (AbstractTree.OAK_CHILD_ORDER.equals(after.getName())) {
+        String name = after.getName();
+        if (AbstractTree.OAK_CHILD_ORDER.equals(name)) {
             String childName = ChildOrderDiff.firstReordered(before, after);
             if (childName != null) {
                 Tree child = parentAfter.getChild(childName);
                 checkPermissions(child, false, 
Permissions.MODIFY_CHILD_NODE_COLLECTION);
             } // else: no re-order but only internal update
+        } else if (isImmutableProperty(name)) {
+            // parent node has been removed and and re-added as
+            checkPermissions(parentAfter, false, 
Permissions.ADD_NODE|Permissions.REMOVE_NODE);
         } else {
             checkPermissions(parentAfter, after, Permissions.MODIFY_PROPERTY);
         }
@@ -101,7 +113,9 @@ class PermissionValidator extends Defaul
 
     @Override
     public void propertyDeleted(PropertyState before) throws 
CommitFailedException {
-        checkPermissions(parentBefore, before, Permissions.REMOVE_PROPERTY);
+        if (!AbstractTree.OAK_CHILD_ORDER.equals(before.getName())) {
+            checkPermissions(parentBefore, before, 
Permissions.REMOVE_PROPERTY);
+        }
     }
 
     @Override
@@ -137,7 +151,7 @@ class PermissionValidator extends Defaul
 
     //------------------------------------------------------------< private 
>---
     private Validator nextValidator(@Nullable Tree parentBefore, @Nullable 
Tree parentAfter, @Nonnull TreePermission treePermission) {
-        Validator validator = new PermissionValidator(parentBefore, 
parentAfter, treePermission, permissionProvider, provider, permission);
+        Validator validator = new PermissionValidator(parentBefore, 
parentAfter, treePermission, this);
         return new VisibleValidator(validator, true, false);
     }
 
@@ -172,11 +186,14 @@ class PermissionValidator extends Defaul
             return;
         }
         long toTest = getPermission(parent, property, defaultPermission);
+        boolean isGranted;
         if (Permissions.isRepositoryPermission(toTest)) {
-            if 
(!permissionProvider.getRepositoryPermission().isGranted(toTest)) {
-                throw new CommitFailedException(ACCESS, 0, "Access denied");
-            }
-        } else if (!parentPermission.isGranted(toTest, property)) {
+            isGranted = 
permissionProvider.getRepositoryPermission().isGranted(toTest);
+        } else {
+            isGranted = parentPermission.isGranted(toTest, property);
+        }
+
+        if (!isGranted) {
             throw new CommitFailedException(ACCESS, 0, "Access denied");
         }
     }
@@ -228,7 +245,10 @@ class PermissionValidator extends Defaul
         } else if (JcrConstants.JCR_MIXINTYPES.equals(name)) {
             perm = Permissions.NODE_TYPE_MANAGEMENT;
         } else if (JcrConstants.JCR_UUID.equals(name)) {
-            if (provider.getNodeTypeManager().isNodeType(parent, 
JcrConstants.MIX_REFERENCEABLE)) {
+            if (isNodeType(parent, JcrConstants.MIX_REFERENCEABLE)) {
+                // property added or removed: jcr:uuid is autocreated in
+                // JCR, thus can't determine here if this was a user supplied
+                // modification or not.
                 perm = Permissions.NO_PERMISSION;
             } else {
                 /* the parent is not referenceable -> check regular permissions
@@ -262,6 +282,21 @@ class PermissionValidator extends Defaul
         }
     }
 
+    private boolean isImmutableProperty(String name) {
+        // TODO: review; cant' rely on autocreated/protected definition as 
this doesn't reveal if a given property is expected to be never modified after 
creation
+        if (JcrConstants.JCR_UUID.equals(name) && isNodeType(parentAfter, 
JcrConstants.MIX_REFERENCEABLE)) {
+            return true;
+        } else if (("jcr:created".equals(name) || 
"jcr:createdBy".equals(name)) && isNodeType(parentAfter, "mix:created")) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private boolean isNodeType(Tree parent, String ntName) {
+        return provider.getNodeTypeManager().isNodeType(parent, ntName);
+    }
+
     private boolean isVersionstorageTree(Tree tree) {
         return permission == Permissions.VERSION_MANAGEMENT &&
                 
VersionConstants.REP_VERSIONSTORAGE.equals(TreeUtil.getPrimaryTypeName(tree));

Added: 
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/AbstractAutoCreatedPropertyTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/AbstractAutoCreatedPropertyTest.java?rev=1541930&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/AbstractAutoCreatedPropertyTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/AbstractAutoCreatedPropertyTest.java
 Thu Nov 14 15:28:17 2013
@@ -0,0 +1,127 @@
+/*
+ * 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.jcr.security.authorization;
+
+import javax.jcr.AccessDeniedException;
+import javax.jcr.Node;
+import javax.jcr.security.Privilege;
+
+import org.junit.Test;
+
+/**
+ * Testing removing and re-adding node which defines autocreated protected 
properties.
+ */
+public abstract class AbstractAutoCreatedPropertyTest extends 
AbstractEvaluationTest {
+
+    Node targetNode;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        Node leaf = superuser.getNode(childNPath);
+        targetNode = leaf.addNode(getNodeName());
+        targetNode.addMixin(getMixinName());
+
+        superuser.save();
+    }
+
+    abstract String getNodeName();
+
+    abstract String getMixinName();
+
+    @Test
+    public void testReplaceNode() throws Exception {
+        allow(path, privilegesFromNames(new String[] {
+                Privilege.JCR_MODIFY_PROPERTIES,
+                Privilege.JCR_NODE_TYPE_MANAGEMENT}));
+
+        testSession.removeItem(targetNode.getPath());
+        Node newNode = 
testSession.getNode(childNPath).addNode(targetNode.getName(), 
targetNode.getPrimaryNodeType().getName());
+        newNode.addMixin(getMixinName());
+        try {
+            testSession.save();
+            fail();
+        } catch (AccessDeniedException e) {
+            testSession.refresh(false);
+        }
+    }
+
+    @Test
+    public void testReplaceNode2() throws Exception {
+        allow(path, privilegesFromNames(new String[] {
+                Privilege.JCR_ADD_CHILD_NODES, 
Privilege.JCR_NODE_TYPE_MANAGEMENT}));
+
+        testSession.removeItem(targetNode.getPath());
+        Node newNode = 
testSession.getNode(childNPath).addNode(targetNode.getName(), 
targetNode.getPrimaryNodeType().getName());
+        newNode.addMixin(getMixinName());
+        try {
+            testSession.save();
+            fail();
+        } catch (AccessDeniedException e) {
+            testSession.refresh(false);
+        }
+    }
+
+    @Test
+    public void testReplaceNode3() throws Exception {
+        allow(path, privilegesFromNames(new String[] {
+                Privilege.JCR_REMOVE_CHILD_NODES, 
Privilege.JCR_NODE_TYPE_MANAGEMENT}));
+
+        testSession.removeItem(targetNode.getPath());
+        Node newNode = 
testSession.getNode(childNPath).addNode(targetNode.getName(), 
targetNode.getPrimaryNodeType().getName());
+        newNode.addMixin(getMixinName());
+        try {
+            testSession.save();
+            fail();
+        } catch (AccessDeniedException e) {
+            testSession.refresh(false);
+        }
+    }
+
+    @Test
+    public void testReplaceNode4() throws Exception {
+        allow(path, privilegesFromNames(new String[] {
+                Privilege.JCR_ADD_CHILD_NODES,
+                Privilege.JCR_REMOVE_NODE,
+                Privilege.JCR_REMOVE_CHILD_NODES,
+                Privilege.JCR_NODE_TYPE_MANAGEMENT}));
+
+        testSession.removeItem(targetNode.getPath());
+        Node newNode = 
testSession.getNode(childNPath).addNode(targetNode.getName(), 
targetNode.getPrimaryNodeType().getName());
+        newNode.addMixin(getMixinName());
+        testSession.save();
+    }
+
+    @Test
+    public void testRemoveReAddMixin() throws Exception {
+        allow(path, privilegesFromNames(new String[] {
+                Privilege.JCR_ADD_CHILD_NODES,
+                Privilege.JCR_REMOVE_NODE,
+                Privilege.JCR_REMOVE_CHILD_NODES}));
+
+        try {
+            Node refNode = testSession.getNode(targetNode.getPath());
+            refNode.removeMixin(getMixinName());
+            refNode.addMixin(getMixinName());
+            testSession.save();
+            fail();
+        } catch (AccessDeniedException e) {
+            // success
+        }
+    }
+}

Added: 
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/MixCreatedTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/MixCreatedTest.java?rev=1541930&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/MixCreatedTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/MixCreatedTest.java
 Thu Nov 14 15:28:17 2013
@@ -0,0 +1,32 @@
+/*
+ * 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.jcr.security.authorization;
+
+/**
+ * Implementation of {@code AbstractAutoCreatedPropertyTest} for mix:created
+ * nodes.
+ */
+public class MixCreatedTest extends AbstractAutoCreatedPropertyTest {
+
+    String getNodeName() {
+        return "mixCreated";
+    }
+
+    String getMixinName() {
+        return "mix:created";
+    }
+}

Added: 
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/MixReferenceableTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/MixReferenceableTest.java?rev=1541930&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/MixReferenceableTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/MixReferenceableTest.java
 Thu Nov 14 15:28:17 2013
@@ -0,0 +1,32 @@
+/*
+ * 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.jcr.security.authorization;
+
+/**
+ * Implementation of {@code AbstractAutoCreatedPropertyTest} for 
mix:referenceable
+ * nodes.
+ */
+public class MixReferenceableTest extends AbstractAutoCreatedPropertyTest {
+
+    String getNodeName() {
+        return "referenceable";
+    }
+
+    String getMixinName() {
+        return mixReferenceable;
+    }
+}


Reply via email to