Propchange: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L3_PrecedenceRulesTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L4_PrivilegesAndPermissionsTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L4_PrivilegesAndPermissionsTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L4_PrivilegesAndPermissionsTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L4_PrivilegesAndPermissionsTest.java
 Thu Jun 18 14:30:16 2015
@@ -0,0 +1,505 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.authorization.permission;
+
+import java.security.Principal;
+import java.util.Map;
+import javax.jcr.AccessDeniedException;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.Privilege;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.api.JackrabbitSession;
+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.api.security.user.UserManager;
+import 
org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
+import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
+import org.apache.jackrabbit.oak.security.ExerciseUtility;
+import 
org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions;import
 org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.apache.jackrabbit.test.api.util.Text;
+
+/**
+ * <pre>
+ * Module: Authorization (Permission Evaluation)
+ * 
=============================================================================
+ *
+ * Title: Privileges and Permissions
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * The aim of this is test is to make you familiar with the subtle differences
+ * between privileges (that are always granted on an existing node) and 
effective
+ * permissions on the individual items (nodes, properties or even non-existing
+ * items).
+ * Having completed this exercise you should also be familiar with the oddities
+ * of those privileges that allow modify the parent collection, while the 
effective
+ * permission is evaluated the target item.
+ *
+ * Exercises:
+ *
+ * - {@link #testAddNodes()}
+ *   This test aims to practise the subtle difference between granting 
'jcr:addChildNode'
+ *   privilege at a given parent node and {@link Session#hasPermission(String, 
String)}
+ *   using {@link Session#ACTION_ADD_NODE}, which effectively tests if a given
+ *   new node could be created.
+ *   Fill in the expected values for the permission discovery with the given
+ *   permission setup. Subsequently, list the expected values for
+ *   {@link javax.jcr.security.AccessControlManager#getPrivileges(String)}.
+ *   Explain the difference given the mini-explanation in the test 
introduction.
+ *
+ * - {@link #testAddProperties()}
+ *   This test grants the test user privilege to add properties at 'childPath'.
+ *   Fill in the expected result of {@link 
javax.jcr.Session#hasPermission(String, String)}
+ *   both for the regular JCR action {@link Session#ACTION_SET_PROPERTY} and
+ *   for the string value of {@link Permissions#ADD_PROPERTY}. Compare and 
explain
+ *   the differences.
+ *
+ * - {@link #testRemoveNodes()} ()}
+ *   This test illustrates what kind of privileges are required in order to
+ *   remove a given node. Fix the test-case by setting the correct permission
+ *   setup.
+ *
+ * - {@link #testRemoveProperties()} ()}
+ *   In this test the test-user is only granted rep:removeProperties privilege
+ *   and lists which properties must be removable. Nevertheless the test-case 
is
+ *   broken... can you identify the root cause without modifying the result map
+ *   nor the permission setup?
+ *
+ * - {@link #testRemoveNonExistingItems()}
+ *   Look at the contract of {@link Session#hasPermission(String, String)} and
+ *   the implementation present in Oak to understand what happens if you test
+ *   permissions for removal of non-existing items.
+ *
+ * - {@link #testModifyProperties()}
+ *   Now the test-user is just allowed to modify properties. Complete the test
+ *   by modifying the result-map: add for each path whether accessing and 
setting
+ *   the properties is expected to succeed. Explain for each path why it passes
+ *   or fails. In case of doubt debug the test to understand what is going on.
+ *
+ * - {@link #testSetProperty()}
+ *   Properties cannot only be modified by calling {@link Property#setValue}
+ *   but also by calling {@link Node#setProperty} each for different types and
+ *   single vs multivalued properties. While they are mostly equivalent there
+ *   are subtle differences that have an impact on the permission evaluation.
+ *   Can you find suitable value(s) for each of these paths such that the
+ *   test passes?
+ *   Hint: passing a 'null' value is defined to be equivalent to removal.
+ *   Discuss your findings.
+ *
+ *   Question: Can you explain the required values if the test user was allowed
+ *   to remove properties instead? -> Modify the test to verify your 
expectations.
+ *
+ * - {@link #testChangingPrimaryAndMixinTypes()}
+ *   In order to change the primary (or mixin) type(s) of a given existing node
+ *   the editing session must have {@link Privilege#JCR_NODE_TYPE_MANAGEMENT}
+ *   privilege granted.
+ *   For consistency with this requirement, also {@link Node#addNode(String, 
String)},
+ *   which explicitly specifies the primary type requires this privilege as
+ *   the effective operation is equivalent to the combination of:
+ *   1. {@link Node#addNode(String)} +
+ *   2. {@link Node#setPrimaryType(String)}
+ *   Use this test case to become familiar with setting or changing the primary
+ *   type and modifying the set of mixin types.
+ *
+ *
+ * Additional Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * - Modifying Nodes
+ *   Discuss why there is no dedicated privilege (and test case) for "modify 
nodes".
+ *   Explain how {@link Privilege#JCR_NODE_TYPE_MANAGEMENT, {@link 
Privilege#JCR_ADD_CHILD_NODES},
+ *   {@link Privilege#JCR_REMOVE_CHILD_NODES} (and maybe others) are linked to
+ *   node modification.
+ *
+ *
+ * Advanced Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * If you wished to become more familiar with the interals of the Oak 
permission
+ * evaluation, it is indispensible to understand the internal representation of
+ * registered privileges (as {@link 
org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits}
+ * and their mapping to {@link 
org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions}.
+ *
+ * Precondition for these advanced exercises is the following test:
+ *
+ * - {@link 
org.apache.jackrabbit.oak.security.privilege.L5_PrivilegeContentTest }
+ *
+ * The following exercises aim to provide you with some insight and allow you
+ * to understand the internal structure of the permission store.
+ *
+ * - PrivilegeBits and the corresponding provider class
+ *   Take a look at the methods exposed by
+ *   {@link 
org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBitsProvider}
+ *   and the {@link 
org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits}
+ *   class itself. Using these classes Oak generates the repository internal
+ *   representation of the privileges that are used for
+ *   - calculation of effective privileges
+ *   - calculation of final permission from effective privileges granted (or 
denied)
+ *
+ * - Mapping Privileges to Permissions
+ *   As you could see in the above exercises there is no 1:1 mapping between
+ *   privileges and permissions as a few privileges (like jcr:addChildNodes and
+ *   jcr:removeChildNodes) are granted for the parent node. This needs to be
+ *   handled specially when evaluating if a given node can be created or 
removed.
+ *   Look at {@link 
org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits#calculatePermissions()}
+ *   and compare the code with the results obtained from the test-cases above.
+ *
+ * - Mapping of JCR Actions to Permissions
+ *   The exercises also illustrated the subtle differences between 'actions'
+ *   as defined on {@link javax.jcr.Session} and the effective permissions
+ *   being evaluated.
+ *   Take a closer look at {@link 
org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions#getPermissions(String,
 org.apache.jackrabbit.oak.plugins.tree.TreeLocation, boolean)}
+ *   to improve your understanding on how the mapping is being implemented
+ *   and discuss the consequences for {@link Session#hasPermission(String, 
String)}.
+ *   Compare the code with the test-results.
+ *
+ *
+ * Related Exercises
+ * 
-----------------------------------------------------------------------------
+ *
+ * - {@link 
org.apache.jackrabbit.oak.security.authorization.permission.L5_SpecialPermissionsTest}
+ * - {@link L7_PermissionContentTest }
+ *
+ * </pre>
+ */
+public class L4_PrivilegesAndPermissionsTest extends AbstractJCRTest {
+
+    private User testUser;
+    private Principal testPrincipal;
+    private Principal testGroupPrincipal;
+    private Session testSession;
+
+    private String childPath;
+    private String grandChildPath;
+    private String propertyPath;
+    private String childPropertyPath;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        Property p = testRootNode.setProperty(propertyName1, "val");
+        propertyPath = p.getPath();
+
+        Node child = testRootNode.addNode(nodeName1);
+        childPath = child.getPath();
+
+        p = child.setProperty(propertyName2, "val");
+        childPropertyPath = p.getPath();
+
+        Node grandChild = child.addNode(nodeName2);
+        grandChildPath = grandChild.getPath();
+
+        testUser = ExerciseUtility.createTestUser(((JackrabbitSession) 
superuser).getUserManager());
+        Group testGroup = ExerciseUtility.createTestGroup(((JackrabbitSession) 
superuser).getUserManager());
+        testGroup.addMember(testUser);
+        superuser.save();
+
+        testPrincipal = testUser.getPrincipal();
+        testGroupPrincipal = testGroup.getPrincipal();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        try {
+            if (testSession != null && testSession.isLive()) {
+                testSession.logout();
+            }
+            UserManager uMgr = ((JackrabbitSession) 
superuser).getUserManager();
+            if (testUser != null) {
+                testUser.remove();
+            }
+            Authorizable testGroup = uMgr.getAuthorizable(testGroupPrincipal);
+            if (testGroup != null) {
+                testGroup.remove();
+            }
+            superuser.save();
+        } finally {
+            super.tearDown();
+        }
+    }
+
+    private Session createTestSession() throws RepositoryException {
+        if (testSession == null) {
+            testSession = 
superuser.getRepository().login(ExerciseUtility.getTestCredentials(testUser.getID()));
+        }
+        return testSession;
+    }
+
+    public void testAddNodes() throws Exception {
+        // grant the test principal jcr:addChildNode privilege at 'childPath'
+        AccessControlUtils.addAccessControlEntry(superuser, childPath, 
testPrincipal, new String[] {Privilege.JCR_ADD_CHILD_NODES}, true);
+        superuser.save();
+
+        Session userSession = createTestSession();
+
+        // EXERCISE: fill in the expected return values for 
Session.hasPermission as performed below
+        // EXERCISE: verify that the test passes and explain the individual 
results
+        Map<String, Boolean> pathHasPermissionMap = ImmutableMap.of(
+                testRootNode.getPath(), null,
+                childPath, null,
+                childPath + "/toCreate", null,
+                grandChildPath + "/nextGeneration", null,
+                propertyPath, null
+        );
+
+        for (String path : pathHasPermissionMap.keySet()) {
+            boolean expectedHasPermission = pathHasPermissionMap.get(path);
+            assertEquals(expectedHasPermission, 
userSession.hasPermission(path, Session.ACTION_ADD_NODE));
+        }
+
+        // EXERCISE: fill in the expected return values for 
AccessControlManager#getPrivileges as performed below
+        // EXERCISE: verify that the test passes and compare the results with 
your findings from the permission-discovery
+        Map<String, Privilege[]> pathPrivilegesMap = ImmutableMap.of(
+                testRootNode.getPath(), null,
+                childPath, null,
+                childPath + "/toCreate", null,
+                grandChildPath + "/nextGeneration", null
+        );
+
+        for (String path : pathPrivilegesMap.keySet()) {
+            Privilege[] expectedPrivileges = pathPrivilegesMap.get(path);
+            assertEquals(ImmutableSet.of(expectedPrivileges), 
ImmutableSet.of(userSession.getAccessControlManager().getPrivileges(path)));
+        }
+
+        // EXERCISE: optionally add nodes at the expected allowed path(s)
+        // EXERCISE: using 'userSession' to verify that it actually works and
+        // EXERCISE: save the changes to trigger the evaluation
+    }
+
+    public void testAddProperties() throws Exception {
+        // grant the test principal rep:addProperties privilege at 'childPath'
+        // EXERCISE: explain the difference between rep:addProperites and 
jcr:modifyProperties privilege!
+        AccessControlUtils.addAccessControlEntry(superuser, childPath, 
testPrincipal, new String[] {PrivilegeConstants.REP_ADD_PROPERTIES}, true);
+        superuser.save();
+
+        // EXERCISE: fill in the expected return values for 
Session.hasPermission as performed below
+        // EXERCISE: verify that the test passes and explain the individual 
results
+        Map<String, Boolean[]> pathHasPermissionMap = ImmutableMap.of(
+                propertyPath, new Boolean[]{null, null},
+                childPath + "/newProp", new Boolean[]{null, null},
+                childPropertyPath, new Boolean[]{null, null},
+                grandChildPath + "/" + JcrConstants.JCR_PRIMARYTYPE, new 
Boolean[]{null, null}
+        );
+
+        Session userSession = createTestSession();
+        for (String path : pathHasPermissionMap.keySet()) {
+            Boolean[] result = pathHasPermissionMap.get(path);
+            boolean setPropertyAction = result[0];
+            boolean addPropertiesPermission = result[1];
+            assertEquals(setPropertyAction, userSession.hasPermission(path, 
Session.ACTION_SET_PROPERTY));
+            assertEquals(addPropertiesPermission, 
userSession.hasPermission(path, 
Permissions.getString(Permissions.ADD_PROPERTY)));
+        }
+    }
+
+    public void testRemoveNodes() throws Exception {
+        // EXERCISE: setup the correct set of privileges such that the test 
passes
+        superuser.save();
+
+        Map<String, Boolean> pathHasPermissionMap = ImmutableMap.of(
+                testRootNode.getPath(), false,
+                childPath, false,
+                grandChildPath, true
+        );
+
+        Session userSession = createTestSession();
+        for (String path : pathHasPermissionMap.keySet()) {
+            boolean expectedHasPermission = pathHasPermissionMap.get(path);
+            assertEquals(expectedHasPermission, 
userSession.hasPermission(path, Session.ACTION_REMOVE));
+        }
+
+        AccessControlManager acMgr = userSession.getAccessControlManager();
+        assertFalse(acMgr.hasPrivileges(childPath, new 
Privilege[]{acMgr.privilegeFromName(Privilege.JCR_REMOVE_NODE)}));
+
+        userSession.getNode(grandChildPath).remove();
+        userSession.save();
+    }
+
+    public void testRemoveProperties() throws Exception {
+        // EXERCISE: fix the test case without changing the result-map :-)
+
+        // grant the test principal rep:removeProperties privilege at 
'childPath'
+        AccessControlUtils.addAccessControlEntry(superuser, childPath, 
testPrincipal, new String[] {PrivilegeConstants.REP_REMOVE_PROPERTIES}, true);
+        superuser.save();
+
+        Map<String, Boolean> pathCanRemoveMap = ImmutableMap.of(
+                propertyPath, false,
+                childPropertyPath, true,
+                grandChildPath + "/" + JcrConstants.JCR_PRIMARYTYPE, false,
+                grandChildPath + "/" + propertyName2, false
+        );
+
+        Session userSession = createTestSession();
+        for (String path : pathCanRemoveMap.keySet()) {
+            boolean canRemove = pathCanRemoveMap.get(path);
+
+            try {
+                userSession.getProperty(path).remove();
+                if (!canRemove) {
+                    fail("property at " + path + " should not be removable.");
+                }
+            } catch (RepositoryException e) {
+                if (canRemove) {
+                    fail("property at " + path + " should be removable.");
+                }
+            } finally {
+                userSession.refresh(false);
+            }
+        }
+    }
+
+    public void testRemoveNonExistingItems() throws Exception {
+        AccessControlUtils.addAccessControlEntry(superuser, childPath, 
testPrincipal, new String[] {
+                Privilege.JCR_REMOVE_NODE,
+                Privilege.JCR_REMOVE_CHILD_NODES,
+                PrivilegeConstants.REP_REMOVE_PROPERTIES}, true);
+        superuser.save();
+
+        // EXERCISE: fill in the expected values for 
Session.hasPermission(path, Session.ACTION_REMOVE) and explain
+        Map<String, Boolean> pathHasPermission = ImmutableMap.of(
+                childPath + "_non_existing_sibling", null,
+                childPath + "/_non_existing_childitem", null,
+                grandChildPath + "/_non_existing_child_item", null
+        );
+
+        Session userSession = createTestSession();
+        for (String nonExistingItemPath : pathHasPermission.keySet()) {
+            boolean hasPermission = 
pathHasPermission.get(nonExistingItemPath).booleanValue();
+            assertEquals(hasPermission, 
userSession.hasPermission(nonExistingItemPath, Session.ACTION_REMOVE));
+        }
+
+        // Additional exercise:
+        // EXERCISE: change the set of privileges granted initially and 
observe the result of Session.hasPermission. Explain the diff
+    }
+
+    public void testModifyProperties() throws Exception {
+        // grant the test principal rep:alterProperties privilege at 
'childPath'
+        AccessControlUtils.addAccessControlEntry(superuser, childPath, 
testPrincipal, new String[] {PrivilegeConstants.REP_ALTER_PROPERTIES}, true);
+        superuser.save();
+
+        // EXERCISE: Fill if setting the property at the path(s) is expected 
to pass or not
+        Map<String, Boolean> pathCanModify = ImmutableMap.of(
+                propertyPath, null,
+                childPropertyPath, null,
+                grandChildPath + "/" + JcrConstants.JCR_PRIMARYTYPE, null,
+                grandChildPath + "/" + propertyName2, null
+        );
+
+        Session userSession = createTestSession();
+        for (String path : pathCanModify.keySet()) {
+            boolean canModify = pathCanModify.get(path);
+            try {
+                userSession.getProperty(path).setValue("newVal");
+                userSession.save();
+                if (!canModify) {
+                    fail("setting property at " + path + " should fail.");
+                }
+            } catch (RepositoryException e) {
+                if (canModify) {
+                    fail("setting property at " + path + " should not fail.");
+                }
+            } finally {
+                userSession.refresh(false);
+            }
+        }
+    }
+
+    public void testSetProperty() throws RepositoryException {
+        // grant the test principal rep:removeProperties privilege at 
'childPath'
+        AccessControlUtils.addAccessControlEntry(superuser, childPath, 
testPrincipal, new String[] {PrivilegeConstants.REP_ALTER_PROPERTIES}, true);
+        superuser.save();
+
+        // EXERCISE: Fill if new properties values such that the test-cases 
succeeds
+        // EXERCISE: Discuss your findings and explain each value.
+
+        Map<String, Value> pathResultMap = Maps.newHashMap();
+        pathResultMap.put(childPropertyPath, (Value) null);
+        pathResultMap.put(grandChildPath + "/nonexisting", (Value) null);
+
+        Session userSession = createTestSession();
+        for (String path : pathResultMap.keySet()) {
+            try {
+                Value val = pathResultMap.get(path);
+
+                Node parent = userSession.getNode(Text.getRelativeParent(path, 
1));
+                parent.setProperty(Text.getName(path), val);
+
+                userSession.save();
+            } finally {
+                userSession.refresh(false);
+            }
+        }
+    }
+
+    public void testChangingPrimaryAndMixinTypes() throws RepositoryException {
+        // 1 - grant privilege to change node type information
+        // EXERCISE: fill in the required privilege name such that the test 
passes
+        String privilegeName = null;
+        AccessControlUtils.addAccessControlEntry(superuser, childPath, 
testPrincipal, new String[] {privilegeName}, true);
+        superuser.save();
+
+        Session userSession = createTestSession();
+        Node n = userSession.getNode(childPath);
+        n.setPrimaryType(NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+        n.addMixin(JcrConstants.MIX_REFERENCEABLE);
+        userSession.save();
+
+        // 2 - additionally grant privilege to add a child node
+        // EXERCISE: extend the set of privileges such that the adding a child 
node succeeds as well
+        privilegeName = null;
+        AccessControlUtils.addAccessControlEntry(superuser, childPath, 
testPrincipal, new String[] {privilegeName}, true);
+        superuser.save();
+
+        userSession.refresh(false);
+        userSession.getNode(childPath).addNode(nodeName4, 
NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+        userSession.save();
+
+        // 3 - revoke privilege to change node type information
+        // EXERCISE: change the permission setup again such that the rest of 
the test passes
+        superuser.save();
+
+        userSession.refresh(false);
+        n = userSession.getNode(childPath);
+        n.addNode(nodeName3);
+        userSession.save();
+
+        try {
+            n.addNode(nodeName1, NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+            userSession.save();
+            fail("Adding node with explicitly the primary type should fail");
+        } catch (AccessDeniedException e) {
+            // success
+        } finally {
+            userSession.refresh(false);
+        }
+
+
+        AccessControlUtils.addAccessControlEntry(superuser, childPath, 
testPrincipal, new String[] {privilegeName}, true);
+
+    }
+}
\ No newline at end of file

Propchange: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L4_PrivilegesAndPermissionsTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L5_SpecialPermissionsTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L5_SpecialPermissionsTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L5_SpecialPermissionsTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L5_SpecialPermissionsTest.java
 Thu Jun 18 14:30:16 2015
@@ -0,0 +1,289 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.authorization.permission;
+
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.List;
+import javax.jcr.AccessDeniedException;
+import javax.jcr.NamespaceRegistry;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.AccessControlPolicy;
+import javax.jcr.security.Privilege;
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionHistory;
+import javax.jcr.version.VersionManager;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
+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.api.security.user.UserManager;
+import 
org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
+import org.apache.jackrabbit.oak.security.ExerciseUtility;
+import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.junit.Test;
+
+/**
+ * <pre>
+ * Module: Authorization (Permission Evaluation)
+ * 
=============================================================================
+ *
+ * Title: Special Permissions
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * So far exercises mostly dealt with regalar read/write privileges. After 
having
+ * completed this exercise you should a better understanding on permission
+ * evaluation for non-regular write operations.
+ *
+ * Exercises:
+ *
+ * - {@link #testVersioning()}
+ *   Performing version operations requires {@link 
Privilege#JCR_VERSION_MANAGEMENT}
+ *   to be granted at the target node. Use this test to verify this.
+ *
+ * - {@link #testReadVersionInformation()}
+ *   Testing read access to version storage at /jcr:system/jcr:versionStore
+ *   Use {@link #testVersioning()} again to take a closer look on how versions
+ *   and version-histories are being retrieved from the version store and how
+ *   the corresponding read-access is being evaluated.
+ *
+ *   Question: Can you explain what the difference is compared to Jackrabbit 
2.x? (hint: oak-doc and jira)
+ *   Question: Can you identify cases where access to 
/jcr:system/jcr:versionstore explicitly needed to be granted?
+ *             If yes: explain why and the impact it may have from a security 
point of view.
+ *
+ * - {@link #testUserManagement()}
+ *   Fix the test case such that there is no privilege escalation from testUser
+ *   to the admin user :-)
+ *
+ * - {@link #testRepositoryLevelPrivileges()}
+ *   The following privileges need to be granted globally for the whole 
repository
+ *   as the associated operations also take effect on the whole repository.
+ *   In order to do so, you need to use the 'null' paths... verify in this test
+ *   that granting those privileges at 'childPath' does not have the desired 
effect.
+ *
+ *
+ * Additional Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * - Write additional test cases for the following privileges:
+ *   - {@link Privilege#JCR_READ_ACCESS_CONTROL}
+ *   - {@link Privilege#JCR_MODIFY_ACCESS_CONTROL}
+ *   - {@link Privilege#JCR_LOCK_MANAGEMENT}
+ *   - {@link 
org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants#REP_INDEX_DEFINITION_MANAGEMENT}
+ *
+ * Related Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * - {@link 
org.apache.jackrabbit.oak.security.privilege.L3_BuiltInPrivilegesTest#testMapItems()}
+ *
+ * </pre>
+ *
+ *
+ * @see org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants
+ * @see 
org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions
+ */
+public class L5_SpecialPermissionsTest extends AbstractJCRTest {
+
+    private User testUser;
+    private User testUser2;
+    private Principal testPrincipal;
+    private Principal testGroupPrincipal;
+    private Session testSession;
+
+    private String childPath;
+    private String grandChildPath;
+    private String propertyPath;
+    private String childPropertyPath;
+
+    private List<String> paths = new ArrayList();
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        Property p = testRootNode.setProperty(propertyName1, "val");
+        propertyPath = p.getPath();
+
+        Node child = testRootNode.addNode(nodeName1);
+        childPath = child.getPath();
+
+        p = child.setProperty(propertyName2, "val");
+        childPropertyPath = p.getPath();
+
+        Node grandChild = child.addNode(nodeName2);
+        grandChildPath = grandChild.getPath();
+
+        testUser = ExerciseUtility.createTestUser(((JackrabbitSession) 
superuser).getUserManager());
+        testUser2 = ExerciseUtility.createTestUser(((JackrabbitSession) 
superuser).getUserManager());
+        Group testGroup = ExerciseUtility.createTestGroup(((JackrabbitSession) 
superuser).getUserManager());
+        testGroup.addMember(testUser);
+        superuser.save();
+
+        testPrincipal = testUser.getPrincipal();
+        testGroupPrincipal = testGroup.getPrincipal();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        try {
+            if (testSession != null && testSession.isLive()) {
+                testSession.logout();
+            }
+            UserManager uMgr = ((JackrabbitSession) 
superuser).getUserManager();
+            if (testUser != null) {
+                testUser.remove();
+            }
+            if (testUser2 != null) {
+                testUser2.remove();
+            }
+            Authorizable testGroup = uMgr.getAuthorizable(testGroupPrincipal);
+            if (testGroup != null) {
+                testGroup.remove();
+            }
+
+            removePolicies(paths);
+
+            superuser.save();
+        } finally {
+            super.tearDown();
+        }
+    }
+
+    private void removePolicies(List<String> paths) throws RepositoryException 
{
+        AccessControlManager acMgr = superuser.getAccessControlManager();
+        for (String path : paths) {
+            AccessControlPolicy[] policies = acMgr.getPolicies(path);
+            for (AccessControlPolicy plc : policies) {
+                if (plc instanceof JackrabbitAccessControlList) {
+                    acMgr.removePolicy(path, plc);
+                }
+            }
+        }
+    }
+
+    private Session createTestSession() throws RepositoryException {
+        if (testSession == null) {
+            testSession = 
superuser.getRepository().login(ExerciseUtility.getTestCredentials(testUser.getID()));
+        }
+        return testSession;
+    }
+
+    public void testVersioning() throws Exception {
+        // EXERCISE: fix the test case
+        superuser.getNode(childPath).addMixin(JcrConstants.MIX_VERSIONABLE);
+        
superuser.getNode(grandChildPath).addMixin(JcrConstants.MIX_VERSIONABLE);
+
+        String privName = Privilege.JCR_VERSION_MANAGEMENT;
+        AccessControlUtils.addAccessControlEntry(superuser, grandChildPath, 
testGroupPrincipal, new String[]{privName}, true);
+        superuser.save();
+
+        Session s = createTestSession();
+
+        Node n = s.getNode(childPath);
+        Version v = n.checkin();
+        n.checkout();
+
+        n = s.getNode(grandChildPath);
+        v = n.checkin();
+        n.checkout();
+    }
+
+    @Test
+    public void testReadVersionInformation() throws RepositoryException {
+        Node childNode = superuser.getNode(childPath);
+        childNode.addMixin(JcrConstants.MIX_VERSIONABLE);
+        superuser.save();
+        childNode.checkin();
+        childNode.checkout();
+
+        // EXERCISE: uncomment the following permission setup and test the 
impact it has!
+        // EXERCISE: discuss and explain your findings
+//        AccessControlUtils.addAccessControlEntry(superuser, "/jcr:system", 
testGroupPrincipal, new String[] {Privilege.JCR_READ}, false);
+//        paths.add("/jcr:system");
+//        superuser.save();
+//
+        Session s = createTestSession();
+
+        // EXERCISE: uncomment to verify the permission setup is as expected
+        //assertFalse(s.nodeExists(VersionConstants.VERSION_STORE_PATH));
+
+        VersionManager versionManager = s.getWorkspace().getVersionManager();
+        VersionHistory vh = versionManager.getVersionHistory(childPath);
+        Version rootVersion = vh.getRootVersion();
+        Version baseVersion = versionManager.getBaseVersion(childPath);
+    }
+
+    @Test
+    public void testUserManagement() throws RepositoryException {
+        // EXERCISE: fix the permission setup and explain why!
+
+        // grant full access to all users for 'testGroup'...
+        paths.add(UserConstants.DEFAULT_USER_PATH);
+        AccessControlUtils.addAccessControlEntry(superuser,
+                UserConstants.DEFAULT_USER_PATH, testGroupPrincipal,
+                new String[]{Privilege.JCR_ALL}, true);
+        // ... but prevent the test user to write the admin user
+        String adminPath = ((JackrabbitSession) 
superuser).getUserManager().getAuthorizable(superuser.getUserID()).getPath();
+        paths.add(adminPath);
+        AccessControlUtils.addAccessControlEntry(superuser,
+                adminPath, EveryonePrincipal.getInstance(),
+                new String[]{PrivilegeConstants.REP_WRITE}, false);
+
+
+        // execute the test verifying that pw of 'testUser2' can be change
+        // but not the pw of the admin user
+        JackrabbitSession s = (JackrabbitSession) createTestSession();
+
+        User u2 = s.getUserManager().getAuthorizable(testUser2.getID(), 
User.class);
+        u2.changePassword("gugus");
+        s.save();
+
+        try {
+            User admin = 
s.getUserManager().getAuthorizable(superuser.getUserID(), User.class);
+            admin.changePassword("gugus");
+            s.save();
+            fail("privilege escalation!");
+        } catch (AccessDeniedException e) {
+            // success
+        } finally {
+            s.refresh(false);
+        }
+    }
+
+    public void testRepositoryLevelPrivileges() throws RepositoryException {
+        // EXERCISE : setup the permissions such that test-session can 
register a
+        // - new namespace|node type|privilege (note: workspace management not 
yet supported)
+
+        // EXERCISE: refactory the test to verify that granting these privs at 
'childPath' doesn;t have the desired effect.
+
+        JackrabbitSession s = (JackrabbitSession) createTestSession();
+
+        NamespaceRegistry nsRegistry = s.getWorkspace().getNamespaceRegistry();
+        nsRegistry.registerNamespace("jr", "http://jackrabbit.apache.org";);
+    }
+}
\ No newline at end of file

Propchange: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L5_SpecialPermissionsTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L6_AdministratativeAccessTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L6_AdministratativeAccessTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L6_AdministratativeAccessTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L6_AdministratativeAccessTest.java
 Thu Jun 18 14:30:16 2015
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.authorization.permission;
+
+import javax.jcr.AccessDeniedException;
+
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.ContentSession;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+import org.apache.jackrabbit.oak.util.NodeUtil;
+import org.junit.Test;
+
+/**
+ * <pre>
+ * Module: Authorization (Permission Evaluation)
+ * 
=============================================================================
+ *
+ * Title: Administrative Permissions
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Learn how the default implementation handles administrative access and makes
+ * sure administrative session always have full access to the repository and
+ * cannot be locked out.
+ *
+ * Exercises:
+ *
+ * - {@link #testAdmininistrativePermissions()}
+ *   Use this test to walk through both read and write access with an 
administrative
+ *   session.
+ *
+ *   Question: Can you identify where there administrative permissions are 
being evaluated?
+ *   Question: Can you list the differences compared to regular permission 
evaluation?
+ *   Question: Can you explain, where the different handling is started and 
what are the criteria?
+ *
+ *
+ * Additional Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * - {@link #testAdministrativeConfiguration()}
+ *   For this test you have to modify the default configuration such that the
+ *   test principal is treated as administrative principal upon evaluation.
+ *   Make sure the test passes and verify the expected result.
+ *
+ * </pre>
+ */
+public class L6_AdministratativeAccessTest extends AbstractSecurityTest {
+
+    @Test
+    public void testAdmininistrativePermissions() throws 
AccessDeniedException, CommitFailedException {
+        // EXERCISE walk through the read access
+        Tree rootTree = root.getTree("/");
+
+        // EXERCISE walk through the add + remove
+        NodeUtil child = new NodeUtil(rootTree).addChild("test", 
NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+        root.commit();
+
+        child.getTree().remove();
+        root.commit();
+    }
+
+    @Override
+    protected ConfigurationParameters getSecurityConfigParameters() {
+        // EXERCISE : change the configuration to make the test principal 
being treated as 'administrative' principal
+        return super.getSecurityConfigParameters();
+    }
+
+    @Test
+    public void testAdministrativeConfiguration() throws Exception {
+        // EXERCISE once you have defined the right permission-eval 
configuration options
+        // EXERCISE the test principal should be treated as 'administrative' 
principal and the test should pass.
+
+        ContentSession testSession = createTestSession();
+        try {
+            Root testRoot = testSession.getLatestRoot();
+            Tree rootTree = testRoot.getTree("/");
+
+            // EXERCISE walk through the add + remove
+            NodeUtil child = new NodeUtil(rootTree).addChild("test", 
NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+            child.setString("prop", "val");
+            testRoot.commit();
+
+            child.getTree().remove();
+            testRoot.commit();
+
+        } finally {
+            testSession.close();
+        }
+
+    }
+}
\ No newline at end of file

Propchange: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L6_AdministratativeAccessTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L7_PermissionContentTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L7_PermissionContentTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L7_PermissionContentTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L7_PermissionContentTest.java
 Thu Jun 18 14:30:16 2015
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.authorization.permission;
+
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.junit.Test;
+
+/**
+ * <pre>
+ * Module: Authorization (Permission Evaluation)
+ * 
=============================================================================
+ *
+ * Title: Representation of Permissions in the Repository
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Understand how the default implementation represents permissions in the 
repository.
+ * This advanced exercise aims to provide you with some insights to the 
permission
+ * store and how permissions are being evaluated from the content stored
+ * therein.
+ *
+ * Exercises:
+ *
+ * - Overview
+ *   Look {@code 
org/apache/jackrabbit/oak/plugins/nodetype/write/builtin_nodetypes.cnd}
+ *   and try to identify the built in node types used to store permission
+ *   content.
+ *
+ *   Question: Can explain the meaning of all types?
+ *   Question: Why are most item definitions protected?
+ *   Question: Can you identify node types that are not used? Can you explain 
why?
+ *
+ * - {@link #testAdministrativeAccessOnly()}
+ *   The permission store is hidden from regular users and can only be
+ *   accessed using an administrative session. Use to test to find out how this
+ *   is enforced by the implementation.
+ *
+ *   Question: Can you imagine why the permission store should only be 
accessible
+ *   to administrative sessions?
+ *   Question: Can you identify the class(es) that actually enforce this?
+ *   Question: Can you explain why the permission store is not 'hidden' like 
the
+ *   index content? Compare these different approaches and discuss your 
findings.
+ *
+ * - {@link #testReadOnly()}
+ *   The permission store is a system maintained structure and cannot be edited
+ *   using JCR or Oak API calls. This test aims to illustrate this behavior.
+ *
+ *   Question: Can you explain why the permission store is read-only?
+ *   Question: Can you identify the class(es) responsible for enforcing the 
read-only nature?
+ *
+ * - {@link #TODO}
+ *
+ * </pre>
+ */
+public class L7_PermissionContentTest extends AbstractSecurityTest {
+
+    @Test
+    public void testReadOnly() {
+        // TODO
+    }
+
+    @Test
+    public void testAdministrativeAccessOnly() {
+        // TODO
+    }
+
+}
\ No newline at end of file

Propchange: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/L7_PermissionContentTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/general/IntroductionTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/general/IntroductionTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/general/IntroductionTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/general/IntroductionTest.java
 Thu Jun 18 14:30:16 2015
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.general;
+
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+
+/**
+ * <pre>
+ * Module: Security General
+ * 
=============================================================================
+ *
+ * Title: Introduction
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Get an overview over the various security related parts and modules present
+ * in Oak and how they interact.
+ *
+ * Exercises:
+ *
+ * - {@link #TODO}
+ *
+ *
+ * Additional Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * TODO
+ *
+ * </pre>
+ *
+ * @see TODO
+ */
+public class IntroductionTest extends AbstractSecurityTest {
+
+
+}
\ No newline at end of file

Propchange: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/general/IntroductionTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L1_IntroductionTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L1_IntroductionTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L1_IntroductionTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L1_IntroductionTest.java
 Thu Jun 18 14:30:16 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.security.principal;
+
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.jackrabbit.test.AbstractJCRTest;
+
+/**
+ * <pre>
+ * Module: Principal Management
+ * 
=============================================================================
+ *
+ * Title: Introduction to Principal Management
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Understand the usage of principal management in Oak and become familiar with
+ * the difference between the Jackrabbit {@link PrincipalManager} and the
+ * {@link PrincipalProvider} exposed by Oak SPI.
+ *
+ * Exercises:
+ *
+ * - Overview and Usages of Principal Management
+ *   Search for usage of principal management API (e.g. the {@link 
org.apache.jackrabbit.api.security.principal.PrincipalManager}
+ *   and {@link 
org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider}
+ *   interface in Oak _and_ Jackrabbit JCR Commons. List your findings and 
discuss the impact.
+ *
+ *   Question: Where is the principal manager|provider being used for?
+ *   Question: Who is the expected API consumer?
+ *   Question: What are the characteristics of this areas?
+ *   Question: What can you say about the relation of principal management and 
authentication?
+ *   Question: What can you say about the relation of principal management and 
authorization?
+ *
+ *
+ * - Configuration
+ *   Look at the default implementation of the {@link 
org.apache.jackrabbit.oak.spi.security.principal.PrincipalConfigurationConfiguration}
+ *   and try to identify the configurable parts. Compare your results with the
+ *   Oak documentation.
+ *
+ *   Question: Can you provide a list of configuration options?
+ *
+ * - Pluggability
+ *   Become familar with the pluggable nature of the principal management
+ *
+ *   Question: What means does Oak provide to change or extend the set of 
principals exposed?
+ *   Question: What interfaces do you need to implement?
+ *   Question: Is it possible to combine different principal implementations? 
How does that work?
+ *
+ *
+ * Additional Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * - Discuss why principal management API is read only.
+ *
+ *   Question: How are principals exposed by the {@link PrincipalManager} 
collected?
+ *   Question: How does the default implementation look like?
+ *
+ *
+ * Advanced Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * If you want to dig deeper into the principal management implementation 
details
+ * you may want to play around with plugging your custom principal provider 
instance
+ * or replacing the default setup altogether.
+ *
+ * - Write your your custom implemenation of the principal provider and deploy 
it
+ *   in an OSGi based repository setup. Observe the effect it has on principal
+ *   management, authentication and authorization.
+ *
+ *
+ * Related Exercises
+ * 
-----------------------------------------------------------------------------
+ *
+ * - {@link L2_PrincipalManagerTest}
+ * - {@link L4_PrincipalProviderTest}
+ * - {@link L3_EveryoneTest}
+ *
+ * </pre>
+ *
+ * @see org.apache.jackrabbit.api.security.principal.PrincipalManager
+ * @see org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider
+ */
+public class L1_IntroductionTest extends AbstractJCRTest {
+
+}
\ No newline at end of file

Propchange: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L1_IntroductionTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L2_PrincipalManagerTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L2_PrincipalManagerTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L2_PrincipalManagerTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L2_PrincipalManagerTest.java
 Thu Jun 18 14:30:16 2015
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.principal;
+
+import java.security.Principal;
+import java.util.Set;
+import javax.jcr.RepositoryException;
+
+import com.google.common.collect.Sets;
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.principal.PrincipalIterator;
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.apache.jackrabbit.test.NotExecutableException;
+
+/**
+ * <pre>
+ * Module: Principal Management
+ * 
=============================================================================
+ *
+ * Title: Principal Manager
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Get familiar with the {@link 
org.apache.jackrabbit.api.security.principal.PrincipalManager}
+ * interface.
+ *
+ * Exercises:
+ *
+ * - {@link #testHasPrincipal()}
+ *   Walk through the test for an existing principal name to become familiar
+ *   with the principal lookup.
+ *   Complete the method {@link #getNonExistingPrincipalName()} such that the 
test passes.
+ *
+ *
+ * - {@link #testGetPrincipal()}
+ *   Same as above for {@link PrincipalManager#getPrincipal(String)}
+ *
+ * - {@link #testFindPrincipals()}
+ *   Become familiar with the principal query: Look at the API contract and
+ *   try different variants of the {@link 
PrincipalManager#findPrincipals(String, int)} call.
+ *
+ * - {@link #testGetGroupMembership()}
+ *   Retrive the principal groups our test principal is member of.
+ *   Question: What is the expected result?
+ *   Question: Is there a minimal set of principals? If yes, why?
+ *
+ *
+ * Additional Exercises
+ * 
-----------------------------------------------------------------------------
+ *
+ * - {@link #testMyPrincipal()}
+ *   Make use of the characteristics of the default principal management
+ *   implementation and adjust the test case such that it passes.
+ *
+ *
+ * Related Exercises
+ * 
-----------------------------------------------------------------------------
+ *
+ * - {@link L3_EveryoneTest}
+ *
+ * </pre>
+ *
+ * @see org.apache.jackrabbit.api.security.principal.PrincipalManager
+ */
+public class L2_PrincipalManagerTest extends AbstractJCRTest {
+
+    private PrincipalManager principalManager;
+
+    private String testPrincipalName;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        principalManager = ((JackrabbitSession) 
superuser).getPrincipalManager();
+
+        // NOTE: this method call doesn't make to much sense outside of a
+        // simple test with a very limited number of principals (!!)
+        PrincipalIterator principalIterator = 
principalManager.getPrincipals(PrincipalManager.SEARCH_TYPE_NOT_GROUP);
+        if (principalIterator.hasNext()) {
+            testPrincipalName = principalIterator.nextPrincipal().getName();
+        }
+
+        if (testPrincipalName == null) {
+            throw new NotExecutableException();
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    private String getNonExistingPrincipalName() {
+        // EXERCISE: return a non existing principal name (Q: what could you 
do instead of guessing?)
+        return null;
+    }
+
+    public void testHasPrincipal() throws RepositoryException {
+        assertTrue(principalManager.hasPrincipal(testPrincipalName));
+
+        
assertFalse(principalManager.hasPrincipal(getNonExistingPrincipalName()));
+    }
+
+    public void testGetPrincipal() throws RepositoryException {
+        Principal principal = principalManager.getPrincipal(testPrincipalName);
+        assertNotNull(principal);
+
+        
assertNull(principalManager.getPrincipal(getNonExistingPrincipalName()));
+    }
+
+    public void testFindPrincipals() throws RepositoryException {
+        String searchHint = testPrincipalName;             // EXERCISE: play 
with the search hint
+        int searchType = PrincipalManager.SEARCH_TYPE_ALL; // EXERCISE: modify 
the type flag
+
+        PrincipalIterator principalIterator = 
principalManager.findPrincipals(testPrincipalName, searchType);
+
+        // EXERCISE: what is the expected query result depending on the search 
hint and the type-flag?
+    }
+
+    public void testGetGroupMembership() throws RepositoryException {
+        Principal principal = principalManager.getPrincipal(testPrincipalName);
+
+        PrincipalIterator groups = 
principalManager.getGroupMembership(principal);
+        // EXERCISE: what group principals do you expect here?
+    }
+
+    public void testMyPrincipal() throws RepositoryException {
+        String principalName = "myPrincipal";
+
+        // EXERCISE : fix the test case
+        // HINT : take advantage of the default implemenation (i.e. it's 
relation to user management)
+
+        try {
+            Principal testPrincipal = 
principalManager.getPrincipal(principalName);
+            assertNotNull(testPrincipal);
+
+            Set<String> groupNames = Sets.newHashSet("myGroup", 
EveryonePrincipal.NAME);
+            PrincipalIterator groups = 
principalManager.getGroupMembership(testPrincipal);
+            while (groups.hasNext()) {
+                groupNames.remove(groups.nextPrincipal().getName());
+            }
+
+            assertTrue(groupNames.isEmpty());
+        } finally {
+            // EXERCISE: cleanup
+        }
+    }
+
+
+}
\ No newline at end of file

Propchange: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L2_PrincipalManagerTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L3_EveryoneTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L3_EveryoneTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L3_EveryoneTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L3_EveryoneTest.java
 Thu Jun 18 14:30:16 2015
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.principal;
+
+import java.security.Principal;
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.principal.PrincipalIterator;
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.test.AbstractJCRTest;
+
+/**
+ * <pre>
+ * Module: Principal Management
+ * 
=============================================================================
+ *
+ * Title: Everyone Test
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Understand the role of the {@link 
org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal}
+ *
+ * Exercises:
+ *
+ * - {@link #testEveryoneExists()}
+ *   Test to illustrate the that everyone principal always exists and always is
+ *   an instanceof {@link java.security.acl.Group} even if there is no 
corresponding
+ *   authorizable.
+ *   Discuss the meaning of the everyone principal and why having a 
corresponding authorizable is optional.
+ *   Note the difference between java.security.acl.Group and 
org.apache.jackrabbit.api.security.user.Group.
+ *
+ * - {@link #testEveryoneName()}
+ *   Test to illustrate that the name of the everyone principal is constant.
+ *   Complete the test case by typing the expected name.
+ *
+ * - {@link #testAccessByName()}
+ *   Even though there exists a dedicated method to retrieve the everyone 
principal
+ *   you can equally access it by name.
+ *   Use the principal management API to retrieve the everyone principal by 
name.
+ *   Discuss the drawback of this approach in an environment where you don't 
have access to the Oak constants.
+ *
+ * - {@link #testEveryoneIsMemberofEveryone()}
+ *   Test case illustrating the dynamic nature of the everyone principal.
+ *   Walk through the test
+ *   Try to extend the test such that the default principal management exposes 
additional user|group principals.
+ *
+ * - {@link #testEveryoneAsAuthorizableGroup()}
+ *   Additional test illustrating that the dynamic nature of the everyone 
principal
+ *   does not change if there exists a corresponding authorizable group.
+ *   > Create a new authorizable that corresponds to the everyone principal 
(Q: what parameters are constants?)
+ *   > Verify that principal exposed by the authorizable corresponds to the 
everyone principal.
+ *   > Assert that the dynamic nature of the principal has not changed.
+ *   > Test if the dynamic nature also applies to the authorizable
+ *
+ *
+ * Additional Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * The following exercises can easily be performed in a Sling based repository
+ * installation (e.g. Granite|CQ) with the same setup as in this test class.
+ *
+ * - Test if there exists an everyone authorizable group.
+ *   If this is the case try what happens if you remove that authorizable and 
discuss the consequences.
+ *   Question: Can you explain why it exists?
+ *
+ * </pre>
+ *
+ * @see org.apache.jackrabbit.oak.security.user.L3_UserVsPrincipalTest
+ */
+public class L3_EveryoneTest extends AbstractJCRTest {
+
+    private PrincipalManager principalManager;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        principalManager = ((JackrabbitSession) 
superuser).getPrincipalManager();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    public void testEveryoneExists() throws RepositoryException {
+        Principal everyone = principalManager.getEveryone();
+
+        assertNotNull(everyone);
+        assertTrue(everyone instanceof java.security.acl.Group);
+
+        Authorizable everyoneAuthorizable = ((JackrabbitSession) 
superuser).getUserManager().getAuthorizable(everyone);
+        assertNull(everyoneAuthorizable);
+    }
+
+    public void testEveryoneName() throws RepositoryException {
+        Principal everyone = principalManager.getEveryone();
+
+        String expectedName = null; // EXERCISE type the expected authorizable 
name using constants defined by oak.
+        assertEquals(expectedName, everyone.getName());
+    }
+
+    public void testAccessByName() throws RepositoryException {
+        Principal everyone = principalManager.getEveryone();
+
+        assertTrue(principalManager.hasPrincipal(everyone.getName()));
+
+        Principal everyoneByName = null; // EXERCISE: retrieve the everyone 
principal by name
+        assertEquals(everyone, everyoneByName);
+    }
+
+    public void testEveryoneIsMemberofEveryone() throws RepositoryException {
+        java.security.acl.Group everyone = (java.security.acl.Group) 
principalManager.getEveryone();
+        PrincipalIterator it = 
principalManager.getPrincipals(PrincipalManager.SEARCH_TYPE_ALL);
+
+        // EXERCISE: discuss the dynamic nature of the everyone group principal
+        while (it.hasNext()) {
+            Principal principal = it.nextPrincipal();
+            if (everyone.equals(principal)) {
+                assertFalse(everyone.isMember(principal));
+            } else {
+                assertTrue(everyone.isMember(principal));
+            }
+        }
+    }
+
+    public void testEveryoneAsAuthorizableGroup() throws RepositoryException {
+        // EXERCISE: create an authorizable that corresponds to the everyone 
principal.
+        org.apache.jackrabbit.api.security.user.Group everyoneAuthorizable = 
null;
+        superuser.save();
+
+        try {
+            java.security.acl.Group everyone = (java.security.acl.Group) 
principalManager.getEveryone();
+
+            assertEquals(everyone, everyoneAuthorizable.getPrincipal());
+
+            // EXERCISE: verify that the everyone principal is still a dynamic 
group
+            // EXERCISE: test if the dyanmic nature also applies to the 
authorizable
+        } finally {
+            if (everyoneAuthorizable != null) {
+                everyoneAuthorizable.remove();
+                superuser.save();
+            }
+        }
+    }
+}
\ No newline at end of file

Propchange: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L3_EveryoneTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L4_PrincipalProviderTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L4_PrincipalProviderTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L4_PrincipalProviderTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L4_PrincipalProviderTest.java
 Thu Jun 18 14:30:16 2015
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.principal;
+
+import java.security.Principal;
+
+import org.apache.jackrabbit.api.security.principal.PrincipalIterator;
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.spi.security.principal.PrincipalConfiguration;
+import org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider;
+import org.apache.jackrabbit.test.NotExecutableException;
+import org.junit.Test;
+
+/**
+ * <pre>
+ * Module: Principal Management
+ * 
=============================================================================
+ *
+ * Title: Principal Provider
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Get familiar with the {@link 
org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider} interface.
+ *
+ * Exercises:
+ *
+ * - {@link #testCorrespondance()}
+ *   List the corresponding calls between {@link PrincipalManager} and {@link 
PrincipalProvider}.
+ *   List also those methods that have no correspondance in either interface.
+ *   Try to identify the reason for having a JCR-level manager and an 
Oak-level provider interface.
+ *
+ *
+ * Additional Exercises
+ * 
-----------------------------------------------------------------------------
+ *
+ * - Take a closer look at the {@link 
org.apache.jackrabbit.oak.spi.security.principal.PrincipalConfiguration}
+ *   and the available implementations.
+ *
+ *   Question: Can you identify how they are used and how principal management 
can
+ *             be extended both in an OSGi-based and regular java setup?
+ *
+ *
+ * Advanced Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * - Complete the {@link 
org.apache.jackrabbit.oak.security.principal.CustomPrincipalProvider}
+ *   stub and deploy the exercise bundle in a Sling base repository 
installation
+ *   (e.g. Cq|Granite).
+ *   > Try to identify the tools that allow you to explore your custom 
principals
+ *   > Play with the dynamic group membership as you define it in the 
principal provider and verify that the subjects calculated upon login are 
correct
+ *   > Play with the authorization part of the principal management 
granting/revoking access for one of your custom principals
+ * </pre>
+ *
+ * @see org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider
+ * @see org.apache.jackrabbit.oak.security.principal.CustomPrincipalProvider
+ * @see 
org.apache.jackrabbit.oak.security.principal.CustomPrincipalConfiguration
+ */
+public class L4_PrincipalProviderTest extends AbstractSecurityTest {
+
+    private PrincipalProvider principalProvider;
+    private PrincipalManager principalManager;
+
+    private String testPrincipalName;
+
+    @Override
+    public void before() throws Exception {
+        super.before();
+
+        principalProvider = 
getConfig(PrincipalConfiguration.class).getPrincipalProvider(root, 
NamePathMapper.DEFAULT);
+        principalManager = 
getConfig(PrincipalConfiguration.class).getPrincipalManager(root, 
NamePathMapper.DEFAULT);
+
+        // NOTE: this method call doesn't make to much sense outside of a
+        // simple test with a very limited number of principals (!!)
+        PrincipalIterator principalIterator = 
principalManager.getPrincipals(PrincipalManager.SEARCH_TYPE_NOT_GROUP);
+        if (principalIterator.hasNext()) {
+            testPrincipalName = principalIterator.nextPrincipal().getName();
+        }
+
+        if (testPrincipalName == null) {
+            throw new NotExecutableException();
+        }
+    }
+
+    @Override
+    public void after() throws Exception {
+        super.after();
+    }
+
+    @Test
+    public void testCorrespondance() {
+        boolean exists = principalManager.hasPrincipal(testPrincipalName);
+        Principal principal = principalManager.getPrincipal(testPrincipalName);
+        PrincipalIterator principalIterator = 
principalManager.findPrincipals(testPrincipalName, 
PrincipalManager.SEARCH_TYPE_ALL);
+        PrincipalIterator groups = 
principalManager.getGroupMembership(principal);
+        PrincipalIterator all = 
principalManager.getPrincipals(PrincipalManager.SEARCH_TYPE_ALL);
+
+        // EXERCISE: write the corresponding calls for the principal provider 
and verify the expected result
+        // EXERCISE: which methods have nor corresponding call in the other 
interface?
+    }
+
+}
\ No newline at end of file

Propchange: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/principal/L4_PrincipalProviderTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L1_IntroductionTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L1_IntroductionTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L1_IntroductionTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L1_IntroductionTest.java
 Thu Jun 18 14:30:16 2015
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.privilege;
+
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+
+/**
+ * <pre>
+ * Module: Privilege Management
+ * 
=============================================================================
+ *
+ * Title: Introduction
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Become familiar with the Privilege Management API defined in
+ * JCR Access Control Management and by the extensions present in Jackrabbit 
API.
+ * Having completed this section should also be familiar with the internals of
+ * privilege management in Oak.
+ *
+ *
+ * Exercises:
+ *
+ * - TODO
+ *
+ *
+ * Related Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * - {@link L2_PrivilegeManagementTest}
+ * - {@link L7_PrivilegeDiscoveryTest}
+ *
+ * </pre>
+ *
+ */
+public class L1_IntroductionTest extends AbstractSecurityTest {
+
+
+}
\ No newline at end of file

Propchange: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L1_IntroductionTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L2_PrivilegeManagementTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L2_PrivilegeManagementTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L2_PrivilegeManagementTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L2_PrivilegeManagementTest.java
 Thu Jun 18 14:30:16 2015
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.privilege;
+
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.JackrabbitWorkspace;
+import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.apache.jackrabbit.test.NotExecutableException;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.Privilege;
+
+/**
+ * <pre>
+ * Module: Privilege Management
+ * 
=============================================================================
+ *
+ * Title: Privilege Management (Basics)
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Learn about the retrieving privileges in {@link 
javax.jcr.security.AccessControlManager)
+ * and the API defined by the {@link 
org.apache.jackrabbit.api.security.authorization.PrivilegeManager}
+ * API extension.
+ *
+ * Exercises:
+ *
+ * - {@link #testGetPrivilege()}
+ *   Use this exercise to become familiar with the different ways to retrieve
+ *   a privilege.
+ *
+ * - {@link #testGetSupportedAndRegisteredPrivileges()}
+ *   Learn about the difference between supported and registered privileges.
+ *   Based on the API contract compare the results of the 2 methods in the 
current
+ *   implementation and discuss different ways of implementation.
+ *
+ *   Question: How could you compare the 'supported' with the 'registered' 
privileges?
+ *   Question: What can you say about the difference?
+ *   Question: What can you say about the default implementation of {@link 
AccessControlManager#getSupportedPrivileges(String)}
+ *
+ *
+ * Related Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * - {@link L3_BuiltInPrivilegesTest}
+ * - {@link L4_CustomPrivilegeTest}
+ *
+ * </pre>
+ *
+ * @see javax.jcr.security.AccessControlManager
+ * @see org.apache.jackrabbit.api.security.authorization.PrivilegeManager
+ */
+public class L2_PrivilegeManagementTest extends AbstractJCRTest {
+
+    private AccessControlManager accessControlManager;
+    private PrivilegeManager privilegeManager;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        accessControlManager = superuser.getAccessControlManager();
+
+        if (!(superuser instanceof JackrabbitSession)) {
+            throw new NotExecutableException("not a JackrabbitSession");
+        }
+        privilegeManager = ((JackrabbitWorkspace) 
superuser.getWorkspace()).getPrivilegeManager();
+    }
+
+    public void testGetPrivilege() throws RepositoryException {
+        String privilegeName = Privilege.JCR_READ;
+
+        Privilege readPriv = null; // EXERCISE: retrieve privilege from 
'accessControlManager'
+        Privilege readPriv2 = null; // EXERCISE: retrive the privilege from 
'privilegeManager'
+
+        assertTrue(readPriv.equals(readPriv2));
+    }
+
+    public void testGetSupportedAndRegisteredPrivileges() throws 
RepositoryException {
+        Privilege[] supportedPrivilges = 
accessControlManager.getSupportedPrivileges(testRoot);
+        Privilege[] registered = privilegeManager.getRegisteredPrivileges();
+
+        // EXERCISE: compare the supported and the registered privileges
+        // EXERCISE: read the API contract for the 2 methods
+    }
+}
\ No newline at end of file

Propchange: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L2_PrivilegeManagementTest.java
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to