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 2015/06/18 16:30:17 UTC

svn commit: r1686235 [4/6] - in /jackrabbit/oak/trunk: ./ oak-doc/src/site/markdown/ oak-exercise/ oak-exercise/src/ oak-exercise/src/main/ oak-exercise/src/main/java/ oak-exercise/src/main/java/org/ oak-exercise/src/main/java/org/apache/ oak-exercise/...

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