You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by an...@apache.org on 2018/04/23 13:36:34 UTC

svn commit: r1829885 - in /jackrabbit/oak/trunk/oak-exercise: ./ src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/ src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ ...

Author: angela
Date: Mon Apr 23 13:36:34 2018
New Revision: 1829885

URL: http://svn.apache.org/viewvc?rev=1829885&view=rev
Log:
OAK-5122 : Exercise for Custom Authorization Models

Added:
    jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/Editor.java   (with props)
    jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/Reader.java   (with props)
Modified:
    jackrabbit/oak/trunk/oak-exercise/pom.xml
    jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/PredefinedPermissionProvider.java
    jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesAccessControlManager.java
    jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesAuthorizationConfiguration.java
    jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesPermissionProvider.java
    jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesTreePermission.java
    jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/Utils.java
    jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/advanced/L3_UnderstandAggregationTest.java
    jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/advanced/L5_CustomPermissionEvaluationTest.java

Modified: jackrabbit/oak/trunk/oak-exercise/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/pom.xml?rev=1829885&r1=1829884&r2=1829885&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-exercise/pom.xml Mon Apr 23 13:36:34 2018
@@ -111,6 +111,11 @@
     </dependency>
     <dependency>
       <groupId>org.apache.jackrabbit</groupId>
+      <artifactId>oak-authorization-cug</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jackrabbit</groupId>
       <artifactId>jackrabbit-api</artifactId>
       <version>${jackrabbit.version}</version>
     </dependency>

Added: jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/Editor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/Editor.java?rev=1829885&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/Editor.java (added)
+++ jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/Editor.java Mon Apr 23 13:36:34 2018
@@ -0,0 +1,26 @@
+/*
+ * 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.exercise.security.authorization.models.predefined;
+
+import javax.annotation.Nonnull;
+
+public class Editor extends Reader {
+
+    public Editor(@Nonnull String name) {
+        super(name);
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/Editor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/PredefinedPermissionProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/PredefinedPermissionProvider.java?rev=1829885&r1=1829884&r2=1829885&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/PredefinedPermissionProvider.java (original)
+++ jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/PredefinedPermissionProvider.java Mon Apr 23 13:36:34 2018
@@ -21,12 +21,16 @@ import java.util.Set;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
+import com.google.common.collect.ImmutableSet;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
 import org.apache.jackrabbit.oak.spi.security.authorization.permission.RepositoryPermission;
 import org.apache.jackrabbit.oak.spi.security.authorization.permission.TreePermission;
 
+/**
+ * EXERCISE: complete PermissionProvider implementation
+ */
 class PredefinedPermissionProvider implements PermissionProvider {
 
     private final Set<Principal> principals;
@@ -37,46 +41,46 @@ class PredefinedPermissionProvider imple
 
     @Override
     public void refresh() {
-        // TODO
+        // EXERCISE: complete PermissionProvider implementation
 
     }
 
     @Nonnull
     @Override
     public Set<String> getPrivileges(@Nullable Tree tree) {
-        // TODO
-        return null;
+        // EXERCISE: complete PermissionProvider implementation
+        return ImmutableSet.of();
     }
 
     @Override
     public boolean hasPrivileges(@Nullable Tree tree, @Nonnull String... privilegeNames) {
-        // TODO
+        // EXERCISE: complete PermissionProvider implementation
         return false;
     }
 
     @Nonnull
     @Override
     public RepositoryPermission getRepositoryPermission() {
-        // TODO
-        return null;
+        // EXERCISE: complete PermissionProvider implementation
+        return RepositoryPermission.EMPTY;
     }
 
     @Nonnull
     @Override
     public TreePermission getTreePermission(@Nonnull Tree tree, @Nonnull TreePermission parentPermission) {
-        // TODO
-        return null;
+        // EXERCISE: complete PermissionProvider implementation
+        return TreePermission.EMPTY;
     }
 
     @Override
     public boolean isGranted(@Nonnull Tree tree, @Nullable PropertyState property, long permissions) {
-        // TODO
+        // EXERCISE: complete PermissionProvider implementation
         return false;
     }
 
     @Override
     public boolean isGranted(@Nonnull String oakPath, @Nonnull String jcrActions) {
-        // TODO
+        // EXERCISE: complete PermissionProvider implementation
         return false;
     }
 }
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/Reader.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/Reader.java?rev=1829885&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/Reader.java (added)
+++ jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/Reader.java Mon Apr 23 13:36:34 2018
@@ -0,0 +1,38 @@
+/*
+ * 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.exercise.security.authorization.models.predefined;
+
+import java.security.Principal;
+
+import javax.annotation.Nonnull;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Reader implements Principal {
+
+    private final String name;
+
+    public Reader(@Nonnull String name) {
+        this.name = name;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/Reader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesAccessControlManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesAccessControlManager.java?rev=1829885&r1=1829884&r2=1829885&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesAccessControlManager.java (original)
+++ jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesAccessControlManager.java Mon Apr 23 13:36:34 2018
@@ -41,30 +41,30 @@ class ThreeRolesAccessControlManager imp
 
     ThreeRolesAccessControlManager(@Nonnull Root root, @Nonnull String supportedPath, @Nonnull SecurityProvider securityProvider) {
         this.supportedPath = supportedPath;
-        // TODO
+        // EXERCISE
     }
 
     @Override
     public Privilege[] getSupportedPrivileges(String absPath) throws PathNotFoundException, RepositoryException {
-        // TODO
+        // EXERCISE
         return new Privilege[0];
     }
 
     @Override
     public Privilege privilegeFromName(String privilegeName) throws AccessControlException, RepositoryException {
-        // TODO
+        // EXERCISE
         return null;
     }
 
     @Override
     public boolean hasPrivileges(String absPath, Privilege[] privileges) throws PathNotFoundException, RepositoryException {
-        // TODO
+        // EXERCISE
         return false;
     }
 
     @Override
     public Privilege[] getPrivileges(String absPath) throws PathNotFoundException, RepositoryException {
-        // TODO
+        // EXERCISE
         return new Privilege[0];
     }
 
@@ -73,38 +73,38 @@ class ThreeRolesAccessControlManager imp
      */
     @Override
     public AccessControlPolicy[] getPolicies(String absPath) throws PathNotFoundException, AccessDeniedException, RepositoryException {
-        // TODO
+        // EXERCISE
         return new AccessControlPolicy[0];
     }
 
     @Override
     public AccessControlPolicy[] getEffectivePolicies(String absPath) throws PathNotFoundException, AccessDeniedException, RepositoryException {
-        // TODO
+        // EXERCISE
         return new AccessControlPolicy[0];
     }
 
     @Override
     public AccessControlPolicyIterator getApplicablePolicies(String absPath) throws PathNotFoundException, AccessDeniedException, RepositoryException {
-        // TODO
+        // EXERCISE
         return new AccessControlPolicyIteratorAdapter(ImmutableList.of());
     }
 
     @Override
     public void setPolicy(String absPath, AccessControlPolicy policy) throws PathNotFoundException, AccessControlException, AccessDeniedException, LockException, VersionException, RepositoryException {
-        // TODO
+        // EXERCISE
 
     }
 
     @Override
     public void removePolicy(String absPath, AccessControlPolicy policy) throws PathNotFoundException, AccessControlException, AccessDeniedException, LockException, VersionException, RepositoryException {
-        // TODO
+        // EXERCISE
 
     }
 
     @Override
     public boolean defines(@Nullable String absPath, @Nonnull AccessControlPolicy accessControlPolicy) {
         if (Utils.isSupportedPath(supportedPath, absPath)) {
-            // TODO
+            // EXERCISE
         }
         return false;
     }

Modified: jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesAuthorizationConfiguration.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesAuthorizationConfiguration.java?rev=1829885&r1=1829884&r2=1829885&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesAuthorizationConfiguration.java (original)
+++ jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesAuthorizationConfiguration.java Mon Apr 23 13:36:34 2018
@@ -170,7 +170,7 @@ public class ThreeRolesAuthorizationConf
         return ImmutableList.of(new ValidatorProvider() {
             @Override
             protected Validator getRootValidator(NodeState before, NodeState after, CommitInfo info) {
-                // TODO: write a validator that meets the following requirements:
+                // EXERCISE: write a validator that meets the following requirements:
                 // 1. check that the item names defined with the node types are only used within the scope of the 2 node types
                 // 2. check that the policies are never nested.
 
@@ -186,7 +186,7 @@ public class ThreeRolesAuthorizationConf
     @Nonnull
     @Override
     public List<ProtectedItemImporter> getProtectedItemImporters() {
-        // TODO
+        // EXERCISE
         return ImmutableList.of();
     }
 

Modified: jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesPermissionProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesPermissionProvider.java?rev=1829885&r1=1829884&r2=1829885&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesPermissionProvider.java (original)
+++ jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesPermissionProvider.java Mon Apr 23 13:36:34 2018
@@ -142,7 +142,7 @@ class ThreeRolesPermissionProvider imple
     @Nonnull
     @Override
     public TreePermission getTreePermission(@Nonnull Tree tree, @Nonnull TreeType type, @Nonnull TreePermission parentPermission) {
-        // TODO : currently this implementation ignores TreeType
+        // EXERCISE : currently this implementation ignores TreeType -> complete implementation
         return getTreePermission(tree, parentPermission);
     }
 

Modified: jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesTreePermission.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesTreePermission.java?rev=1829885&r1=1829884&r2=1829885&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesTreePermission.java (original)
+++ jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesTreePermission.java Mon Apr 23 13:36:34 2018
@@ -44,7 +44,7 @@ class ThreeRolesTreePermission implement
         if (isAcContent) {
             return this;
         } else {
-            // TODO: respect access controlled content defined by other modules
+            // EXERCISE: respect access controlled content defined by other modules
             return new ThreeRolesTreePermission(role, REP_3_ROLES_POLICY.equals(childName));
         }
     }

Modified: jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/Utils.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/Utils.java?rev=1829885&r1=1829884&r2=1829885&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/Utils.java (original)
+++ jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/Utils.java Mon Apr 23 13:36:34 2018
@@ -19,12 +19,7 @@ package org.apache.jackrabbit.oak.exerci
 import javax.annotation.Nonnull;
 
 import org.apache.jackrabbit.util.Text;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-/**
- * Utils... TODO
- */
 final class Utils {
 
     private Utils() {}

Modified: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/advanced/L3_UnderstandAggregationTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/advanced/L3_UnderstandAggregationTest.java?rev=1829885&r1=1829884&r2=1829885&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/advanced/L3_UnderstandAggregationTest.java (original)
+++ jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/advanced/L3_UnderstandAggregationTest.java Mon Apr 23 13:36:34 2018
@@ -16,6 +16,39 @@
  */
 package org.apache.jackrabbit.oak.exercise.security.authorization.advanced;
 
+import javax.jcr.GuestCredentials;
+import javax.jcr.security.AccessControlList;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.AccessControlPolicy;
+import javax.jcr.security.AccessControlPolicyIterator;
+
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
+import org.apache.jackrabbit.api.security.authorization.PrincipalSetPolicy;
+import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.ContentSession;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
+import org.apache.jackrabbit.oak.plugins.tree.TreeUtil;
+import org.apache.jackrabbit.oak.security.authorization.composite.CompositeAuthorizationConfiguration;
+import org.apache.jackrabbit.oak.security.internal.SecurityProviderHelper;
+import org.apache.jackrabbit.oak.spi.namespace.NamespaceConstants;
+import org.apache.jackrabbit.oak.spi.nodetype.NodeTypeConstants;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+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.cug.impl.CugConfiguration;
+import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
 /**
  * <pre>
  * Module: Advanced Authorization Topics
@@ -25,14 +58,310 @@ package org.apache.jackrabbit.oak.exerci
  * -----------------------------------------------------------------------------
  *
  * Goal:
- * TODO
+ * Understand the inner working of aggregated authorization by stepping through
+ * access control management and permission evaluation.
+ * Note that this exercise uses a non-OSGi setup for training purpose relying on
+ * helpers available only for test setup.
  *
  * Exercises:
- * TODO
+ * Debug through each of the test methods in order to get an understand on how
+ * the composite setup works.
+ *
+ * - {@link #testTestUserReadPermissions()}
+ * - {@link #testTestUserWritePermissions()}
+ * - {@link #testGuestReadPermissions()}
+ * - {@link #testGuestWritePermissions()}
+ * - {@link #testAdminReadPermissions()}
+ * - {@link #testAdminWritePermissions()}
+ * - {@link #testEffectivePolicies()}
+ * - {@link #testApplicablePolicies()}
+ * - {@link #testGetPolicies()}
+ * - {@link #testRemovePolicy()}
+ *
+ * - Explain the {@link org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.PolicyOwner} interface.
+ *
+ * - Write more tests to explore aggregation of additional features within the
+ *   authorization setup such as e.g.
+ *   > Privilege discovery
+ *   > Repository level privileges such as e.g. ability to register a new node type.
+ *   > XML Import
+ *   > Validation
+ *   > Repository Initialization
+ *
+ *
+ * Advanced Exercises
+ * -----------------------------------------------------------------------------
+ *
+ * - Change the 'authorizationCompositionType' to 'OR' and discuss the expected effect
+ *   on the tests. Re-run the tests to verify your expectations.
+ *
+ * - Take another look at {@link org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregatedPermissionProvider}.
+ *   What happens if a given {@link AuthorizationConfiguration} exposes a simple
+ *   {@link org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider}
+ *   that doesn't implement the aggregation-extension?
+ *   To verify your findings write a test-setup that combines the default authorization model with
+ *   {@link org.apache.jackrabbit.oak.exercise.security.authorization.models.predefined.PredefinedAuthorizationConfiguration}
  *
  * </pre>
  */
-public class L3_UnderstandAggregationTest {
+public class L3_UnderstandAggregationTest extends AbstractSecurityTest {
+
+    private PropertyState prop;
+
+    private AccessControlManager acMgr;
+
+    @Override
+    public void before() throws Exception {
+        super.before();
+
+        prop = PropertyStates.createProperty("prop", "value");
+
+        Tree var = TreeUtil.addChild(root.getTree("/"), "var", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+        var.setProperty(prop);
+
+        Tree content = TreeUtil.addChild(root.getTree("/"), "content", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+        content.setProperty(prop);
+
+        Tree c1 = TreeUtil.addChild(content, "c1", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+        c1.setProperty(prop);
+
+        Tree c2 = TreeUtil.addChild(content, "c2", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+        c2.setProperty(prop);
+
+        acMgr = getAccessControlManager(root);
+
+        // at /content grant read-access for everyone using default model
+        AccessControlList acl = AccessControlUtils.getAccessControlList(acMgr, content.getPath());
+        acl.addAccessControlEntry(EveryonePrincipal.getInstance(), privilegesFromNames(PrivilegeConstants.JCR_READ));
+        acMgr.setPolicy(content.getPath(), acl);
+
+        // at /content/c1 deny reading properties (default model) and establish
+        // a CUG that limits access to test user
+        AccessControlPolicyIterator it = acMgr.getApplicablePolicies(c1.getPath());
+        while (it.hasNext()) {
+            AccessControlPolicy policy = it.nextAccessControlPolicy();
+            if (policy instanceof PrincipalSetPolicy) {
+                PrincipalSetPolicy psp = (PrincipalSetPolicy) policy;
+                psp.addPrincipals(getTestUser().getPrincipal());
+                acMgr.setPolicy(c1.getPath(), psp);
+            } else if (policy instanceof JackrabbitAccessControlList) {
+                JackrabbitAccessControlList jacl = (JackrabbitAccessControlList) policy;
+                jacl.addEntry(EveryonePrincipal.getInstance(), privilegesFromNames(PrivilegeConstants.REP_ADD_PROPERTIES), true);
+                acMgr.setPolicy(c1.getPath(), jacl);
+            }
+        }
+        root.commit();
+    }
+
+    @Override
+    public void after() throws Exception {
+        try {
+            root.getTree("/content").remove();
+            root.getTree("/var").remove();
+            root.commit();
+        } finally {
+            super.after();
+        }
+    }
+
+    @Override
+    protected SecurityProvider initSecurityProvider() {
+        SecurityProvider sp = super.initSecurityProvider();
+        CugConfiguration cugConfiguration = new CugConfiguration();
+        cugConfiguration.setParameters(ConfigurationParameters.of("cugSupportedPaths", new String[] {"/content"}, "cugEnabled", true));
+
+        SecurityProviderHelper.updateConfig(sp, cugConfiguration, AuthorizationConfiguration.class);
+        return sp;
+    }
+
+    @Override
+    protected ConfigurationParameters getSecurityConfigParameters() {
+        return ConfigurationParameters.of("authorizationCompositionType", CompositeAuthorizationConfiguration.CompositionType.AND.toString());
+    }
+
+    @Test
+    public void testTestUserReadPermissions() throws Exception {
+        try (ContentSession cs = createTestSession()) {
+            Root r = cs.getLatestRoot();
+
+            assertFalse(r.getTree("/").exists());
+            assertFalse(r.getTree("/var").exists());
+
+            Tree t = r.getTree("/content");
+            assertTrue(t.exists());
+            assertTrue(t.hasProperty(prop.getName()));
+
+            t = r.getTree("/content/c2");
+            assertTrue(t.exists());
+            assertTrue(t.hasProperty(prop.getName()));
+
+            t = r.getTree("/content/c1");
+            assertTrue(t.exists());
+            assertTrue(t.hasProperty(prop.getName()));
+        }
+    }
+
+    @Test
+    public void testTestUserWritePermissions() throws Exception {
+        try (ContentSession cs = createTestSession()) {
+            Root r = cs.getLatestRoot();
+
+            Tree t = r.getTree("/content/c1");
+            t.setProperty("addingProperty", "value");
+            root.commit();
+
+            assertFalse(getAccessControlManager(r).hasPrivileges("/content/c1", privilegesFromNames(PrivilegeConstants.JCR_ADD_CHILD_NODES)));
+            assertFalse(getAccessControlManager(r).hasPrivileges("/content/c1", privilegesFromNames(PrivilegeConstants.JCR_REMOVE_CHILD_NODES)));
+            assertFalse(getAccessControlManager(r).hasPrivileges("/content/c1", privilegesFromNames(PrivilegeConstants.REP_REMOVE_PROPERTIES)));
+            assertFalse(getAccessControlManager(r).hasPrivileges("/content/c1", privilegesFromNames(PrivilegeConstants.REP_ALTER_PROPERTIES)));
+        }
+    }
+
+    @Test
+    public void testGuestReadPermissions() throws Exception {
+        try (ContentSession cs = login(new GuestCredentials())) {
+            Root r = cs.getLatestRoot();
+
+            assertFalse(r.getTree("/").exists());
+            assertFalse(r.getTree("/var").exists());
+
+            Tree t = r.getTree("/content");
+            assertTrue(t.exists());
+            assertTrue(t.hasProperty(prop.getName()));
+
+            t = r.getTree("/content/c2");
+            assertTrue(t.exists());
+            assertTrue(t.hasProperty(prop.getName()));
+
+            assertFalse(r.getTree("/content/c1").exists());
+        }
+    }
+
+    @Test(expected = CommitFailedException.class)
+    public void testGuestWritePermissions() throws Exception {
+        try (ContentSession cs = login(new GuestCredentials())) {
+            Root r = cs.getLatestRoot();
+
+            // EXERCISE: write additional code testing permissions required for
+            //           another property and child node.
+
+            Tree t = r.getTree("/content");
+            t.setProperty("prop2", "value");
+            t.addChild("anotherChild");
+
+            r.commit();
+        }
+    }
+
+    @Test
+    public void testAdminReadPermissions() {
+        assertTrue(root.getTree("/").exists());
+        assertTrue(root.getTree("/var").exists());
+
+        Tree t = root.getTree("/content");
+        assertTrue(t.exists());
+        assertTrue(t.hasProperty(prop.getName()));
+
+        t = root.getTree("/content/c2");
+        assertTrue(t.exists());
+        assertTrue(t.hasProperty(prop.getName()));
+
+        t = root.getTree("/content/c1");
+        assertTrue(t.exists());
+        assertTrue(t.hasProperty(prop.getName()));
+    }
+
+    @Test
+    public void testAdminWritePermissions() throws Exception {
+        for (String p : new String[] {"/", "/var", "/content", "/content/c1", "/content/c2"}) {
+            assertTrue(acMgr.hasPrivileges(p, privilegesFromNames(PrivilegeConstants.JCR_ALL)));
+        }
+    }
+
+    @Test
+    public void testEffectivePolicies() throws Exception {
+        // EXERCISE: inspect the effective policies to be discovered at the various paths
+        //           explain the result and the differences.
+
+        // EXERCISE: compare list of effective policies to policies return upon AccessControlManager.getPolicies
+
+        AccessControlPolicy[] effective = acMgr.getEffectivePolicies("/content/c1");
+        assertEquals(3, effective.length);
+
+        effective = acMgr.getEffectivePolicies("/content/c2");
+        assertEquals(1, effective.length);
+
+        effective = acMgr.getEffectivePolicies("/var");
+        assertEquals(0, effective.length);
+
+        effective = acMgr.getEffectivePolicies(NamespaceConstants.NAMESPACES_PATH);
+        assertEquals(1, effective.length);
+
+        // EXERCISE: try to modify the policies obtained in any of the calls
+
+        // EXERCISE: try to write back the effective policies using AccessControlManager.setPolicy
+    }
+
+    @Test
+    public void testApplicablePolicies() throws Exception {
+        // EXERCISE: observe the type of applicable policies and explain differences
+        //           between the 3 paths.
+        AccessControlPolicyIterator it = acMgr.getApplicablePolicies("/content/c2");
+        int cnt = 0;
+        while (it.hasNext()) {
+            AccessControlPolicy policy = it.nextAccessControlPolicy();
+            cnt++;
+        }
+        assertEquals(2, cnt);
+
+        it = acMgr.getApplicablePolicies("/var");
+        cnt = 0;
+        while (it.hasNext()) {
+            AccessControlPolicy policy = it.nextAccessControlPolicy();
+            cnt++;
+        }
+        assertEquals(1, cnt);
+
+        it = acMgr.getApplicablePolicies("/content");
+        cnt = 0;
+        while (it.hasNext()) {
+            AccessControlPolicy policy = it.nextAccessControlPolicy();
+            cnt++;
+        }
+        assertEquals(1, cnt);
+
+        // EXERCISE: expand the test by optionally modifying the applicable policies
+        //           and writing them back using AccessControlManager.setPolicy
+
+        // EXERCISE: explain the effective permissions resulting from both applying
+        //           empty and modified policies.
+    }
+
+    @Test
+    public void testGetSetPolicies() throws Exception {
+        AccessControlPolicy[] policies = acMgr.getPolicies("/content/c1");
+
+        assertEquals(2, policies.length);
+
+        // EXERCISE: observe how the different authorization models claim responsibility for the setPolicy call.
+        for (AccessControlPolicy policy : policies) {
+            acMgr.setPolicy("/content/c1", policy);
+        }
+
+        assertEquals(2, acMgr.getPolicies("/content/c1").length);
+    }
+
+    @Test
+    public void testRemovePolicy() throws Exception {
+        AccessControlPolicy[] policies = acMgr.getPolicies("/content/c1");
+
+        assertEquals(2, policies.length);
 
+        // EXERCISE: observe how the different authorization models claim responsibility for the removal.
+        for (AccessControlPolicy policy : policies) {
+            acMgr.removePolicy("/content/c1", policy);
+        }
 
+        assertEquals(0, acMgr.getPolicies("/content/c1").length);
+    }
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/advanced/L5_CustomPermissionEvaluationTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/advanced/L5_CustomPermissionEvaluationTest.java?rev=1829885&r1=1829884&r2=1829885&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/advanced/L5_CustomPermissionEvaluationTest.java (original)
+++ jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/advanced/L5_CustomPermissionEvaluationTest.java Mon Apr 23 13:36:34 2018
@@ -22,16 +22,22 @@ import java.util.Set;
 import javax.annotation.Nonnull;
 import javax.jcr.GuestCredentials;
 import javax.jcr.Session;
+import javax.jcr.security.Privilege;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
 import org.apache.jackrabbit.oak.AbstractSecurityTest;
 import org.apache.jackrabbit.oak.api.ContentSession;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Root;
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.exercise.security.authorization.models.predefined.Editor;
 import org.apache.jackrabbit.oak.exercise.security.authorization.models.predefined.PredefinedAuthorizationConfiguration;
+import org.apache.jackrabbit.oak.exercise.security.authorization.models.predefined.Reader;
 import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
 import org.apache.jackrabbit.oak.plugins.tree.TreeUtil;
 import org.apache.jackrabbit.oak.security.authentication.AuthenticationConfigurationImpl;
@@ -46,6 +52,7 @@ import org.apache.jackrabbit.oak.spi.sec
 import org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
 import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
 import org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions;
+import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
 import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
 import org.apache.jackrabbit.util.Text;
 import org.junit.Test;
@@ -71,13 +78,46 @@ import static org.junit.Assert.assertTru
  * Complete the implementation of {@link org.apache.jackrabbit.oak.exercise.security.authorization.models.predefined.PredefinedPermissionProvider}
  * such that the tests pass.
  *
+ * - {@link #testAdministrativeAccess}
+ *   Complete the {@link org.apache.jackrabbit.oak.exercise.security.authorization.models.predefined.PredefinedPermissionProvider}
+ *   such that at least the admin principal has full access everywhere.
  *
- * Advanced Exercise
+ *   Questions:
+ *   - How can you identify the 'administrator' from a given set of principals?
+ *   - Would it make sense to include other principals in that category? How would you identify them?
+ *   - Take another look at the built-in authorization models (default and oak-authorization-cug):
+ *     Can you describe what types of 'administrative' access they define? And how?
+ *
+ * - {@link #testGuestAccess()}
+ *   The {@link org.apache.jackrabbit.oak.exercise.security.authorization.models.predefined.PredefinedPermissionProvider}
+ *   assumes that the guest account doesn't have any permissions granted. Complete
+ *   the permission provider implementation accordingly.
+ *
+ *   Question:
+ *   Do you need to explicitly identify the guest account? If yes, how would you do that?
+ *
+ * - {@link #testWriteAccess()}
+ *   This tests asserts that 'editors' have basic read/write permissions. Complete
+ *   the permission provider implementation accordingly.
+ *
+ *   Questions:
+ *   - The test hard-codes the 'editor' principal. Can you come up with a setup scenario
+ *     where the Editor principal would be placed into the Subject upon login? What are the criteria?
+ *   - Can you make sure a given test-user won't be able to map itself to the 'editor' principal?
+ *
+ * - {@link #testReadAccess()}
+ *   This tests asserts that 'readers' exclusively have basic read access. Complete
+ *   the permission provider implementation accordingly.
+ *
+ *
+ * Advanced Exercises
  * -----------------------------------------------------------------------------
  *
+ * 1. Aggregation
+ *
  * Currently the {@link org.apache.jackrabbit.oak.exercise.security.authorization.models.predefined.PredefinedPermissionProvider}
  * doesn't implement {@link org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregatedPermissionProvider} interface
- * and can therefore not be used in a setup that combines multipe authorization models.
+ * and can therefore not be used in a setup that combines multiple authorization models.
  *
  * As an advanced exercise modify the {@link org.apache.jackrabbit.oak.exercise.security.authorization.models.predefined.PredefinedPermissionProvider}
  * to additionally implement {@link org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregatedPermissionProvider}
@@ -88,6 +128,26 @@ import static org.junit.Assert.assertTru
  * - Clarify which type of 'Authorization Composition' your implementation should be used.
  * - Observe the result of your combination and explain the results to effective permissions.
  *
+ *
+ * 2. Limit Access
+ *
+ * Currently the predefined {@code PermissionProvider} grants/denies the same permissions
+ * on the whole content repository. As an advanced exercise discuss how you would
+ * limit the permissions to certain parts of the content repository.
+ *
+ * For example: Imagine the first hierarchy level would define a trust-boundary
+ * based on continent. So, every 'Editor' only has write access to the continent
+ * he/she has been assigned to.
+ *
+ * Questions:
+ *
+ * - Should read-access be granted across continents?
+ * - Do you need a distinction between repository-administrators and continent-administrators?
+ * - How do you identify a given continent and map it to the access pattern of a given principal set?
+ * - Can you come up with your own PrincipalConfiguration serving a custom Principal implementation that help you with that task?
+ * - Are the items used for continent-identification properly protected to prevent unintended (or malicious) meddling?
+ * - At which point would you additionally need access control management?
+ *
  * </pre>
  */
 public class L5_CustomPermissionEvaluationTest extends AbstractSecurityTest {
@@ -155,8 +215,14 @@ public class L5_CustomPermissionEvaluati
         return Iterables.transform(trees, Tree::getPath);
     }
 
+    private Set<Principal> getGuestPrincipals() throws Exception {
+        try (ContentSession guest = login(new GuestCredentials())) {
+            return guest.getAuthInfo().getPrincipals();
+        }
+    }
+
     @Test
-    public void testAdministratorHasFullAccessEverywhere() {
+    public void testAdministrativeAccess() {
         for (String path : getTreePaths()) {
             Tree t = root.getTree(path);
             assertFalse(t.exists());
@@ -176,7 +242,7 @@ public class L5_CustomPermissionEvaluati
     }
 
     @Test
-    public void testGuestHasNowherePermissions() throws Exception {
+    public void testGuestAccess() throws Exception {
         try (ContentSession guest = login(new GuestCredentials())) {
             Root r = guest.getLatestRoot();
             for (String path : getTreePaths()) {
@@ -201,5 +267,95 @@ public class L5_CustomPermissionEvaluati
         }
     }
 
-    // TODO: add more tests
+    @Test
+    public void testWriteAccess() throws Exception {
+        List<Set<Principal>> editors = ImmutableList.<Set<Principal>>of(
+                ImmutableSet.<Principal>of(new Editor("ida")),
+                ImmutableSet.<Principal>of(EveryonePrincipal.getInstance(), new Editor("amanda")),
+                ImmutableSet.<Principal>of(getTestUser().getPrincipal(),new Editor("susi")),
+                ImmutableSet.<Principal>builder().addAll(getGuestPrincipals()).add(new Editor("naima")).build()
+        );
+
+        for (Set<Principal> principals : editors) {
+            PermissionProvider pp = getPermissionProvider(principals);
+            for (Tree t : trees) {
+                assertTrue(pp.hasPrivileges(t, PrivilegeConstants.JCR_READ, PrivilegeConstants.JCR_WRITE));
+
+                assertFalse(pp.hasPrivileges(t, PrivilegeConstants.JCR_WRITE, PrivilegeConstants.JCR_NODE_TYPE_MANAGEMENT));
+                assertFalse(pp.hasPrivileges(t, PrivilegeConstants.JCR_READ_ACCESS_CONTROL, PrivilegeConstants.JCR_MODIFY_ACCESS_CONTROL, PrivilegeConstants.REP_USER_MANAGEMENT));
+                assertFalse(pp.hasPrivileges(t, PrivilegeConstants.JCR_ALL));
+
+                assertTrue(pp.isGranted(t, null, Permissions.WRITE | Permissions.READ));
+                assertTrue(pp.isGranted(t, prop, Permissions.WRITE|Permissions.READ));
+
+                assertFalse(pp.isGranted(t, null, Permissions.ALL));
+                assertFalse(pp.isGranted(t, prop, Permissions.ALL));
+
+                assertFalse(pp.isGranted(t, null, Permissions.READ_ACCESS_CONTROL|Permissions.MODIFY_ACCESS_CONTROL|Permissions.USER_MANAGEMENT));
+                assertFalse(pp.isGranted(t, prop, Permissions.READ_ACCESS_CONTROL | Permissions.MODIFY_ACCESS_CONTROL | Permissions.USER_MANAGEMENT));
+
+
+                for (String action : ACTION_NAMES) {
+                    String treePath = t.getPath();
+                    assertTrue(pp.isGranted(treePath, action));
+                    assertTrue(pp.isGranted(PathUtils.concat(treePath, prop.getName()), action));
+                }
+
+                String deniedActions = Text.implode(new String[] {JackrabbitSession.ACTION_MODIFY_ACCESS_CONTROL, JackrabbitSession.ACTION_READ_ACCESS_CONTROL, JackrabbitSession.ACTION_USER_MANAGEMENT}, ",");
+                assertFalse(pp.isGranted(t.getPath(), deniedActions));
+            }
+        }
+    }
+
+    @Test
+    public void testReadAccess() throws Exception {
+        List<Set<Principal>> readers = ImmutableList.<Set<Principal>>of(
+                ImmutableSet.<Principal>of(new Reader("ida")),
+                ImmutableSet.<Principal>of(EveryonePrincipal.getInstance(), new Reader("fairuz")),
+                ImmutableSet.<Principal>of(getTestUser().getPrincipal(),new Editor("juni")),
+                ImmutableSet.<Principal>builder().addAll(getGuestPrincipals()).add(new Editor("ale")).build()
+        );
+
+        PrivilegeManager privilegeManager = getPrivilegeManager(root);
+        Privilege all = privilegeManager.getPrivilege(PrivilegeConstants.JCR_ALL);
+        Set<String> readPrivNames = ImmutableSet.of(PrivilegeConstants.JCR_READ, PrivilegeConstants.REP_READ_NODES, PrivilegeConstants.REP_READ_PROPERTIES);
+
+        for (Set<Principal> principals : readers) {
+            PermissionProvider pp = getPermissionProvider(principals);
+            for (Tree t : trees) {
+                assertTrue(pp.hasPrivileges(t, readPrivNames.toArray(new String[readPrivNames.size()])));
+
+                for (Privilege p : all.getAggregatePrivileges()) {
+                    String pName = p.getName();
+                    if (readPrivNames.contains(pName)) {
+                        assertTrue(pp.hasPrivileges(t, pName));
+                    } else {
+                        assertFalse(pp.hasPrivileges(t, pName));
+                    }
+                }
+                assertFalse(pp.hasPrivileges(t, PrivilegeConstants.JCR_ALL, PrivilegeConstants.JCR_READ));
+
+                assertTrue(pp.isGranted(t, null, Permissions.READ));
+                assertTrue(pp.isGranted(t, null, Permissions.READ_NODE));
+                assertTrue(pp.isGranted(t, prop, Permissions.READ_PROPERTY));
+
+                assertFalse(pp.isGranted(t, null, Permissions.ALL));
+                assertFalse(pp.isGranted(t, prop, Permissions.ALL));
+
+                assertFalse(pp.isGranted(t, null, Permissions.WRITE|Permissions.VERSION_MANAGEMENT|Permissions.READ_ACCESS_CONTROL));
+                assertFalse(pp.isGranted(t, prop, Permissions.SET_PROPERTY|Permissions.VERSION_MANAGEMENT|Permissions.READ_ACCESS_CONTROL));
+
+                String treePath = t.getPath();
+                assertTrue(pp.isGranted(treePath, Session.ACTION_READ));
+                assertTrue(pp.isGranted(PathUtils.concat(treePath, prop.getName()), Session.ACTION_READ));
+
+                String deniedActions = Text.implode(new String[] {Session.ACTION_ADD_NODE, Session.ACTION_SET_PROPERTY, Session.ACTION_REMOVE, JackrabbitSession.ACTION_READ_ACCESS_CONTROL}, ",");
+                assertFalse(pp.isGranted(t.getPath(), deniedActions));
+            }
+
+            assertTrue(pp.isGranted("/path/to/nonexisting/item", Session.ACTION_READ));
+            assertFalse(pp.isGranted("/path/to/nonexisting/item", Session.ACTION_SET_PROPERTY));
+        }
+    }
+
 }
\ No newline at end of file