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 2013/02/19 17:14:13 UTC
svn commit: r1447789 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/security/authorization/
main/java/org/apache/jackrabbit/oak/spi/security/authorization/
test/java/org/apache/jackrabbit/oak/security/authorization/
Author: angela
Date: Tue Feb 19 16:14:11 2013
New Revision: 1447789
URL: http://svn.apache.org/r1447789
Log:
OAK-51 : Access Control Management (WIP)
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/ACL.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/PermissionProviderImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/ACE.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/ACLTest.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/ACL.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/ACL.java?rev=1447789&r1=1447788&r2=1447789&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/ACL.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/ACL.java Tue Feb 19 16:14:11 2013
@@ -17,6 +17,7 @@
package org.apache.jackrabbit.oak.security.authorization;
import java.security.Principal;
+import java.security.acl.Group;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@@ -31,10 +32,15 @@ import javax.jcr.security.AccessControlE
import javax.jcr.security.AccessControlException;
import javax.jcr.security.Privilege;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlEntry;
import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
import org.apache.jackrabbit.api.security.principal.PrincipalManager;
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.security.privilege.PrivilegeBits;
+import org.apache.jackrabbit.oak.security.privilege.PrivilegeDefinitionStore;
import org.apache.jackrabbit.oak.spi.security.authorization.ACE;
import org.apache.jackrabbit.oak.spi.security.authorization.AbstractAccessControlList;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.Restriction;
@@ -43,9 +49,6 @@ import org.slf4j.LoggerFactory;
/**
* ACL... TODO
- * <p/>
- * TODO: - remove redundant entries from the list
- * TODO: - remove redundant privileges from entries
*/
abstract class ACL extends AbstractAccessControlList {
@@ -69,6 +72,8 @@ abstract class ACL extends AbstractAcces
abstract PrivilegeManager getPrivilegeManager();
+ abstract PrivilegeDefinitionStore getPrivilegeStore();
+
//------------------------------------------< AbstractAccessControlList >---
@Nonnull
@Override
@@ -112,12 +117,12 @@ abstract class ACL extends AbstractAcces
rs.add(getRestrictionProvider().createRestriction(getOakPath(), name, restrictions.get(name)));
}
}
- JackrabbitAccessControlEntry entry = new ACE(principal, privileges, isAllow, rs);
+ ACE entry = new ACE(principal, privileges, isAllow, rs);
if (entries.contains(entry)) {
log.debug("Entry is already contained in policy -> no modification.");
return false;
} else {
- return addEntry(entry);
+ return internalAddEntry(entry);
}
}
@@ -165,15 +170,83 @@ abstract class ACL extends AbstractAcces
* @return The validated {@code ACE}.
* @throws AccessControlException If the specified entry is invalid.
*/
- private static JackrabbitAccessControlEntry checkACE(AccessControlEntry entry) throws AccessControlException {
+ private static ACE checkACE(AccessControlEntry entry) throws AccessControlException {
if (!(entry instanceof ACE)) {
throw new AccessControlException("Invalid access control entry.");
}
return (ACE) entry;
}
- private boolean addEntry(JackrabbitAccessControlEntry entry) {
- // TODO: remove redundancy
- return entries.add(entry);
+ private boolean internalAddEntry(@Nonnull ACE entry) throws RepositoryException {
+ final Principal principal = entry.getPrincipal();
+ List<JackrabbitAccessControlEntry> subList = Lists.newArrayList(Iterables.filter(entries, new Predicate<JackrabbitAccessControlEntry>() {
+ @Override
+ public boolean apply(@Nullable JackrabbitAccessControlEntry ace) {
+ return (ace != null) && ace.getPrincipal().equals(principal);
+ }
+ }));
+
+ for (JackrabbitAccessControlEntry ace : subList) {
+ ACE existing = (ACE) ace;
+ PrivilegeBits existingBits = getPrivilegeBits(existing);
+ PrivilegeBits entryBits = getPrivilegeBits(entry);
+ if (entry.getRestrictions().equals(existing.getRestrictions())) {
+ if (isRedundantOrExtending(existing, entry)) {
+ if (existingBits.includes(entryBits)) {
+ return false;
+ } else {
+ // merge existing and new ace
+ existingBits.add(entryBits);
+ int index = entries.indexOf(existing);
+ entries.remove(existing);
+ entries.add(index, createACE(existing, existingBits));
+ return true;
+ }
+ }
+
+ // clean up redundant privileges defined by the existing entry
+ // and append the new entry at the end of the list.
+ PrivilegeBits updated = PrivilegeBits.getInstance(existingBits).diff(entryBits);
+ if (updated.isEmpty()) {
+ // remove the existing entry as the new entry covers all privileges
+ entries.remove(ace);
+ } else if (!updated.includes(existingBits)) {
+ // replace the existing entry having it's privileges adjusted
+ int index = entries.indexOf(existing);
+ entries.remove(ace);
+ entries.add(index, createACE(existing, updated));
+ } /* else: no collision that requires adjusting the existing entry.*/
+ }
+ }
+
+ // finally add the new entry at the end of the list
+ entries.add(entry);
+ return true;
+ }
+
+ // TODO
+ private boolean isRedundantOrExtending(ACE existing, ACE entry) {
+ return existing.isAllow() == entry.isAllow()
+ && (!(existing.getPrincipal() instanceof Group) || entries.indexOf(existing) == entries.size() - 1);
+ }
+
+ private ACE createACE(ACE existing, PrivilegeBits newPrivilegeBits) throws RepositoryException {
+ return new ACE(existing.getPrincipal(), getPrivileges(newPrivilegeBits), existing.isAllow(), existing.getRestrictions());
+ }
+
+ private Set<Privilege> getPrivileges(PrivilegeBits bits) throws RepositoryException {
+ Set<Privilege> privileges = new HashSet<Privilege>();
+ for (String name : getPrivilegeStore().getPrivilegeNames(bits)) {
+ privileges.add(getPrivilegeManager().getPrivilege(name));
+ }
+ return privileges;
+ }
+
+ private PrivilegeBits getPrivilegeBits(ACE entry) {
+ PrivilegeBits bits = PrivilegeBits.getInstance();
+ for (Privilege privilege : entry.getPrivileges()) {
+ bits.add(getPrivilegeStore().getBits(privilege.getName()));
+ }
+ return bits;
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java?rev=1447789&r1=1447788&r2=1447789&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java Tue Feb 19 16:14:11 2013
@@ -62,6 +62,7 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager;
import org.apache.jackrabbit.oak.security.authorization.restriction.PrincipalRestrictionProvider;
import org.apache.jackrabbit.oak.security.principal.PrincipalImpl;
+import org.apache.jackrabbit.oak.security.privilege.PrivilegeDefinitionStore;
import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
import org.apache.jackrabbit.oak.spi.security.authorization.ACE;
import org.apache.jackrabbit.oak.spi.security.authorization.AccessControlConfiguration;
@@ -613,6 +614,11 @@ public class AccessControlManagerImpl im
PrivilegeManager getPrivilegeManager() {
return privilegeManager;
}
+
+ @Override
+ PrivilegeDefinitionStore getPrivilegeStore() {
+ return new PrivilegeDefinitionStore(root);
+ }
}
private final class PrincipalACL extends NodeACL {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/PermissionProviderImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/PermissionProviderImpl.java?rev=1447789&r1=1447788&r2=1447789&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/PermissionProviderImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/PermissionProviderImpl.java Tue Feb 19 16:14:11 2013
@@ -213,7 +213,6 @@ public class PermissionProviderImpl impl
}
}
- // TODO: deal with activities/configurations
@CheckForNull
private String getVersionablePath(@Nonnull Tree versionStoreTree, @Nullable PropertyState property) {
String relPath = "";
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/ACE.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/ACE.java?rev=1447789&r1=1447788&r2=1447789&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/ACE.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/ACE.java Tue Feb 19 16:14:11 2013
@@ -120,13 +120,14 @@ public class ACE implements JackrabbitAc
}
//-------------------------------------------------------------< Object >---
+
/**
* @see Object#hashCode()
*/
@Override
public int hashCode() {
if (hashCode == 0) {
- hashCode = Objects.hashCode(principal, aggrPrivNames(), isAllow, restrictions);
+ hashCode = Objects.hashCode(principal.getName(), aggrPrivNames(), isAllow, restrictions);
}
return hashCode;
}
@@ -138,7 +139,7 @@ public class ACE implements JackrabbitAc
}
if (obj instanceof ACE) {
ACE other = (ACE) obj;
- return principal.equals(other.principal)
+ return principal.getName().equals(other.principal.getName())
&& isAllow == other.isAllow
&& aggrPrivNames().equals(other.aggrPrivNames())
&& restrictions.equals(other.restrictions);
@@ -162,7 +163,7 @@ public class ACE implements JackrabbitAc
if (priv.isAggregate()) {
for (Privilege aggr : priv.getAggregatePrivileges()) {
if (!aggr.isAggregate()) {
- aggrPrivNames.add(aggr.getName());
+ aggrPrivNames.add(aggr.getName());
}
}
} else {
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/ACLTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/ACLTest.java?rev=1447789&r1=1447788&r2=1447789&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/ACLTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/ACLTest.java Tue Feb 19 16:14:11 2013
@@ -17,16 +17,20 @@
package org.apache.jackrabbit.oak.security.authorization;
import java.security.Principal;
+import java.security.acl.Group;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import javax.jcr.PropertyType;
import javax.jcr.Value;
+import javax.jcr.ValueFactory;
import javax.jcr.security.AccessControlEntry;
import javax.jcr.security.AccessControlException;
import javax.jcr.security.Privilege;
+import com.google.common.collect.Sets;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlEntry;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
@@ -35,6 +39,7 @@ import org.apache.jackrabbit.oak.namepat
import org.apache.jackrabbit.oak.plugins.value.ValueFactoryImpl;
import org.apache.jackrabbit.oak.security.principal.PrincipalImpl;
import org.apache.jackrabbit.oak.security.privilege.PrivilegeConstants;
+import org.apache.jackrabbit.oak.security.privilege.PrivilegeDefinitionStore;
import org.apache.jackrabbit.oak.spi.security.authorization.ACE;
import org.apache.jackrabbit.oak.spi.security.authorization.AbstractAccessControlList;
import org.apache.jackrabbit.oak.spi.security.authorization.AbstractAccessControlListTest;
@@ -42,10 +47,12 @@ import org.apache.jackrabbit.oak.spi.sec
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -55,12 +62,12 @@ import static org.junit.Assert.fail;
* TODO: test restrictions
* TODO: add test with multiple entries
*/
-public class ACLTest extends AbstractAccessControlListTest {
+public class ACLTest extends AbstractAccessControlListTest implements PrivilegeConstants {
private PrivilegeManager privilegeManager;
private PrincipalManager principalManager;
- private AbstractAccessControlList emptyAcl;
+ private AbstractAccessControlList acl;
private Principal testPrincipal;
private Privilege[] testPrivileges;
@@ -72,9 +79,9 @@ public class ACLTest extends AbstractAcc
privilegeManager = getPrivilegeManager();
principalManager = getSecurityProvider().getPrincipalConfiguration().getPrincipalManager(root, getNamePathMapper());
- emptyAcl = createEmptyACL();
+ acl = createEmptyACL();
testPrincipal = getTestPrincipal();
- testPrivileges = privilegesFromNames(PrivilegeConstants.JCR_ADD_CHILD_NODES, PrivilegeConstants.JCR_LOCK_MANAGEMENT);
+ testPrivileges = privilegesFromNames(JCR_ADD_CHILD_NODES, JCR_LOCK_MANAGEMENT);
}
@Override
@@ -98,14 +105,28 @@ public class ACLTest extends AbstractAcc
PrivilegeManager getPrivilegeManager() {
return privilegeManager;
}
+
+ @Override
+ PrivilegeDefinitionStore getPrivilegeStore() {
+ return new PrivilegeDefinitionStore(root);
+ }
};
}
+ private ValueFactory getValueFactory() {
+ return new ValueFactoryImpl(root.getBlobFactory(), NamePathMapper.DEFAULT);
+ }
+
+ private static void assertACE(JackrabbitAccessControlEntry ace, boolean isAllow, Privilege... privileges) {
+ assertEquals(isAllow, ace.isAllow());
+ assertEquals(Sets.newHashSet(privileges), Sets.newHashSet(ace.getPrivileges()));
+ }
+
@Test
public void testAddInvalidEntry() throws Exception {
Principal unknownPrincipal = new PrincipalImpl("unknown");
try {
- emptyAcl.addAccessControlEntry(unknownPrincipal, privilegesFromNames(Privilege.JCR_READ));
+ acl.addAccessControlEntry(unknownPrincipal, privilegesFromNames(JCR_READ));
fail("Adding an ACE with an unknown principal should fail");
} catch (AccessControlException e) {
// success
@@ -115,13 +136,13 @@ public class ACLTest extends AbstractAcc
@Test
public void testAddEntryWithoutPrivilege() throws Exception {
try {
- emptyAcl.addAccessControlEntry(testPrincipal, new Privilege[0]);
+ acl.addAccessControlEntry(testPrincipal, new Privilege[0]);
fail("Adding an ACE with empty privilege array should fail.");
} catch (AccessControlException e) {
// success
}
try {
- emptyAcl.addAccessControlEntry(testPrincipal, null);
+ acl.addAccessControlEntry(testPrincipal, null);
fail("Adding an ACE with null privileges should fail.");
} catch (AccessControlException e) {
// success
@@ -131,7 +152,7 @@ public class ACLTest extends AbstractAcc
@Test
public void testAddEntryWithInvalidPrivilege() throws Exception {
try {
- emptyAcl.addAccessControlEntry(testPrincipal, new Privilege[]{new InvalidPrivilege()});
+ acl.addAccessControlEntry(testPrincipal, new Privilege[]{new InvalidPrivilege()});
fail("Adding an ACE with invalid privileges should fail.");
} catch (AccessControlException e) {
// success
@@ -140,21 +161,21 @@ public class ACLTest extends AbstractAcc
@Test
public void testAddEntry() throws Exception {
- assertTrue(emptyAcl.addEntry(testPrincipal, testPrivileges, true, Collections.<String, Value>emptyMap()));
- assertFalse(emptyAcl.isEmpty());
+ assertTrue(acl.addEntry(testPrincipal, testPrivileges, true, Collections.<String, Value>emptyMap()));
+ assertFalse(acl.isEmpty());
}
@Test
public void testAddEntryTwice() throws Exception {
- emptyAcl.addEntry(testPrincipal, testPrivileges, true, Collections.<String, Value>emptyMap());
- assertFalse(emptyAcl.addEntry(testPrincipal, testPrivileges, true, Collections.<String, Value>emptyMap()));
+ acl.addEntry(testPrincipal, testPrivileges, true, Collections.<String, Value>emptyMap());
+ assertFalse(acl.addEntry(testPrincipal, testPrivileges, true, Collections.<String, Value>emptyMap()));
}
@Test
public void testAddEntryWithInvalidRestrictions() throws Exception {
Map<String, Value> restrictions = Collections.singletonMap("unknownRestriction", new ValueFactoryImpl(root.getBlobFactory(), namePathMapper).createValue("value"));
try {
- emptyAcl.addEntry(testPrincipal, testPrivileges, false, restrictions);
+ acl.addEntry(testPrincipal, testPrivileges, false, restrictions);
fail("Invalid restrictions -> AccessControlException expected");
} catch (AccessControlException e) {
// success
@@ -163,9 +184,9 @@ public class ACLTest extends AbstractAcc
@Test
public void testRemoveEntry() throws Exception {
- assertTrue(emptyAcl.addAccessControlEntry(testPrincipal, testPrivileges));
- emptyAcl.removeAccessControlEntry(emptyAcl.getAccessControlEntries()[0]);
- assertTrue(emptyAcl.isEmpty());
+ assertTrue(acl.addAccessControlEntry(testPrincipal, testPrivileges));
+ acl.removeAccessControlEntry(acl.getAccessControlEntries()[0]);
+ assertTrue(acl.isEmpty());
}
@Test
@@ -180,7 +201,7 @@ public class ACLTest extends AbstractAcc
@Test
public void testRemoveInvalidEntry() throws Exception {
try {
- emptyAcl.removeAccessControlEntry(new JackrabbitAccessControlEntry() {
+ acl.removeAccessControlEntry(new JackrabbitAccessControlEntry() {
public boolean isAllow() {
return false;
}
@@ -210,7 +231,7 @@ public class ACLTest extends AbstractAcc
@Test
public void testRemoveNonExisting() throws Exception {
try {
- emptyAcl.removeAccessControlEntry(new ACE(testPrincipal, testPrivileges, true, null));
+ acl.removeAccessControlEntry(new ACE(testPrincipal, testPrivileges, true, null));
fail("Removing a non-existing ACE should fail.");
} catch (AccessControlException e) {
// success
@@ -219,8 +240,8 @@ public class ACLTest extends AbstractAcc
@Test
public void testReorderToTheEnd() throws Exception {
- Privilege[] read = privilegesFromNames(PrivilegeConstants.JCR_READ, PrivilegeConstants.JCR_READ_ACCESS_CONTROL);
- Privilege[] write = privilegesFromNames(PrivilegeConstants.JCR_WRITE);
+ Privilege[] read = privilegesFromNames(JCR_READ, JCR_READ_ACCESS_CONTROL);
+ Privilege[] write = privilegesFromNames(JCR_WRITE);
AbstractAccessControlList acl = createEmptyACL();
acl.addAccessControlEntry(testPrincipal, read);
@@ -239,8 +260,8 @@ public class ACLTest extends AbstractAcc
@Test
public void testReorder() throws Exception {
- Privilege[] read = privilegesFromNames(PrivilegeConstants.JCR_READ, PrivilegeConstants.JCR_READ_ACCESS_CONTROL);
- Privilege[] write = privilegesFromNames(PrivilegeConstants.JCR_WRITE);
+ Privilege[] read = privilegesFromNames(JCR_READ, JCR_READ_ACCESS_CONTROL);
+ Privilege[] write = privilegesFromNames(JCR_WRITE);
AbstractAccessControlList acl = createEmptyACL();
acl.addAccessControlEntry(testPrincipal, read);
@@ -268,28 +289,305 @@ public class ACLTest extends AbstractAcc
}
@Test
- public void testReorderInvalidElements() throws Exception {
- Privilege[] read = privilegesFromNames(PrivilegeConstants.JCR_READ, PrivilegeConstants.JCR_READ_ACCESS_CONTROL);
- Privilege[] write = privilegesFromNames(PrivilegeConstants.JCR_WRITE);
+ public void testReorderInvalidEntries() throws Exception {
+ Privilege[] read = privilegesFromNames(JCR_READ, JCR_READ_ACCESS_CONTROL);
+ Privilege[] write = privilegesFromNames(JCR_WRITE);
- emptyAcl.addAccessControlEntry(testPrincipal, read);
- emptyAcl.addAccessControlEntry(EveryonePrincipal.getInstance(), write);
+ acl.addAccessControlEntry(testPrincipal, read);
+ acl.addAccessControlEntry(EveryonePrincipal.getInstance(), write);
AccessControlEntry invalid = new ACE(testPrincipal, write, false, Collections.<Restriction>emptySet());
try {
- emptyAcl.orderBefore(invalid, emptyAcl.getEntries().get(0));
+ acl.orderBefore(invalid, acl.getEntries().get(0));
fail("src entry not contained in list -> reorder should fail.");
} catch (AccessControlException e) {
// success
}
try {
- emptyAcl.orderBefore(emptyAcl.getEntries().get(0), invalid);
+ acl.orderBefore(acl.getEntries().get(0), invalid);
fail("dest entry not contained in list -> reorder should fail.");
} catch (AccessControlException e) {
// success
}
}
+ @Test
+ public void testMultipleEntries() throws Exception {
+ Privilege[] privileges = privilegesFromNames(JCR_READ);
+ acl.addEntry(testPrincipal, privileges, true);
+
+ // new entry extends privileges.
+ privileges = privilegesFromNames(JCR_READ, JCR_ADD_CHILD_NODES);
+ assertTrue(acl.addEntry(testPrincipal, privileges, true));
+
+ // expected: only a single allow-entry with both privileges
+ assertTrue(acl.size() == 1);
+ assertACE(acl.getEntries().get(0), true, privileges);
+ }
+
+ @Test
+ public void testMultipleEntries2() throws Exception {
+ Privilege[] privileges = privilegesFromNames(JCR_READ, JCR_ADD_CHILD_NODES);
+ acl.addEntry(testPrincipal, privileges, true);
+
+ // adding just ADD_CHILD_NODES -> must not remove READ privilege
+ Privilege[] achPrivs = privilegesFromNames(JCR_ADD_CHILD_NODES);
+ assertFalse(acl.addEntry(testPrincipal, achPrivs, true));
+
+ // expected: only a single allow-entry with add_child_nodes + read privilege
+ assertTrue(acl.size() == 1);
+ assertACE(acl.getEntries().get(0), true, privileges);
+ }
+
+ @Test
+ public void testComplementaryEntry() throws Exception {
+ Privilege[] privileges = privilegesFromNames(JCR_READ);
+ acl.addEntry(testPrincipal, privileges, true);
+
+ // same entry but with revers 'isAllow' flag
+ assertTrue(acl.addEntry(testPrincipal, privileges, false));
+
+ // expected: only a single deny-read entry
+ assertEquals(1, acl.size());
+ assertACE(acl.getEntries().get(0), false, privileges);
+ }
+
+ @Test
+ public void testComplementaryEntry1() throws Exception {
+ Privilege[] privileges = privilegesFromNames(JCR_READ, JCR_ADD_CHILD_NODES);
+ acl.addEntry(testPrincipal, privileges, true);
+
+ // revoke the 'READ' privilege
+ privileges = privilegesFromNames(JCR_READ);
+ assertTrue(acl.addEntry(testPrincipal, privileges, false));
+
+ // expected: 2 entries one allowing ADD_CHILD_NODES, the other denying READ
+ assertTrue(acl.size() == 2);
+
+ assertACE(acl.getEntries().get(0), true, privilegesFromNames(JCR_ADD_CHILD_NODES));
+ assertACE(acl.getEntries().get(1), false, privilegesFromNames(JCR_READ));
+ }
+
+ @Test
+ public void testComplementaryEntry2() throws Exception {
+ Privilege[] repwrite = privilegesFromNames(REP_WRITE);
+ acl.addAccessControlEntry(testPrincipal, repwrite);
+
+ // add deny entry for mod_props
+ Privilege[] modProperties = privilegesFromNames(JCR_MODIFY_PROPERTIES);
+ assertTrue(acl.addEntry(testPrincipal, modProperties, false));
+
+ // expected: 2 entries with the allow entry being adjusted
+ assertTrue(acl.size() == 2);
+
+ Privilege[] expected = privilegesFromNames(JCR_ADD_CHILD_NODES, JCR_REMOVE_CHILD_NODES, JCR_REMOVE_NODE, JCR_NODE_TYPE_MANAGEMENT);
+ assertACE(acl.getEntries().get(0), true, expected);
+ assertACE(acl.getEntries().get(1), false, modProperties);
+ }
+
+ @Test
+ public void testMultiplePrincipals() throws Exception {
+ Principal everyone = principalManager.getEveryone();
+ Privilege[] privs = privilegesFromNames(JCR_READ);
+
+ acl.addAccessControlEntry(testPrincipal, privs);
+ assertFalse(acl.addAccessControlEntry(testPrincipal, privs));
+
+ // add same privileges for another principal -> must modify as well.
+ assertTrue(acl.addAccessControlEntry(everyone, privs));
+ // .. 2 entries must be present.
+ assertTrue(acl.getAccessControlEntries().length == 2);
+ assertEquals(everyone, acl.getAccessControlEntries()[1].getPrincipal());
+ }
+
+ @Test
+ public void testSetEntryForGroupPrincipal() throws Exception {
+ Privilege[] privs = privilegesFromNames(JCR_READ);
+ Group grPrincipal = (Group) principalManager.getEveryone();
+
+ // adding allow-entry must succeed
+ assertTrue(acl.addAccessControlEntry(grPrincipal, privs));
+
+ // adding deny-entry must succeed
+ assertTrue(acl.addEntry(grPrincipal, privs, false));
+ assertEquals(1, acl.size());
+ assertFalse(acl.getEntries().get(0).isAllow());
+ }
+
+ @Ignore("OAK-51") // TODO
+ @Test
+ public void testUpdateGroupEntry() throws Exception {
+ Privilege[] readPriv = privilegesFromNames(JCR_READ);
+ Privilege[] writePriv = privilegesFromNames(JCR_WRITE);
+
+ Principal everyone = principalManager.getEveryone();
+
+ acl.addEntry(testPrincipal, readPriv, true);
+ acl.addEntry(everyone, readPriv, true);
+ acl.addEntry(testPrincipal, writePriv, false);
+
+ // adding an entry that should update the existing allow-entry for everyone.
+ acl.addEntry(everyone, writePriv, true);
+
+ AccessControlEntry[] entries = acl.getAccessControlEntries();
+ assertEquals(3, entries.length);
+ JackrabbitAccessControlEntry princ2AllowEntry = (JackrabbitAccessControlEntry) entries[1];
+ assertEquals(everyone, princ2AllowEntry.getPrincipal());
+ assertACE(princ2AllowEntry, true, privilegesFromNames(JCR_READ, JCR_WRITE));
+ }
+
+ @Ignore("OAK-51") // TODO
+ @Test
+ public void testComplementaryGroupEntry() throws Exception {
+ Privilege[] readPriv = privilegesFromNames(JCR_READ);
+ Privilege[] writePriv = privilegesFromNames(JCR_WRITE);
+ Principal everyone = principalManager.getEveryone();
+
+ acl.addEntry(testPrincipal, readPriv, true);
+ acl.addEntry(everyone, readPriv, true);
+ acl.addEntry(testPrincipal, writePriv, false);
+ acl.addEntry(everyone, writePriv, true);
+ // entry complementary to the first entry
+ // -> must remove the allow-READ entry and update the deny-WRITE entry.
+ acl.addEntry(testPrincipal, readPriv, false);
+
+ AccessControlEntry[] entries = acl.getAccessControlEntries();
+
+ assertEquals(2, entries.length);
+
+ JackrabbitAccessControlEntry first = (JackrabbitAccessControlEntry) entries[0];
+ assertEquals(everyone, first.getPrincipal());
+
+ JackrabbitAccessControlEntry second = (JackrabbitAccessControlEntry) entries[1];
+ assertEquals(testPrincipal, second.getPrincipal());
+ assertACE(second, false, privilegesFromNames(JCR_READ, JCR_WRITE));
+ }
+
+ @Test
+ public void testUpdateAndComplementary() throws Exception {
+ Privilege[] readPriv = privilegesFromNames(JCR_READ);
+ Privilege[] writePriv = privilegesFromNames(JCR_WRITE);
+ Privilege[] acReadPriv = privilegesFromNames(JCR_READ_ACCESS_CONTROL);
+
+ assertTrue(acl.addEntry(testPrincipal, readPriv, true));
+ assertTrue(acl.addEntry(testPrincipal, writePriv, true));
+ assertTrue(acl.addEntry(testPrincipal, acReadPriv, true));
+ assertEquals(1, acl.size());
+
+ assertTrue(acl.addEntry(testPrincipal, readPriv, false));
+ assertEquals(2, acl.size());
+
+ assertACE(acl.getEntries().get(0), true, privilegesFromNames(JCR_WRITE, JCR_READ_ACCESS_CONTROL));
+ assertACE(acl.getEntries().get(1), false, readPriv);
+ }
+
+ @Test
+ public void testDifferentPrivilegeImplementation() throws Exception {
+ Privilege[] readPriv = privilegesFromNames(JCR_READ);
+ acl.addEntry(testPrincipal, readPriv, false);
+
+ assertFalse(acl.addEntry(new PrincipalImpl(testPrincipal.getName()), readPriv, false));
+ assertFalse(acl.addEntry(new Principal() {
+ public String getName() {
+ return testPrincipal.getName();
+ }
+ }, readPriv, false));
+ }
+
+ @Test
+ public void testNewEntriesAppendedAtEnd() throws Exception {
+ Privilege[] readPriv = privilegesFromNames(JCR_READ);
+ Privilege[] writePriv = privilegesFromNames(JCR_WRITE);
+
+ acl.addEntry(testPrincipal, readPriv, true);
+ acl.addEntry(principalManager.getEveryone(), readPriv, true);
+ acl.addEntry(testPrincipal, writePriv, false);
+
+ AccessControlEntry[] entries = acl.getAccessControlEntries();
+
+ assertEquals(3, entries.length);
+
+ JackrabbitAccessControlEntry last = (JackrabbitAccessControlEntry) entries[2];
+ assertEquals(testPrincipal, last.getPrincipal());
+ assertACE(last, false, writePriv);
+ }
+
+ @Test
+ public void testRestrictions() throws Exception {
+ String[] names = acl.getRestrictionNames();
+ assertNotNull(names);
+ assertEquals(1, names.length);
+ assertEquals(AccessControlConstants.REP_GLOB, names[0]);
+ assertEquals(PropertyType.STRING, acl.getRestrictionType(names[0]));
+
+ Privilege[] writePriv = privilegesFromNames(JCR_WRITE);
+
+ // add entry without restr. -> must succeed
+ assertTrue(acl.addAccessControlEntry(testPrincipal, writePriv));
+ assertEquals(1, acl.getAccessControlEntries().length);
+
+ // ... again -> no modification.
+ assertFalse(acl.addAccessControlEntry(testPrincipal, writePriv));
+ assertEquals(1, acl.getAccessControlEntries().length);
+
+ // ... again using different method -> no modification.
+ assertFalse(acl.addEntry(testPrincipal, writePriv, true));
+ assertEquals(1, acl.getAccessControlEntries().length);
+
+ // ... complementary entry -> must modify the acl
+ assertTrue(acl.addEntry(testPrincipal, writePriv, false));
+ assertEquals(1, acl.getAccessControlEntries().length);
+
+ // add an entry with a restrictions:
+ Map<String, Value> restrictions = Collections.singletonMap(AccessControlConstants.REP_GLOB, getValueFactory().createValue("/.*"));
+ assertTrue(acl.addEntry(testPrincipal, writePriv, false, restrictions));
+ assertEquals(2, acl.getAccessControlEntries().length);
+
+ // ... same again -> no modification.
+ assertFalse(acl.addEntry(testPrincipal, writePriv, false, restrictions));
+ assertEquals(2, acl.getAccessControlEntries().length);
+
+ // ... complementary entry -> must modify the acl.
+ assertTrue(acl.addEntry(testPrincipal, writePriv, true, restrictions));
+ assertEquals(2, acl.getAccessControlEntries().length);
+ }
+
+ @Test
+ public void testInsertionOrder() throws Exception {
+ Privilege[] readPriv = privilegesFromNames(JCR_READ);
+ Privilege[] writePriv = privilegesFromNames(JCR_WRITE);
+ Privilege[] addNodePriv = privilegesFromNames(JCR_ADD_CHILD_NODES);
+
+ Map<String, Value> restrictions = Collections.singletonMap(AccessControlConstants.REP_GLOB, getValueFactory().createValue("/.*"));
+
+ acl.addEntry(testPrincipal, readPriv, true);
+ acl.addEntry(testPrincipal, writePriv, false);
+ acl.addEntry(testPrincipal, addNodePriv, true, restrictions);
+
+ List<JackrabbitAccessControlEntry> entries = acl.getEntries();
+ assertACE(entries.get(0), true, readPriv);
+ assertACE(entries.get(1), false, writePriv);
+ assertACE(entries.get(2), true, addNodePriv);
+ }
+
+ @Test
+ public void testInsertionOrder2() throws Exception {
+ Privilege[] readPriv = privilegesFromNames(JCR_READ);
+ Privilege[] writePriv = privilegesFromNames(JCR_WRITE);
+ Privilege[] addNodePriv = privilegesFromNames(JCR_ADD_CHILD_NODES);
+
+ Map<String, Value> restrictions = Collections.singletonMap(AccessControlConstants.REP_GLOB, getValueFactory().createValue("/.*"));
+
+ acl.addEntry(testPrincipal, readPriv, true);
+ acl.addEntry(testPrincipal, addNodePriv, true, restrictions);
+ acl.addEntry(testPrincipal, writePriv, false);
+
+ List<JackrabbitAccessControlEntry> entries = acl.getEntries();
+ assertACE(entries.get(0), true, readPriv);
+ assertACE(entries.get(1), true, addNodePriv);
+ assertACE(entries.get(2), false, writePriv);
+ }
+
//--------------------------------------------------------------------------
private class InvalidPrivilege implements Privilege {