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/19 15:22:47 UTC

svn commit: r1829562 [1/2] - in /jackrabbit/oak/trunk/oak-exercise/src: main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/ main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/readonly/ main/jav...

Author: angela
Date: Thu Apr 19 15:22:47 2018
New Revision: 1829562

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

Added:
    jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/
    jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/PredefinedAuthorizationConfiguration.java   (with props)
    jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/PredefinedPermissionProvider.java   (with props)
    jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/
    jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/Role.java   (with props)
    jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesAccessControlManager.java   (with props)
    jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesAuthorizationConfiguration.java   (with props)
    jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesConstants.java   (with props)
    jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesPermissionProvider.java   (with props)
    jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesTreePermission.java   (with props)
    jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/Utils.java   (with props)
    jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/advanced/L4_CustomAccessControlManagementTest.java
      - copied, changed from r1829512, jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/advanced/L5_CustomAccessControlManagementTest.java
    jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/advanced/L5_CustomPermissionEvaluationTest.java
      - copied, changed from r1829512, jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/advanced/L6_CustomPermissionEvaluationTest.java
Removed:
    jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/advanced/L4_CustomAuthorizationTest.java
    jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/advanced/L5_CustomAccessControlManagementTest.java
    jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/advanced/L6_CustomPermissionEvaluationTest.java
Modified:
    jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/readonly/ReadOnlyAuthorizationConfiguration.java
    jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/principal/CustomPrincipalConfiguration.java
    jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/principal/CustomPrincipalProvider.java
    jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/advanced/L2_SetupAggregationTest.java

Added: jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/PredefinedAuthorizationConfiguration.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/PredefinedAuthorizationConfiguration.java?rev=1829562&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/PredefinedAuthorizationConfiguration.java (added)
+++ jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/PredefinedAuthorizationConfiguration.java Thu Apr 19 15:22:47 2018
@@ -0,0 +1,128 @@
+/*
+ * 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 java.util.Collections;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.jcr.security.AccessControlException;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.AccessControlPolicy;
+import javax.jcr.security.AccessControlPolicyIterator;
+
+import com.google.common.collect.ImmutableSet;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlPolicy;
+import org.apache.jackrabbit.commons.iterator.AccessControlPolicyIteratorAdapter;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.spi.security.CompositeConfiguration;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationBase;
+import org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
+import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AbstractAccessControlManager;
+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.restriction.RestrictionProvider;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+
+import static org.apache.jackrabbit.oak.spi.security.RegistrationConstants.OAK_SECURITY_NAME;
+
+@Component(metatype = true, policy = org.apache.felix.scr.annotations.ConfigurationPolicy.REQUIRE)
+@Service({AuthorizationConfiguration.class, org.apache.jackrabbit.oak.spi.security.SecurityConfiguration.class})
+@Properties({
+        @Property(name = CompositeConfiguration.PARAM_RANKING,
+                label = "Ranking",
+                description = "Ranking of this configuration in a setup with multiple authorization configurations.",
+                intValue = 400),
+        @Property(name = OAK_SECURITY_NAME,
+                propertyPrivate = true,
+                value = "org.apache.jackrabbit.oak.exercise.security.authorization.models.predefined.PredefinedAuthorizationConfiguration")
+})
+public final class PredefinedAuthorizationConfiguration extends ConfigurationBase implements AuthorizationConfiguration {
+
+    private static final long READ_PERMISSIONS = Permissions.READ | Permissions.READ_ACCESS_CONTROL;
+    private static final Set<String> READ_PRIVILEGE_NAMES = ImmutableSet.of(PrivilegeConstants.JCR_READ, PrivilegeConstants.JCR_READ_ACCESS_CONTROL, PrivilegeConstants.REP_READ_NODES, PrivilegeConstants.REP_READ_PROPERTIES);
+
+    @Nonnull
+    @Override
+    public AccessControlManager getAccessControlManager(@Nonnull Root root, @Nonnull NamePathMapper namePathMapper) {
+        return new AbstractAccessControlManager(root, namePathMapper, getSecurityProvider()) {
+
+            @Override
+            public AccessControlPolicy[] getPolicies(String absPath) {
+                return new AccessControlPolicy[0];
+            }
+
+            @Override
+            public AccessControlPolicy[] getEffectivePolicies(String absPath) {
+                return new AccessControlPolicy[0];
+            }
+
+            @Override
+            public AccessControlPolicyIterator getApplicablePolicies(String absPath) {
+                return new AccessControlPolicyIteratorAdapter(Collections.emptyIterator());
+            }
+
+            @Override
+            public void setPolicy(String absPath, AccessControlPolicy policy) throws AccessControlException {
+                throw new AccessControlException();
+            }
+
+            @Override
+            public void removePolicy(String absPath, AccessControlPolicy policy) throws AccessControlException {
+                throw new AccessControlException();
+            }
+
+            @Override
+            public JackrabbitAccessControlPolicy[] getApplicablePolicies(Principal principal) {
+                return new JackrabbitAccessControlPolicy[0];
+            }
+
+            @Override
+            public JackrabbitAccessControlPolicy[] getPolicies(Principal principal) {
+                return new JackrabbitAccessControlPolicy[0];
+            }
+
+            @Override
+            public AccessControlPolicy[] getEffectivePolicies(Set<Principal> set) {
+                return new AccessControlPolicy[0];
+            }
+        };
+    }
+
+    @Nonnull
+    @Override
+    public RestrictionProvider getRestrictionProvider() {
+        return RestrictionProvider.EMPTY;
+    }
+
+    @Nonnull
+    @Override
+    public PermissionProvider getPermissionProvider(@Nonnull Root root, @Nonnull String workspaceName, @Nonnull Set<Principal> principals) {
+        return new PredefinedPermissionProvider(principals);
+    }
+
+    @Nonnull
+    @Override
+    public String getName() {
+        return AuthorizationConfiguration.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/PredefinedAuthorizationConfiguration.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 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=1829562&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/PredefinedPermissionProvider.java (added)
+++ jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/predefined/PredefinedPermissionProvider.java Thu Apr 19 15:22:47 2018
@@ -0,0 +1,82 @@
+/*
+ * 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 java.util.Set;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+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;
+
+class PredefinedPermissionProvider implements PermissionProvider {
+
+    private final Set<Principal> principals;
+
+    PredefinedPermissionProvider(@Nonnull Set<Principal> principals) {
+        this.principals = principals;
+    }
+
+    @Override
+    public void refresh() {
+        // TODO
+
+    }
+
+    @Nonnull
+    @Override
+    public Set<String> getPrivileges(@Nullable Tree tree) {
+        // TODO
+        return null;
+    }
+
+    @Override
+    public boolean hasPrivileges(@Nullable Tree tree, @Nonnull String... privilegeNames) {
+        // TODO
+        return false;
+    }
+
+    @Nonnull
+    @Override
+    public RepositoryPermission getRepositoryPermission() {
+        // TODO
+        return null;
+    }
+
+    @Nonnull
+    @Override
+    public TreePermission getTreePermission(@Nonnull Tree tree, @Nonnull TreePermission parentPermission) {
+        // TODO
+        return null;
+    }
+
+    @Override
+    public boolean isGranted(@Nonnull Tree tree, @Nullable PropertyState property, long permissions) {
+        // TODO
+        return false;
+    }
+
+    @Override
+    public boolean isGranted(@Nonnull String oakPath, @Nonnull String jcrActions) {
+        // TODO
+        return false;
+    }
+}
\ No newline at end of file

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

Modified: jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/readonly/ReadOnlyAuthorizationConfiguration.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/readonly/ReadOnlyAuthorizationConfiguration.java?rev=1829562&r1=1829561&r2=1829562&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/readonly/ReadOnlyAuthorizationConfiguration.java (original)
+++ jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/readonly/ReadOnlyAuthorizationConfiguration.java Thu Apr 19 15:22:47 2018
@@ -31,6 +31,9 @@ import javax.jcr.security.NamedAccessCon
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlPolicy;
 import org.apache.jackrabbit.commons.iterator.AccessControlPolicyIteratorAdapter;
 import org.apache.jackrabbit.oak.api.PropertyState;
@@ -45,6 +48,7 @@ import org.apache.jackrabbit.oak.spi.com
 import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider;
 import org.apache.jackrabbit.oak.spi.lifecycle.RepositoryInitializer;
 import org.apache.jackrabbit.oak.spi.lifecycle.WorkspaceInitializer;
+import org.apache.jackrabbit.oak.spi.security.CompositeConfiguration;
 import org.apache.jackrabbit.oak.spi.security.ConfigurationBase;
 import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
 import org.apache.jackrabbit.oak.spi.security.Context;
@@ -64,7 +68,6 @@ import org.apache.jackrabbit.oak.spi.sec
 import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.jackrabbit.oak.spi.xml.ProtectedItemImporter;
-import org.osgi.service.component.annotations.Component;
 
 import static org.apache.jackrabbit.oak.spi.security.RegistrationConstants.OAK_SECURITY_NAME;
 
@@ -127,7 +130,10 @@ import static org.apache.jackrabbit.oak.
  *
  * <h2>Configuration</h2>
  *
- * This model doesn't come with any configuration options.
+ * This model comes with a single mandatory configurable property:
+ *
+ * - configurationRanking : {@link  CompositeConfiguration#PARAM_RANKING}, no default value.
+ *
  *
  * <h2>Installation Instructions</h2>
  *
@@ -135,6 +141,7 @@ import static org.apache.jackrabbit.oak.
  *
  * <ul>
  *     <li>Upload the oak-exercise bundle</li>
+ *     <li>Edit configuration of 'ReadOnlyAuthorizationConfiguration' specifying the mandatory ranking property</li>
  *     <li>Edit configuration of {@link org.apache.jackrabbit.oak.security.internal.SecurityProviderRegistration}
  *     <ul>
  *         <li>add {@code org.apache.jackrabbit.oak.exercise.security.authorization.models.readonly.ReadOnlyAuthorizationConfiguration}
@@ -146,10 +153,17 @@ import static org.apache.jackrabbit.oak.
  * </ul>
  *
  */
-@Component(
-        service = {AuthorizationConfiguration.class, SecurityConfiguration.class},
-        immediate = true,
-        property = OAK_SECURITY_NAME + "=org.apache.jackrabbit.oak.exercise.security.authorization.models.readonly.ReadOnlyAuthorizationConfiguration")
+@org.apache.felix.scr.annotations.Component(metatype = true, policy = org.apache.felix.scr.annotations.ConfigurationPolicy.REQUIRE)
+@Service({AuthorizationConfiguration.class, org.apache.jackrabbit.oak.spi.security.SecurityConfiguration.class})
+@Properties({
+        @Property(name = CompositeConfiguration.PARAM_RANKING,
+                label = "Ranking",
+                description = "Ranking of this configuration in a setup with multiple authorization configurations.",
+                intValue = 300),
+        @Property(name = OAK_SECURITY_NAME,
+                propertyPrivate = true,
+                value = "org.apache.jackrabbit.oak.exercise.security.authorization.models.readonly.ReadOnlyAuthorizationConfiguration")
+})
 public final class ReadOnlyAuthorizationConfiguration extends ConfigurationBase implements AuthorizationConfiguration {
 
     private static final long READ_PERMISSIONS = Permissions.READ | Permissions.READ_ACCESS_CONTROL;

Added: jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/Role.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/Role.java?rev=1829562&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/Role.java (added)
+++ jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/Role.java Thu Apr 19 15:22:47 2018
@@ -0,0 +1,56 @@
+/*
+ * 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.simplifiedroles;
+
+import java.util.Set;
+import javax.annotation.Nonnull;
+
+import com.google.common.collect.ImmutableSet;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+
+final class Role {
+    static final Role NONE = new Role(Permissions.NO_PERMISSION);
+    static final Role READER = new Role(Permissions.READ, PrivilegeConstants.JCR_READ);
+    static final Role EDITOR = new Role(READER,
+            Permissions.WRITE|Permissions.MODIFY_CHILD_NODE_COLLECTION|Permissions.NODE_TYPE_MANAGEMENT|Permissions.VERSION_MANAGEMENT,
+            PrivilegeConstants.REP_WRITE, PrivilegeConstants.JCR_VERSION_MANAGEMENT);
+    static final Role OWNER = new Role(EDITOR,
+            Permissions.READ_ACCESS_CONTROL|Permissions.MODIFY_ACCESS_CONTROL,
+            PrivilegeConstants.JCR_READ_ACCESS_CONTROL, PrivilegeConstants.JCR_MODIFY_ACCESS_CONTROL);
+
+    private final long permissions;
+    private final Set<String> privilegeNames;
+
+    private Role(long permissions, String... privilegeNames) {
+        this.permissions = permissions;
+        this.privilegeNames = ImmutableSet.copyOf(privilegeNames);
+    }
+
+    private Role(@Nonnull Role base, long permissions, String... privilegeNames) {
+        this.permissions = base.permissions|permissions;
+        this.privilegeNames = ImmutableSet.<String>builder().addAll(base.privilegeNames).add(privilegeNames).build();
+    }
+
+    boolean grants(long permissions) {
+        return Permissions.includes(this.permissions, permissions);
+    }
+
+    Set<String> getPrivilegeNames() {
+        return privilegeNames;
+    }
+}

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

Added: 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=1829562&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesAccessControlManager.java (added)
+++ jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesAccessControlManager.java Thu Apr 19 15:22:47 2018
@@ -0,0 +1,111 @@
+/*
+ * 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.simplifiedroles;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.jcr.AccessDeniedException;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.RepositoryException;
+import javax.jcr.lock.LockException;
+import javax.jcr.security.AccessControlException;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.AccessControlPolicy;
+import javax.jcr.security.AccessControlPolicyIterator;
+import javax.jcr.security.Privilege;
+import javax.jcr.version.VersionException;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.jackrabbit.commons.iterator.AccessControlPolicyIteratorAdapter;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
+import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.PolicyOwner;
+
+class ThreeRolesAccessControlManager implements PolicyOwner, AccessControlManager {
+
+    private final String supportedPath;
+
+    ThreeRolesAccessControlManager(@Nonnull Root root, @Nonnull String supportedPath, @Nonnull SecurityProvider securityProvider) {
+        this.supportedPath = supportedPath;
+        // TODO
+    }
+
+    @Override
+    public Privilege[] getSupportedPrivileges(String absPath) throws PathNotFoundException, RepositoryException {
+        // TODO
+        return new Privilege[0];
+    }
+
+    @Override
+    public Privilege privilegeFromName(String privilegeName) throws AccessControlException, RepositoryException {
+        // TODO
+        return null;
+    }
+
+    @Override
+    public boolean hasPrivileges(String absPath, Privilege[] privileges) throws PathNotFoundException, RepositoryException {
+        // TODO
+        return false;
+    }
+
+    @Override
+    public Privilege[] getPrivileges(String absPath) throws PathNotFoundException, RepositoryException {
+        // TODO
+        return new Privilege[0];
+    }
+
+    /**
+     * See {@code L5_CustomAccessControlManagementTest.testGetPolicies}
+     */
+    @Override
+    public AccessControlPolicy[] getPolicies(String absPath) throws PathNotFoundException, AccessDeniedException, RepositoryException {
+        // TODO
+        return new AccessControlPolicy[0];
+    }
+
+    @Override
+    public AccessControlPolicy[] getEffectivePolicies(String absPath) throws PathNotFoundException, AccessDeniedException, RepositoryException {
+        // TODO
+        return new AccessControlPolicy[0];
+    }
+
+    @Override
+    public AccessControlPolicyIterator getApplicablePolicies(String absPath) throws PathNotFoundException, AccessDeniedException, RepositoryException {
+        // TODO
+        return new AccessControlPolicyIteratorAdapter(ImmutableList.of());
+    }
+
+    @Override
+    public void setPolicy(String absPath, AccessControlPolicy policy) throws PathNotFoundException, AccessControlException, AccessDeniedException, LockException, VersionException, RepositoryException {
+        // TODO
+
+    }
+
+    @Override
+    public void removePolicy(String absPath, AccessControlPolicy policy) throws PathNotFoundException, AccessControlException, AccessDeniedException, LockException, VersionException, RepositoryException {
+        // TODO
+
+    }
+
+    @Override
+    public boolean defines(@Nullable String absPath, @Nonnull AccessControlPolicy accessControlPolicy) {
+        if (Utils.isSupportedPath(supportedPath, absPath)) {
+            // TODO
+        }
+        return false;
+    }
+}
\ No newline at end of file

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

Added: 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=1829562&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesAuthorizationConfiguration.java (added)
+++ jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesAuthorizationConfiguration.java Thu Apr 19 15:22:47 2018
@@ -0,0 +1,248 @@
+/*
+ * 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.simplifiedroles;
+
+import java.io.ByteArrayInputStream;
+import java.security.Principal;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.jcr.RepositoryException;
+import javax.jcr.security.AccessControlManager;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Modified;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+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.PropertiesUtil;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore;
+import org.apache.jackrabbit.oak.plugins.name.NamespaceEditorProvider;
+import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager;
+import org.apache.jackrabbit.oak.plugins.nodetype.TypeEditorProvider;
+import org.apache.jackrabbit.oak.plugins.nodetype.write.NodeTypeRegistry;
+import org.apache.jackrabbit.oak.plugins.tree.TreeLocation;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+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.Validator;
+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;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+import org.apache.jackrabbit.oak.spi.security.Context;
+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.EmptyPermissionProvider;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
+import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
+import org.apache.jackrabbit.oak.spi.security.principal.AdminPrincipal;
+import org.apache.jackrabbit.oak.spi.security.principal.SystemPrincipal;
+import org.apache.jackrabbit.oak.spi.state.ApplyDiff;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.apache.jackrabbit.oak.spi.xml.ProtectedItemImporter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.jackrabbit.oak.spi.security.RegistrationConstants.OAK_SECURITY_NAME;
+
+@Component(metatype = true, policy = org.apache.felix.scr.annotations.ConfigurationPolicy.REQUIRE)
+@Service({AuthorizationConfiguration.class, org.apache.jackrabbit.oak.spi.security.SecurityConfiguration.class})
+@Properties({
+        @Property(name = "supportedPath",
+                label = "Supported Path"),
+        @Property(name = CompositeConfiguration.PARAM_RANKING,
+                label = "Ranking",
+                description = "Ranking of this configuration in a setup with multiple authorization configurations.",
+                intValue = 10),
+        @Property(name = OAK_SECURITY_NAME,
+                propertyPrivate = true,
+                value = "org.apache.jackrabbit.oak.exercise.security.authorization.models.simplifiedroles.ThreeRolesAuthorizationConfiguration")
+})
+public class ThreeRolesAuthorizationConfiguration extends ConfigurationBase implements AuthorizationConfiguration, ThreeRolesConstants {
+
+    private static final Logger log = LoggerFactory.getLogger(ThreeRolesAuthorizationConfiguration.class);
+
+
+    private String supportedPath;
+
+    @org.apache.felix.scr.annotations.Activate
+    private void activate(Map<String, Object> properties) {
+        supportedPath = PropertiesUtil.toString(properties.get("supportedPath"), (String) null);
+    }
+
+    @Modified
+    private void modified(Map<String, Object> properties) {
+        supportedPath = PropertiesUtil.toString(properties.get("supportedPath"), (String) null);
+    }
+
+    @Deactivate
+    private void deactivate(Map<String, Object> properties) {
+        supportedPath = null;
+    }
+
+    @Nonnull
+    @Override
+    public AccessControlManager getAccessControlManager(@Nonnull Root root, @Nonnull NamePathMapper namePathMapper) {
+        return new ThreeRolesAccessControlManager(root, supportedPath, getSecurityProvider());
+    }
+
+    @Nonnull
+    @Override
+    public RestrictionProvider getRestrictionProvider() {
+        return RestrictionProvider.EMPTY;
+    }
+
+    @Nonnull
+    @Override
+    public PermissionProvider getPermissionProvider(@Nonnull Root root, @Nonnull String workspaceName, @Nonnull Set<Principal> principals) {
+        if (supportedPath == null || isAdminOrSystem(principals)) {
+            return EmptyPermissionProvider.getInstance();
+        } else {
+            return new ThreeRolesPermissionProvider(root, principals, supportedPath, getContext(), getRootProvider());
+        }
+    }
+
+    @Nonnull
+    @Override
+    public String getName() {
+        return AuthorizationConfiguration.NAME;
+    }
+
+    @Nonnull
+    @Override
+    public RepositoryInitializer getRepositoryInitializer() {
+        String cnd = "<rep='internal'>\n" +
+                     "["+MIX_REP_THREE_ROLES_POLICY+"] \n   mixin\n " +
+                     "  +"+REP_3_ROLES_POLICY+" ("+NT_REP_THREE_ROLES_POLICY+") protected IGNORE\n\n" +
+                     "["+NT_REP_THREE_ROLES_POLICY+"] > "+ AccessControlConstants.NT_REP_POLICY+"\n" +
+                     "  - "+REP_READERS +" (STRING) multiple protected IGNORE\n" +
+                     "  - "+REP_EDITORS+" (STRING) multiple protected IGNORE\n" +
+                     "  - "+REP_OWNERS+" (STRING) multiple protected IGNORE";
+        System.out.println(cnd);
+
+        return builder -> {
+            NodeState base = builder.getNodeState();
+            NodeStore store = new MemoryNodeStore(base);
+
+            Root root = getRootProvider().createSystemRoot(store,
+                    new EditorHook(new CompositeEditorProvider(new NamespaceEditorProvider(), new TypeEditorProvider())));
+
+            try {
+                if (!ReadOnlyNodeTypeManager.getInstance(root, NamePathMapper.DEFAULT).hasNodeType(MIX_REP_THREE_ROLES_POLICY)) {
+                    NodeTypeRegistry.register(root, new ByteArrayInputStream(cnd.getBytes()), "oak exercise");
+                        NodeState target = store.getRoot();
+                        target.compareAgainstBaseState(base, new ApplyDiff(builder));
+                }
+            } catch (RepositoryException e) {
+                log.error(e.getMessage());
+            }
+        };
+    }
+
+    @Nonnull
+    @Override
+    public List<? extends ValidatorProvider> getValidators(@Nonnull String workspaceName, @Nonnull Set<Principal> principals, @Nonnull MoveTracker moveTracker) {
+        return ImmutableList.of(new ValidatorProvider() {
+            @Override
+            protected Validator getRootValidator(NodeState before, NodeState after, CommitInfo info) {
+                // TODO: 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.
+
+                // NOTE: having this validator allows to rely on item names in
+                // Context implementation and simplify the permission evaluation
+                // i.e. preventing expensive effective node type calculation/verification
+                // and checks for nested policies in time critical evaluation steps.
+                return null;
+            }
+        });
+    }
+
+    @Nonnull
+    @Override
+    public List<ProtectedItemImporter> getProtectedItemImporters() {
+        // TODO
+        return ImmutableList.of();
+    }
+
+    @Nonnull
+    @Override
+    public Context getContext() {
+        /**
+         * Simplified implementation of the Context interface that just tests
+         * item names without every evaluating node type information.
+         * See {@link #getValidators(String, Set, MoveTracker)} above.
+         */
+        return new Context() {
+            @Override
+            public boolean definesProperty(@Nonnull Tree parent, @Nonnull PropertyState property) {
+                return definesTree(parent) && NAMES.contains(property.getName());
+            }
+
+            @Override
+            public boolean definesContextRoot(@Nonnull Tree tree) {
+                return definesTree(tree);
+            }
+
+            @Override
+            public boolean definesTree(@Nonnull Tree tree) {
+                return REP_3_ROLES_POLICY.equals(tree.getName());
+            }
+
+            @Override
+            public boolean definesLocation(@Nonnull TreeLocation location) {
+                String name = location.getName();
+                return NAMES.contains(name);
+            }
+
+            @Override
+            public boolean definesInternal(@Nonnull Tree tree) {
+                return false;
+            }
+        };
+    }
+
+    private static boolean isAdminOrSystem(@Nonnull Set<Principal> principals) {
+        if (principals.contains(SystemPrincipal.INSTANCE)) {
+            return true;
+        } else {
+            for (Principal principal : principals) {
+                if (principal instanceof AdminPrincipal) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    @Override
+    public void setParameters(@Nonnull ConfigurationParameters config) {
+        super.setParameters(config);
+        supportedPath = config.getConfigValue("supportedPath", null);
+    }
+}
\ No newline at end of file

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

Added: jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesConstants.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesConstants.java?rev=1829562&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesConstants.java (added)
+++ jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesConstants.java Thu Apr 19 15:22:47 2018
@@ -0,0 +1,45 @@
+/*
+ * 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.simplifiedroles;
+
+import java.util.Set;
+
+import com.google.common.collect.ImmutableSet;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions;
+
+public interface ThreeRolesConstants {
+
+    String MIX_REP_THREE_ROLES_POLICY = "rep:ThreeRolesMixin";
+    String NT_REP_THREE_ROLES_POLICY = "rep:ThreeRolesPolicy";
+
+    String REP_3_ROLES_POLICY = "rep:threeRolesPolicy";
+
+    String REP_READERS = "rep:readers";
+    String REP_EDITORS = "rep:editors";
+    String REP_OWNERS = "rep:owners";
+
+    Set<String> NAMES = ImmutableSet.of(REP_3_ROLES_POLICY, REP_READERS, REP_EDITORS, REP_OWNERS);
+
+    long SUPPORTED_PERMISSIONS =
+                    Permissions.READ |
+                    Permissions.MODIFY_CHILD_NODE_COLLECTION |
+                    Permissions.WRITE |
+                    Permissions.NODE_TYPE_MANAGEMENT |
+                    Permissions.VERSION_MANAGEMENT |
+                    Permissions.READ_ACCESS_CONTROL |
+                    Permissions.MODIFY_ACCESS_CONTROL;
+}
\ No newline at end of file

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

Added: 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=1829562&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesPermissionProvider.java (added)
+++ jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesPermissionProvider.java Thu Apr 19 15:22:47 2018
@@ -0,0 +1,283 @@
+/*
+ * 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.simplifiedroles;
+
+import java.security.Principal;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+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.tree.ReadOnly;
+import org.apache.jackrabbit.oak.plugins.tree.RootProvider;
+import org.apache.jackrabbit.oak.plugins.tree.TreeLocation;
+import org.apache.jackrabbit.oak.plugins.tree.TreeType;
+import org.apache.jackrabbit.oak.plugins.tree.TreeUtil;
+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.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.util.Text;
+
+class ThreeRolesPermissionProvider implements AggregatedPermissionProvider, ThreeRolesConstants {
+
+    private static final PrivilegeBits SUPPORTED_PRIVBITS = PrivilegeBits.getInstance(
+            PrivilegeBits.BUILT_IN.get(PrivilegeConstants.JCR_READ),
+            PrivilegeBits.BUILT_IN.get(PrivilegeConstants.REP_WRITE),
+            PrivilegeBits.BUILT_IN.get(PrivilegeConstants.JCR_VERSION_MANAGEMENT),
+            PrivilegeBits.BUILT_IN.get(PrivilegeConstants.JCR_READ_ACCESS_CONTROL),
+            PrivilegeBits.BUILT_IN.get(PrivilegeConstants.JCR_MODIFY_ACCESS_CONTROL));
+
+    private final Root root;
+    private final Set<String> principalNames;
+    private final String supportedPath;
+    private final Context ctx;
+    private final RootProvider rootProvider;
+
+    private Root readOnlyRoot;
+
+    ThreeRolesPermissionProvider(@Nonnull Root root, Set<Principal> principals,
+                                 @Nonnull String supportedPath, @Nonnull Context ctx,
+                                 @Nonnull RootProvider rootProvider) {
+        this.root = root;
+        this.principalNames = ImmutableSet.copyOf(Iterables.transform(principals, (Function<Principal, String>) Principal::getName));
+        this.supportedPath = supportedPath;
+        this.ctx = ctx;
+        this.rootProvider = rootProvider;
+
+        this.readOnlyRoot = rootProvider.createReadOnlyRoot(root);
+    }
+
+    @Nonnull
+    @Override
+    public PrivilegeBits supportedPrivileges(@Nullable Tree tree, @Nullable PrivilegeBits privilegeBits) {
+        if (tree == null) {
+            return PrivilegeBits.EMPTY;
+        }
+
+        PrivilegeBits pb;
+        if (privilegeBits == null) {
+            pb = SUPPORTED_PRIVBITS;
+        } else {
+            pb = PrivilegeBits.getInstance(privilegeBits);
+            pb.retain(SUPPORTED_PRIVBITS);
+        }
+
+        if (pb.isEmpty() || !Utils.isSupportedPath(supportedPath, tree.getPath())) {
+            return PrivilegeBits.EMPTY;
+        } else {
+            return pb;
+        }
+    }
+
+    @Override
+    public long supportedPermissions(@Nullable Tree tree, @Nullable PropertyState property, long permissions) {
+        if (tree == null) {
+            // repository level permissions are not supported
+            return Permissions.NO_PERMISSION;
+        }
+
+        long supported = permissions & SUPPORTED_PERMISSIONS;
+        if (supported != Permissions.NO_PERMISSION && Utils.isSupportedPath(supportedPath, tree.getPath())) {
+            return supported;
+        } else {
+            return Permissions.NO_PERMISSION;
+        }
+    }
+
+    @Override
+    public long supportedPermissions(@Nonnull TreeLocation location, long permissions) {
+        long supported = permissions & SUPPORTED_PERMISSIONS;
+        if (supported != Permissions.NO_PERMISSION && Utils.isSupportedPath(supportedPath, location.getPath())) {
+            return supported;
+        } else {
+            return Permissions.NO_PERMISSION;
+        }
+    }
+
+    @Override
+    public long supportedPermissions(@Nonnull TreePermission treePermission, @Nullable PropertyState property, long permissions) {
+        long supported = permissions & SUPPORTED_PERMISSIONS;
+        if (supported != Permissions.NO_PERMISSION && (treePermission instanceof ThreeRolesTreePermission)) {
+            return supported;
+        } else {
+            return Permissions.NO_PERMISSION;
+        }
+    }
+
+    @Override
+    public boolean isGranted(@Nonnull TreeLocation location, long permissions) {
+        if (Utils.isSupportedPath(supportedPath, location.getPath())) {
+            TreePermission tp = getTreePermission(location);
+
+            PropertyState property = location.getProperty();
+            return (property == null) ? tp.isGranted(permissions) : tp.isGranted(permissions, property);
+        } else {
+            return false;
+        }
+    }
+
+    @Nonnull
+    @Override
+    public TreePermission getTreePermission(@Nonnull Tree tree, @Nonnull TreeType type, @Nonnull TreePermission parentPermission) {
+        // TODO : currently this implementation ignores TreeType
+        return getTreePermission(tree, parentPermission);
+    }
+
+    @Override
+    public void refresh() {
+        this.readOnlyRoot = rootProvider.createReadOnlyRoot(root);
+
+    }
+
+    @Nonnull
+    @Override
+    public Set<String> getPrivileges(@Nullable Tree tree) {
+        if (tree != null) {
+            TreePermission tp = getTreePermission(getReadOnlyTree(tree));
+            if (tp instanceof ThreeRolesTreePermission) {
+                return ((ThreeRolesTreePermission) tp).getRole().getPrivilegeNames();
+            }
+        }
+
+        return ImmutableSet.of();
+    }
+
+    @Override
+    public boolean hasPrivileges(@Nullable Tree tree, @Nonnull String... privilegeNames) {
+        return getPrivileges(tree).containsAll(ImmutableSet.copyOf(privilegeNames));
+    }
+
+    @Nonnull
+    @Override
+    public RepositoryPermission getRepositoryPermission() {
+        return RepositoryPermission.EMPTY;
+    }
+
+    @Nonnull
+    @Override
+    public TreePermission getTreePermission(@Nonnull Tree tree, @Nonnull TreePermission parentPermission) {
+        if (parentPermission instanceof ThreeRolesTreePermission) {
+            // nested policies are not supported => within a given tree defined
+            // by a ThreeRolePolicy all items share the same permission setup.
+            return parentPermission;
+        }
+
+        String path = tree.getPath();
+        if (Utils.isSupportedPath(supportedPath, path)) {
+            Tree t = getReadOnlyTree(tree);
+            if (t.hasChild(REP_3_ROLES_POLICY)) {
+                return new ThreeRolesTreePermission(getRole(t), ctx.definesContextRoot(t));
+            } else {
+                return TreePermission.EMPTY;
+            }
+        } else if (isAncestor(path)) {
+            return TreePermission.EMPTY;
+        } else {
+            return TreePermission.NO_RECOURSE;
+        }
+    }
+
+    @Override
+    public boolean isGranted(@Nonnull Tree tree, @Nullable PropertyState property, long permissions) {
+        if (Utils.isSupportedPath(supportedPath, tree.getPath())) {
+            TreePermission tp = getTreePermission(tree);
+            return (property == null) ? tp.isGranted(permissions) : tp.isGranted(permissions, property);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public boolean isGranted(@Nonnull String oakPath, @Nonnull String jcrActions) {
+        TreeLocation tl = TreeLocation.create(readOnlyRoot, oakPath);
+        long permissions = Permissions.getPermissions(jcrActions, tl, ctx.definesLocation(tl));
+
+        return isGranted(tl, permissions);
+    }
+
+    //--------------------------------------------------------------------------
+
+    private boolean isAncestor(@Nonnull String path) {
+        return Text.isDescendant(path, supportedPath);
+    }
+
+    private Role getRole(@Nonnull Tree tree) {
+        Tree policy = tree.getChild(REP_3_ROLES_POLICY);
+        if (policy.exists()) {
+            if (containsAny(policy, REP_OWNERS)) {
+                return Role.OWNER;
+            } else if (containsAny(policy, REP_EDITORS)) {
+                return Role.EDITOR;
+            } else if (containsAny(policy, REP_READERS)) {
+                return Role.READER;
+            }
+        }
+        return Role.NONE;
+    }
+
+    private boolean containsAny(@Nonnull Tree policyTree, @Nonnull String propName) {
+        Iterable<String> names = TreeUtil.getStrings(policyTree, propName);
+        if (names != null) {
+            for (String principalName : names) {
+                if (principalNames.contains(principalName)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private Tree getReadOnlyTree(@Nonnull Tree tree) {
+        if (tree instanceof ReadOnly) {
+            return tree;
+        } else {
+            return readOnlyRoot.getTree(tree.getPath());
+        }
+    }
+
+    private TreePermission getTreePermission(@Nonnull Tree readOnlyTree) {
+        Tree t = readOnlyTree;
+        while (Utils.isSupportedPath(supportedPath, t.getPath())) {
+            if (t.hasChild(REP_3_ROLES_POLICY)) {
+                return new ThreeRolesTreePermission(getRole(t), ctx.definesContextRoot(t));
+            }
+            t = t.getParent();
+        }
+        return TreePermission.EMPTY;
+    }
+
+    private TreePermission getTreePermission(@Nonnull TreeLocation location) {
+        TreeLocation l = location;
+        while (Utils.isSupportedPath(supportedPath, l.getPath())) {
+            Tree tree = location.getTree();
+            if (tree != null) {
+                return getTreePermission(getReadOnlyTree(tree));
+            }
+            l = l.getParent();
+        }
+        return TreePermission.EMPTY;
+    }
+}
\ No newline at end of file

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

Added: 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=1829562&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesTreePermission.java (added)
+++ jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/ThreeRolesTreePermission.java Thu Apr 19 15:22:47 2018
@@ -0,0 +1,85 @@
+/*
+ * 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.simplifiedroles;
+
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.oak.api.PropertyState;
+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.state.NodeState;
+
+class ThreeRolesTreePermission implements TreePermission, ThreeRolesConstants {
+
+    private final Role role;
+    private final boolean isAcContent;
+
+    ThreeRolesTreePermission(@Nonnull Role role, boolean isAcContent) {
+        this.role = role;
+        this.isAcContent = isAcContent;
+    }
+
+    @Nonnull
+    Role getRole() {
+        return role;
+    }
+
+    @Nonnull
+    @Override
+    public TreePermission getChildPermission(@Nonnull String childName, @Nonnull NodeState childState) {
+        if (isAcContent) {
+            return this;
+        } else {
+            // TODO: respect access controlled content defined by other modules
+            return new ThreeRolesTreePermission(role, REP_3_ROLES_POLICY.equals(childName));
+        }
+    }
+
+    @Override
+    public boolean canRead() {
+        if (isAcContent) {
+            return isGranted(Permissions.READ_ACCESS_CONTROL);
+        } else {
+            return isGranted(Permissions.READ);
+        }
+    }
+
+    @Override
+    public boolean canRead(@Nonnull PropertyState property) {
+        return canRead();
+    }
+
+    @Override
+    public boolean canReadAll() {
+        return false;
+    }
+
+    @Override
+    public boolean canReadProperties() {
+        return canRead();
+    }
+
+    @Override
+    public boolean isGranted(long permissions) {
+        return role.grants(permissions);
+    }
+
+    @Override
+    public boolean isGranted(long permissions, @Nonnull PropertyState property) {
+        return isGranted(permissions);
+    }
+}

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

Added: 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=1829562&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/Utils.java (added)
+++ jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/authorization/models/simplifiedroles/Utils.java Thu Apr 19 15:22:47 2018
@@ -0,0 +1,36 @@
+/*
+ * 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.simplifiedroles;
+
+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() {}
+
+    static boolean isSupportedPath(@Nonnull String configuredPath, @Nonnull String path) {
+        return Text.isDescendantOrEqual(configuredPath, path);
+    }
+
+}
\ No newline at end of file

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

Modified: jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/principal/CustomPrincipalConfiguration.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/principal/CustomPrincipalConfiguration.java?rev=1829562&r1=1829561&r2=1829562&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/principal/CustomPrincipalConfiguration.java (original)
+++ jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/principal/CustomPrincipalConfiguration.java Thu Apr 19 15:22:47 2018
@@ -31,6 +31,7 @@ import org.apache.jackrabbit.oak.api.Roo
 import org.apache.jackrabbit.oak.commons.PropertiesUtil;
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 import org.apache.jackrabbit.oak.spi.security.ConfigurationBase;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
 import org.apache.jackrabbit.oak.spi.security.principal.PrincipalConfiguration;
 import org.apache.jackrabbit.oak.spi.security.principal.PrincipalManagerImpl;
 import org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider;
@@ -90,4 +91,10 @@ public class CustomPrincipalConfiguratio
         knownPrincipals = new String[0];
         log.info("CustomPrincipalConfiguration.deactivate");
     }
+
+    @Override
+    public void setParameters(@Nonnull ConfigurationParameters config) {
+        super.setParameters(config);
+        knownPrincipals = config.getConfigValue("knownPrincipals", new String[0]);
+    }
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/principal/CustomPrincipalProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/principal/CustomPrincipalProvider.java?rev=1829562&r1=1829561&r2=1829562&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/principal/CustomPrincipalProvider.java (original)
+++ jackrabbit/oak/trunk/oak-exercise/src/main/java/org/apache/jackrabbit/oak/exercise/security/principal/CustomPrincipalProvider.java Thu Apr 19 15:22:47 2018
@@ -24,7 +24,6 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterators;
 import org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider;
 
 /**
@@ -44,7 +43,11 @@ class CustomPrincipalProvider implements
     @Override
     public Principal getPrincipal(@Nonnull String principalName) {
         // EXERCISE: complete
-        return null;
+        if (knownPrincipalNames.contains(principalName)) {
+            return () -> principalName;
+        } else {
+            return null;
+        }
     }
 
     @Nonnull

Modified: jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/advanced/L2_SetupAggregationTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/advanced/L2_SetupAggregationTest.java?rev=1829562&r1=1829561&r2=1829562&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/advanced/L2_SetupAggregationTest.java (original)
+++ jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/advanced/L2_SetupAggregationTest.java Thu Apr 19 15:22:47 2018
@@ -68,6 +68,7 @@ package org.apache.jackrabbit.oak.exerci
  *   Questions:
  *   > Would it be an option to use "OR" as the composition type with the setup you chose?
  *   > What would be the result if this was a valid option?
+ *   > If it was a valid option, imaging a setup scenario where it would not work.
  *   > If it wasn't an option, explain why. Think about a scenario where it was valid.
  *
  * </pre>