Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L3_BuiltInPrivilegesTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L3_BuiltInPrivilegesTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L3_BuiltInPrivilegesTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L3_BuiltInPrivilegesTest.java
 Thu Jun 18 14:30:16 2015
@@ -0,0 +1,189 @@
+/*
+ * 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 java.util.Map;
+import java.util.Set;
+import javax.annotation.Nullable;
+import javax.jcr.RepositoryException;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.AccessControlPolicy;
+import javax.jcr.security.Privilege;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
+import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
+import 
org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.ContentSession;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBitsProvider;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * <pre>
+ * Module: Privilege Management
+ * 
=============================================================================
+ *
+ * Title: The Built-in Privileges
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Understand what built-in privileges are provided by JCR specification and
+ * the Oak repository and what type of operations and items they take
+ * effect upon.
+ *
+ * Exercises:
+ *
+ * - Privilege Overview
+ *   List all privileges defined by JSR 283 and Oak and mark if they are
+ *   aggregated privileges (if yes: what's the aggregation). Try to understand
+ *   the meaning of the individual privileges.
+ *
+ * - {@link #testAggregation()}
+ *   For all built-in aggregated privileges defined the mapping of the name
+ *   to the declared aggregated privileges such that the test passes.
+ *
+ *   Question: What can you say about the nature of {@link Privilege#JCR_READ}
+ *   Question: Review again what JSR 283 states about {@link Privilege#JCR_ALL}
+ *
+ * - {@link #testMapItems()}
+ *   This allows you to become familiar with the mapping of individual 
privileges
+ *   to items. Use the Oak API to change those items directly (instead of using
+ *   the corresponding JCR API call.
+ *   Use the JCR specification, the privilege definitions and {@link 
org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions}
+ *
+ *   Question: Can you map the items to the corresponding JCR API calls? (see 
additional exercises below)
+ *   Question: Can you extract the rules when a dedicated specific privilege is
+ *   being used instead of regular JCR write privileges?
+ *
+ *
+ * Additional Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * - Create a new test-case similar to {@link #testMapItems()} extending from
+ *   {@link org.apache.jackrabbit.test.AbstractJCRTest} and verify your 
findings
+ *   by executing the corresponding JCR API calls.
+ *
+ * Related Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * - {@link L4_CustomPrivilegeTest}
+ *
+ * </pre>
+ *
+ * @see javax.jcr.security.Privilege
+ * @see org.apache.jackrabbit.api.security.authorization.PrivilegeManager
+ * @see javax.jcr.security.AccessControlManager#privilegeFromName(String)
+ * @see org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants
+ */
+public class L3_BuiltInPrivilegesTest extends AbstractSecurityTest {
+
+    private ContentSession testSession;
+    private Root testRoot;
+
+    private AccessControlManager acMgr;
+    private PrivilegeBitsProvider privilegeBitsProvider;
+
+    @Override
+    public void before() throws Exception {
+        super.before();
+
+        testSession = createTestSession();
+        testRoot = testSession.getLatestRoot();
+
+        acMgr = getAccessControlManager(root);
+    }
+
+    @Override
+    public void after() throws Exception {
+        try {
+            if (testSession != null) {
+                testSession.close();
+            }
+        } finally {
+            super.after();
+        }
+    }
+
+    @Test
+    public void testAggregation() throws RepositoryException {
+        PrivilegeManager privilegeManager = getPrivilegeManager(root);
+
+        // EXERCISE: for all aggregated privileges define the mapping of the 
privilege name to declaredAggregates
+        Map<String, Set<Privilege>> expectedResults = ImmutableMap.of(
+                /* EXERCISE */
+        );
+
+        Iterable<Privilege> aggregated = Iterables.<Privilege>filter(
+                
ImmutableList.<Privilege>copyOf(privilegeManager.getRegisteredPrivileges()),
+                new Predicate<Privilege>() {
+                    @Override
+                    public boolean apply(@Nullable Privilege input) {
+                        return input != null && input.isAggregate();
+                    }
+                });
+
+        for (Privilege aggrPrivilege : aggregated) {
+            Set<Privilege> expected = 
expectedResults.get(aggrPrivilege.getName());
+            assertEquals(expected, 
ImmutableSet.copyOf(aggrPrivilege.getDeclaredAggregatePrivileges()));
+        }
+    }
+
+    @Test
+    public void testMapItems() throws Exception {
+        Privilege jcrAll = acMgr.privilegeFromName(PrivilegeConstants.JCR_ALL);
+        for (Privilege privilege : jcrAll.getAggregatePrivileges()) {
+            try {
+                // EXERCISE : modify item(s) affected by the given privilege 
and verify that it fails
+
+                setupAcl(privilege, acMgr);
+                testRoot.refresh();
+
+                // EXERCISE : modify the same item(s) again and verify that it 
succeeds
+
+            } finally {
+                clearAcl(acMgr);
+                testRoot.refresh();
+            }
+
+        }
+    }
+
+    private void setupAcl(Privilege privilege, AccessControlManager acMgr) 
throws Exception {
+        JackrabbitAccessControlList acl = 
AccessControlUtils.getAccessControlList(acMgr, "/");
+        acl.addEntry(getTestUser().getPrincipal(), new Privilege[] 
{privilege}, true);
+        acMgr.setPolicy("/", acl);
+        root.commit();
+    }
+
+    public void clearAcl(AccessControlManager acMgr) throws 
RepositoryException, CommitFailedException {
+        AccessControlPolicy[] policies = acMgr.getPolicies("/");
+        for (AccessControlPolicy policy : policies) {
+            acMgr.removePolicy("/", policy);
+        }
+        root.commit();
+    }
+}
\ No newline at end of file

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

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L4_CustomPrivilegeTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L4_CustomPrivilegeTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L4_CustomPrivilegeTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L4_CustomPrivilegeTest.java
 Thu Jun 18 14:30:16 2015
@@ -0,0 +1,164 @@
+/*
+ * 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 java.security.Principal;
+import java.util.Set;
+import java.util.UUID;
+import javax.annotation.Nullable;
+import javax.jcr.security.Privilege;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
+import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * <pre>
+ * Module: Privilege Management
+ * 
=============================================================================
+ *
+ * Title: Custom Privileges
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * The aim of this exercise is to make you familiar with the API to register
+ * custom privileges and provide you with the basic understanding on how those
+ * are being evaluated and enforced.
+ *
+ * Exercises:
+ *
+ * - {@link #testCustomPrivilege()}
+ *   Use this test to verify the nature of the aggregated custom privilege
+ *   registered in the setup.
+ *
+ * - {@link #testJcrAll()}
+ *   Verify that our custom privileges properly listed in the aggregated 
privileges
+ *   exposed by jcr:all.
+ *
+ *   Question: Having completed this test, what can you say about the nature 
of jcr:all?
+ *   Question: What does that mean for the internal representation of jcr:all?
+ *
+ * - {@link #testHasPrivilege()}
+ *   Fix the test case such that the given set of test princials is granted the
+ *   custom privileges at the test node.
+ *
+ *   Question: Would it also work if you would grant jcr:all for any of the 
test principals?
+ *
+ *
+ * Advanced Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * As you can see in the permission evaluation implementation custom privileges
+ * will NOT be enforced upon read/write to the repository as the nature of the
+ * custom privilege is by definition known to the application responsible for
+ * the registration and therefore must be evaluated/enforced on the application
+ * level as well.
+ *
+ * - Verify this by taking another look at the Oak internal permission 
evaluation.
+ *
+ *   Question: Can you identify which parts in Oak would need to be extended 
and
+ *             which interfaces you would need to implement and plug/replace if
+ *             you wanted to enforce your custom privileges in the repository?
+ *
+ *
+ * Related Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * - {@link org.apache.jackrabbit.oak.security.privilege.L6_JcrAllTest}
+ *
+ * </pre>
+ *
+ * @see 
org.apache.jackrabbit.api.security.authorization.PrivilegeManager#registerPrivilege(String,
 boolean, String[])
+ */
+public class L4_CustomPrivilegeTest extends AbstractSecurityTest {
+
+    private PrivilegeManager privilegeManager;
+    private Privilege customAbstractPriv;
+    private Privilege customAggrPriv;
+
+    @Override
+    public void before() throws Exception {
+        super.before();
+
+        privilegeManager = getPrivilegeManager(root);
+        customAbstractPriv = privilegeManager.registerPrivilege(
+                "customAbstractPriv_" + UUID.randomUUID().toString(), true, 
new String[0]);
+        customAggrPriv = privilegeManager.registerPrivilege(
+                "customAbstractPriv_" + UUID.randomUUID().toString(), false,
+                new String[] {customAbstractPriv.getName(), 
PrivilegeConstants.JCR_READ});
+    }
+
+    private static void assertEqualPrivileges(Set<String> expectedNames, 
Privilege[] result) {
+        if (expectedNames.size() != result.length) {
+            fail();
+        }
+
+        Iterable<String> resultNames = 
Iterables.transform(Sets.newHashSet(result), new Function<Privilege, String>() {
+            @Nullable
+            @Override
+            public String apply(Privilege input) {
+                return input.toString();
+            }
+        });
+
+        Iterables.removeAll(resultNames, expectedNames);
+        assertFalse(resultNames.iterator().hasNext());
+    }
+
+    @Test
+    public void testCustomPrivilege() {
+        Set<String> expected = null; //EXERCISE
+        assertEqualPrivileges(expected, 
customAggrPriv.getDeclaredAggregatePrivileges());
+
+        expected = null; // EXERCISE
+        assertEqualPrivileges(expected, 
customAggrPriv.getAggregatePrivileges());
+
+        Boolean expectedIsAbstract = null; // EXERCISE
+        assertEquals(expectedIsAbstract.booleanValue(), 
customAggrPriv.isAbstract());
+    }
+
+    @Test
+    public void testJcrAll() {
+        // EXERCISE : verify that the custom privileges are contained in the 
jcr:all aggregation
+    }
+
+    @Test
+    public void testHasPrivilege() throws Exception {
+        try {
+            // EXERCISE : fix the test case such that the test principals have 
the specified privileges granted at "/"
+
+            Privilege[] testPrivileges = new Privilege[] {customAbstractPriv, 
customAggrPriv};
+            Set<Principal> testPrincipals = 
ImmutableSet.of(EveryonePrincipal.getInstance(), getTestUser().getPrincipal());
+            boolean hasPrivilege = 
getAccessControlManager(root).hasPrivileges("/", testPrincipals, 
testPrivileges);
+
+            assertTrue(hasPrivilege);
+        } finally {
+            // EXERCISE: cleanup the changes.
+        }
+    }
+}
\ No newline at end of file

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

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L5_PrivilegeContentTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L5_PrivilegeContentTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L5_PrivilegeContentTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L5_PrivilegeContentTest.java
 Thu Jun 18 14:30:16 2015
@@ -0,0 +1,176 @@
+/*
+ * 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 java.util.Set;
+import javax.jcr.RepositoryException;
+import javax.jcr.security.Privilege;
+
+import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBitsProvider;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeDefinition;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeUtil;
+import org.apache.jackrabbit.oak.util.TreeUtil;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * <pre>
+ * Module: Privilege Management
+ * 
=============================================================================
+ *
+ * Title: Representation of Privileges in the Repository
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Understand how privileges are represented in the repository content.
+ *
+ * Exercises:
+ *
+ * - {@link #testPrivilegeRoot()}
+ *   This test retrieves the root node below which all registered privileges 
are
+ *   being stored. Make yourself familiar with the structure by looking at the
+ *   node type definitions in 'builtin-nodetypes.cnd' and complete the test 
case
+ *   such that it passes.
+ *
+ *   Question: What can you say about the structure of the privileges tree in 
the repository?
+ *   Question: Can you explain why it is located below /jcr:system ?
+ *   Question: Go back to {@link 
org.apache.jackrabbit.oak.security.privilege.L4_CustomPrivilegeTest}
+ *   and take a closer look at the tree/node that stores your custom privilege.
+ *
+ * - {@link #testPrivilegeDefinition()}
+ *   Each tree/node presenting a privilege in fact just stores the basic 
definition
+ *   of the privilege. Use this exercise to compare the difference between the
+ *   definition (and it's tree) and the resulting privilege.
+ *
+ *   Question: What properties stored on the privilege definition tree are not 
exposed by
+ *             {@link 
org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeDefinition}?
+ *             -> see advanced exercises.
+ *
+ *
+ * Advanced Exercises
+ * 
-----------------------------------------------------------------------------
+ *
+ * - {@link #testPrivilegeBits()}
+ *   For internal handling of privileges the Oak repository doesn't use the
+ *   privilege names (and the expensive resolution of the aggregation) but
+ *   rather makes use of internal long representation of the privileges.
+ *   Use this exercise to become familiar with
+ *   - {@link 
org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBitsProvider}
+ *   - {@link org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits}
+ *   and how they are represented in the privilege content and how they are
+ *   used to internally deal with privileges.
+ *
+ *   Question: How are PrivilegeBits created from privilege name(s)
+ *   Question: How are they stored with the privilege definition?
+ *   Question: Can you also retrieve the PropertyState on the privilege trees 
that
+ *             effectively stores the long presentation as used in the 
PrivilegeBits?
+ *
+ * - {@link #testNext()}
+ *   This exercises aims to help you understand how the implementation keeps
+ *   track of the internal long representation of privileges and how those
+ *   long representations are being calculated for newly registered privileges.
+ *   Resolve the TODOs in the test-case and explain the behavior.
+ *
+ *   Question: Can you identify where 'rep:next' is being updated?
+ *   Question: Try to set the value of rep:next manually and explain what 
happens.
+ *
+ *
+ * Related Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * - {@link org.apache.jackrabbit.oak.security.privilege.L6_JcrAllTest}
+ * - {@link 
org.apache.jackrabbit.oak.security.authorization.permission.L4_PrivilegesAndPermissionsTest}
+ * - {@link 
org.apache.jackrabbit.oak.security.authorization.permission.L7_PermissionContentTest}
+ *
+ * </pre>
+ */
+public class L5_PrivilegeContentTest extends AbstractSecurityTest {
+
+
+    @Test
+    public void testPrivilegeRoot() {
+        Tree privilegesRoot = root.getTree(PrivilegeConstants.PRIVILEGES_PATH);
+
+        String name = null; // TODO
+        assertEquals(name, privilegesRoot.getName());
+
+        String primaryType = null; // TODO
+        assertEquals(primaryType, TreeUtil.getPrimaryTypeName(privilegesRoot));
+
+        // TODO: look at the node type definition in the file 
'builtin-nodetypes.cnd'
+        // Question: can you predict how the tree defined the 'privilegesRoot' 
tree looks like?
+    }
+
+    @Test
+    public void testPrivilegeDefinition() throws RepositoryException {
+        Tree repWriteTree = 
PrivilegeUtil.getPrivilegesTree(root).getChild(PrivilegeConstants.REP_WRITE);
+
+        PrivilegeDefinition def = PrivilegeUtil.readDefinition(repWriteTree);
+
+        String expectedName = null; // TODO
+        assertEquals(expectedName, def.getName());
+
+        boolean isAbstract = false; // TODO
+        assertEquals(isAbstract, def.isAbstract());
+
+        Set<String> expectedAggregates = null; // TODO
+        assertEquals(expectedAggregates, def.getDeclaredAggregateNames());
+
+        // TODO: compare the internal privilege definition (and it's tree 
representation) with the privilege itself.
+        Privilege repWritePrivilege = 
getPrivilegeManager(root).getPrivilege(PrivilegeConstants.REP_WRITE);
+    }
+
+    @Test
+    public void testPrivilegeBits() {
+        Tree jcrReadTree = 
PrivilegeUtil.getPrivilegesTree(root).getChild(PrivilegeConstants.JCR_READ);
+        Tree repWriteTree = 
PrivilegeUtil.getPrivilegesTree(root).getChild(PrivilegeConstants.REP_WRITE);
+
+        PrivilegeBitsProvider provider = new PrivilegeBitsProvider(root);
+        PrivilegeBits privilegeBits = 
provider.getBits(PrivilegeConstants.REP_WRITE, PrivilegeBits.JCR_READ);
+
+        PrivilegeBits readBits = PrivilegeBits.getInstance(jcrReadTree);
+        PrivilegeBits writeBits = PrivilegeBits.getInstance(jcrReadTree);
+
+        // TODO: play with 'PrivilegeBits' methods to compare 'privilegeBits' 
with 'readBits' and 'writeBits'
+        // TODO: retrieve the property that stores the long representation of 
each privilege above
+    }
+
+    @Test
+    public void testNext() throws RepositoryException, CommitFailedException {
+        PropertyState next = 
PrivilegeUtil.getPrivilegesTree(root).getProperty(PrivilegeConstants.REP_NEXT);
+
+        PrivilegeManager privilegeManager = getPrivilegeManager(root);
+        Privilege newPrivilege = 
privilegeManager.registerPrivilege("myPrivilege", true, null);
+        root.commit();
+
+        // TODO: compare the 'next' property state with rep:bits property of 
the newly created privilege.
+
+        PropertyState nextAgain = 
PrivilegeUtil.getPrivilegesTree(root).getProperty(PrivilegeConstants.REP_NEXT);
+
+        // TODO: look at the new value of rep:next and explain it. Q: where 
did it get modified?
+
+        // TODO: try to modify rep:next manually and explain what happens.
+    }
+}
\ No newline at end of file

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

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L6_JcrAllTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L6_JcrAllTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L6_JcrAllTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L6_JcrAllTest.java
 Thu Jun 18 14:30:16 2015
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.privilege;
+
+import javax.jcr.security.Privilege;
+
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeUtil;
+import org.junit.Test;
+
+/**
+ * <pre>
+ * Module: Privilege Management
+ * 
=============================================================================
+ *
+ * Title: The Privilege 'jcr:all'
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Understand the meaning of the jcr:all privilege and how it is maintained
+ * in the Oak repository.
+ *
+ * Exercises:
+ *
+ * - Overview
+ *   Read again what JSR 283 states about {@link Privilege#JCR_ALL) and review
+ *   again the result of {@link L4_CustomPrivilegeTest#testJcrAll()}
+ *
+ * - {@link #testManualModification()}
+ *   This test case tries to modify the tree storing the jcr:all privilege
+ *   definition. Walk through the test and explain what happens.
+ *   Fix the test case such that it passes.
+ *
+ *   Question: Can you identify the relevant class in the Oak code base?
+ *   Question: Can you explain what it does and why?
+ *
+ *
+ * Advanced Exercise
+ * 
-----------------------------------------------------------------------------
+ *
+ * - {@link #testJcrAllInPermissionStore()}
+ *   Due to the dynamic nature of jcr:all the long-representation of this 
privilege
+ *   may change over time.
+ *   This exercise aim to show you how granting|denying jcr:all is reflected
+ *   in the permission store.
+ *
+ *
+ * </pre>
+ */
+public class L6_JcrAllTest extends AbstractSecurityTest {
+
+    @Test
+    public void testManualModification() throws Exception {
+        // TODO: fix the test case such that it passes.
+
+        Tree jcrAllTree = 
PrivilegeUtil.getPrivilegesTree(root).getChild(PrivilegeConstants.JCR_ALL);
+
+        jcrAllTree.removeProperty(PrivilegeConstants.REP_AGGREGATES);
+        root.commit();
+    }
+
+    @Test
+    public void testJcrAllInPermissionStore() {
+        // TODO
+    }
+}
\ No newline at end of file

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

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L7_PrivilegeDiscoveryTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L7_PrivilegeDiscoveryTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L7_PrivilegeDiscoveryTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/privilege/L7_PrivilegeDiscoveryTest.java
 Thu Jun 18 14:30:16 2015
@@ -0,0 +1,74 @@
+/*
+ * 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.test.AbstractJCRTest;
+
+/**
+ * <pre>
+ * Module: Privilege Management | Authorization
+ * 
=============================================================================
+ *
+ * Title: Privilege Discovery
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * The aim of this exercise is to make you familiar on how to discover 
privileges
+ * granted for a given {@link javax.jcr.Session} or a given set of {@link 
java.security.Principal}s.
+ * After having completed this exercise you should be able to explain the 
difference
+ * compare to permission discovery as well as the benefit/drawback of using
+ * this API.
+ *
+ * Exercises:
+ *
+ * - {@link #testHasPrivileges()}
+ *   TODO
+ *
+ * - {@link #testGetPrivileges()}
+ *   TODO
+ *
+ * - {@link #testCanAddNode()}
+ *   TODO
+ *
+ *
+ * Related Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * - {@link 
org.apache.jackrabbit.oak.security.authorization.permission.L2_PermissionDiscoveryTest}
+ * - {@link 
org.apache.jackrabbit.oak.security.authorization.permission.L4_PrivilegesAndPermissionsTest}
+ *
+ * </pre>
+ *
+ * @see TODO
+ */
+public class L7_PrivilegeDiscoveryTest extends AbstractJCRTest {
+
+    public void testHasPrivileges() {
+        // TODO
+    }
+
+    public void testGetPrivileges() {
+        // TODO
+    }
+
+    public void testCanAddNode() {
+        // TODO
+    }
+    // TODO; diff wrt session.haspermission
+    // TODO: Acmgr.hasPrivilege || getPrivileges
+
+}
\ No newline at end of file

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

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L10_RemovalAndMembershipTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L10_RemovalAndMembershipTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L10_RemovalAndMembershipTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L10_RemovalAndMembershipTest.java
 Thu Jun 18 14:30:16 2015
@@ -0,0 +1,177 @@
+/*
+ * 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.user;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.security.ExerciseUtility;
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * <pre>
+ * Module: User Management
+ * 
=============================================================================
+ *
+ * Title: Authorizable Removal and Group Membership
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Understand how the removal of a given authorizable affects it's group 
membership.
+ *
+ * Exercises:
+ *
+ * - {@link #testMemberAfterRecreation()}
+ *   Run the test and explain why after removal and re-creation the new user is
+ *   automatically member of the test group.
+ *
+ * - {@link #testNotMemberAfterRecreation()}
+ *   This is the same test as above but now the re-created test-user must not
+ *   be member of 'administrators'. How do you need to do in order to make the
+ *   test case pass?
+ *
+ *
+ * Additional Exercise:
+ * 
-----------------------------------------------------------------------------
+ *
+ * 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:
+ *
+ * 1. Test Setup
+ *
+ * - Login as 'admin'
+ * - Create a test-user and make it member of the 'administrators' group.
+ * - Create a second user 'uadmin:uadmin' and make sure it is granted all 
privileges
+ *   at the node of the test-user (Variant: make it member of 
'user-administrators'.
+ * - Verify that your changes have been persisted.
+ *
+ * 2. Automatic Membership Cleanup
+ *
+ * - Configure your system such that membership cleanup is performed upon
+ *   removal of the test user.
+ *   Explain what you need to do (Hint: authorizable actions).
+ *
+ * 3. Test Execution with 'uadmin'
+ *
+ * - Logout
+ * - Login with the 'uadmin' user which can remove the test-user
+ * - Remove the test-user and persist the changes
+ * - Login as 'admin' again and test if the user has been removed; if yes, 
recreate
+ *   it and verify and if members-list at 'administrators' has been adjust 
(test-user removed).
+ *
+ * - Explain the result both for the main and variant.
+ *   > the removal failed: explain why?
+ *   > the member-cleanup didn't succeed: explain why?
+ *
+ * 4. Test Execution with 'admin'
+ *
+ * - Perform the same test as 'admin' and compare the result with 3.
+ * - Explain whats the difference and why it works.
+ *
+ *
+ * Advanced Exercise:
+ * 
-----------------------------------------------------------------------------
+ *
+ * - Discuss the possibilities Oak which could help to address the drawback 
you identified
+ *   with the {@link 
org.apache.jackrabbit.oak.spi.security.user.action.AuthorizableAction}
+ *   approach.
+ *
+ *
+ * Related Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * - {@link L9_RemoveAuthorizableTest ()}
+ *
+ * </pre>
+ *
+ * @see Group#addMember(org.apache.jackrabbit.api.security.user.Authorizable)
+ * @see 
Group#removeMember(org.apache.jackrabbit.api.security.user.Authorizable)
+ * @see Group#isMember(org.apache.jackrabbit.api.security.user.Authorizable)
+ * @see org.apache.jackrabbit.api.security.user.Authorizable#memberOf()
+ * @see 
org.apache.jackrabbit.oak.spi.security.user.action.ClearMembershipAction
+ */
+public class L10_RemovalAndMembershipTest extends AbstractSecurityTest {
+
+    private User user;
+    private Group administrators;
+
+    @Override
+    public void before() throws Exception {
+        super.before();
+
+        user = getTestUser();
+
+        administrators = getUserManager(root).createGroup("administrators");
+        administrators.addMember(user);
+
+        root.commit();
+    }
+
+    @Override
+    public void after() throws Exception {
+        try {
+            if (administrators != null) {
+                administrators.remove();
+                root.commit();
+            }
+        } finally {
+            super.after();
+        }
+    }
+
+    @Test
+    public void testMemberAfterRecreation() throws RepositoryException, 
CommitFailedException {
+        // remove the user
+        String id = user.getID();
+        user.remove();
+        root.commit();
+
+        // create a new user with the same ID
+        User u = getUserManager(root).createUser(id, ExerciseUtility.TEST_PW);
+        root.commit();
+
+        // EXERCISE: explain why this user cannot be added as member?
+        assertFalse(administrators.addMember(u));
+
+        // EXERCISE: explain why is this user is still member of the test 
group?
+        assertTrue(administrators.isDeclaredMember(u));
+    }
+
+    @Test
+    public void testNotMemberAfterRecreation() throws RepositoryException, 
CommitFailedException {
+
+        // EXERCISE : adjust the test-case such that upon re-creation the user 
is not member of administrators.
+        // HINT : do it right here
+
+        // remove the user
+        String id = user.getID();
+        user.remove();
+        root.commit();
+
+        // create a new user with the same ID
+        User u = getUserManager(root).createUser(id, ExerciseUtility.TEST_PW);
+        root.commit();
+
+        assertFalse(administrators.isDeclaredMember(u));
+    }
+}
\ No newline at end of file

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

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L11_PasswordTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L11_PasswordTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L11_PasswordTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L11_PasswordTest.java
 Thu Jun 18 14:30:16 2015
@@ -0,0 +1,209 @@
+/*
+ * 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.user;
+
+import javax.jcr.Credentials;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.oak.security.ExerciseUtility;
+import org.apache.jackrabbit.test.AbstractJCRTest;
+
+import static org.apache.jackrabbit.oak.security.ExerciseUtility.TEST_PW;
+
+/**
+ * <pre>
+ * Module: User Management
+ * 
=============================================================================
+ *
+ * Title: Password Test
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Become familiar with password related parts of the user management API and
+ * get to know some implementation details.
+ *
+ * Exercises:
+ *
+ * - {@link #testGetCredentials()}
+ *   Understand that the password is not exposed as plain-word property from
+ *   the user. Look at the return-value of the {@link 
org.apache.jackrabbit.api.security.user.User#getCredentials()}
+ *   call and what it looks like. Fix the test-case accordingly.
+ *
+ *   Question: Can you use the exposed Credentials to login to the repository?
+ *
+ * - {@link #testPasswordInContent()}
+ *   Creates a new user with a valid password. Inspect how the password is 
being
+ *   store in the repository (Note: implementation detail!) and fill in the
+ *   right property name to get the test-case pass.
+ *   Explain why the password property doesn't contain the password string.
+ *
+ * - {@link #testCreateUserAndLogin()}
+ *   Same as {@link #testPasswordInContent()} but additional aims to login as
+ *   the new user.
+ *   Fix the test by creating the correct {@link javax.jcr.Credentials}.
+ *
+ * - {@link #testCreateUserWithoutPassword()}
+ *   This test creates a new user with a 'null' password. Inspect the user node
+ *   created by this method and add the correct assertion wrt password.
+ *
+ * - {@link #testCreateUserWithoutPasswordAndLogin()}
+ *   Same as {@link #testCreateUserWithoutPassword()}. This time fix the test
+ *   case to properly reflect the expected behavior upon login for that new 
user.
+ *
+ * - {@link #testChangePassword()}
+ *   Change the password of an existing user. Use both variants and get 
familiar
+ *   with the implementation specific constraints.
+ *
+ *
+ * Additional Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * In a OSGI-based Oak installation (Sling|Granite|CQ) you can easily perform 
the
+ * following additional test.
+ * Note: You can also do that in Java by building a new Jcr/Oak repository with
+ * the corresponding configuration parameters set.
+ *
+ * - Go to the system console and change the default configuration parameters
+ *   in the 'Apache Jackrabbit Oak UserConfiguration' and play with the 
following
+ *   configuration parameters:
+ *   - {@link 
org.apache.jackrabbit.oak.spi.security.user.UserConstants#PARAM_PASSWORD_HASH_ALGORITHM}
+ *   - {@link 
org.apache.jackrabbit.oak.spi.security.user.UserConstants#PARAM_PASSWORD_HASH_ITERATIONS}
+ *   - {@link 
org.apache.jackrabbit.oak.spi.security.user.UserConstants#PARAM_PASSWORD_SALT_SIZE}
+ *   Change the password of a test user and observe the changes.
+ *
+ * - Go to the system console and look for the 'Apache Jackrabbit Oak 
AuthorizableActionProvider'.
+ *   Enable the password validation action and then change the password of
+ *   an existing test user.
+ *
+ *
+ * Advanced Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * - Write a custom password validation action and plug it into your 
repository.
+ *   See Oak documentation for some hints.
+ *
+ *
+ * Related Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * - {@link L12_PasswordExpiryTest ()}
+ * - {@link 
org.apache.jackrabbit.oak.security.user.action.L2_AuthorizableActionTest ()}
+ *
+ * </pre>
+ *
+ * @see User#changePassword(String, String)
+ * @see User#changePassword(String)
+ * @see 
org.apache.jackrabbit.oak.spi.security.user.action.PasswordValidationAction
+ * @see org.apache.jackrabbit.oak.spi.security.user.util.PasswordUtil
+ */
+public class L11_PasswordTest extends AbstractJCRTest {
+
+    private UserManager userManager;
+
+    private String testId;
+    private User testUser;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        userManager = ((JackrabbitSession) superuser).getUserManager();
+        testId = ExerciseUtility.getTestId("testUser");
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        try {
+            if (testUser != null) {
+                testUser.remove();
+            }
+            superuser.save();
+        } finally {
+            super.tearDown();
+        }
+    }
+
+    public void testGetCredentials() throws RepositoryException {
+        testUser = userManager.createUser(testId, TEST_PW);
+        Credentials creds = testUser.getCredentials();
+
+        // EXERCISE fix the expectation
+        Credentials expected = null;
+        assertEquals(expected, creds);
+
+        // EXERCISE : complete and explain the expected behavior
+        getHelper().getRepository().login(creds).logout();
+    }
+
+    public void testPasswordInContent() throws RepositoryException {
+        testUser = userManager.createUser(testId, TEST_PW);
+        superuser.save();
+
+        Node userNode = superuser.getNode(testUser.getPath());
+        String pwPropertyName = null; // EXERCISE: fill in
+
+        Property pwProperty = userNode.getProperty(pwPropertyName);
+
+        // EXERCISE: explain why the password property doesn't contain the 
'pw' string
+        assertFalse(TEST_PW.equals(pwProperty.getString()));
+    }
+
+    public void testCreateUserAndLogin() throws RepositoryException {
+        testUser = userManager.createUser(testId, TEST_PW);
+        superuser.save();
+
+        Credentials creds = null; // EXERCISE build the credentials
+        getHelper().getRepository().login(creds).logout();
+    }
+
+    public void testCreateUserWithoutPassword() throws RepositoryException {
+        testUser = userManager.createUser(testId, null);
+        superuser.save();
+
+        // EXERCISE: look at the user node. does it have a password property 
set?
+        // EXERCISE: add the correct assertion
+        Node userNode = superuser.getNode(testUser.getPath());
+    }
+
+    public void testCreateUserWithoutPasswordAndLogin() throws 
RepositoryException {
+        testUser = userManager.createUser(testId, null);
+        superuser.save();
+
+        // EXERCISE: build the credentials and fix the test-case such that it 
no longer fails
+        Credentials creds = null;
+        getHelper().getRepository().login(creds).logout();
+    }
+
+    public void testChangePassword() throws RepositoryException {
+        testUser = userManager.createUser(testId, null);
+        superuser.save();
+
+        String newPassword = null; // EXERCISE : define valid value(s)
+        testUser.changePassword(newPassword);
+
+        String oldPassword = null; // EXERCISE : fill in the correct value
+        newPassword = null;        // EXERCISE : fill in a valid value; Q: can 
you use null?
+        testUser.changePassword(newPassword, oldPassword);
+
+        superuser.save();
+    }
+}
\ No newline at end of file

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

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L12_PasswordExpiryTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L12_PasswordExpiryTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L12_PasswordExpiryTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L12_PasswordExpiryTest.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.user;
+
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+
+/**
+ * <pre>
+ * Module: User Management
+ * 
=============================================================================
+ *
+ * Title: Password Expiration
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Understand the password expiration feature how it can be enabled in the
+ * repository.
+ *
+ * Exercises:
+ *
+ * - {@link #TODO}
+ *
+ *
+ * Additional Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * TODO
+ *
+ * </pre>
+ *
+ * @see TODO
+ */
+public class L12_PasswordExpiryTest extends AbstractSecurityTest {
+
+
+}
\ No newline at end of file

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

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L13_SystemUserTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L13_SystemUserTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L13_SystemUserTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L13_SystemUserTest.java
 Thu Jun 18 14:30:16 2015
@@ -0,0 +1,213 @@
+/*
+ * 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.user;
+
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import javax.jcr.Credentials;
+import javax.jcr.RepositoryException;
+
+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.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.security.ExerciseUtility;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import org.apache.jackrabbit.oak.util.TreeUtil;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * <pre>
+ * Module: User Management
+ * 
=============================================================================
+ *
+ * Title: System Users
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Understand the difference between system users and regular users and why we
+ * decided to introduce a dedicated API for system users in Jackrabbit API 
2.10.
+ *
+ * Exercises:
+ *
+ * - Overview
+ *   Walk through the system user creation in the setup and also take a closer
+ *   look at the node type definition in the builtin_nodetypes.cnd
+ *
+ *   Question: What can you say about the {@code rep:SystemUser} node type 
definition?
+ *   Question: Can you explain how this is reflected in the default user 
management implementation?
+ *   Question: How is a system user different from a regular user? Can you 
list all differences?
+ *
+ * - {@link #testSystemUser()}
+ *   This test retrieves the system user created in the setup. Complete the
+ *   test to become familiar with the handing of system users in the user
+ *   management API.
+ *
+ * - {@link #testSystemUserNode()}
+ *   This test illustrates some of the implementation details on how system 
users
+ *   are being represented in the repository. Complete the test to get it pass.
+ *
+ *   Question: Can you explain what the 'memberOf' method will return if there
+ *             exists an everyone authorizable group?
+ *
+ * - {@link #testSystemUserPrincipal()}
+ *   Look at the principal associated with the system user created in the 
setup.
+ *   Verify your expectations wrt principal name and type of principal and the
+ *   group membership and fix the test accordingly.
+ *
+ *   Question: Can you elaborate about the impact of the test results when it 
comes to
+ *             permission evaluation for system users?
+ *             Use {@link 
org.apache.jackrabbit.oak.security.authorization.permission.L3_PrecedenceRulesTest}
+ *             to verify your expectations or to get some more insight.
+ *
+ * - {@link #testSetPassword()}
+ *   This test attempts to set a password to the system user created in the
+ *   setup. Fix the test and the assertion and explain the behavior.
+ *
+ *   Question: How is setting passwords different for system users compared to 
regular users?
+ *   Question: Look at the node type definition again. What can you state wrt 
rep:password in the effective node type?
+ *   Question: Walk through the test again. Can you identify the exact 
location(s) for special handling?
+ *
+ * - {@link #testGetCredentials()}
+ *   Look at the credentials object exposed by the system user and compare it
+ *   with the result as return in {@link L11_PasswordTest#testGetCredentials()}
+ *
+ * </pre>
+ *
+ * @see <a href="https://issues.apache.org/jira/browse/JCR-3802";>JCR-3802</a>
+ */
+public class L13_SystemUserTest extends AbstractSecurityTest {
+
+    private User systemUser;
+    private Group testGroup;
+
+    @Override
+    public void before() throws Exception {
+        super.before();
+
+        systemUser = 
getUserManager(root).createSystemUser(ExerciseUtility.getTestId("testSystemUser"),
 null);
+        testGroup = ExerciseUtility.createTestGroup(getUserManager(root));
+        testGroup.addMember(systemUser);
+        root.commit();
+    }
+
+    @Override
+    public void after() throws Exception {
+        try {
+            if (systemUser != null) {
+                systemUser.remove();
+            }
+            if (testGroup != null) {
+                testGroup.remove();
+            }
+            root.commit();
+        } finally {
+            super.after();
+        }
+    }
+
+    @Test
+    public void testSystemUser() throws RepositoryException {
+        UserManager userMgr = getUserManager(root);
+        Authorizable authorizable = 
userMgr.getAuthorizable(systemUser.getID());
+
+        Boolean isGroup = null; // EXERCISE
+        assertEquals(isGroup.booleanValue(), authorizable.isGroup());
+
+        Boolean isAdmin = null; // EXERCISE
+        assertEquals(isAdmin.booleanValue(), systemUser.isAdmin());
+
+        // EXERCISE: retrieve the authorizable by class: what is the correct 
authorizble-class to use?
+        Class cls = null;
+        Authorizable sUser = userMgr.getAuthorizable(systemUser.getID(), cls);
+
+        Iterator<Group> memberOf = sUser.memberOf();
+        Set<Group> expectedGroups = null; // EXERCISE
+        while (memberOf.hasNext()) {
+            assertTrue(expectedGroups.remove(memberOf.next()));
+        }
+        assertTrue(expectedGroups.isEmpty());
+    }
+
+    @Test
+    public void testSystemUserNode() throws RepositoryException {
+        Tree systemUserTree = root.getTree(systemUser.getPath());
+        assertTrue(systemUserTree.exists());
+
+        String expectedPrimaryTypeName = null; // EXERCISE
+        assertEquals(expectedPrimaryTypeName, 
TreeUtil.getPrimaryTypeName(systemUserTree));
+
+        String expectedId = null; // EXERCISE
+        assertEquals(expectedId, TreeUtil.getString(systemUserTree, 
UserConstants.REP_AUTHORIZABLE_ID));
+
+        String expectedPw = null; // EXERCISE
+        assertEquals(expectedPw, TreeUtil.getString(systemUserTree, 
UserConstants.REP_PASSWORD));
+    }
+
+    @Test
+    public void testSystemUserPrincipal() throws RepositoryException {
+        Authorizable authorizable = 
getUserManager(root).getAuthorizable(systemUser.getID());
+
+        // EXERCISE: what is the nature of the principal of the system user? 
Assert your expectedation.
+        Principal principal = authorizable.getPrincipal();
+
+        PrincipalManager principalManager = getPrincipalManager(root);
+        PrincipalIterator pIter = 
principalManager.getGroupMembership(principal);
+        int expectedSize = -1; // EXERCISE
+        assertEquals(expectedSize, pIter.getSize());
+
+        List<Principal> expectedGroupPrincipals = null; // EXERCISE
+        while (pIter.hasNext()) {
+            Principal group = pIter.nextPrincipal();
+            assertTrue(expectedGroupPrincipals.remove(group));
+        }
+        assertTrue(expectedGroupPrincipals.isEmpty());
+    }
+
+    @Test
+    public void testSetPassword() throws RepositoryException, 
CommitFailedException {
+        systemUser.changePassword(ExerciseUtility.TEST_PW);
+
+        Tree systemUserTree = root.getTree(systemUser.getPath());
+        String expectedPw = null; // EXERCISE
+        assertEquals(expectedPw, TreeUtil.getString(systemUserTree, 
UserConstants.REP_PASSWORD));
+
+        systemUserTree.setProperty(UserConstants.REP_PASSWORD, "anotherPw");
+        root.commit();
+    }
+
+    @Test
+    public void testGetCredentials() throws RepositoryException {
+        // EXERCISE look at the Credentials object returned from the system 
user and compare it with the result from PasswordTest#getCredentials()
+
+        Credentials creds = systemUser.getCredentials();
+
+        // EXERCISE fix the expectation
+        Credentials expected = null;
+        assertEquals(expected, creds);
+    }
+}
\ No newline at end of file

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

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L14_AuthorizableNodeNameTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L14_AuthorizableNodeNameTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L14_AuthorizableNodeNameTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L14_AuthorizableNodeNameTest.java
 Thu Jun 18 14:30:16 2015
@@ -0,0 +1,136 @@
+/*
+ * 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.user;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+import org.apache.jackrabbit.oak.spi.security.user.AuthorizableNodeName;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import org.apache.jackrabbit.test.api.util.Text;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * <pre>
+ * Module: User Management
+ * 
=============================================================================
+ *
+ * Title: Authorizable Node Name
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Become familiar with the {@link 
org.apache.jackrabbit.oak.spi.security.user.AuthorizableNodeName}
+ * interface and how it is used in the default implementation. After having
+ * completed this test you should also be able to write and configure a custom
+ * implemenation understanding the impact it will have on the default user
+ * management.
+ *
+ * Exercises:
+ *
+ * - {@link #testAuthorizableNodeName()}
+ *   Test the fallback behaviour as implemented in Oak if no
+ *   {@link org.apache.jackrabbit.oak.spi.security.user.AuthorizableNodeName}
+ *   interface is configured.
+ *
+ * - {@link #testRandomAuthorizableNodeName()}
+ *   Same as above but with an {@link 
org.apache.jackrabbit.oak.spi.security.user.AuthorizableNodeName}
+ *   configured.
+ *
+ *
+ * Advanced Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * - Create a custom implementation of the {@link 
org.apache.jackrabbit.oak.spi.security.user.AuthorizableNodeName}
+ *   interface.
+ *
+ * - Make your implementation a OSGi service as described in the documentation
+ *   and deploy it in your Sling (Granite|CQ) repository.
+ *   Verify that creating a new user or group actually makes use of your
+ *   implementation.
+ *
+ * </pre>
+ *
+ * @see org.apache.jackrabbit.oak.spi.security.user.AuthorizableNodeName
+ * @see org.apache.jackrabbit.oak.security.user.RandomAuthorizableNodeName
+ */
+public class L14_AuthorizableNodeNameTest extends AbstractSecurityTest {
+
+    private UserManager userManager;
+    private User testUser;
+
+    private AuthorizableNodeName nameGenerator = new 
RandomAuthorizableNodeName();
+
+    @Override
+    public void before() throws Exception {
+        super.before();
+
+        userManager = getUserManager(root);
+    }
+
+    @Override
+    public void after() throws Exception {
+        try {
+            if (testUser != null) {
+                testUser.remove();
+            }
+            root.commit();
+        } finally {
+            super.after();
+        }
+    }
+
+    @Override
+    protected ConfigurationParameters getSecurityConfigParameters() {
+        // EXERCISE: un-comment for 'testRandomAuthorizableNodeName'
+//        ConfigurationParameters userConfig = 
ConfigurationParameters.of(UserConstants.PARAM_AUTHORIZABLE_NODE_NAME, 
nameGenerator);
+//        return ConfigurationParameters.of(UserConfiguration.NAME, 
userConfig);
+        return ConfigurationParameters.EMPTY;
+    }
+
+    @Test
+    public void testAuthorizableNodeName() throws RepositoryException {
+        testUser = userManager.createUser("test/:User", null);
+
+        String nodeName = Text.getName(testUser.getPath());
+        String expectedNodeName = null; // EXERCISE : fill in the expected 
value
+
+        assertEquals(expectedNodeName, nodeName);
+    }
+
+    @Test
+    public void testRandomAuthorizableNodeName() throws RepositoryException {
+        // EXERCISE: uncomment the setup in 'getSecurityConfigParameters' 
before running this test.
+
+        // verify that the configuration is correct:
+        AuthorizableNodeName configured = 
getUserConfiguration().getParameters().getConfigValue(UserConstants.PARAM_AUTHORIZABLE_NODE_NAME,
 AuthorizableNodeName.DEFAULT);
+        assertNotSame(AuthorizableNodeName.DEFAULT, configured);
+        assertTrue(configured instanceof RandomAuthorizableNodeName);
+
+        testUser = userManager.createUser("test/:User", null);
+
+        String nodeName = Text.getName(testUser.getPath());
+
+        // EXERCISE: write the correct assertion wrt the generated node name.
+    }
+}
\ No newline at end of file

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

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L15_RepositoryWithoutAnonymousTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L15_RepositoryWithoutAnonymousTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L15_RepositoryWithoutAnonymousTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L15_RepositoryWithoutAnonymousTest.java
 Thu Jun 18 14:30:16 2015
@@ -0,0 +1,76 @@
+/*
+ * 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.user;
+
+import javax.jcr.GuestCredentials;
+
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.api.ContentSession;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
+import org.junit.Test;
+
+import static org.junit.Assert.fail;
+
+/**
+ * <pre>
+ * Module: User Management (Authentication)
+ * 
=============================================================================
+ *
+ * Title: Repository without Anonymous
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Understand how the repository can be setup without having an anonymous user
+ * and how this affects the guest login.
+ *
+ * Exercises:
+ *
+ * - {@link #testAnonymousLogin()}
+ *   Use the test to setup a new Oak repository that doesn't allow any 
anonymous access
+ *
+ * </pre>
+ *
+ * @see org.apache.jackrabbit.oak.security.user.UserInitializer
+ * @see 
org.apache.jackrabbit.oak.spi.security.user.UserConstants#PARAM_ANONYMOUS_ID
+ */
+public class L15_RepositoryWithoutAnonymousTest extends AbstractSecurityTest {
+
+    @Override
+    protected ConfigurationParameters getSecurityConfigParameters() {
+        // EXERCISE : use the built-in oak configuration settings to prevent 
anonymous access altogether
+        ConfigurationParameters userConfig = ConfigurationParameters.EMPTY;
+
+        return ConfigurationParameters.of(UserConfiguration.NAME, userConfig);
+    }
+
+    @Test
+    public void testAnonymousLogin() throws Exception {
+        ContentSession oakSession = null;
+        try {
+            oakSession = login(new GuestCredentials());
+            fail("Anonymous login must fail.");
+        } catch (javax.security.auth.login.LoginException e) {
+            // success
+        } finally {
+            if (oakSession != null) {
+                oakSession.close();
+            }
+        }
+    }
+
+}
\ No newline at end of file

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

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L16_RepositoryWithoutUserManagement.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L16_RepositoryWithoutUserManagement.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L16_RepositoryWithoutUserManagement.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L16_RepositoryWithoutUserManagement.java
 Thu Jun 18 14:30:16 2015
@@ -0,0 +1,142 @@
+/*
+ * 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.user;
+
+import javax.jcr.Credentials;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.RepositoryException;
+import javax.security.auth.login.Configuration;
+import javax.security.auth.login.LoginException;
+
+import org.apache.jackrabbit.api.JackrabbitRepository;
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.Oak;
+import org.apache.jackrabbit.oak.api.AuthInfo;
+import org.apache.jackrabbit.oak.api.ContentRepository;
+import org.apache.jackrabbit.oak.api.ContentSession;
+import org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent;
+import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
+import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
+
+/**
+ * <pre>
+ * Module: User Management & Authentication
+ * 
=============================================================================
+ *
+ * Title: Repository without User Management
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * This advanced exercise aims to help you understand that user management
+ * is in fact an optional part of the Oak repository implementation.
+ * While existing application may rely on the user management to be present
+ * by default it isn't too hard to come up with a setup that omits this
+ * module altogether (e.g. if user/group information is being held outside
+ * of the repository content).
+ *
+ * - Define an repository setup that doesn't require a user management 
implementation.
+ *
+ *   Question: Which parts need to be modified?
+ *   Question: What are the consequences for Jcr/Jackrabbit API consumers?
+ *
+ * This exercise mainly consists of defined a
+ * - SecurityProvider implementation
+ * - JAAS configuration
+ * that provides the desired repository setup without user management.
+ *
+ * It comes with the following test cases:
+ *
+ * - {@link #testUserManagementDescriptor()}
+ *   Verifies that the repository descriptiors don't list {@link 
org.apache.jackrabbit.api.JackrabbitRepository#OPTION_USER_MANAGEMENT_SUPPORTED}
+ *   This test passes if your setup is correct.
+ *
+ * - {@link #testNoUserManagementSupported()}
+ *   This test verifies that no {@link 
org.apache.jackrabbit.oak.spi.security.user.UserConfiguration}
+ *   can be obtained from the specified SecurityProvider.
+ *
+ * - {@link #testLogin()}
+ *   Finally, a test should prove that a user with the some Credentials (valid
+ *   for your custom setup) can actually login to the repository and is 
associated
+ *   with a valid {@link org.apache.jackrabbit.oak.api.AuthInfo}.
+ *
+ *
+ * Additional Exercises:
+ * 
-----------------------------------------------------------------------------
+ *
+ * You may want to write additional test-cases that verify that the
+ * {@link org.apache.jackrabbit.api.security.principal.PrincipalManager} allows
+ * you to retrieve valid principals, which can be used to setup access control
+ * content for your repository (which for simplicity might use the built-in
+ * authorization functionality).
+ *
+ * </pre>
+ *
+ * @see org.apache.jackrabbit.oak.spi.security.SecurityProvider
+ * @see org.apache.jackrabbit.oak.spi.security.user.UserConfiguration
+ */
+public class L16_RepositoryWithoutUserManagement extends AbstractSecurityTest {
+
+    @Override
+    protected SecurityProvider getSecurityProvider() {
+        // EXERCISE: define a security provider that doesn't support user 
management
+        // EXERCISE: and therefore doesn't expose a UserConfiguration 
implementation.
+        // hint: you need a custom way to look up principals
+        // hint: make use of CustomPrincipalConfiguration and 
CustomPrincipalProvider
+        // and adjust it according to your needs!
+        return super.getSecurityProvider();
+    }
+
+    @Override
+    protected Configuration getConfiguration() {
+        // EXERCISE: define a suitable jaas configuration that doesn't tries to
+        // EXERCISE: validate credentials against the user information stored 
in the repository
+        // hint: define a configuration with CustomLoginModule (and adjust the 
latter for your needs)
+        return super.getConfiguration();
+    }
+
+    @Test
+    public void testUserManagementDescriptor() throws RepositoryException {
+        Oak oak = new Oak()
+                .with(new InitialContent())
+                .with(getSecurityProvider());
+        ContentRepository contentRepository = oak.createContentRepository();
+
+        
assertFalse(contentRepository.getDescriptors().getValue(JackrabbitRepository.OPTION_USER_MANAGEMENT_SUPPORTED).getBoolean());
+
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testNoUserManagementSupported() {
+        getSecurityProvider().getConfiguration(UserConfiguration.class);
+    }
+
+    @Test
+    public void testLogin() throws LoginException, NoSuchWorkspaceException {
+        String expectedId = null; // EXERCISE define the userID for the login
+        Credentials creds = null; // EXERCISE define credentials that work in 
your setup.
+        ContentSession s = login(creds);
+        AuthInfo authInfo = s.getAuthInfo();
+
+        assertNotSame(AuthInfo.EMPTY, authInfo);
+        assertEquals(expectedId, authInfo.getUserID());
+    }
+}
\ No newline at end of file

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

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L1_IntroductionTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L1_IntroductionTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L1_IntroductionTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L1_IntroductionTest.java
 Thu Jun 18 14:30:16 2015
@@ -0,0 +1,58 @@
+/*
+ * 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.user;
+
+import org.apache.jackrabbit.test.AbstractJCRTest;
+
+/**
+ * <pre>
+ * Module: User Management
+ * 
=============================================================================
+ *
+ * Title: Introduction to User Management
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Understand the usage of user management in Oak.
+ *
+ * Exercises:
+ *
+ * - Overview and Usages of User Management
+ *   Search for usage of user management API (e.g. the {@link 
org.apache.jackrabbit.api.security.user.UserManager}
+ *   interface in Oak. List your findings and discuss the impact.
+ *
+ *   Question: Where is the user management API being used?
+ *   Question: What are the characteristics of this areas? E.g. are they 
configurable/pluggable?
+ *   Question: What can you say about the usage of user management in the 
authorization code base?
+ *
+ * - Configuration
+ *   Look at the default implementation of the {@link 
org.apache.jackrabbit.oak.spi.security.user.UserConfiguration}
+ *   and try to identify the configurable parts. Compare your results with the
+ *   Oak documentation.
+ *
+ *   Question: Can you provide a list of configuration options?
+ *
+ * - Pluggability
+ *   Starting from the {@link UserConfiguration} again, investigate
+ *   how the default implementation could be replaced.
+ *
+ *   Question: Is it possible to combine different user management 
implementations?
+ *
+ * </pre>
+ */
+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/user/L1_IntroductionTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L2_CreateAndGetTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L2_CreateAndGetTest.java?rev=1686235&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L2_CreateAndGetTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/security/user/L2_CreateAndGetTest.java
 Thu Jun 18 14:30:16 2015
@@ -0,0 +1,132 @@
+/*
+ * 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.user;
+
+import java.security.Principal;
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.api.JackrabbitSession;
+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.oak.spi.security.principal.PrincipalImpl;
+import org.apache.jackrabbit.test.AbstractJCRTest;
+
+/**
+ * <pre>
+ * Module: User Management
+ * 
=============================================================================
+ *
+ * Title: User Management Basics
+ * 
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Make yourself familiar with the basic user management functionality as 
present
+ * in Jackrabbit API
+ *
+ * Exercises:
+ *
+ * - {@link #testCreateUser()}
+ *   Use this test to create a new user. Play with the parameters.
+ *   Question: What are valid values for the parameters?
+ *   Question: Which parameters can be 'null'?
+ *   Question: What's the effect if one/some parameters are 'null'?
+ *
+ * - {@link #testCreateGroup()}
+ *   Use to method to create a new group. Play with the parameters.
+ *   Question: What are valid values for the parameters?
+ *   Question: Which parameters can be 'null'?
+ *   Question: What's the effect if one/some parameters are 'null'?
+ *
+ * - {@link #testGetAuthorizable()}
+ *   Play around wit the various methods defined on {@link 
org.apache.jackrabbit.api.security.user.UserManager}
+ *   to retrieve an existing user or group.
+ *
+ * </pre>
+ */
+public class L2_CreateAndGetTest extends AbstractJCRTest {
+
+    private UserManager userManager;
+
+    private User testUser;
+    private Group testGroup;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        userManager = ((JackrabbitSession) superuser).getUserManager();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        try {
+            if (testUser != null) {
+                testUser.remove();
+            }
+            if (testGroup != null) {
+                testGroup.remove();
+            }
+            superuser.save();
+        } finally {
+            super.tearDown();
+        }
+    }
+
+    public void testCreateUser() throws RepositoryException {
+        // EXERCISE: use the following parameters (with suitable values) to 
create a new user.
+        // EXERCISE: play with the values. what are valid values? which params 
can be null? what is the effect?
+        String userID = null;
+        String password = null;
+        Principal principal = null;
+        String intermediatePath = null;
+
+        // EXERCISE: use both methods to create a new user. what's the effect?
+        testUser = userManager.createUser(userID, password, principal, 
intermediatePath);
+        //testUser = userManager.createUser(userID password);
+
+        superuser.save();
+    }
+
+    public void testCreateGroup() throws RepositoryException {
+        // EXERCISE: use the following parameters (with suitable values) to 
create a new group.
+        // EXERCISE: play with the values. what are valid values? which params 
can be null? what is the effect?
+        String groupID = null;
+        Principal principal = null;
+        String intermediatePath = null;
+
+        // EXERCISE: use both methods to create a new group. what's the effect?
+        testGroup = userManager.createGroup(groupID, principal, 
intermediatePath);
+//        testGroup = userManager.createGroup(groupID);
+//        testGroup = userManager.createGroup(principal);
+//        testGroup = userManager.createGroup(principal, intermediatePath);
+
+        superuser.save();
+    }
+
+    public void testGetAuthorizable() throws RepositoryException {
+        testUser = userManager.createUser("testUser", null, new 
PrincipalImpl("testPrincipal"), null);
+        testGroup = userManager.createGroup("testGroup", new 
PrincipalImpl("testGroupPrincipal"), null);
+        superuser.save();
+
+        // EXERCISE: use all methods provided on UserManager interface to 
retrieve a given user/group.
+        // - lookup by id
+        // - lookup by path
+        // - lookup by principal
+        // - lookup by id + class
+    }
+}
\ No newline at end of file

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


Reply via email to