Author: angela
Date: Tue Mar  3 10:51:54 2015
New Revision: 1663623

URL: http://svn.apache.org/r1663623
Log:
OAK-1268 

Add support for composite authorization setup,
OAK-2008 :  authorization setup for closed user groups

Added:
    
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugValidatorProvider.java
    
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/SupportedPaths.java
    
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugValidatorTest.java
    
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/SupportedPathsTest.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAuthorizationConfigurationTest.java
Removed:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/ControlFlag.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/AbstractCompositeTest.java
Modified:
    
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManager.java
    
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugConfiguration.java
    
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProvider.java
    
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/AbstractCugTest.java
    
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManagerTest.java
    
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugConfigurationTest.java
    
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugEvaluationTest.java
    
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProviderTest.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationConfigurationImpl.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAuthorizationConfiguration.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProvider.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImpl.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/accesscontrol/PolicyOwner.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/AggregatedPermissionProvider.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProvider.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/TreeUtil.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/CompositeTokenConfigurationTest.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAccessControlManagerTest.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProviderTest.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/AbstractCompositeConfigurationTest.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/CompositeConfigurationTest.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProviderTest.java

Modified: 
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManager.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManager.java?rev=1663623&r1=1663622&r2=1663623&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManager.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManager.java
 Tue Mar  3 10:51:54 2015
@@ -42,6 +42,7 @@ import org.apache.jackrabbit.oak.api.Roo
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import 
org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.PolicyOwner;
 import org.apache.jackrabbit.oak.spi.security.authorization.cug.CugPolicy;
 import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
 import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
@@ -62,7 +63,7 @@ import static org.apache.jackrabbit.oak.
  * Implementation of the {@link 
org.apache.jackrabbit.api.security.JackrabbitAccessControlManager}
  * interface that allows to create, modify and remove closed user group 
policies.
  */
-class CugAccessControlManager extends AbstractAccessControlManager implements 
CugConstants {
+class CugAccessControlManager extends AbstractAccessControlManager implements 
CugConstants, PolicyOwner {
 
     private static final Logger log = 
LoggerFactory.getLogger(CugAccessControlManager.class);
 
@@ -124,7 +125,8 @@ class CugAccessControlManager extends Ab
         } else {
             CugPolicy cug = getCugPolicy(oakPath);
             if (cug == null) {
-                return new 
AccessControlPolicyIteratorAdapter(ImmutableSet.of(new CugPolicyImpl(oakPath, 
getNamePathMapper(), principalManager, CugUtil.getImportBehavior(config))));
+                cug = new CugPolicyImpl(oakPath, getNamePathMapper(), 
principalManager, CugUtil.getImportBehavior(config));
+                return new 
AccessControlPolicyIteratorAdapter(ImmutableSet.of(cug));
             } else {
                 return AccessControlPolicyIteratorAdapter.EMPTY;
             }
@@ -190,6 +192,12 @@ class CugAccessControlManager extends Ab
         return new AccessControlPolicy[0];
     }
 
+    //--------------------------------------------------------< PolicyOwner 
>---
+    @Override
+    public boolean defines(@Nullable String absPath, @Nonnull 
AccessControlPolicy accessControlPolicy) {
+        return isValidPolicy(absPath, accessControlPolicy);
+    }
+
     
//--------------------------------------------------------------------------
 
     private boolean isSupportedPath(@Nullable String oakPath) throws 
RepositoryException {
@@ -237,12 +245,16 @@ class CugAccessControlManager extends Ab
         }
     }
 
+    private static boolean isValidPolicy(@Nullable String absPath, @Nonnull 
AccessControlPolicy policy) {
+        return policy instanceof CugPolicyImpl && ((CugPolicyImpl) 
policy).getPath().equals(absPath);
+    }
+
     private static void checkValidPolicy(@Nullable String absPath, @Nonnull 
AccessControlPolicy policy) throws AccessControlException {
         if (!(policy instanceof CugPolicyImpl)) {
             throw new AccessControlException("Unsupported policy 
implementation: " + policy);
         }
 
-        CugPolicy cug = (CugPolicy) policy;
+        CugPolicyImpl cug = (CugPolicyImpl) policy;
         if (!cug.getPath().equals(absPath)) {
             throw new AccessControlException("Path mismatch: Expected " + 
cug.getPath() + ", Found: " + absPath);
         }

Modified: 
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugConfiguration.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugConfiguration.java?rev=1663623&r1=1663622&r2=1663623&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugConfiguration.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugConfiguration.java
 Tue Mar  3 10:51:54 2015
@@ -29,12 +29,12 @@ import javax.jcr.security.AccessControlM
 import javax.security.auth.Subject;
 import javax.security.auth.login.LoginException;
 
+import com.google.common.collect.ImmutableList;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.ConfigurationPolicy;
 import org.apache.felix.scr.annotations.Properties;
 import org.apache.felix.scr.annotations.Property;
-import org.apache.felix.scr.annotations.PropertyOption;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.Service;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
@@ -48,6 +48,8 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.tree.RootFactory;
 import org.apache.jackrabbit.oak.spi.commit.CompositeEditorProvider;
 import org.apache.jackrabbit.oak.spi.commit.EditorHook;
+import org.apache.jackrabbit.oak.spi.commit.MoveTracker;
+import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider;
 import org.apache.jackrabbit.oak.spi.lifecycle.RepositoryInitializer;
 import org.apache.jackrabbit.oak.spi.security.CompositeConfiguration;
 import org.apache.jackrabbit.oak.spi.security.ConfigurationBase;
@@ -58,8 +60,6 @@ import org.apache.jackrabbit.oak.spi.sec
 import org.apache.jackrabbit.oak.spi.security.authentication.SystemSubject;
 import 
org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
 import org.apache.jackrabbit.oak.spi.security.authorization.cug.CugExclude;
-import 
org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregatedPermissionProvider;
-import 
org.apache.jackrabbit.oak.spi.security.authorization.permission.ControlFlag;
 import 
org.apache.jackrabbit.oak.spi.security.authorization.permission.EmptyPermissionProvider;
 import 
org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
 import 
org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
@@ -71,7 +71,7 @@ import org.apache.jackrabbit.oak.spi.xml
 
 @Component(metatype = true,
         label = "CUG Configuration",
-        description = "Component to enable Allows to exclude principal(s) with 
the configured name(s) from CUG evaluation.",
+        description = "Authorization configuration dedicated to setup and 
evaluation 'closed user group' permissions.",
         policy = ConfigurationPolicy.REQUIRE)
 @Service({AuthorizationConfiguration.class, SecurityConfiguration.class})
 @Properties({
@@ -86,15 +86,7 @@ import org.apache.jackrabbit.oak.spi.xml
         @Property(name = CompositeConfiguration.PARAM_RANKING,
                 label = "Ranking",
                 description = "Ranking of this configuration in a setup with 
multiple authorization configurations.",
-                intValue = 200),
-        @Property(name = AggregatedPermissionProvider.PARAM_CONTROL_FLAG,
-                label = "Control Flag",
-                description = "Control flag defining if the permission 
provider is SUFFICIENT or REQUISITE.",
-                options = {
-                        @PropertyOption(name = ControlFlag.SUFFICIENT_NAME, 
value = ControlFlag.SUFFICIENT_NAME),
-                        @PropertyOption(name = ControlFlag.REQUISITE_NAME, 
value = ControlFlag.REQUISITE_NAME)
-                },
-                value = ControlFlag.REQUISITE_NAME)
+                intValue = 200)
 })
 public class CugConfiguration extends ConfigurationBase implements 
AuthorizationConfiguration, CugConstants {
 
@@ -107,6 +99,7 @@ public class CugConfiguration extends Co
     @Reference
     private CugExclude exclude = new CugExclude.Default();
 
+    @SuppressWarnings("UnusedDeclaration")
     public CugConfiguration() {
         super();
     }
@@ -134,8 +127,7 @@ public class CugConfiguration extends Co
         if (!enabled || supportedPaths.length == 0 || 
getExclude().isExcluded(principals)) {
             return EmptyPermissionProvider.getInstance();
         } else {
-            ControlFlag flag = 
ControlFlag.valueOf(params.getConfigValue(AggregatedPermissionProvider.PARAM_CONTROL_FLAG,
 ControlFlag.REQUISITE_NAME));
-            return new CugPermissionProvider(root, principals, supportedPaths, 
flag, getContext());
+            return new CugPermissionProvider(root, principals, supportedPaths, 
getContext());
         }
     }
 
@@ -164,6 +156,12 @@ public class CugConfiguration extends Co
         };
     }
 
+    @Nonnull
+    @Override
+    public List<? extends ValidatorProvider> getValidators(String 
workspaceName, Set<Principal> principals, MoveTracker moveTracker) {
+        return ImmutableList.of(new CugValidatorProvider());
+    }
+
     @Override
     public List<ProtectedItemImporter> getProtectedItemImporters() {
         return Collections.<ProtectedItemImporter>singletonList(new 
CugImporter());
@@ -175,7 +173,7 @@ public class CugConfiguration extends Co
     }
 
     //----------------------------------------------------< SCR Integration 
>---
-
+    @SuppressWarnings("UnusedDeclaration")
     @Activate
     protected void activate() throws IOException, CommitFailedException, 
PrivilegedActionException, RepositoryException {
         ContentSession systemSession = null;
@@ -198,6 +196,7 @@ public class CugConfiguration extends Co
     }
 
     
//--------------------------------------------------------------------------
+    @Nonnull
     private CugExclude getExclude() {
         return (exclude == null) ? new CugExclude.Default() : exclude;
     }

Modified: 
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProvider.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProvider.java?rev=1663623&r1=1663622&r2=1663623&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProvider.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProvider.java
 Tue Mar  3 10:51:54 2015
@@ -22,6 +22,7 @@ import java.util.HashSet;
 import java.util.Set;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import javax.jcr.Session;
 
 import com.google.common.base.Predicates;
@@ -35,14 +36,15 @@ import org.apache.jackrabbit.oak.commons
 import org.apache.jackrabbit.oak.plugins.tree.TreeLocation;
 import org.apache.jackrabbit.oak.spi.security.Context;
 import 
org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregatedPermissionProvider;
-import 
org.apache.jackrabbit.oak.spi.security.authorization.permission.ControlFlag;
 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.authorization.permission.RepositoryPermission;
 import 
org.apache.jackrabbit.oak.spi.security.authorization.permission.TreePermission;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits;
 import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.jackrabbit.oak.plugins.tree.RootFactory;
+import org.apache.jackrabbit.oak.util.TreeUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -62,21 +64,24 @@ class CugPermissionProvider implements P
             PrivilegeConstants.REP_READ_PROPERTIES
     );
 
+    private static final Set<PrivilegeBits> READ_PRIVILEGE_BITS = 
ImmutableSet.of(
+            PrivilegeBits.BUILT_IN.get(PrivilegeConstants.JCR_READ),
+            PrivilegeBits.BUILT_IN.get(PrivilegeConstants.REP_READ_NODES),
+            PrivilegeBits.BUILT_IN.get(PrivilegeConstants.REP_READ_PROPERTIES)
+    );
+
     private final Root root;
     private final Set<String> principalNames;
 
-    private final ControlFlag flag;
     private final Context ctx;
 
-    private final String[] supportedPaths;
-    private final String[] supportedAltPaths;
+    private final SupportedPaths supportedPaths;
 
     private Root immutableRoot;
 
     CugPermissionProvider(@Nonnull Root root,
                           @Nonnull Set<Principal> principals,
                           @Nonnull String[] supportedPaths,
-                          @Nonnull ControlFlag flag,
                           @Nonnull Context ctx) {
         this.root = root;
 
@@ -86,32 +91,22 @@ class CugPermissionProvider implements P
             principalNames.add(p.getName());
         }
 
-        this.flag = flag;
-
-        this.supportedPaths = supportedPaths;
-        supportedAltPaths = new String[supportedPaths.length];
-        int i = 0;
-        for (String p : supportedPaths) {
-            supportedAltPaths[i++] = p + '/';
-        }
-
+        this.supportedPaths = new SupportedPaths(supportedPaths);
         this.ctx = ctx;
     }
 
     //---------------------------------------< AggregatedPermissionProvider 
>---
-
-    public ControlFlag getFlag() {
-        return flag;
-    }
-
+    @Override
     public boolean handles(String path, String jcrAction) {
         return isReadAction(jcrAction) && 
includesCug(immutableRoot.getTree(path), path);
     }
 
-    public boolean handles(Tree tree) {
-        return includesCug(tree, tree.getPath());
+    @Override
+    public boolean handles(@Nonnull Tree tree, PrivilegeBits privilegeBits) {
+        return READ_PRIVILEGE_BITS.contains(privilegeBits) && 
includesCug(tree, tree.getPath());
     }
 
+    @Override
     public boolean handles(Tree tree, long permission) {
         return isRead(permission) && includesCug(tree, tree.getPath());
     }
@@ -125,15 +120,18 @@ class CugPermissionProvider implements P
         }
     }
 
+    @Override
     public boolean handlesRepositoryPermissions() {
         return false;
     }
 
     //-------------------------------------------------< PermissionProvider 
>---
+    @Override
     public void refresh() {
         immutableRoot = RootFactory.createReadOnlyRoot(root);
     }
 
+    @Override
     public Set<String> getPrivileges(Tree tree) {
         if (canRead(tree)) {
             return READ_PRIVILEGE_NAMES;
@@ -142,6 +140,7 @@ class CugPermissionProvider implements P
         }
     }
 
+    @Override
     public boolean hasPrivileges(Tree tree, String... privilegeNames) {
         for (String privilegeName : privilegeNames) {
             if (!READ_PRIVILEGE_NAMES.contains(privilegeName)) {
@@ -151,35 +150,39 @@ class CugPermissionProvider implements P
         return canRead(tree);
     }
 
+    @Override
     public RepositoryPermission getRepositoryPermission() {
         throw new UnsupportedOperationException("Not supported");
     }
 
+    @Override
     public TreePermission getTreePermission(Tree tree, TreePermission 
parentPermission) {
         Tree immutableTree = getImmutableTree(tree);
-        if (ctx.definesContextRoot(immutableTree)) {
+        if (parentPermission == TreePermission.EMPTY && 
!immutableTree.isRoot() || isAcContent(immutableTree, true)) {
             return TreePermission.EMPTY;
         }
+
+        TreePermission tp;
         if (parentPermission instanceof CugTreePermission) {
+            tp =  new CugTreePermission(immutableTree, ((CugTreePermission) 
parentPermission).allow);
             if (hasCug(immutableTree)) {
-                return createCugPermission(immutableTree);
-            } else {
-                return new CugTreePermission(immutableTree, 
((CugTreePermission) parentPermission).allow);
+                // a new (nested) cug starts off here
+                tp = createCugPermission(immutableTree, tp);
             }
-        } else if (parentPermission == TreePermission.EMPTY && 
!immutableTree.isRoot()) {
-            return TreePermission.EMPTY;
         } else {
             String path = immutableTree.getPath();
-            if (includes(path)) {
-                return createCugPermission(immutableTree);
-            } else if (mayContainCug(path)) {
-                return new EmptyCugPermission(immutableTree);
+            if (supportedPaths.includes(path)) {
+                tp =  createCugPermission(immutableTree, null);
+            } else if (supportedPaths.mayContainCug(path)) {
+                tp =  new EmptyCugPermission(immutableTree);
             } else {
-                return TreePermission.EMPTY;
+                tp = TreePermission.EMPTY;
             }
         }
+        return tp;
     }
 
+    @Override
     public boolean isGranted(Tree tree, PropertyState property, long 
permissions) {
         if (isRead(permissions)) {
             return canRead(tree);
@@ -188,9 +191,10 @@ class CugPermissionProvider implements P
         }
     }
 
+    @Override
     public boolean isGranted(String oakPath, String jcrActions) {
         TreeLocation location = TreeLocation.create(immutableRoot, oakPath);
-        boolean isAcContent = ctx.definesLocation(location);
+        boolean isAcContent = isAcContent(location);
         long permissions = Permissions.getPermissions(jcrActions, location, 
isAcContent);
 
         if (isRead(permissions)) {
@@ -221,34 +225,45 @@ class CugPermissionProvider implements P
         return tree.exists() && tree.hasChild(REP_CUG_POLICY);
     }
 
-    private boolean includes(@Nonnull String path) {
-        for (String p : supportedAltPaths) {
-            if (p.startsWith(path)) {
-                return true;
-            }
-        }
-        for (String p : supportedPaths) {
-            if (p.equals(path)) {
-                return true;
-            }
-        }
-        return false;
+    private boolean isAcContent(@Nonnull Tree tree, boolean testForCtxRoot) {
+        // FIXME: this should also take other ac-configurations into 
considerations
+        return (testForCtxRoot) ? ctx.definesContextRoot(tree) : 
ctx.definesTree(tree);
+    }
+
+    private boolean isAcContent(@Nonnull TreeLocation location) {
+        // FIXME: this should also take other ac-configurations into 
considerations
+        return ctx.definesLocation(location);
     }
 
     private boolean includesCug(@Nonnull Tree tree, @Nonnull String path) {
         return getCugRoot(tree, path) != null;
     }
 
+    /**
+     * Returns the {@code tree} that holds a CUG policy in the ancestry of the
+     * given {@code tree} with the specified {@code path} or {@code null} if no
+     * such tree exists and thus no CUG is effective at the specified path.
+     *
+     * @param tree The target tree.
+     * @param path The path of the given target tree.
+     * @return the {@code tree} holding the CUG policy that effects the 
specified
+     * path or {@code null} if no such policy exists.
+     */
     @CheckForNull
     private Tree getCugRoot(@Nonnull Tree tree, @Nonnull String path) {
-        if (!includes(path)) {
+        if (!supportedPaths.includes(path)) {
             return null;
         }
         Tree immutableTree = getImmutableTree(tree);
         if (hasCug(immutableTree)) {
             return immutableTree;
         }
+        String parentPath;
         while (!immutableTree.isRoot()) {
+            parentPath = PathUtils.getParentPath(path);
+            if (!supportedPaths.includes(parentPath)) {
+                break;
+            }
             immutableTree = immutableTree.getParent();
             if (hasCug(immutableTree)) {
                 return immutableTree;
@@ -257,37 +272,29 @@ class CugPermissionProvider implements P
         return null;
     }
 
-    private boolean mayContainCug(@Nonnull String path) {
-        String path2 = path + '/';
-        for (String sp : supportedPaths) {
-            if (path.equals(sp) || sp.startsWith(path2)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     private boolean canRead(@Nonnull Tree tree) {
         Tree immutableTree = getImmutableTree(tree);
-        if (ctx.definesTree(immutableTree)) {
+        if (isAcContent(immutableTree, false)) {
             // cug defining access control content is not accessible
             return false;
         }
         Tree cugRoot = getCugRoot(immutableTree, immutableTree.getPath());
-        return cugRoot != null && createCugPermission(cugRoot).canRead();
+        return cugRoot != null && createCugPermission(cugRoot, null).canRead();
     }
 
+    @Nonnull
     private Tree getImmutableTree(@Nonnull Tree tree) {
-        return immutableRoot.getTree(tree.getPath());
+        return TreeUtil.isReadOnlyTree(tree) ? tree : 
immutableRoot.getTree(tree.getPath());
     }
 
-    private TreePermission createCugPermission(@Nonnull Tree tree) {
+    @Nonnull
+    private TreePermission createCugPermission(@Nonnull Tree tree, @Nullable 
TreePermission fallback) {
         Tree cugTree = tree.getChild(REP_CUG_POLICY);
         if (CugUtil.definesCug(cugTree)) {
-            PropertyState pNameState = 
cugTree.getProperty(REP_PRINCIPAL_NAMES);
-            if (pNameState != null) {
+            PropertyState princNamesState = 
cugTree.getProperty(REP_PRINCIPAL_NAMES);
+            if (princNamesState != null) {
                 boolean allow = false;
-                for (String pName : pNameState.getValue(Type.STRINGS)) {
+                for (String pName : princNamesState.getValue(Type.STRINGS)) {
                     if (principalNames.contains(pName)) {
                         allow = true;
                         break;
@@ -298,10 +305,15 @@ class CugPermissionProvider implements P
                 log.warn("Tree at {0} doesn't represent a valid CUG.", 
cugTree.getPath());
             }
         }
-        return new EmptyCugPermission(tree);
+        return (fallback == null) ? new EmptyCugPermission(tree) : fallback;
     }
 
     
//--------------------------------------------------------------------------
+
+    /**
+     * Same as {@link 
org.apache.jackrabbit.oak.spi.security.authorization.permission.TreePermission#EMPTY}
+     * from a permission point of view but indicating that
+     */
     private final class EmptyCugPermission implements TreePermission {
 
         private Tree tree;
@@ -346,6 +358,9 @@ class CugPermissionProvider implements P
         }
     }
 
+    /**
+     * {@code TreePermission} implementation for all items located with a CUG.
+     */
     private final class CugTreePermission implements TreePermission {
 
         private final Tree tree;

Added: 
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugValidatorProvider.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugValidatorProvider.java?rev=1663623&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugValidatorProvider.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugValidatorProvider.java
 Tue Mar  3 10:51:54 2015
@@ -0,0 +1,93 @@
+/*
+ * 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.spi.security.authorization.cug.impl;
+
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.plugins.nodetype.TypePredicate;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.commit.DefaultValidator;
+import org.apache.jackrabbit.oak.spi.commit.Validator;
+import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider;
+import org.apache.jackrabbit.oak.spi.commit.VisibleValidator;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
+
+import static 
org.apache.jackrabbit.oak.api.CommitFailedException.ACCESS_CONTROL;
+
+class CugValidatorProvider extends ValidatorProvider implements CugConstants {
+
+    private TypePredicate isMixCug;
+
+    @Override
+    protected Validator getRootValidator(NodeState before, NodeState after, 
CommitInfo info) {
+        this.isMixCug = new TypePredicate(after, MIX_REP_CUG_MIXIN);
+        return new CugValidator(after);
+    }
+
+    private static CommitFailedException accessViolation(int code, String 
message) {
+        return new CommitFailedException(ACCESS_CONTROL, code, message);
+    }
+
+    private void validateCugNode(@Nonnull NodeState parent, @Nonnull NodeState 
nodeState) throws CommitFailedException {
+        if 
(!NT_REP_CUG_POLICY.equals(NodeStateUtils.getPrimaryTypeName(nodeState))) {
+            throw accessViolation(21, "Reserved name 'rep:cugPolicy' must only 
be used for nodes of type 'rep:CugPolicy'.");
+        }
+        if (!isMixCug.apply(parent)) {
+            throw accessViolation(22, "Parent node not of mixin type 
'rep:CugMixin'.");
+        }
+    }
+
+    private final class CugValidator extends DefaultValidator {
+        private final NodeState parentAfter;
+
+        private CugValidator(@Nonnull NodeState parentAfter) {
+            this.parentAfter = parentAfter;
+        }
+
+        //------------------------------------------------------< Validator 
>---
+        @Override
+        public void propertyChanged(PropertyState before, PropertyState after) 
throws CommitFailedException {
+            String name = after.getName();
+            if (JcrConstants.JCR_PRIMARYTYPE.equals(name)) {
+                if (NT_REP_CUG_POLICY.equals(before.getValue(Type.STRING)) || 
NT_REP_CUG_POLICY.equals(after.getValue(Type.STRING))) {
+                    throw accessViolation(20, "Attempt to change primary type 
of/to CUG policy.");
+                }
+            }
+        }
+
+        @Override
+        public Validator childNodeAdded(String name, NodeState after) throws 
CommitFailedException {
+            if (REP_CUG_POLICY.equals(name)) {
+                validateCugNode(parentAfter, after);
+            }
+            return new VisibleValidator(new CugValidator(after), true, true);
+        }
+
+        @Override
+        public Validator childNodeChanged(String name, NodeState before, 
NodeState after) throws CommitFailedException {
+            if (after.hasChildNode(REP_CUG_POLICY)) {
+                validateCugNode(after, after.getChildNode(REP_CUG_POLICY));
+            }
+            return new VisibleValidator(new CugValidator(after), true, true);
+        }
+    }
+}
\ No newline at end of file

Added: 
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/SupportedPaths.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/SupportedPaths.java?rev=1663623&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/SupportedPaths.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/SupportedPaths.java
 Tue Mar  3 10:51:54 2015
@@ -0,0 +1,99 @@
+/*
+ * 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.spi.security.authorization.cug.impl;
+
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.oak.commons.PathUtils;
+
+class SupportedPaths {
+
+    private final String[] supportedPaths;
+    private final String[] supportedAltPaths;
+
+    private final boolean includesRootPath;
+
+    SupportedPaths(@Nonnull String[] supportedPaths) {
+        this.supportedPaths = supportedPaths;
+        supportedAltPaths = new String[supportedPaths.length];
+
+        boolean foundRootPath = false;
+        int i = 0;
+        for (String p : supportedPaths) {
+            if (PathUtils.denotesRoot(p)) {
+                foundRootPath = true;
+            } else {
+                supportedAltPaths[i++] = p + '/';
+            }
+        }
+        includesRootPath = foundRootPath;
+    }
+
+    /**
+     * Test if the specified {@code path} is contained in any of the configured
+     * supported paths for CUGs.
+     *
+     * @param path An absolute path.
+     * @return {@code true} if the specified {@code path} is equal to or a
+     * descendant of one of the configured supported paths.
+     */
+    boolean includes(@Nonnull String path) {
+        if (supportedPaths.length == 0) {
+            return false;
+        }
+        if (includesRootPath) {
+            return true;
+        }
+        for (String p : supportedAltPaths) {
+            if (path.startsWith(p)) {
+                return true;
+            }
+        }
+        for (String p : supportedPaths) {
+            if (path.equals(p)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Tests if further evaluation below {@code path} is required as one of the
+     * configured supported paths is a descendant (e.g. there might be CUGs
+     * in the subtree although the specified {@code path} does not directly
+     * support CUGs.
+     *
+     * @param path An absolute path
+     * @return {@code true} if there exists a configured supported path that is
+     * a descendant of the given {@code path}.
+     */
+    boolean mayContainCug(@Nonnull String path) {
+        if (supportedPaths.length == 0) {
+            return false;
+        }
+        if (includesRootPath || PathUtils.denotesRoot(path)) {
+            return true;
+        }
+        String path2 = path + '/';
+        for (String sp : supportedPaths) {
+            if (sp.startsWith(path2)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
\ No newline at end of file

Modified: 
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/AbstractCugTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/AbstractCugTest.java?rev=1663623&r1=1663622&r2=1663623&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/AbstractCugTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/AbstractCugTest.java
 Tue Mar  3 10:51:54 2015
@@ -16,24 +16,65 @@
  */
 package org.apache.jackrabbit.oak.spi.security.authorization.cug.impl;
 
+import java.security.Principal;
 import java.util.Iterator;
 import java.util.Set;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
+import javax.jcr.RepositoryException;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.AccessControlPolicy;
+import javax.jcr.security.AccessControlPolicyIterator;
 
+import com.google.common.collect.ImmutableMap;
 import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
+import 
org.apache.jackrabbit.oak.security.authorization.composite.CompositeAuthorizationConfiguration;
 import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
 import org.apache.jackrabbit.oak.spi.security.SecurityConfiguration;
 import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
 import 
org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
-import 
org.apache.jackrabbit.oak.security.authorization.composite.CompositeAuthorizationConfiguration;
+import org.apache.jackrabbit.oak.spi.security.authorization.cug.CugPolicy;
+import org.apache.jackrabbit.oak.util.NodeUtil;
 
 /**
  * Base class for CUG related test that setup the authorization configuration
  * to expose the CUG specific implementations of {@code AccessControlManager}
  * and {@code PermissionProvider}.
  */
-public class AbstractCugTest extends AbstractSecurityTest {
+public class AbstractCugTest extends AbstractSecurityTest implements 
CugConstants {
+
+    static final String SUPPORTED_PATH = "/content";
+    static final String SUPPORTED_PATH2 = "/content2";
+    static final String UNSUPPORTED_PATH = "/testNode";
+    static final String INVALID_PATH = "/path/to/non/existing/tree";
+
+    static final ConfigurationParameters CUG_CONFIG = 
ConfigurationParameters.of(
+            CugConstants.PARAM_CUG_SUPPORTED_PATHS, new String[] 
{SUPPORTED_PATH, SUPPORTED_PATH2},
+            CugConstants.PARAM_CUG_ENABLED, true);
+
+    @Override
+    public void before() throws Exception {
+        super.before();
+
+        NodeUtil rootNode = new NodeUtil(root.getTree("/"));
+        NodeUtil content = rootNode.addChild("content", 
NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+        content.addChild("subtree", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+        rootNode.addChild("content2", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+        rootNode.addChild("testNode", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+        root.commit();
+    }
+
+    @Override
+    public void after() throws Exception {
+        try {
+            root.getTree(SUPPORTED_PATH).remove();
+            root.getTree(UNSUPPORTED_PATH).remove();
+            root.commit();
+        } finally {
+            super.after();
+        }
+    }
 
     @Override
     protected SecurityProvider getSecurityProvider() {
@@ -43,6 +84,27 @@ public class AbstractCugTest extends Abs
         return securityProvider;
     }
 
+    @Override
+    protected ConfigurationParameters getSecurityConfigParameters() {
+        return ConfigurationParameters.of(ImmutableMap.of(
+                AuthorizationConfiguration.NAME, CUG_CONFIG)
+        );
+    }
+
+    void createCug(@Nonnull String absPath, @Nonnull Principal principal) 
throws RepositoryException {
+        AccessControlManager acMgr = getAccessControlManager(root);
+        AccessControlPolicyIterator it = acMgr.getApplicablePolicies(absPath);
+        while (it.hasNext()) {
+            AccessControlPolicy policy = it.nextAccessControlPolicy();
+            if (policy instanceof CugPolicy) {
+                ((CugPolicy) policy).addPrincipals(principal);
+                acMgr.setPolicy(absPath, policy);
+                return;
+            }
+        }
+        throw new IllegalStateException("Unable to create CUG at " + absPath);
+    }
+
     final class CugSecurityProvider implements SecurityProvider {
 
         private final SecurityProvider base;
@@ -86,8 +148,8 @@ public class AbstractCugTest extends Abs
             T c = base.getConfiguration(configClass);
             if (AuthorizationConfiguration.class == configClass) {
                 CompositeAuthorizationConfiguration composite = new 
CompositeAuthorizationConfiguration(this);
-                composite.addConfiguration((AuthorizationConfiguration) c);
                 composite.addConfiguration(cugConfiguration);
+                composite.addConfiguration((AuthorizationConfiguration) c);
                 return (T) composite;
             } else {
                 return c;

Modified: 
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManagerTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManagerTest.java?rev=1663623&r1=1663622&r2=1663623&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManagerTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManagerTest.java
 Tue Mar  3 10:51:54 2015
@@ -37,13 +37,10 @@ import org.apache.jackrabbit.oak.api.Tre
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
-import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
-import 
org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
 import org.apache.jackrabbit.oak.spi.security.authorization.cug.CugPolicy;
 import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
 import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
 import org.apache.jackrabbit.oak.spi.xml.ImportBehavior;
-import org.apache.jackrabbit.oak.util.NodeUtil;
 import org.apache.jackrabbit.oak.util.TreeUtil;
 import org.junit.Test;
 
@@ -56,42 +53,15 @@ import static org.junit.Assert.fail;
 
 public class CugAccessControlManagerTest extends AbstractCugTest {
 
-    private static final String SUPPORTED_PATH = "/content";
-    private static final String UNSUPPORTED_PATH = "/testNode";
-    private static final String INVALID_PATH = "/path/to/non/existing/tree";
-    private static final ConfigurationParameters CUG_CONFIG = 
ConfigurationParameters.of(CugConstants.PARAM_CUG_SUPPORTED_PATHS, 
SUPPORTED_PATH);
-
     private CugAccessControlManager cugAccessControlManager;
 
     @Override
     public void before() throws Exception {
         super.before();
 
-        NodeUtil rootNode = new NodeUtil(root.getTree("/"));
-        NodeUtil content = rootNode.addChild("content", 
NodeTypeConstants.NT_OAK_UNSTRUCTURED);
-        content.addChild("subtree", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
-        rootNode.addChild("testNode", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
-        root.commit();
-
         cugAccessControlManager = new CugAccessControlManager(root, 
NamePathMapper.DEFAULT, getSecurityProvider());
     }
 
-    @Override
-    public void after() throws Exception {
-        try {
-            root.getTree(SUPPORTED_PATH).remove();
-            root.getTree(UNSUPPORTED_PATH).remove();
-            root.commit();
-        } finally {
-            super.after();
-        }
-    }
-
-    @Override
-    protected ConfigurationParameters getSecurityConfigParameters() {
-        return 
ConfigurationParameters.of(ImmutableMap.of(AuthorizationConfiguration.NAME, 
CUG_CONFIG));
-    }
-
     private CugPolicy createCug(@Nonnull String path) {
         return new CugPolicyImpl(path, NamePathMapper.DEFAULT, 
getPrincipalManager(root), ImportBehavior.ABORT);
     }
@@ -307,6 +277,9 @@ public class CugAccessControlManagerTest
         cugAccessControlManager.removePolicy(SUPPORTED_PATH, 
createCug(SUPPORTED_PATH + "/subtree"));
     }
 
+    /**
+     * An invalid (unsupported) implementation of {@link CugPolicy}.
+     */
     private static final class InvalidCug implements CugPolicy {
 
         private static final InvalidCug INSTANCE = new InvalidCug();

Modified: 
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugConfigurationTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugConfigurationTest.java?rev=1663623&r1=1663622&r2=1663623&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugConfigurationTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugConfigurationTest.java
 Tue Mar  3 10:51:54 2015
@@ -18,7 +18,6 @@ package org.apache.jackrabbit.oak.spi.se
 
 import java.security.Principal;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import javax.jcr.security.AccessControlManager;
 
@@ -59,11 +58,10 @@ public class CugConfigurationTest extend
 
     @Test
     public void testGetPermissionProviderDisabled2() {
-        Map<String, Object> params = ImmutableMap.<String, Object>of(
+        ConfigurationParameters params = ConfigurationParameters.of(
                 CugConstants.PARAM_CUG_ENABLED, false,
                 CugConstants.PARAM_CUG_SUPPORTED_PATHS, "/content");
-        CugConfiguration cc = 
createConfiguration(ConfigurationParameters.of(params));
-
+        CugConfiguration cc = createConfiguration(params);
         PermissionProvider pp = cc.getPermissionProvider(root, "default", 
ImmutableSet.<Principal>of(EveryonePrincipal.getInstance()));
         assertSame(EmptyPermissionProvider.getInstance(), pp);
     }
@@ -87,10 +85,10 @@ public class CugConfigurationTest extend
 
     @Test
     public void testGetPermissionProviderSupportedPaths() {
-        Map<String, Object> params = ImmutableMap.<String, Object>of(
+        ConfigurationParameters params = ConfigurationParameters.of(
                 CugConstants.PARAM_CUG_ENABLED, true,
                 CugConstants.PARAM_CUG_SUPPORTED_PATHS, "/content");
-        CugConfiguration cc = 
createConfiguration(ConfigurationParameters.of(params));
+        CugConfiguration cc = createConfiguration(params);
 
         PermissionProvider pp = cc.getPermissionProvider(root, "default", 
ImmutableSet.<Principal>of(EveryonePrincipal.getInstance()));
         assertTrue(pp instanceof CugPermissionProvider);
@@ -114,10 +112,10 @@ public class CugConfigurationTest extend
 
     @Test
     public void testGetAccessControlManagerSupportedPaths() {
-        Map<String, Object> params = ImmutableMap.<String, Object>of(
+        ConfigurationParameters params = ConfigurationParameters.of(
                 CugConstants.PARAM_CUG_ENABLED, true,
                 CugConstants.PARAM_CUG_SUPPORTED_PATHS, "/content");
-        CugConfiguration cc = 
createConfiguration(ConfigurationParameters.of(params));
+        CugConfiguration cc = createConfiguration(params);
 
         AccessControlManager acMgr = cc.getAccessControlManager(root, 
NamePathMapper.DEFAULT);
         assertTrue(acMgr instanceof CugAccessControlManager);
@@ -125,11 +123,10 @@ public class CugConfigurationTest extend
 
     @Test
     public void testExcludedPrincipals() {
-        Map<String, Object> params = ImmutableMap.<String, Object>of(
+        ConfigurationParameters params = ConfigurationParameters.of(
                 CugConstants.PARAM_CUG_ENABLED, true,
                 CugConstants.PARAM_CUG_SUPPORTED_PATHS, "/content");
-
-        CugConfiguration cc = 
createConfiguration(ConfigurationParameters.of(params));
+        CugConfiguration cc = createConfiguration(params);
 
         List<Principal> excluded = ImmutableList.of(
                 SystemPrincipal.INSTANCE,

Modified: 
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugEvaluationTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugEvaluationTest.java?rev=1663623&r1=1663622&r2=1663623&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugEvaluationTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugEvaluationTest.java
 Tue Mar  3 10:51:54 2015
@@ -16,7 +16,435 @@
  */
 package org.apache.jackrabbit.oak.spi.security.authorization.cug.impl;
 
-public class CugEvaluationTest extends AbstractCugTest {
+import java.security.Principal;
+import java.util.List;
+import java.util.Set;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.security.AccessControlList;
+import javax.jcr.security.AccessControlManager;
 
-    // TODO
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.User;
+import 
org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.ContentSession;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
+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.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.oak.util.NodeUtil;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class CugEvaluationTest extends AbstractCugTest implements 
NodeTypeConstants {
+
+    private static final String TEST_GROUP_ID = "testGroup";
+    private static final String TEST_USER2_ID = "testUser2";
+
+    private ContentSession testSession;
+    private Root testRoot;
+    private Principal testGroupPrincipal;
+
+    @Before
+    @Override
+    public void before() throws Exception {
+        super.before();
+
+        Group testGroup = getUserManager(root).createGroup(TEST_GROUP_ID);
+        testGroupPrincipal = testGroup.getPrincipal();
+        User testUser2 = getUserManager(root).createUser(TEST_USER2_ID, 
TEST_USER2_ID);
+        testGroup.addMember(testUser2);
+        root.commit();
+
+        // add more child nodes
+        NodeUtil n = new NodeUtil(root.getTree(SUPPORTED_PATH));
+        n.addChild("a", NT_OAK_UNSTRUCTURED).addChild("b", 
NT_OAK_UNSTRUCTURED).addChild("c", NT_OAK_UNSTRUCTURED);
+        n.addChild("aa", NT_OAK_UNSTRUCTURED).addChild("bb", 
NT_OAK_UNSTRUCTURED).addChild("cc", NT_OAK_UNSTRUCTURED);
+
+        // create cugs
+        createCug("/content/a", testGroupPrincipal);
+        createCug("/content/aa/bb", testGroupPrincipal);
+        createCug("/content/a/b/c", EveryonePrincipal.getInstance());
+        createCug("/content2", EveryonePrincipal.getInstance());
+
+        // setup regular acl at /content
+        AccessControlManager acMgr = getAccessControlManager(root);
+        AccessControlList acl = AccessControlUtils.getAccessControlList(acMgr, 
"/content");
+        acl.addAccessControlEntry(getTestUser().getPrincipal(), 
privilegesFromNames(
+                PrivilegeConstants.JCR_READ));
+        acl.addAccessControlEntry(testGroupPrincipal, privilegesFromNames(
+                PrivilegeConstants.JCR_READ, PrivilegeConstants.REP_WRITE, 
PrivilegeConstants.JCR_READ_ACCESS_CONTROL)
+        );
+        acMgr.setPolicy("/content", acl);
+
+        root.commit();
+
+        testSession = createTestSession();
+        testRoot = testSession.getLatestRoot();
+    }
+
+    @Override
+    public void after() throws Exception {
+        try {
+            // revert transient pending changes (that might be invalid)
+            root.refresh();
+
+            // remove the test group and second test user
+            Authorizable testGroup = 
getUserManager(root).getAuthorizable(TEST_GROUP_ID);
+            if (testGroup != null) {
+                testGroup.remove();
+            }
+            Authorizable testUser2 = 
getUserManager(root).getAuthorizable(TEST_USER2_ID);
+            if (testUser2 != null) {
+                testUser2.remove();
+            }
+            root.commit();
+        } finally {
+            if (testSession != null) {
+                testSession.close();
+            }
+            super.after();
+        }
+    }
+
+    private PermissionProvider createPermissionProvider(Set<Principal> 
principals) {
+        return 
getSecurityProvider().getConfiguration(AuthorizationConfiguration.class).getPermissionProvider(root,
 adminSession.getWorkspaceName(), principals);
+    }
+
+    @Test
+    public void testRead() throws Exception {
+        List<String> noAccess = ImmutableList.of(
+                "/", UNSUPPORTED_PATH, /* no access */
+                "/content/a", "/content/a/b", "/content/aa/bb", /* granted by 
ace, denied by cug */
+                "/content2"            /* granted by cug only */
+        );
+        for (String p : noAccess) {
+            assertFalse(p, testRoot.getTree(p).exists());
+        }
+
+        List<String> readAccess = ImmutableList.of("/content", 
"/content/subtree", "/content/a/b/c", "/content/aa");
+        for (String p : readAccess) {
+            assertTrue(p, testRoot.getTree(p).exists());
+        }
+    }
+
+    @Test
+    public void testReadAcl() throws Exception {
+        assertFalse(testRoot.getTree("/content/rep:policy").exists());
+    }
+
+    @Test
+    public void testReadAcl2() throws Exception {
+        ContentSession cs = login(new SimpleCredentials(TEST_USER2_ID, 
TEST_USER2_ID.toCharArray()));
+        try {
+            Root r = cs.getLatestRoot();
+
+            assertTrue(r.getTree("/content/rep:policy").exists());
+            assertFalse(r.getTree("/content2/rep:cugPolicy").exists());
+        } finally {
+            cs.close();
+        }
+    }
+
+    @Ignore("FIXME: cugpolicy not detected as ac-content") // FIXME
+    @Test
+    public void testReadCug() throws Exception {
+        List<String> noAccess = ImmutableList.of(
+                "/content/a/rep:cugPolicy", "/content/aa/bb/rep:cugPolicy", 
"/content2/rep:cugPolicy"
+        );
+        for (String p : noAccess) {
+            assertFalse(p, testRoot.getTree(p).exists());
+        }
+    }
+
+    @Test
+    public void testReadCug2() throws Exception {
+        ContentSession cs = login(new SimpleCredentials(TEST_USER2_ID, 
TEST_USER2_ID.toCharArray()));
+        try {
+            Root r = cs.getLatestRoot();
+
+            assertTrue(r.getTree("/content/a/rep:cugPolicy").exists());
+            assertFalse(r.getTree("/content2/rep:cugPolicy").exists());
+        } finally {
+            cs.close();
+        }
+    }
+
+    @Test
+    public void testWrite() throws Exception {
+        List<String> readOnly = ImmutableList.of("/content", "/content/a/b/c");
+        for (String p : readOnly) {
+            try {
+                NodeUtil content = new NodeUtil(testRoot.getTree(p));
+                content.addChild("writeTest", NT_OAK_UNSTRUCTURED);
+                testRoot.commit();
+                fail();
+            } catch (CommitFailedException e) {
+                assertTrue(e.isAccessViolation());
+            } finally {
+                testRoot.refresh();
+            }
+        }
+    }
+
+    @Test
+    public void testWrite2() throws Exception {
+        ContentSession cs = login(new SimpleCredentials(TEST_USER2_ID, 
TEST_USER2_ID.toCharArray()));
+        Root r = cs.getLatestRoot();
+        try {
+            List<String> readOnly = ImmutableList.of("/content", 
"/content/a/b/c");
+            for (String p : readOnly) {
+                NodeUtil content = new NodeUtil(r.getTree(p));
+                content.addChild("writeTest", NT_OAK_UNSTRUCTURED);
+                r.commit();
+            }
+        } finally {
+            r.refresh();
+            cs.close();
+        }
+    }
+
+    @Test
+    public void testWriteAcl() throws Exception {
+        ContentSession cs = login(new SimpleCredentials(TEST_USER2_ID, 
TEST_USER2_ID.toCharArray()));
+        Root r = cs.getLatestRoot();
+        try {
+            Tree tree = r.getTree("/content/a/b/c");
+            tree.setProperty(JCR_MIXINTYPES, 
ImmutableList.of(MIX_REP_CUG_MIXIN, 
AccessControlConstants.MIX_REP_ACCESS_CONTROLLABLE), Type.NAMES);
+            
tree.addChild(AccessControlConstants.REP_POLICY).setProperty(JCR_PRIMARYTYPE, 
AccessControlConstants.NT_REP_ACL, Type.NAME);
+            r.commit();
+            fail();
+        } catch (CommitFailedException e) {
+            assertTrue(e.isAccessViolation());
+        } finally {
+            r.refresh();
+        }
+    }
+
+    @Ignore("FIXME: cugpolicy not detected as ac-content") // FIXME
+    @Test
+    public void testWriteCug() throws Exception {
+        ContentSession cs = login(new SimpleCredentials(TEST_USER2_ID, 
TEST_USER2_ID.toCharArray()));
+        Root r = cs.getLatestRoot();
+        try {
+            // modify the existing cug
+            Tree tree = r.getTree("/content/a/rep:cugPolicy");
+            tree.setProperty(REP_PRINCIPAL_NAMES, 
ImmutableList.of(EveryonePrincipal.NAME, testGroupPrincipal.getName()), 
Type.STRINGS);
+            r.commit();
+            fail();
+        } catch (CommitFailedException e) {
+            assertTrue(e.isAccessViolation());
+        } finally {
+            r.refresh();
+        }
+    }
+
+    @Test
+    public void testIsGranted() throws Exception {
+        Tree content = root.getTree("/content");
+        Tree a = root.getTree("/content/a");
+        Tree c = root.getTree("/content/a/b/c");
+
+        // testGroup
+        Set<Principal> principals = ImmutableSet.of(testGroupPrincipal);
+        PermissionProvider pp = createPermissionProvider(principals);
+
+        assertTrue(pp.isGranted(content, null, Permissions.READ));
+        assertTrue(pp.isGranted(a, null, Permissions.READ));
+        assertFalse(pp.isGranted(c, null, Permissions.READ));
+
+        assertTrue(pp.isGranted(content, null, 
Permissions.READ_ACCESS_CONTROL));
+        assertTrue(pp.isGranted(a, null, Permissions.READ_ACCESS_CONTROL));
+        assertTrue(pp.isGranted(c, null, Permissions.READ_ACCESS_CONTROL));
+
+        // everyone
+        principals = 
ImmutableSet.<Principal>of(EveryonePrincipal.getInstance());
+        pp = createPermissionProvider(principals);
+
+        assertFalse(pp.isGranted(content, null, Permissions.READ));
+        assertFalse(pp.isGranted(a, null, Permissions.READ));
+        assertFalse(pp.isGranted(c, null, Permissions.READ));
+
+        assertFalse(pp.isGranted(content, null, 
Permissions.READ_ACCESS_CONTROL));
+        assertFalse(pp.isGranted(a, null, Permissions.READ_ACCESS_CONTROL));
+        assertFalse(pp.isGranted(c, null, Permissions.READ_ACCESS_CONTROL));
+
+        // testGroup + everyone
+        principals = ImmutableSet.of(testGroupPrincipal, 
EveryonePrincipal.getInstance());
+        pp = createPermissionProvider(principals);
+
+        assertTrue(pp.isGranted(content, null, Permissions.READ));
+        assertTrue(pp.isGranted(a, null, Permissions.READ));
+        assertTrue(pp.isGranted(c, null, Permissions.READ));
+
+        assertTrue(pp.isGranted(content, null, 
Permissions.READ_ACCESS_CONTROL));
+        assertTrue(pp.isGranted(a, null, Permissions.READ_ACCESS_CONTROL));
+        assertTrue(pp.isGranted(c, null, Permissions.READ_ACCESS_CONTROL));
+
+        // testUser + everyone
+        principals = ImmutableSet.of(getTestUser().getPrincipal(), 
EveryonePrincipal.getInstance());
+        pp = createPermissionProvider(principals);
+
+        assertTrue(pp.isGranted(content, null, Permissions.READ));
+        assertFalse(pp.isGranted(a, null, Permissions.READ));
+        assertTrue(pp.isGranted(c, null, Permissions.READ));
+
+        assertFalse(pp.isGranted(content, null, 
Permissions.READ_ACCESS_CONTROL));
+        assertFalse(pp.isGranted(a, null, Permissions.READ_ACCESS_CONTROL));
+        assertFalse(pp.isGranted(c, null, Permissions.READ_ACCESS_CONTROL));
+    }
+
+    @Test
+    public void testHasPrivileges() throws Exception {
+        Tree content = root.getTree("/content");
+        Tree a = root.getTree("/content/a");
+        Tree c = root.getTree("/content/a/b/c");
+
+        // testGroup
+        Set<Principal> principals = ImmutableSet.of(testGroupPrincipal);
+        PermissionProvider pp = createPermissionProvider(principals);
+
+        assertTrue(pp.hasPrivileges(content, PrivilegeConstants.JCR_READ));
+        assertTrue(pp.hasPrivileges(a, PrivilegeConstants.JCR_READ));
+        assertFalse(pp.hasPrivileges(c, PrivilegeConstants.JCR_READ));
+
+        assertTrue(pp.hasPrivileges(content, PrivilegeConstants.REP_WRITE, 
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+        assertTrue(pp.hasPrivileges(a, PrivilegeConstants.REP_WRITE, 
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+        assertTrue(pp.hasPrivileges(c, PrivilegeConstants.REP_WRITE, 
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+
+        // everyone
+        principals = 
ImmutableSet.<Principal>of(EveryonePrincipal.getInstance());
+        pp = createPermissionProvider(principals);
+
+        assertFalse(pp.hasPrivileges(content, PrivilegeConstants.JCR_READ));
+        assertFalse(pp.hasPrivileges(a, PrivilegeConstants.JCR_READ));
+        assertFalse(pp.hasPrivileges(c, PrivilegeConstants.JCR_READ));
+
+        assertFalse(pp.hasPrivileges(content, PrivilegeConstants.REP_WRITE, 
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+        assertFalse(pp.hasPrivileges(a, PrivilegeConstants.REP_WRITE, 
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+        assertFalse(pp.hasPrivileges(c, PrivilegeConstants.REP_WRITE, 
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+
+        // testGroup + everyone
+        principals = ImmutableSet.of(testGroupPrincipal, 
EveryonePrincipal.getInstance());
+        pp = createPermissionProvider(principals);
+
+        assertTrue(pp.hasPrivileges(content, PrivilegeConstants.JCR_READ));
+        assertTrue(pp.hasPrivileges(a, PrivilegeConstants.JCR_READ));
+        assertTrue(pp.hasPrivileges(c, PrivilegeConstants.JCR_READ));
+
+        assertTrue(pp.hasPrivileges(content, PrivilegeConstants.REP_WRITE, 
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+        assertTrue(pp.hasPrivileges(a, PrivilegeConstants.REP_WRITE, 
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+        assertTrue(pp.hasPrivileges(c, PrivilegeConstants.REP_WRITE, 
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+
+        // testUser + everyone
+        principals = ImmutableSet.of(getTestUser().getPrincipal(), 
EveryonePrincipal.getInstance());
+        pp = createPermissionProvider(principals);
+
+        assertTrue(pp.hasPrivileges(content, PrivilegeConstants.JCR_READ));
+        assertFalse(pp.hasPrivileges(a, PrivilegeConstants.JCR_READ));
+        assertTrue(pp.hasPrivileges(c, PrivilegeConstants.JCR_READ));
+
+        assertFalse(pp.hasPrivileges(content, PrivilegeConstants.REP_WRITE, 
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+        assertFalse(pp.hasPrivileges(a, PrivilegeConstants.REP_WRITE, 
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+        assertFalse(pp.hasPrivileges(c, PrivilegeConstants.REP_WRITE, 
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+    }
+
+    @Test
+    public void testHasAllPrivileges() throws Exception {
+        // testGroup
+        Set<Principal> principals = ImmutableSet.of(testGroupPrincipal);
+        PermissionProvider pp = createPermissionProvider(principals);
+
+        assertFalse(pp.hasPrivileges(root.getTree("/content"), 
PrivilegeConstants.JCR_ALL));
+        assertFalse(pp.hasPrivileges(root.getTree("/content/a"), 
PrivilegeConstants.JCR_ALL));
+        assertFalse(pp.hasPrivileges(root.getTree("/content/b/c"), 
PrivilegeConstants.JCR_ALL));
+    }
+
+    @Test
+    public void testHasAllPrivileges2() throws Exception {
+        AccessControlManager acMgr = getAccessControlManager(root);
+        AccessControlList acl = AccessControlUtils.getAccessControlList(acMgr, 
"/content/a");
+        acl.addAccessControlEntry(testGroupPrincipal, 
privilegesFromNames(PrivilegeConstants.JCR_ALL));
+        acMgr.setPolicy("/content/a", acl);
+        root.commit();
+
+        // testGroup
+        Set<Principal> principals = ImmutableSet.of(testGroupPrincipal);
+        PermissionProvider pp = createPermissionProvider(principals);
+
+        assertFalse(pp.hasPrivileges(root.getTree("/content"), 
PrivilegeConstants.JCR_ALL));
+        assertTrue(pp.hasPrivileges(root.getTree("/content/a"), 
PrivilegeConstants.JCR_ALL));
+        assertTrue(pp.hasPrivileges(root.getTree("/content/a/b"), 
PrivilegeConstants.JCR_ALL));
+        assertFalse(pp.hasPrivileges(root.getTree("/content/a/b/c"), 
PrivilegeConstants.JCR_ALL));
+    }
+
+    @Test
+    public void testHasAllPrivileges3() throws Exception {
+        // admin principal
+        Set<Principal> principals = adminSession.getAuthInfo().getPrincipals();
+        PermissionProvider pp = createPermissionProvider(principals);
+
+        assertTrue(pp.hasPrivileges(root.getTree("/content"), 
PrivilegeConstants.JCR_ALL));
+        assertTrue(pp.hasPrivileges(root.getTree("/content/a"), 
PrivilegeConstants.JCR_ALL));
+        assertTrue(pp.hasPrivileges(root.getTree("/content/a/b/c"), 
PrivilegeConstants.JCR_ALL));
+    }
+
+    @Ignore() // FIXME
+    @Test
+    public void testGetPrivileges() throws Exception {
+        Tree content = root.getTree("/content");
+        Tree a = root.getTree("/content/a");
+        Tree c = root.getTree("/content/a/b/c");
+
+        Set<String> r = ImmutableSet.of(PrivilegeConstants.JCR_READ);
+        Set<String> w_rac = ImmutableSet.of(PrivilegeConstants.REP_WRITE, 
PrivilegeConstants.JCR_READ_ACCESS_CONTROL);
+        Set<String> r_w_rac = ImmutableSet.of(PrivilegeConstants.JCR_READ, 
PrivilegeConstants.REP_WRITE, PrivilegeConstants.JCR_READ_ACCESS_CONTROL);
+
+        // testGroup
+        Set<Principal> principals = ImmutableSet.of(testGroupPrincipal);
+        PermissionProvider pp = createPermissionProvider(principals);
+
+        assertEquals(r_w_rac, pp.getPrivileges(content));
+        assertEquals(r_w_rac, pp.getPrivileges(a));
+        assertEquals(w_rac, pp.getPrivileges(c));
+
+        // everyone
+        principals = 
ImmutableSet.<Principal>of(EveryonePrincipal.getInstance());
+        pp = createPermissionProvider(principals);
+
+        assertTrue(pp.getPrivileges(content).isEmpty());
+        assertTrue(pp.getPrivileges(a).isEmpty());
+        assertTrue(pp.getPrivileges(c).isEmpty());
+
+        // testGroup + everyone
+        principals = ImmutableSet.of(testGroupPrincipal, 
EveryonePrincipal.getInstance());
+        pp = createPermissionProvider(principals);
+
+        assertEquals(r_w_rac, pp.getPrivileges(content));
+        assertEquals(r_w_rac, pp.getPrivileges(a));
+        assertEquals(r_w_rac, pp.getPrivileges(c));
+
+        // testUser + everyone
+        principals = ImmutableSet.of(getTestUser().getPrincipal(), 
EveryonePrincipal.getInstance());
+        pp = createPermissionProvider(principals);
+
+        assertEquals(r, pp.getPrivileges(content));
+        assertTrue(pp.getPrivileges(a).isEmpty());
+        assertEquals(r, pp.getPrivileges(c));
+    }
 }
\ No newline at end of file

Modified: 
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProviderTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProviderTest.java?rev=1663623&r1=1663622&r2=1663623&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProviderTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProviderTest.java
 Tue Mar  3 10:51:54 2015
@@ -17,62 +17,337 @@
 package org.apache.jackrabbit.oak.spi.security.authorization.cug.impl;
 
 import java.security.Principal;
-import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.Set;
+import javax.jcr.AccessDeniedException;
+import javax.jcr.Session;
 
-import 
org.apache.jackrabbit.oak.spi.security.authorization.permission.ControlFlag;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
+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.authorization.permission.TreePermission;
+import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.apache.jackrabbit.oak.util.NodeUtil;
 import org.junit.Before;
 import org.junit.Test;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
 
-public class CugPermissionProviderTest extends AbstractCugTest {
+public class CugPermissionProviderTest extends AbstractCugTest implements 
NodeTypeConstants {
 
-    private CugPermissionProvider ppSufficient;
-    private CugPermissionProvider ppRequisite;
+    private static final String TEST_GROUP_ID = "testGroupForCugTest";
+
+    private Principal testGroupPrincipal;
+    private CugPermissionProvider cugPermProvider;
 
     @Before
     @Override
     public void before() throws Exception {
         super.before();
 
-        Set<Principal> principals = Collections.emptySet(); // TODO
-        String[] supportedPaths = new String[0]; // TODO
+        Group testGroup = getUserManager(root).createGroup(TEST_GROUP_ID);
+        root.commit();
+
+        // add more child nodes
+        NodeUtil n = new NodeUtil(root.getTree(SUPPORTED_PATH));
+        n.addChild("a", NT_OAK_UNSTRUCTURED).addChild("b", 
NT_OAK_UNSTRUCTURED).addChild("c", NT_OAK_UNSTRUCTURED);
+        n.addChild("aa", NT_OAK_UNSTRUCTURED).addChild("bb", 
NT_OAK_UNSTRUCTURED).addChild("cc", NT_OAK_UNSTRUCTURED);
+
+        testGroupPrincipal = testGroup.getPrincipal();
+        createCug("/content/a", testGroupPrincipal);
+        createCug("/content/a/b/c", EveryonePrincipal.getInstance());
+        createCug("/content/aa/bb", testGroupPrincipal);
+
+        root.commit();
 
-        ppSufficient = new CugPermissionProvider(root, principals, 
supportedPaths, ControlFlag.SUFFICIENT, CugContext.INSTANCE);
-        ppRequisite = new CugPermissionProvider(root, principals, 
supportedPaths, ControlFlag.REQUISITE, CugContext.INSTANCE);
+        Set<Principal> principals = 
ImmutableSet.of(getTestUser().getPrincipal(), EveryonePrincipal.getInstance());
+        String[] supportedPaths = new String[] {SUPPORTED_PATH};
+
+        cugPermProvider = new CugPermissionProvider(root, principals, 
supportedPaths, CugContext.INSTANCE);
     }
 
-    @Test
-    public void testGetFlag() {
-        assertSame(ControlFlag.SUFFICIENT, ppSufficient.getFlag());
-        assertSame(ControlFlag.REQUISITE, ppRequisite.getFlag());
+    @Override
+    public void after() throws Exception {
+        try {
+            // revert transient pending changes (that might be invalid)
+            root.refresh();
+
+            // remove the test group
+            Authorizable testGroup = 
getUserManager(root).getAuthorizable(TEST_GROUP_ID);
+            if (testGroup != null) {
+                testGroup.remove();
+            }
+            root.commit();
+        } finally {
+            super.after();
+        }
     }
 
     @Test
     public void testHandlesPath() {
-        // TODO
+        Map<String, Boolean> pathMap = new HashMap<String, Boolean>();
+        pathMap.put(SUPPORTED_PATH, false);
+        pathMap.put("/content/a", true);
+        pathMap.put("/content/a/rep:cugPolicy", true);
+        pathMap.put("/content/a/b", true);
+        pathMap.put("/content/a/b/c/jcr:primaryType", true);
+        pathMap.put("/content/aa", false);
+        pathMap.put("/content/aa/bb/cc", true);
+        // paths that may not contain cugs anyway
+        pathMap.put(NODE_TYPES_PATH, false);
+        pathMap.put("/", false);
+        pathMap.put(UNSUPPORTED_PATH, false);
+        pathMap.put(INVALID_PATH, false);
+
+        for (String path : pathMap.keySet()) {
+            boolean expected = pathMap.get(path);
+
+            assertEquals(path, expected, cugPermProvider.handles(path, 
Session.ACTION_READ));
+            assertFalse(cugPermProvider.handles(path, 
Session.ACTION_ADD_NODE));
+        }
     }
 
     @Test
     public void testHandlesTree() {
-        // TODO
+        Map<Tree, Boolean> pathMap = new HashMap<Tree, Boolean>();
+        pathMap.put(root.getTree(SUPPORTED_PATH), false);
+        pathMap.put(root.getTree("/content/a"), true);
+        pathMap.put(root.getTree("/content/a/rep:cugPolicy"), true);
+        pathMap.put(root.getTree("/content/a/b"), true);
+        pathMap.put(root.getTree("/content/a/b/c/jcr:primaryType"), true);
+        pathMap.put(root.getTree("/content/aa"), false);
+        pathMap.put(root.getTree("/content/aa/bb/cc"), true);
+        // paths that may not contain cugs anyway
+        pathMap.put(root.getTree(NODE_TYPES_PATH), false);
+        pathMap.put(root.getTree("/"), false);
+        pathMap.put(root.getTree(UNSUPPORTED_PATH), false);
+        pathMap.put(root.getTree(INVALID_PATH), false);
+
+        for (Tree tree : pathMap.keySet()) {
+            boolean expected = pathMap.get(tree);
+
+            assertEquals(tree.getPath(), expected, 
cugPermProvider.handles(tree, 
PrivilegeBits.BUILT_IN.get(PrivilegeConstants.JCR_READ)));
+            assertEquals(tree.getPath(), expected, 
cugPermProvider.handles(tree, Permissions.READ));
+            assertEquals(tree.getPath(), expected, 
cugPermProvider.handles(tree, Permissions.READ_PROPERTY));
+            assertEquals(tree.getPath(), expected, 
cugPermProvider.handles(tree, Permissions.READ_NODE));
+
+            assertFalse(cugPermProvider.handles(tree, 
Permissions.ADD_NODE|Permissions.REMOVE));
+        }
+    }
+
+    @Test
+    public void testHandlesTreePermission() {
+        TreePermission rootTp = 
cugPermProvider.getTreePermission(root.getTree("/"), TreePermission.EMPTY);
+
+        Map<TreePermission, Boolean> tpMap = new HashMap<TreePermission, 
Boolean>();
+
+        TreePermission contentTp = 
cugPermProvider.getTreePermission(root.getTree(SUPPORTED_PATH), rootTp);
+        tpMap.put(contentTp, false);
+
+        TreePermission aTp = 
cugPermProvider.getTreePermission(root.getTree("/content/a"), contentTp);
+        tpMap.put(aTp, true);
+        
tpMap.put(cugPermProvider.getTreePermission(root.getTree("/content/a/rep:cugPolicy"),
 aTp), true);
+
+        TreePermission bTp = 
cugPermProvider.getTreePermission(root.getTree("/content/a/b"), aTp);
+        tpMap.put(bTp, true);
+        
tpMap.put(cugPermProvider.getTreePermission(root.getTree("/content/a/b/c"), 
bTp), true);
+
+        TreePermission aaTp = 
cugPermProvider.getTreePermission(root.getTree("/content/aa"), contentTp);
+        tpMap.put(aaTp, false);
+
+        TreePermission bbTp = 
cugPermProvider.getTreePermission(root.getTree("/content/aa/bb"), aaTp);
+        
tpMap.put(cugPermProvider.getTreePermission(root.getTree("/content/aa/bb/cc"), 
bbTp), true);
+
+        // paths that may not contain cugs anyway
+        
tpMap.put(cugPermProvider.getTreePermission(root.getTree("/jcr:system"), 
rootTp), false);
+        tpMap.put(rootTp, false);
+        
tpMap.put(cugPermProvider.getTreePermission(root.getTree(UNSUPPORTED_PATH), 
rootTp), false);
+
+        for (TreePermission tp : tpMap.keySet()) {
+            boolean expected = tpMap.get(tp);
+
+            assertEquals(expected, cugPermProvider.handles(tp, 
Permissions.READ));
+            assertEquals(expected, cugPermProvider.handles(tp, 
Permissions.READ_NODE));
+            assertEquals(expected, cugPermProvider.handles(tp, 
Permissions.READ_PROPERTY));
+
+            assertFalse(cugPermProvider.handles(tp, 
Permissions.ADD_NODE|Permissions.REMOVE));
+        }
     }
 
     @Test
     public void testHandlesRepositoryPermissions() {
-        assertFalse(ppSufficient.handlesRepositoryPermissions());
-        assertFalse(ppRequisite.handlesRepositoryPermissions());
+        assertFalse(cugPermProvider.handlesRepositoryPermissions());
     }
 
     @Test
     public void getPrivileges() {
-        // TODO
+        List<String> paths = ImmutableList.of("/", UNSUPPORTED_PATH,
+                "/content", "/content/a", "/content/a/b",
+                "/content/aa", "/content/bb", "/content/aa/bb/rep:cugPolicy");
+        for (String p : paths) {
+            
assertTrue(cugPermProvider.getPrivileges(root.getTree(p)).isEmpty());
+        }
     }
 
     @Test
-    public void hasPrivileges() {
-        // TODO
+    public void testGetPrivilegesAtCug() {
+        Set<String> expected = ImmutableSet.of(
+                        PrivilegeConstants.JCR_READ,
+                        PrivilegeConstants.REP_READ_NODES,
+                        PrivilegeConstants.REP_READ_PROPERTIES);
+        assertEquals(expected, 
cugPermProvider.getPrivileges(root.getTree("/content/a/b/c")));
+    }
+
+    @Test
+    public void testGetPrivilegesAtCug2() {
+        PermissionProvider pp = new CugPermissionProvider(root, 
ImmutableSet.of(testGroupPrincipal), new String[] {SUPPORTED_PATH}, 
CugContext.INSTANCE);
+
+        Set<String> expected = ImmutableSet.of(
+                PrivilegeConstants.JCR_READ,
+                PrivilegeConstants.REP_READ_NODES,
+                PrivilegeConstants.REP_READ_PROPERTIES);
+        assertEquals(expected, pp.getPrivileges(root.getTree("/content/a")));
+        assertEquals(expected, 
pp.getPrivileges(root.getTree("/content/aa/bb")));
+
+        assertTrue(pp.getPrivileges(root.getTree("/content/a/b/c")).isEmpty());
+    }
+
+    @Test
+    public void hasReadPrivileges() {
+        List<String> paths = ImmutableList.of("/", UNSUPPORTED_PATH,
+                "/content", "/content/a", "/content/a/b",
+                "/content/aa", "/content/bb", "/content/aa/bb/rep:cugPolicy");
+        for (String p : paths) {
+            Tree tree = root.getTree(p);
+            assertFalse(cugPermProvider.hasPrivileges(tree, 
PrivilegeConstants.JCR_READ));
+            assertFalse(cugPermProvider.hasPrivileges(tree, 
PrivilegeConstants.REP_READ_NODES));
+            assertFalse(cugPermProvider.hasPrivileges(tree, 
PrivilegeConstants.REP_READ_PROPERTIES));
+            assertFalse(cugPermProvider.hasPrivileges(tree, 
PrivilegeConstants.REP_READ_NODES, PrivilegeConstants.REP_READ_PROPERTIES));
+        }
+
+        Tree cugTree = root.getTree("/content/a/b/c");
+        assertTrue(cugPermProvider.hasPrivileges(cugTree, 
PrivilegeConstants.JCR_READ));
+        assertTrue(cugPermProvider.hasPrivileges(cugTree, 
PrivilegeConstants.REP_READ_NODES));
+        assertTrue(cugPermProvider.hasPrivileges(cugTree, 
PrivilegeConstants.REP_READ_PROPERTIES));
+        assertTrue(cugPermProvider.hasPrivileges(cugTree, 
PrivilegeConstants.REP_READ_NODES, PrivilegeConstants.REP_READ_PROPERTIES));
+    }
+
+    @Test
+    public void hasNonReadPrivileges() {
+        List<String> paths = ImmutableList.of("/", UNSUPPORTED_PATH,
+                "/content", "/content/a", "/content/a/b", "/content/a/b/c",
+                "/content/aa", "/content/bb", "/content/aa/bb/rep:cugPolicy");
+        for (String p : paths) {
+            Tree tree = root.getTree(p);
+            assertFalse(cugPermProvider.hasPrivileges(tree, 
PrivilegeConstants.JCR_WRITE));
+            assertFalse(cugPermProvider.hasPrivileges(tree, 
PrivilegeConstants.JCR_LIFECYCLE_MANAGEMENT));
+            assertFalse(cugPermProvider.hasPrivileges(tree, 
PrivilegeConstants.JCR_READ, PrivilegeConstants.JCR_LIFECYCLE_MANAGEMENT));
+            assertFalse(cugPermProvider.hasPrivileges(tree, 
PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+            assertFalse(cugPermProvider.hasPrivileges(tree, 
PrivilegeConstants.JCR_ALL));
+        }
+    }
+
+    @Test
+    public void testIsGrantedRead() {
+        List<String> paths = ImmutableList.of("/", UNSUPPORTED_PATH,
+                "/content", "/content/a", "/content/a/b",
+                "/content/aa", "/content/bb", "/content/aa/bb/rep:cugPolicy");
+        for (String p : paths) {
+            Tree tree = root.getTree(p);
+            assertFalse(cugPermProvider.isGranted(tree, null, 
Permissions.READ));
+            assertFalse(cugPermProvider.isGranted(tree, 
tree.getProperty(JCR_PRIMARYTYPE), Permissions.READ_PROPERTY));
+        }
+
+        Tree cugTree = root.getTree("/content/a/b/c");
+        assertTrue(cugPermProvider.isGranted(cugTree, null, Permissions.READ));
+        assertTrue(cugPermProvider.isGranted(cugTree, null, 
Permissions.READ_NODE));
+        assertTrue(cugPermProvider.isGranted(cugTree, 
cugTree.getProperty(JCR_PRIMARYTYPE), Permissions.READ_PROPERTY));
+    }
+
+    @Test
+    public void testIsGrantedNonRead() {
+        List<String> paths = ImmutableList.of("/", UNSUPPORTED_PATH,
+                        "/content", "/content/a", "/content/a/b", 
"/content/a/b/c",
+                        "/content/aa", "/content/bb", 
"/content/aa/bb/rep:cugPolicy");
+        for (String p : paths) {
+            Tree tree = root.getTree(p);
+            assertFalse(cugPermProvider.isGranted(tree, null, 
Permissions.ALL));
+            assertFalse(cugPermProvider.isGranted(tree, null, 
Permissions.READ|Permissions.READ_ACCESS_CONTROL));
+            assertFalse(cugPermProvider.isGranted(tree, null, 
Permissions.REMOVE_NODE));
+        }
+    }
+
+    @Test
+    public void testIsGrantedJcrActions() {
+        List<String> paths = ImmutableList.of("/", UNSUPPORTED_PATH,
+                "/content", "/content/a", "/content/a/b",
+                "/content/aa", "/content/bb", "/content/aa/bb/rep:cugPolicy");
+        for (String p : paths) {
+            assertFalse(cugPermProvider.isGranted(p, Session.ACTION_READ));
+            assertFalse(cugPermProvider.isGranted(p, Session.ACTION_ADD_NODE));
+            assertFalse(cugPermProvider.isGranted(p, Session.ACTION_READ + ',' 
+ Session.ACTION_ADD_NODE));
+        }
+
+        assertTrue(cugPermProvider.isGranted("/content/a/b/c", 
Session.ACTION_READ));
+        assertFalse(cugPermProvider.isGranted("/content/a/b/c", 
Session.ACTION_ADD_NODE));
+        assertFalse(cugPermProvider.isGranted("/content/a/b/c", 
Session.ACTION_READ + ',' + Session.ACTION_ADD_NODE));
+    }
+
+    @Test
+    public void testGetTreePermissions() throws AccessDeniedException {
+        TreePermission rootTp = 
cugPermProvider.getTreePermission(root.getTree("/"), TreePermission.EMPTY);
+        assertTrue(rootTp.getClass().getName().endsWith("EmptyCugPermission"));
+
+        TreePermission contentTp = 
cugPermProvider.getTreePermission(root.getTree(SUPPORTED_PATH), rootTp);
+        
assertTrue(contentTp.getClass().getName().endsWith("EmptyCugPermission"));
+
+        TreePermission aTp = 
cugPermProvider.getTreePermission(root.getTree("/content/a"), contentTp);
+        assertTrue(aTp.getClass().getName().endsWith("CugTreePermission"));
+
+        TreePermission bTp = 
cugPermProvider.getTreePermission(root.getTree("/content/a/b"), aTp);
+        assertTrue(bTp.getClass().getName().endsWith("CugTreePermission"));
+
+        TreePermission cTp = 
cugPermProvider.getTreePermission(root.getTree("/content/a/b/c"), bTp);
+        assertTrue(cTp.getClass().getName().endsWith("CugTreePermission"));
+
+        TreePermission aaTp = 
cugPermProvider.getTreePermission(root.getTree("/content/aa"), contentTp);
+        assertTrue(aaTp.getClass().getName().endsWith("EmptyCugPermission"));
+
+        TreePermission bbTp = 
cugPermProvider.getTreePermission(root.getTree("/content/aa/bb"), aaTp);
+        assertTrue(bbTp.getClass().getName().endsWith("CugTreePermission"));
+
+        TreePermission ccTp = 
cugPermProvider.getTreePermission(root.getTree("/content/aa/bb/cc"), bbTp);
+        assertTrue(ccTp.getClass().getName().endsWith("CugTreePermission"));
+
+        // false cug-policy node (wrong nt)
+        Tree aaTree = root.getTree("/content/aa");
+        new NodeUtil(aaTree).addChild(CugConstants.REP_CUG_POLICY, 
NT_OAK_UNSTRUCTURED);
+        TreePermission aaTp2 = 
cugPermProvider.getTreePermission(root.getTree("/content/aa"), contentTp);
+        assertTrue(aaTp2.getClass().getName().endsWith("EmptyCugPermission"));
+
+        TreePermission falseCugTp = 
cugPermProvider.getTreePermission(root.getTree("/content/aa/rep:cugPolicy"), 
aaTp2);
+        assertNotSame(TreePermission.EMPTY, falseCugTp);
+
+        // ac content
+        TreePermission cugTp = 
cugPermProvider.getTreePermission(root.getTree("/content/a/rep:cugPolicy"), 
aTp);
+        assertSame(TreePermission.EMPTY, cugTp);
+        // TODO: for regular acl-node
+
+        // paths that may not contain cugs anyway
+        assertSame(TreePermission.EMPTY, 
cugPermProvider.getTreePermission(root.getTree("/jcr:system"), rootTp));
+        assertSame(TreePermission.EMPTY, 
cugPermProvider.getTreePermission(root.getTree(UNSUPPORTED_PATH), rootTp));
     }
 }
\ No newline at end of file


Reply via email to