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 2017/03/08 15:25:27 UTC

svn commit: r1785986 - in /jackrabbit/oak/trunk/oak-core/src: main/java/org/apache/jackrabbit/oak/security/privilege/ test/java/org/apache/jackrabbit/oak/security/privilege/

Author: angela
Date: Wed Mar  8 15:25:27 2017
New Revision: 1785986

URL: http://svn.apache.org/viewvc?rev=1785986&view=rev
Log:
OAK-5882 : Improve coverage for oak.security code in oak-core (wip)
minor improvement: add more annotations to oak.security.privilege code

Added:
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeConfigurationImplTest.java   (with props)
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeImplTest.java   (with props)
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeManagerImplTest.java
      - copied, changed from r1785843, jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/privilege/PrivilegeManagerTest.java
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeDefinitionReader.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeManagerImpl.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeDefinitionWriterTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeValidatorTest.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeDefinitionReader.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeDefinitionReader.java?rev=1785986&r1=1785985&r2=1785986&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeDefinitionReader.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeDefinitionReader.java Wed Mar  8 15:25:27 2017
@@ -48,7 +48,7 @@ class PrivilegeDefinitionReader implemen
      */
     @Nonnull
     Map<String, PrivilegeDefinition> readDefinitions() {
-        Map<String, PrivilegeDefinition> definitions = new HashMap<String, PrivilegeDefinition>();
+        Map<String, PrivilegeDefinition> definitions = new HashMap();
         for (Tree child : privilegesTree.getChildren()) {
             if (isPrivilegeDefinition(child)) {
                 PrivilegeDefinition def = PrivilegeUtil.readDefinition(child);
@@ -66,7 +66,7 @@ class PrivilegeDefinitionReader implemen
      *         if the name doesn't refer to a registered privilege.
      */
     @CheckForNull
-    PrivilegeDefinition readDefinition(String privilegeName) {
+    PrivilegeDefinition readDefinition(@Nonnull String privilegeName) {
         if (!privilegesTree.exists() || !privilegesTree.hasChild(privilegeName)) {
             return null;
         } else {

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeManagerImpl.java?rev=1785986&r1=1785985&r2=1785986&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeManagerImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeManagerImpl.java Wed Mar  8 15:25:27 2017
@@ -55,7 +55,7 @@ class PrivilegeManagerImpl implements Pr
     //---------------------------------------------------< PrivilegeManager >---
     @Override
     public Privilege[] getRegisteredPrivileges() throws RepositoryException {
-        Set<Privilege> privileges = new HashSet<Privilege>();
+        Set<Privilege> privileges = new HashSet();
         for (PrivilegeDefinition def : getPrivilegeDefinitions()) {
             privileges.add(getPrivilege(def));
         }
@@ -97,12 +97,12 @@ class PrivilegeManagerImpl implements Pr
     }
 
     @Nonnull
-    private Set<String> getOakNames(String[] jcrNames) throws RepositoryException {
+    private Set<String> getOakNames(@CheckForNull String[] jcrNames) throws RepositoryException {
         Set<String> oakNames;
         if (jcrNames == null || jcrNames.length == 0) {
             oakNames = Collections.emptySet();
         } else {
-            oakNames = new HashSet<String>(jcrNames.length);
+            oakNames = new HashSet(jcrNames.length);
             for (String jcrName : jcrNames) {
                 String oakName = getOakName(jcrName);
                 oakNames.add(oakName);
@@ -112,7 +112,7 @@ class PrivilegeManagerImpl implements Pr
     }
 
     @Nonnull
-    private String getOakName(String jcrName) throws RepositoryException {
+    private String getOakName(@CheckForNull String jcrName) throws RepositoryException {
         if (jcrName == null) {
             throw new AccessControlException("Invalid privilege name 'null'");
         }
@@ -124,7 +124,7 @@ class PrivilegeManagerImpl implements Pr
     }
 
     @Nonnull
-    private Privilege getPrivilege(PrivilegeDefinition definition) {
+    private Privilege getPrivilege(@Nonnull PrivilegeDefinition definition) {
         return new PrivilegeImpl(definition);
     }
 
@@ -135,7 +135,7 @@ class PrivilegeManagerImpl implements Pr
     }
 
     @CheckForNull
-    private PrivilegeDefinition getPrivilegeDefinition(String oakName) {
+    private PrivilegeDefinition getPrivilegeDefinition(@Nonnull String oakName) {
         return getReader().readDefinition(oakName);
     }
 
@@ -153,7 +153,7 @@ class PrivilegeManagerImpl implements Pr
 
         private final PrivilegeDefinition definition;
 
-        private PrivilegeImpl(PrivilegeDefinition definition) {
+        private PrivilegeImpl(@Nonnull PrivilegeDefinition definition) {
             this.definition = definition;
         }
 
@@ -176,7 +176,7 @@ class PrivilegeManagerImpl implements Pr
         @Override
         public Privilege[] getDeclaredAggregatePrivileges() {
             Set<String> declaredAggregateNames = definition.getDeclaredAggregateNames();
-            Set<Privilege> declaredAggregates = new HashSet<Privilege>(declaredAggregateNames.size());
+            Set<Privilege> declaredAggregates = new HashSet(declaredAggregateNames.size());
             for (String oakName : declaredAggregateNames) {
                 if (oakName.equals(definition.getName())) {
                     log.warn("Found cyclic privilege aggregation -> ignore declared aggregate " + oakName);
@@ -194,7 +194,7 @@ class PrivilegeManagerImpl implements Pr
 
         @Override
         public Privilege[] getAggregatePrivileges() {
-            Set<Privilege> aggr = new HashSet<Privilege>();
+            Set<Privilege> aggr = new HashSet();
             for (Privilege decl : getDeclaredAggregatePrivileges()) {
                 aggr.add(decl);
                 if (decl.isAggregate()) {

Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeConfigurationImplTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeConfigurationImplTest.java?rev=1785986&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeConfigurationImplTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeConfigurationImplTest.java Wed Mar  8 15:25:27 2017
@@ -0,0 +1,75 @@
+/*
+ * 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.List;
+
+import com.google.common.collect.ImmutableSet;
+import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.spi.commit.CommitHook;
+import org.apache.jackrabbit.oak.spi.commit.MoveTracker;
+import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConfiguration;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+public class PrivilegeConfigurationImplTest {
+
+    private final PrivilegeConfigurationImpl configuration = new PrivilegeConfigurationImpl();
+
+    @Test
+    public void testGetName() {
+        assertEquals(PrivilegeConfiguration.NAME, configuration.getName());
+    }
+
+    @Test
+    public void testGetPrivilegeManager() {
+        PrivilegeManager pMgr = configuration.getPrivilegeManager(Mockito.mock(Root.class), NamePathMapper.DEFAULT);
+        assertTrue(pMgr instanceof PrivilegeManagerImpl);
+    }
+
+    @Test
+    public void testGetRepositoryInitializer() {
+        assertTrue(configuration.getRepositoryInitializer() instanceof PrivilegeInitializer);
+    }
+
+    @Test
+    public void testGetCommitHooks() {
+        List<? extends CommitHook> l = configuration.getCommitHooks("wspName");
+        assertEquals(1, l.size());
+        assertTrue(l.get(0) instanceof JcrAllCommitHook);
+    }
+
+    @Test
+    public void testGetValidators() {
+        List<? extends ValidatorProvider> l = configuration.getValidators("wspName", ImmutableSet.<Principal>of(), new MoveTracker());
+        assertEquals(1, l.size());
+        assertTrue(l.get(0) instanceof PrivilegeValidatorProvider);
+    }
+
+    @Test
+    public void testGetContext() {
+        assertSame(PrivilegeContext.getInstance(), configuration.getContext());
+    }
+}
\ No newline at end of file

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

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeDefinitionWriterTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeDefinitionWriterTest.java?rev=1785986&r1=1785985&r2=1785986&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeDefinitionWriterTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeDefinitionWriterTest.java Wed Mar  8 15:25:27 2017
@@ -20,6 +20,7 @@ import javax.jcr.RepositoryException;
 
 import org.apache.jackrabbit.oak.AbstractSecurityTest;
 import org.apache.jackrabbit.oak.Oak;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.ContentRepository;
 import org.apache.jackrabbit.oak.api.Root;
 import org.apache.jackrabbit.oak.api.Tree;
@@ -31,11 +32,13 @@ import org.junit.After;
 import org.junit.Test;
 
 import com.google.common.collect.Iterables;
+import org.mockito.Mockito;
 
 import static java.util.Arrays.asList;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.mockito.Mockito.doThrow;
 
 public class PrivilegeDefinitionWriterTest extends AbstractSecurityTest implements PrivilegeConstants {
 
@@ -90,4 +93,15 @@ public class PrivilegeDefinitionWriterTe
                 new String[] {JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL},
                 Iterables.toArray(TreeUtil.getStrings(tmpTree, REP_AGGREGATES), String.class));
     }
+
+    @Test(expected = RepositoryException.class)
+    public void testCommitFails() throws Exception {
+        Root r = Mockito.spy(root);
+        doThrow(new CommitFailedException(CommitFailedException.OAK, 1, "msg")).when(r).commit();
+
+
+        PrivilegeDefinitionWriter writer = new PrivilegeDefinitionWriter(r);
+        writer.writeDefinition(new ImmutablePrivilegeDefinition(
+                "tmp", true, asList(JCR_READ_ACCESS_CONTROL, JCR_MODIFY_ACCESS_CONTROL)));
+    }
 }
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeImplTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeImplTest.java?rev=1785986&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeImplTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeImplTest.java Wed Mar  8 15:25:27 2017
@@ -0,0 +1,187 @@
+/*
+ * 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.annotation.Nonnull;
+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.privilege.PrivilegeConstants;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeDefinition;
+import org.apache.jackrabbit.oak.util.NodeUtil;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class PrivilegeImplTest extends AbstractSecurityTest implements PrivilegeConstants {
+
+    private Privilege privilege;
+    private Privilege abstractPrivilege;
+    private Privilege allPrivilege;
+    private Privilege aggrPrivilege;
+
+    @Override
+    public void before() throws Exception {
+        super.before();
+
+        PrivilegeManager pMgr = getPrivilegeManager(root);
+        privilege = pMgr.getPrivilege(JCR_READ_ACCESS_CONTROL);
+        aggrPrivilege = pMgr.getPrivilege(REP_WRITE);
+        allPrivilege = pMgr.getPrivilege(JCR_ALL);
+        abstractPrivilege = pMgr.registerPrivilege("abstractPrivilege", true, null);
+    }
+
+    @Override
+    public void after() throws Exception {
+        root.refresh();
+        super.after();
+    }
+
+    private static void assertAggregation(@Nonnull Privilege[] aggr, @Nonnull String... expectedNames) {
+        assertEquals(expectedNames.length, aggr.length);
+
+        Set<String> expected = Sets.newHashSet(expectedNames);
+        Set<String> result = Sets.newHashSet(Iterables.transform(ImmutableSet.copyOf(aggr), new Function<Privilege, String>() {
+            @Nullable
+            @Override
+            public String apply(Privilege input) {
+                return input.getName();
+            }
+        }));
+
+        assertEquals(expected, result);
+    }
+
+    @Test
+    public void testGetName() {
+        assertEquals(JCR_READ_ACCESS_CONTROL, privilege.getName());
+    }
+
+    @Test
+    public void testIsAbstract() {
+        assertFalse(privilege.isAbstract());
+        assertFalse(allPrivilege.isAbstract());
+        assertFalse(aggrPrivilege.isAbstract());
+
+        assertTrue(abstractPrivilege.isAbstract());
+    }
+
+    @Test
+    public void testIsAggregate() {
+        assertFalse(privilege.isAggregate());
+
+        assertTrue(allPrivilege.isAggregate());
+        assertTrue(aggrPrivilege.isAggregate());
+
+        assertFalse(abstractPrivilege.isAggregate());
+    }
+
+    @Test
+    public void testGetDeclaredAggregatedPrivilegesSimple() {
+        assertAggregation(privilege.getDeclaredAggregatePrivileges());
+        assertAggregation(aggrPrivilege.getDeclaredAggregatePrivileges(), JCR_NODE_TYPE_MANAGEMENT, JCR_WRITE);
+    }
+
+
+    @Test
+    public void testGetAggregatedPrivileges() {
+        assertAggregation(privilege.getAggregatePrivileges());
+        assertAggregation(aggrPrivilege.getAggregatePrivileges(),
+                JCR_NODE_TYPE_MANAGEMENT,
+                JCR_WRITE, JCR_ADD_CHILD_NODES, JCR_REMOVE_CHILD_NODES, JCR_REMOVE_NODE,
+                JCR_MODIFY_PROPERTIES, REP_ADD_PROPERTIES, REP_ALTER_PROPERTIES, REP_REMOVE_PROPERTIES);
+    }
+
+    @Test
+    public void testEquals() throws Exception {
+        assertEquals(privilege, privilege);
+        assertEquals(privilege, getPrivilegeManager(root).getPrivilege(privilege.getName()));
+    }
+
+    @Test
+    public void testNotEquals() throws Exception {
+        assertNotEquals(privilege, aggrPrivilege);
+        assertNotEquals(allPrivilege, privilege);
+
+        final PrivilegeDefinition def = new PrivilegeDefinitionReader(root).readDefinition(privilege.getName());
+        assertNotNull(def);
+        assertNotEquals(privilege, new Privilege() {
+
+            @Override
+            public String getName() {
+                return def.getName();
+            }
+
+            @Override
+            public boolean isAbstract() {
+                return def.isAbstract();
+            }
+
+            @Override
+            public boolean isAggregate() {
+                return !def.getDeclaredAggregateNames().isEmpty();
+            }
+
+            @Override
+            public Privilege[] getDeclaredAggregatePrivileges() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public Privilege[] getAggregatePrivileges() {
+                throw new UnsupportedOperationException();
+            }
+        });
+    }
+
+    @Test
+    public void testToString() {
+        PrivilegeDefinition def = new PrivilegeDefinitionReader(root).readDefinition(privilege.getName());
+        assertEquals(def.getName(), privilege.toString());
+    }
+
+    @Test
+    public void testInvalidDeclaredAggregate() throws Exception {
+        NodeUtil privilegeDefs = new NodeUtil(root.getTree(PRIVILEGES_PATH));
+        NodeUtil privDef = privilegeDefs.addChild("test", NT_REP_PRIVILEGE);
+        privDef.setNames(REP_AGGREGATES, JCR_READ, "invalid");
+
+        Privilege p = getPrivilegeManager(root).getPrivilege("test");
+        assertAggregation(p.getDeclaredAggregatePrivileges(), JCR_READ);
+    }
+
+    @Test
+    public void testCyclicDeclaredAggregate() throws Exception {
+        NodeUtil privilegeDefs = new NodeUtil(root.getTree(PRIVILEGES_PATH));
+        NodeUtil privDef = privilegeDefs.addChild("test", NT_REP_PRIVILEGE);
+        privDef.setNames(REP_AGGREGATES, JCR_READ, "test");
+
+        Privilege p = getPrivilegeManager(root).getPrivilege("test");
+        assertAggregation(p.getDeclaredAggregatePrivileges(), JCR_READ);
+    }
+}
\ No newline at end of file

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

Copied: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeManagerImplTest.java (from r1785843, jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/privilege/PrivilegeManagerTest.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeManagerImplTest.java?p2=jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeManagerImplTest.java&p1=jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/privilege/PrivilegeManagerTest.java&r1=1785843&r2=1785986&rev=1785986&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/privilege/PrivilegeManagerTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeManagerImplTest.java Wed Mar  8 15:25:27 2017
@@ -14,168 +14,200 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.oak.jcr.security.privilege;
+package org.apache.jackrabbit.oak.security.privilege;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.Map;
+import javax.annotation.Nonnull;
+import javax.jcr.NamespaceRegistry;
 import javax.jcr.RepositoryException;
 import javax.jcr.security.AccessControlException;
 import javax.jcr.security.Privilege;
 
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.namepath.GlobalNameMapper;
+import org.apache.jackrabbit.oak.namepath.LocalNameMapper;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.namepath.NamePathMapperImpl;
+import org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState;
+import org.apache.jackrabbit.oak.plugins.name.ReadWriteNamespaceRegistry;
+import org.apache.jackrabbit.oak.plugins.tree.RootFactory;
 import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
-import org.junit.After;
+import org.apache.jackrabbit.oak.util.TreeUtil;
 import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Mockito;
 
-/**
- * PrivilegeManagerTest...
- */
-public class PrivilegeManagerTest extends AbstractPrivilegeTest {
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+public class PrivilegeManagerImplTest extends AbstractSecurityTest {
 
-    private PrivilegeManager privilegeManager;
+    private PrivilegeManagerImpl privilegeManager;
 
     @Before
-    public void setUp() throws Exception {
-        super.setUp();
-        privilegeManager = getPrivilegeManager(superuser);
+    public void before() throws Exception {
+        super.before();
+        privilegeManager = create(root);
+    }
+
+    private static PrivilegeManagerImpl create(@Nonnull Root root) {
+        return new PrivilegeManagerImpl(root, NamePathMapper.DEFAULT);
     }
 
-    @After
-    public void tearDown() throws Exception {
-        privilegeManager = null;
-        super.tearDown();
+    private static PrivilegeManagerImpl create(@Nonnull Root root, @Nonnull NamePathMapper mapper) {
+        return new PrivilegeManagerImpl(root, mapper);
     }
 
     @Test
     public void testGetRegisteredPrivileges() throws RepositoryException {
         Privilege[] registered = privilegeManager.getRegisteredPrivileges();
-        Set<Privilege> set = new HashSet<Privilege>();
-        Privilege all = privilegeManager.getPrivilege(Privilege.JCR_ALL);
-        set.add(all);
-        set.addAll(Arrays.asList(all.getAggregatePrivileges()));
-
-        for (Privilege p : registered) {
-            assertTrue(p.getName(), set.remove(p));
-        }
-        assertTrue(set.isEmpty());
-    }
-    
-    @Test
-    public void testGetPrivilege() throws RepositoryException {
-        Set<String> aggregatedPrivilegeNames = ImmutableSet.of("jcr:read",
-                "jcr:modifyProperties", "jcr:write", "rep:write", "jcr:all");
-
-        for (Privilege priv : privilegeManager.getRegisteredPrivileges()) {
-            String privName = priv.getName();
-            boolean isAggregate = aggregatedPrivilegeNames.contains(privName);
-            assertPrivilege(priv, privName, isAggregate, false);
-        }
-    }
-
-    @Test
-    public void testJcrAll() throws RepositoryException {
-        Privilege all = privilegeManager.getPrivilege(Privilege.JCR_ALL);
-        assertPrivilege(all, "jcr:all", true, false);
-
-        List<Privilege> decl = Arrays.asList(all.getDeclaredAggregatePrivileges());
-        List<Privilege> aggr = new ArrayList<Privilege>(Arrays.asList(all.getAggregatePrivileges()));
-
-        assertFalse(decl.contains(all));
-        assertFalse(aggr.contains(all));
-
-        // declared and aggregated privileges are the same for jcr:all
-        assertTrue(decl.containsAll(aggr));
-
-        // test individual built-in privileges are listed in the aggregates
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(Privilege.JCR_READ)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(Privilege.JCR_ADD_CHILD_NODES)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(Privilege.JCR_REMOVE_CHILD_NODES)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(Privilege.JCR_MODIFY_PROPERTIES)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(Privilege.JCR_REMOVE_NODE)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(Privilege.JCR_READ_ACCESS_CONTROL)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(Privilege.JCR_MODIFY_ACCESS_CONTROL)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(Privilege.JCR_LIFECYCLE_MANAGEMENT)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(Privilege.JCR_LOCK_MANAGEMENT)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(Privilege.JCR_NODE_TYPE_MANAGEMENT)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(Privilege.JCR_RETENTION_MANAGEMENT)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(Privilege.JCR_VERSION_MANAGEMENT)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(Privilege.JCR_WRITE)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(PrivilegeConstants.REP_WRITE)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(PrivilegeConstants.REP_READ_NODES)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(PrivilegeConstants.REP_READ_PROPERTIES)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(PrivilegeConstants.REP_ADD_PROPERTIES)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(PrivilegeConstants.REP_ALTER_PROPERTIES)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(PrivilegeConstants.REP_REMOVE_PROPERTIES)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(PrivilegeConstants.JCR_NAMESPACE_MANAGEMENT)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(PrivilegeConstants.JCR_NODE_TYPE_DEFINITION_MANAGEMENT)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(PrivilegeConstants.JCR_WORKSPACE_MANAGEMENT)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(PrivilegeConstants.REP_PRIVILEGE_MANAGEMENT)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(PrivilegeConstants.REP_USER_MANAGEMENT)));
-        assertTrue(aggr.remove(privilegeManager.getPrivilege(PrivilegeConstants.REP_INDEX_DEFINITION_MANAGEMENT)));
+        assertNotNull(registered);
+        assertNotEquals(1, registered.length);
+    }
 
-        // there may be no privileges left
-        assertTrue(aggr.isEmpty());
+    @Test
+    public void testGetRegisteredPrivilegesFromEmptyRoot() throws RepositoryException {
+        Privilege[] registered = create(RootFactory.createReadOnlyRoot(EmptyNodeState.EMPTY_NODE)).getRegisteredPrivileges();
+        assertNotNull(registered);
+        assertEquals(0, registered.length);
     }
 
     @Test
-    public void testGetPrivilegeFromName() throws AccessControlException, RepositoryException {
-        Privilege p = privilegeManager.getPrivilege(Privilege.JCR_VERSION_MANAGEMENT);
+    public void testGetPrivilege() throws Exception {
+        Privilege p = privilegeManager.getPrivilege(PrivilegeConstants.JCR_VERSION_MANAGEMENT);
 
-        assertTrue(p != null);
+        assertNotNull(p);
         assertEquals(PrivilegeConstants.JCR_VERSION_MANAGEMENT, p.getName());
-        assertFalse(p.isAggregate());
+    }
 
-        p = privilegeManager.getPrivilege(Privilege.JCR_WRITE);
+    @Test(expected = AccessControlException.class)
+    public void testGetPrivilegeExpandedNameMissingMapper() throws Exception {
+        Privilege p = privilegeManager.getPrivilege(Privilege.JCR_VERSION_MANAGEMENT);
 
-        assertTrue(p != null);
-        assertEquals(PrivilegeConstants.JCR_WRITE, p.getName());
-        assertTrue(p.isAggregate());
+        assertNotNull(p);
+        assertEquals(PrivilegeConstants.JCR_VERSION_MANAGEMENT, p.getName());
     }
 
     @Test
-    public void testGetPrivilegesFromInvalidName() throws RepositoryException {
-        try {
-            privilegeManager.getPrivilege("unknown");
-            fail("invalid privilege name");
-        } catch (AccessControlException e) {
-            // OK
-        }
+    public void testGetPrivilegeExpandedName() throws Exception {
+        Privilege p = create(root, new NamePathMapperImpl(new GlobalNameMapper(root))).getPrivilege(Privilege.JCR_VERSION_MANAGEMENT);
+
+        assertNotNull(p);
+        assertNotEquals(Privilege.JCR_VERSION_MANAGEMENT, p.getName());
+        assertEquals(PrivilegeConstants.JCR_VERSION_MANAGEMENT, p.getName());
     }
 
     @Test
-    public void testGetPrivilegesFromInvalidName2() throws RepositoryException {
-    	String nonExistingPrivilegeName = "{http://www.nonexisting.com/1.0}nonexisting";
-    	try{
-    		privilegeManager.getPrivilege(nonExistingPrivilegeName);
-    	} catch(AccessControlException e){
-    		//expected
-    	}
+    public void testGetPrivilegeRemappedNamespace() throws Exception {
+        NamePathMapper mapper = new NamePathMapperImpl(new LocalNameMapper(root, ImmutableMap.of("prefix", NamespaceRegistry.NAMESPACE_JCR)));
+        Privilege p = create(root, mapper).getPrivilege("prefix:read");
+
+        assertNotNull(p);
+        assertNotEquals(Privilege.JCR_READ, p.getName());
+        assertNotEquals(PrivilegeConstants.JCR_READ, p.getName());
+        assertEquals("prefix:read", p.getName());
     }
 
-    @Test
-    public void testGetPrivilegesFromEmptyNames() {
-        try {
-            privilegeManager.getPrivilege("");
-            fail("invalid privilege name array");
-        } catch (AccessControlException e) {
-            // OK
-        } catch (RepositoryException e) {
-            // OK
-        }
+    @Test(expected = AccessControlException.class)
+    public void testGetPrivilegeInvalidRemappedNamespace() throws Exception {
+        NamePathMapper mapper = new NamePathMapperImpl(new LocalNameMapper(root, ImmutableMap.of("prefix", "unknownUri")));
+        create(root, mapper).getPrivilege("prefix:read");
+    }
+
+    @Test(expected = AccessControlException.class)
+    public void testGetPrivilegeFromEmptyRoot() throws Exception {
+        create(RootFactory.createReadOnlyRoot(EmptyNodeState.EMPTY_NODE)).getPrivilege(PrivilegeConstants.JCR_READ);
     }
 
+    @Test(expected = AccessControlException.class)
+    public void testGetUnknownPrivilege() throws Exception {
+        create(RootFactory.createReadOnlyRoot(EmptyNodeState.EMPTY_NODE)).getPrivilege("jcr:someName");
+    }
+
+    @Test(expected = AccessControlException.class)
+    public void testGetPrivilegeEmptyName() throws Exception {
+        create(RootFactory.createReadOnlyRoot(EmptyNodeState.EMPTY_NODE)).getPrivilege("");
+    }
+
+    @Test(expected = AccessControlException.class)
+    public void testGetPrivilegeNullName() throws Exception {
+        create(RootFactory.createReadOnlyRoot(EmptyNodeState.EMPTY_NODE)).getPrivilege(null);
+    }
+
+    @Test(expected = RepositoryException.class)
+    public void testRegisterPrivilegePendingChanges() throws Exception {
+        Root r = Mockito.mock(Root.class);
+        when(r.hasPendingChanges()).thenReturn(true);
+        create(r).registerPrivilege("privName", true, null);
+    }
+
+    @Test(expected = RepositoryException.class)
+    public void testRegisterPrivilegeEmptyName() throws Exception {
+        privilegeManager.registerPrivilege("", true, new String[]{"jcr:read", "jcr:write"});
+    }
+
+    @Test(expected = RepositoryException.class)
+    public void testRegisterPrivilegeNullName() throws Exception {
+        privilegeManager.registerPrivilege(null, true, new String[]{"jcr:read", "jcr:write"});
+    }
+
+    @Test(expected = RepositoryException.class)
+    public void testRegisterPrivilegeUnknownAggreate() throws Exception {
+        privilegeManager.registerPrivilege(null, true, new String[]{"unknown", "jcr:read"});
+    }
+
+    @Test(expected = RepositoryException.class)
+    public void testRegisterPrivilegeReservedNamespace() throws Exception {
+        privilegeManager.registerPrivilege("jcr:customPrivilege", true, new String[]{"jcr:read", "jcr:write"});
+    }
+
+    @Test(expected = RepositoryException.class)
+    public void testRegisterPrivilegeReservedRemappedNamespace() throws Exception {
+        NamePathMapper mapper = new NamePathMapperImpl(new LocalNameMapper(root, ImmutableMap.of("prefix", NamespaceRegistry.NAMESPACE_JCR)));
+        PrivilegeManager pmgr = create(root, mapper);
+        pmgr.registerPrivilege("prefix:customPrivilege", true, new String[] {"prefix:read", "prefix:write"});    }
+
     @Test
-    public void testGetPrivilegesFromNullNames() {
-        try {
-            privilegeManager.getPrivilege(null);
-            fail("invalid privilege name (null)");
-        } catch (Exception e) {
-            // OK
-        }
+    public void testRegisterPrivilegeRemappedNamespace() throws Exception {
+        ReadWriteNamespaceRegistry nsRegistry = new ReadWriteNamespaceRegistry(root) {
+            @Override
+            protected Root getWriteRoot() {
+                return root;
+            }
+        };
+        nsRegistry.registerNamespace("ns", "http://jackrabbit.apache.org/oak/ns");
+
+        Map<String, String> localMapping = ImmutableMap.of(
+                "prefix", NamespaceRegistry.NAMESPACE_JCR,
+                "prefix2", "http://jackrabbit.apache.org/oak/ns");
+
+        NamePathMapper mapper = new NamePathMapperImpl(new LocalNameMapper(root, localMapping));
+        PrivilegeManager pmgr = create(root, mapper);
+
+        Privilege p = pmgr.registerPrivilege("prefix2:customPrivilege", true, new String[] {"prefix:read", "prefix:write"});
+
+        assertEquals("prefix2:customPrivilege", p.getName());
+        assertEquals(2, p.getDeclaredAggregatePrivileges().length);
+
+        Tree privilegesTree = root.getTree(PrivilegeConstants.PRIVILEGES_PATH);
+        assertFalse(privilegesTree.hasChild("prefix2:customPrivilege"));
+
+        Tree privTree = privilegesTree.getChild("ns:customPrivilege");
+        assertTrue(privTree.exists());
+        assertTrue(TreeUtil.getBoolean(privTree, PrivilegeConstants.REP_IS_ABSTRACT));
+
+        Iterable<String> aggr = TreeUtil.getStrings(privTree, PrivilegeConstants.REP_AGGREGATES);
+        assertNotNull(aggr);
+        assertEquals(ImmutableSet.of("jcr:read", "jcr:write"), ImmutableSet.copyOf(aggr));
+
     }
 }

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeValidatorTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeValidatorTest.java?rev=1785986&r1=1785985&r2=1785986&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeValidatorTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeValidatorTest.java Wed Mar  8 15:25:27 2017
@@ -17,14 +17,18 @@
 package org.apache.jackrabbit.oak.security.privilege;
 
 import java.util.Collections;
+import javax.annotation.Nonnull;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
 import org.apache.jackrabbit.JcrConstants;
 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.api.Type;
 import org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState;
+import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeBuilder;
 import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
 import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits;
 import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBitsProvider;
@@ -53,9 +57,10 @@ public class PrivilegeValidatorTest exte
         privilegesTree = checkNotNull(bitsProvider.getPrivilegesTree());
     }
 
-    private Tree createPrivilegeTree() {
-        Tree privTree = privilegesTree.addChild("test");
+    private Tree createPrivilegeTree(@Nonnull String privName, @Nonnull String... aggr) {
+        Tree privTree = privilegesTree.addChild(privName);
         privTree.setProperty(JcrConstants.JCR_PRIMARYTYPE, NT_REP_PRIVILEGE, Type.NAME);
+        privTree.setProperty(REP_AGGREGATES, ImmutableSet.copyOf(aggr), Type.NAMES);
         return privTree;
     }
 
@@ -66,7 +71,7 @@ public class PrivilegeValidatorTest exte
     @Test
     public void testMissingPrivilegeBits() {
         try {
-            createPrivilegeTree();
+            createPrivilegeTree("test");
             root.commit();
             fail("Missing privilege bits property must be detected.");
         } catch (CommitFailedException e) {
@@ -80,13 +85,14 @@ public class PrivilegeValidatorTest exte
     @Test
     public void testBitsConflict() {
         try {
-            Tree privTree = createPrivilegeTree();
+            Tree privTree = createPrivilegeTree("test");
             bitsProvider.getBits(JCR_READ).writeTo(privTree);
             root.commit();
             fail("Conflicting privilege bits property must be detected.");
         } catch (CommitFailedException e) {
             // success
-            assertEquals("OakConstraint0049: PrivilegeBits already in used.", e.getMessage());
+            assertTrue(e.isConstraintViolation());
+            assertEquals(49, e.getCode());
         } finally {
             root.refresh();
         }
@@ -95,7 +101,7 @@ public class PrivilegeValidatorTest exte
     @Test
     public void testBitsConflictWithAggregation() {
         try {
-            Tree privTree = createPrivilegeTree();
+            Tree privTree = createPrivilegeTree("test");
             privTree.setProperty(PropertyStates.createProperty(REP_AGGREGATES,
                     ImmutableList.of(JCR_READ, JCR_MODIFY_PROPERTIES), Type.NAMES));
             setPrivilegeBits(privTree, REP_BITS, 340);
@@ -104,7 +110,8 @@ public class PrivilegeValidatorTest exte
             fail("Privilege bits don't match the aggregation.");
         } catch (CommitFailedException e) {
             // success
-            assertEquals("OakConstraint0053: Invalid privilege bits for aggregated privilege definition.", e.getMessage());
+            assertTrue(e.isConstraintViolation());
+            assertEquals(53, e.getCode());
         } finally {
             root.refresh();
         }
@@ -115,14 +122,15 @@ public class PrivilegeValidatorTest exte
     @Test
     public void testNextNotUpdated() {
         try {
-            Tree privTree = createPrivilegeTree();
+            Tree privTree = createPrivilegeTree("test");
             PrivilegeBits.getInstance(privilegesTree).writeTo(privTree);
 
             root.commit();
             fail("Outdated rep:next property must be detected.");
         } catch (CommitFailedException e) {
             // success
-            assertEquals("OakConstraint0043: Next bits not updated", e.getMessage());
+            assertTrue(e.isConstraintViolation());
+            assertEquals(43, e.getCode());
         } finally {
             root.refresh();
         }
@@ -136,7 +144,8 @@ public class PrivilegeValidatorTest exte
             fail("Outdated rep:next property must be detected.");
         } catch (CommitFailedException e) {
             // success
-            assertEquals("OakConstraint0043: Next bits not updated", e.getMessage());
+            assertTrue(e.isConstraintViolation());
+            assertEquals(43, e.getCode());
         } finally {
             root.refresh();
         }
@@ -145,7 +154,7 @@ public class PrivilegeValidatorTest exte
     @Test
     public void testSingularAggregation() {
         try {
-            Tree privTree = createPrivilegeTree();
+            Tree privTree = createPrivilegeTree("test");
             privTree.setProperty(PropertyStates.createProperty(REP_AGGREGATES, Collections.singletonList(JCR_READ), Type.NAMES));
             PrivilegeBits.getInstance(bitsProvider.getBits(JCR_READ)).writeTo(privTree);
 
@@ -153,7 +162,8 @@ public class PrivilegeValidatorTest exte
             fail("Aggregation of a single privilege is invalid.");
         } catch (CommitFailedException e) {
             // success
-            assertEquals("OakConstraint0050: Singular aggregation is equivalent to existing privilege.", e.getMessage());
+            assertTrue(e.isConstraintViolation());
+            assertEquals(50, e.getCode());
         } finally {
             root.refresh();
         }
@@ -174,6 +184,7 @@ public class PrivilegeValidatorTest exte
         try {
             pv.childNodeChanged("test", privilegeDefinition, EmptyNodeState.EMPTY_NODE);
         } catch (CommitFailedException e) {
+            assertTrue(e.isConstraintViolation());
             assertEquals(41, e.getCode());
         }
     }
@@ -195,7 +206,7 @@ public class PrivilegeValidatorTest exte
     @Test
     public void testAggregatesIncludesJcrAll() throws Exception {
         try {
-            Tree privTree = createPrivilegeTree();
+            Tree privTree = createPrivilegeTree("test");
             privTree.setProperty(PropertyStates.createProperty(REP_AGGREGATES, ImmutableList.of(JCR_ALL, JCR_READ, JCR_WRITE), Type.NAMES));
             PrivilegeBits.getInstance(bitsProvider.getBits(JCR_ALL, JCR_READ, JCR_WRITE)).writeTo(privTree);
 
@@ -209,4 +220,122 @@ public class PrivilegeValidatorTest exte
             root.refresh();
         }
     }
+
+    @Test
+    public void testPropertyChanged() throws Exception {
+        try {
+            PropertyState before = PropertyStates.createProperty(REP_AGGREGATES, ImmutableList.of(REP_READ_NODES, REP_READ_PROPERTIES), Type.NAMES);
+            PropertyState after = PropertyStates.createProperty(REP_AGGREGATES, ImmutableList.of(REP_READ_NODES), Type.NAMES);
+
+            PrivilegeValidator validator = new PrivilegeValidator(root, root);
+            validator.propertyChanged(before, after);
+            fail("modifying property in privilege store must fail.");
+        } catch (CommitFailedException e) {
+            // success
+            assertTrue(e.isConstraintViolation());
+            assertEquals(45, e.getCode());
+        }
+    }
+
+    @Test
+    public void testPropertyDeleted() throws Exception {
+        try {
+            PropertyState before = PropertyStates.createProperty(REP_AGGREGATES, ImmutableList.of(REP_READ_NODES, REP_READ_PROPERTIES), Type.NAMES);
+
+            PrivilegeValidator validator = new PrivilegeValidator(root, root);
+            validator.propertyDeleted(before);
+            fail("removing property from privilege store must fail.");
+        } catch (CommitFailedException e) {
+            // success
+            assertTrue(e.isConstraintViolation());
+            assertEquals(46, e.getCode());
+        }
+    }
+
+    @Test
+    public void testChildNodeDeleted() {
+        try {
+            root.getTree(PRIVILEGES_PATH).getChild(JCR_READ).remove();
+            root.commit();
+            fail("removing privilege from privilege store must fail.");
+        } catch (CommitFailedException e) {
+            // success
+            assertTrue(e.isConstraintViolation());
+            assertEquals(42, e.getCode());
+        }
+    }
+
+    @Test
+    public void testPrivBitsMissing() {
+        try {
+            NodeState newDef = new MemoryNodeBuilder(EmptyNodeState.EMPTY_NODE)
+                    .setProperty(JcrConstants.JCR_PRIMARYTYPE, NT_REP_PRIVILEGE)
+                    .getNodeState();
+
+            PrivilegeValidator validator = new PrivilegeValidator(root, root);
+            validator.childNodeAdded("test", newDef);
+            fail("missing priv bits must be detected.");
+        } catch (CommitFailedException e) {
+            assertTrue(e.isConstraintViolation());
+            assertEquals(48, e.getCode());
+        }
+    }
+
+    @Test
+    public void testUnknownAggregate() {
+        try {
+            NodeState newDef = new MemoryNodeBuilder(EmptyNodeState.EMPTY_NODE)
+                    .setProperty(JcrConstants.JCR_PRIMARYTYPE, NT_REP_PRIVILEGE)
+                    .setProperty(REP_BITS, 8)
+                    .setProperty(REP_AGGREGATES, ImmutableList.of("unknown", JCR_READ), Type.NAMES)
+                    .getNodeState();
+
+            PrivilegeValidator validator = new PrivilegeValidator(root, root);
+            validator.childNodeAdded("test", newDef);
+            fail("unknown aggregate must be detected.");
+        } catch (CommitFailedException e) {
+            assertTrue(e.isConstraintViolation());
+            assertEquals(51, e.getCode());
+        }
+    }
+
+    @Test
+    public void testCircularAggregate() {
+        try {
+            createPrivilegeTree("test");
+
+            NodeState newDef = new MemoryNodeBuilder(EmptyNodeState.EMPTY_NODE)
+                    .setProperty(JcrConstants.JCR_PRIMARYTYPE, NT_REP_PRIVILEGE)
+                    .setProperty(REP_BITS, 8)
+                    .setProperty(REP_AGGREGATES, ImmutableList.of("test", JCR_READ), Type.NAMES)
+                    .getNodeState();
+
+            PrivilegeValidator validator = new PrivilegeValidator(root, root);
+            validator.childNodeAdded("test", newDef);
+            fail("unknown aggregate must be detected.");
+        } catch (CommitFailedException e) {
+            assertTrue(e.isConstraintViolation());
+            assertEquals(52, e.getCode());
+        }
+    }
+
+    @Test
+    public void testCircularAggregate2() {
+        try {
+            createPrivilegeTree("test2", "test");
+
+            NodeState newDef = new MemoryNodeBuilder(EmptyNodeState.EMPTY_NODE)
+                    .setProperty(JcrConstants.JCR_PRIMARYTYPE, NT_REP_PRIVILEGE)
+                    .setProperty(REP_BITS, 8)
+                    .setProperty(REP_AGGREGATES, ImmutableList.of("test2", JCR_READ), Type.NAMES)
+                    .getNodeState();
+
+            PrivilegeValidator validator = new PrivilegeValidator(root, root);
+            validator.childNodeAdded("test", newDef);
+            fail("unknown aggregate must be detected.");
+        } catch (CommitFailedException e) {
+            assertTrue(e.isConstraintViolation());
+            assertEquals(52, e.getCode());
+        }
+    }
 }
\ No newline at end of file