Added: jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugValidatorTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugValidatorTest.java?rev=1663623&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugValidatorTest.java (added) +++ jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugValidatorTest.java Tue Mar 3 10:51:54 2015 @@ -0,0 +1,120 @@ +/* + * 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.spi.security.authorization.cug.impl; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.oak.api.CommitFailedException; +import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants; +import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal; +import org.apache.jackrabbit.oak.util.NodeUtil; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +public class CugValidatorTest extends AbstractCugTest { + + private NodeUtil node; + + @Override + public void before() throws Exception { + super.before(); + + node = new NodeUtil(root.getTree(SUPPORTED_PATH)); + } + + @Test + public void testChangePrimaryType() { + try { + node.setName(JcrConstants.JCR_PRIMARYTYPE, NT_REP_CUG_POLICY); + root.commit(); + fail(); + } catch (CommitFailedException e) { + assertTrue(e.isAccessControlViolation()); + assertEquals(20, e.getCode()); + } + } + + @Test + public void testChangePrimaryTypeOfCug() throws Exception { + node.setNames(JcrConstants.JCR_MIXINTYPES, MIX_REP_CUG_MIXIN); + NodeUtil cug = node.addChild(REP_CUG_POLICY, NT_REP_CUG_POLICY); + cug.setStrings(REP_PRINCIPAL_NAMES, EveryonePrincipal.NAME); + root.commit(); + + try { + cug.setName(JcrConstants.JCR_PRIMARYTYPE, NodeTypeConstants.NT_OAK_UNSTRUCTURED); + root.commit(); + fail(); + } catch (CommitFailedException e) { + assertTrue(e.isAccessControlViolation()); + assertEquals(21, e.getCode()); + } + } + + @Test + public void testInvalidPrimaryType() throws Exception { + NodeUtil cug = node.addChild(REP_CUG_POLICY, NodeTypeConstants.NT_OAK_UNSTRUCTURED); + cug.setStrings(REP_PRINCIPAL_NAMES, EveryonePrincipal.NAME); + + try { + root.commit(); + fail(); + } catch (CommitFailedException e) { + assertTrue(e.isAccessControlViolation()); + assertEquals(21, e.getCode()); + } finally { + root.refresh(); + } + } + + @Test + public void testMissingMixin() throws Exception { + NodeUtil cug = node.addChild(REP_CUG_POLICY, NT_REP_CUG_POLICY); + cug.setStrings(REP_PRINCIPAL_NAMES, EveryonePrincipal.NAME); + + try { + root.commit(); + fail(); + } catch (CommitFailedException e) { + assertTrue(e.isAccessControlViolation()); + assertEquals(22, e.getCode()); + } finally { + root.refresh(); + } + } + + @Test + public void testRemoveMixin() throws Exception { + node.setNames(JcrConstants.JCR_MIXINTYPES, MIX_REP_CUG_MIXIN); + NodeUtil cug = node.addChild(REP_CUG_POLICY, NT_REP_CUG_POLICY); + cug.setStrings(REP_PRINCIPAL_NAMES, EveryonePrincipal.NAME); + root.commit(); + + try { + node.removeProperty(JcrConstants.JCR_MIXINTYPES); + root.commit(); + fail(); + } catch (CommitFailedException e) { + assertTrue(e.isAccessControlViolation()); + assertEquals(22, e.getCode()); + } finally { + root.refresh(); + } + } +} \ No newline at end of file
Added: jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/SupportedPathsTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/SupportedPathsTest.java?rev=1663623&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/SupportedPathsTest.java (added) +++ jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/SupportedPathsTest.java Tue Mar 3 10:51:54 2015 @@ -0,0 +1,71 @@ +/* + * 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.spi.security.authorization.cug.impl; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class SupportedPathsTest { + + @Test + public void testIncludes() { + SupportedPaths supportedPaths = new SupportedPaths(new String[] {"/content"}); + + Map<String, Boolean> pathMap = new HashMap<String, Boolean>(); + pathMap.put("/content", true); + pathMap.put("/content/a", true); + pathMap.put("/content/a/rep:cugPolicy", true); + pathMap.put("/content/a/b", true); + pathMap.put("/content/a/b/c/jcr:primaryType", true); + pathMap.put("/content/aa", true); + pathMap.put("/content/aa/bb/cc", true); + pathMap.put("/jcr:system", false); + pathMap.put("/", false); + pathMap.put("/testRoot", false); + pathMap.put("/some/other/path", false); + + for (String path : pathMap.keySet()) { + boolean expected = pathMap.get(path); + + assertEquals(path, expected, supportedPaths.includes(path)); + assertEquals(path, expected, supportedPaths.includes(path + '/')); + } + } + + @Test + public void testMayContainCug() { + SupportedPaths supportedPaths = new SupportedPaths(new String[] {"/content/a"}); + + Map<String, Boolean> pathMap = new HashMap<String, Boolean>(); + pathMap.put("/", true); + pathMap.put("/content", true); + pathMap.put("/jcr:system", false); + pathMap.put("/testRoot", false); + pathMap.put("/some/other/path", false); + pathMap.put("/content/a", false); + pathMap.put("/content/a/b", false); + + for (String path : pathMap.keySet()) { + boolean expected = pathMap.get(path); + assertEquals(path, expected, supportedPaths.mayContainCug(path)); + } + } +} \ No newline at end of file Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationConfigurationImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationConfigurationImpl.java?rev=1663623&r1=1663622&r2=1663623&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationConfigurationImpl.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationConfigurationImpl.java Tue Mar 3 10:51:54 2015 @@ -56,8 +56,6 @@ import org.apache.jackrabbit.oak.spi.sec import org.apache.jackrabbit.oak.spi.security.SecurityProvider; import org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration; import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants; -import org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregatedPermissionProvider; -import org.apache.jackrabbit.oak.spi.security.authorization.permission.ControlFlag; import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionConstants; import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider; import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider; @@ -102,21 +100,14 @@ import org.apache.jackrabbit.oak.spi.xml @Property(name = CompositeConfiguration.PARAM_RANKING, label = "Ranking", description = "Ranking of this configuration in a setup with multiple authorization configurations.", - intValue = 100), - @Property(name = AggregatedPermissionProvider.PARAM_CONTROL_FLAG, - label = "Control Flag", - description = "Control flag defining if the permission provider is SUFFICIENT or REQUIRED.", - options = { - @PropertyOption(name = ControlFlag.SUFFICIENT_NAME, value = ControlFlag.SUFFICIENT_NAME), - @PropertyOption(name = ControlFlag.REQUISITE_NAME, value = ControlFlag.REQUISITE_NAME) - }, - value = ControlFlag.REQUISITE_NAME) + intValue = 100) }) public class AuthorizationConfigurationImpl extends ConfigurationBase implements AuthorizationConfiguration { public AuthorizationConfigurationImpl() { super(); } + @SuppressWarnings("UnusedDeclaration") @Activate private void activate(Map<String, Object> properties) { setParameters(ConfigurationParameters.of(properties)); Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAuthorizationConfiguration.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAuthorizationConfiguration.java?rev=1663623&r1=1663622&r2=1663623&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAuthorizationConfiguration.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAuthorizationConfiguration.java Tue Mar 3 10:51:54 2015 @@ -52,7 +52,7 @@ public class CompositeAuthorizationConfi final @Nonnull NamePathMapper namePathMapper) { List<AuthorizationConfiguration> configurations = getConfigurations(); switch (configurations.size()) { - case 0: throw new IllegalArgumentException(); + case 0: throw new IllegalStateException(); case 1: return configurations.get(0).getAccessControlManager(root, namePathMapper); default: List<AccessControlManager> mgrs = Lists.transform(configurations, new Function<AuthorizationConfiguration, AccessControlManager>() { @@ -86,7 +86,7 @@ public class CompositeAuthorizationConfi final @Nonnull Set<Principal> principals) { List<AuthorizationConfiguration> configurations = getConfigurations(); switch (configurations.size()) { - case 0: throw new IllegalArgumentException(); + case 0: throw new IllegalStateException(); case 1: return configurations.get(0).getPermissionProvider(root, workspaceName, principals); default: List<AggregatedPermissionProvider> aggrPermissionProviders = Lists.newArrayListWithCapacity(configurations.size()); @@ -96,7 +96,11 @@ public class CompositeAuthorizationConfi aggrPermissionProviders.add((AggregatedPermissionProvider) pProvider); } } - return new CompositePermissionProvider(root, aggrPermissionProviders); + if (aggrPermissionProviders.size() == 1) { + return aggrPermissionProviders.get(0); + } else { + return new CompositePermissionProvider(root, aggrPermissionProviders); + } } } } \ No newline at end of file Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProvider.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProvider.java?rev=1663623&r1=1663622&r2=1663623&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProvider.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProvider.java Tue Mar 3 10:51:54 2015 @@ -33,7 +33,6 @@ import org.apache.jackrabbit.oak.api.Tre import org.apache.jackrabbit.oak.plugins.tree.RootFactory; import org.apache.jackrabbit.oak.plugins.tree.impl.ImmutableTree; import org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregatedPermissionProvider; -import org.apache.jackrabbit.oak.spi.security.authorization.permission.ControlFlag; import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider; import org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions; import org.apache.jackrabbit.oak.spi.security.authorization.permission.RepositoryPermission; @@ -58,7 +57,7 @@ class CompositePermissionProvider implem private Root immutableRoot; private PrivilegeBitsProvider pbp; - public CompositePermissionProvider(@Nonnull Root root, @Nonnull List<AggregatedPermissionProvider> pps) { + CompositePermissionProvider(@Nonnull Root root, @Nonnull List<AggregatedPermissionProvider> pps) { this.root = root; this.pps = pps; @@ -67,6 +66,7 @@ class CompositePermissionProvider implem pbp = new PrivilegeBitsProvider(immutableRoot); } + //-------------------------------------------------< PermissionProvider >--- @Override public void refresh() { immutableRoot = RootFactory.createReadOnlyRoot(root); @@ -78,13 +78,43 @@ class CompositePermissionProvider implem } @Override - public Set<String> getPrivileges(@Nullable Tree tree) { - return pbp.getPrivilegeNames(getPrivilegeBits(tree)); + public Set<String> getPrivileges(final @Nullable Tree tree) { + PrivilegeBits result = null; + Iterable<AggregatedPermissionProvider> providers = Iterables.filter(pps, new Predicate<AggregatedPermissionProvider>() { + @Override + public boolean apply(@Nullable AggregatedPermissionProvider pp) { + return pp != null && ((tree != null) || pp.handlesRepositoryPermissions()); + } + }); + for (AggregatedPermissionProvider pp : providers) { + PrivilegeBits privs = pbp.getBits(pp.getPrivileges(tree)); + if (result == null) { + result = PrivilegeBits.getInstance(); + result.add(privs); + } else { + // FIXME: only retain privs that are handled by prev. pp (and thus are denied) + result.retain(privs); + } + } + return pbp.getPrivilegeNames(result); } @Override - public boolean hasPrivileges(@Nullable Tree tree, @Nonnull String... privilegeNames) { - return getPrivilegeBits(tree).includes(pbp.getBits(privilegeNames)); + public boolean hasPrivileges(final @Nullable Tree tree, @Nonnull String... privilegeNames) { + for (final String privName : pbp.getAggregatedPrivilegeNames(privilegeNames)) { + Iterable<AggregatedPermissionProvider> providers = Iterables.filter(pps, new Predicate<AggregatedPermissionProvider>() { + @Override + public boolean apply(@Nullable AggregatedPermissionProvider pp) { + return pp != null && ((tree == null) ? pp.handlesRepositoryPermissions() : pp.handles(tree, pbp.getBits(privName))); + } + }); + for (AggregatedPermissionProvider pp : providers) { + if (!pp.hasPrivileges(tree, privName)) { + return false; + } + } + } + return true; } @Override @@ -132,15 +162,15 @@ class CompositePermissionProvider implem } @Override - public boolean isGranted(final @Nonnull String oakPath, final @Nonnull String jcrActions) { - String[] actions = Text.explode(jcrActions, ',', false); + public boolean isGranted(final @Nonnull String oakPath, @Nonnull String jcrActions) { + final String[] actions = Text.explode(jcrActions, ',', false); switch (actions.length) { case 0: return true; case 1: Iterable<AggregatedPermissionProvider> providers = Iterables.filter(pps, new Predicate<AggregatedPermissionProvider>() { @Override public boolean apply(@Nullable AggregatedPermissionProvider pp) { - return pp != null && pp.handles(oakPath, jcrActions); + return pp != null && pp.handles(oakPath, actions[0]); } }); return grantsAction(oakPath, actions[0], providers); @@ -161,38 +191,6 @@ class CompositePermissionProvider implem } //-------------------------------------------------------------------------- - private PrivilegeBits getPrivilegeBits(@Nullable final Tree tree) { - PrivilegeBits sufficient = PrivilegeBits.getInstance(); - PrivilegeBits required = null; - - Iterable<AggregatedPermissionProvider> providers = Iterables.filter(pps, new Predicate<AggregatedPermissionProvider>() { - @Override - public boolean apply(@Nullable AggregatedPermissionProvider pp) { - return pp != null && ((tree == null) ? pp.handlesRepositoryPermissions() : pp.handles(tree)); - } - }); - for (AggregatedPermissionProvider pp : providers) { - PrivilegeBits privs = pbp.getBits(pp.getPrivileges(tree)); - ControlFlag flag = pp.getFlag(); - if (ControlFlag.SUFFICIENT == flag) { - sufficient.add(privs); - if (required != null) { - sufficient.retain(required); - } - } else if (ControlFlag.REQUISITE == flag) { - if (required == null) { - required = PrivilegeBits.getInstance(); - required.add(privs); - } else { - required.retain(privs); - } - } - } - if (required != null) { - sufficient.add(required); - } - return sufficient; - } private static boolean grantsPermission(@Nonnull final Tree parent, @Nullable PropertyState property, @@ -202,7 +200,7 @@ class CompositePermissionProvider implem while (it.hasNext()) { AggregatedPermissionProvider pp = it.next(); boolean isGranted = pp.isGranted(parent, property, permission); - if (!it.hasNext() || evalComplete(isGranted, pp.getFlag())) { + if (!it.hasNext() || !isGranted) { return isGranted; } } @@ -216,7 +214,7 @@ class CompositePermissionProvider implem while (it.hasNext()) { AggregatedPermissionProvider pp = it.next(); boolean isGranted = pp.isGranted(oakPath, action); - if (!it.hasNext() || evalComplete(isGranted, pp.getFlag())) { + if (!it.hasNext() || !isGranted) { return isGranted; } } @@ -228,7 +226,7 @@ class CompositePermissionProvider implem while (it.hasNext()) { AggregatedPermissionProvider pp = it.next(); boolean isGranted = pp.getRepositoryPermission().isGranted(permission); - if (!it.hasNext() || evalComplete(isGranted, pp.getFlag())) { + if (!it.hasNext() || !isGranted) { return isGranted; } @@ -236,25 +234,6 @@ class CompositePermissionProvider implem return false; } - private static boolean evalComplete(boolean isGranted, ControlFlag flag) { - switch (flag) { - case SUFFICIENT: - if (isGranted) { - return true; - } - break; - case REQUISITE: - if (!isGranted) { - return true; - } - break; - default: - throw new IllegalArgumentException("Unsupported PermissionProvider Control Flag " + flag); - - } - return false; - } - //-------------------------------------------------------------------------- private final class CompositeTreePermission implements TreePermission { @@ -300,7 +279,7 @@ class CompositePermissionProvider implem TreePermission tp = entry.getValue(); if (entry.getKey().handles(tp, Permissions.READ_NODE)) { boolean isGranted = entry.getValue().canRead(); - if (!it.hasNext() || evalComplete(isGranted, entry.getKey().getFlag())) { + if (!it.hasNext() || !isGranted) { this.canRead = isGranted; break; } @@ -318,7 +297,7 @@ class CompositePermissionProvider implem TreePermission tp = entry.getValue(); if (entry.getKey().handles(tp, Permissions.READ_PROPERTY)) { boolean isGranted = entry.getValue().canRead(property); - if (!it.hasNext() || evalComplete(isGranted, entry.getKey().getFlag())) { + if (!it.hasNext() || !isGranted) { return isGranted; } } @@ -371,7 +350,7 @@ class CompositePermissionProvider implem if (entry.getKey().handles(this, permission)) { TreePermission tp = entry.getValue(); boolean isGranted = (property == null) ? tp.isGranted(permission) : tp.isGranted(permission, property); - if (!it.hasNext() || evalComplete(isGranted, entry.getKey().getFlag())) { + if (!it.hasNext() || !isGranted) { return isGranted; } } @@ -387,8 +366,6 @@ class CompositePermissionProvider implem } return (parent == null) ? TreePermission.EMPTY : parent; } - - } private class CompositeRepositoryPermission implements RepositoryPermission { Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImpl.java?rev=1663623&r1=1663622&r2=1663623&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImpl.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImpl.java Tue Mar 3 10:51:54 2015 @@ -33,7 +33,6 @@ import org.apache.jackrabbit.oak.plugins import org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration; import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants; import org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregatedPermissionProvider; -import org.apache.jackrabbit.oak.spi.security.authorization.permission.ControlFlag; import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionConstants; import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider; import org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions; @@ -41,6 +40,7 @@ import org.apache.jackrabbit.oak.spi.sec import org.apache.jackrabbit.oak.spi.security.authorization.permission.TreePermission; import org.apache.jackrabbit.oak.spi.security.principal.AdminPrincipal; import org.apache.jackrabbit.oak.spi.security.principal.SystemPrincipal; +import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits; public class PermissionProviderImpl implements PermissionProvider, AccessControlConstants, PermissionConstants, AggregatedPermissionProvider { @@ -54,8 +54,6 @@ public class PermissionProviderImpl impl private Root immutableRoot; - private ControlFlag flag; - public PermissionProviderImpl(@Nonnull Root root, @Nonnull String workspaceName, @Nonnull Set<Principal> principals, @Nonnull AuthorizationConfiguration acConfig) { this.root = root; @@ -69,8 +67,6 @@ public class PermissionProviderImpl impl } else { compiledPermissions = CompiledPermissionImpl.create(immutableRoot, workspaceName, principals, acConfig); } - - flag = ControlFlag.valueOf(acConfig.getParameters().getConfigValue(AggregatedPermissionProvider.PARAM_CONTROL_FLAG, ControlFlag.REQUISITE_NAME)); } @Override @@ -124,17 +120,12 @@ public class PermissionProviderImpl impl //---------------------------------------< AggregatedPermissionProvider >--- @Override - public ControlFlag getFlag() { - return flag; - } - - @Override public boolean handles(@Nonnull String path, @Nonnull String jcrAction) { return true; } @Override - public boolean handles(@Nonnull Tree tree) { + public boolean handles(@Nonnull Tree tree, PrivilegeBits privilegeBits) { return true; } Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/accesscontrol/PolicyOwner.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/accesscontrol/PolicyOwner.java?rev=1663623&r1=1663622&r2=1663623&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/accesscontrol/PolicyOwner.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/accesscontrol/PolicyOwner.java Tue Mar 3 10:51:54 2015 @@ -16,13 +16,15 @@ */ package org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import javax.jcr.security.AccessControlPolicy; /** * Interface to improve pluggability of the {@link javax.jcr.security.AccessControlManager}, * namely the interaction of multiple managers within a * single repository. It provides a single method {@link #defines(String, javax.jcr.security.AccessControlPolicy)} - * that allows to termine the responsible manager upon + * that allows to determine the responsible manager upon * {@link javax.jcr.security.AccessControlManager#setPolicy(String, javax.jcr.security.AccessControlPolicy) setPolicy} * and * {@link javax.jcr.security.AccessControlManager#removePolicy(String, javax.jcr.security.AccessControlPolicy) removePolicy}. @@ -31,7 +33,7 @@ public interface PolicyOwner { /** * Determines if the implementing {@code AccessManager} defines the specified - * {@code acceessControlPolicy} at the given {@code absPath}. If this method + * {@code accessControlPolicy} at the given {@code absPath}. If this method * returns {@code true} it is expected that the given policy is valid to be * {@link javax.jcr.security.AccessControlManager#setPolicy(String, javax.jcr.security.AccessControlPolicy) set} * or {@link javax.jcr.security.AccessControlManager#removePolicy(String, javax.jcr.security.AccessControlPolicy) removed} @@ -42,5 +44,5 @@ public interface PolicyOwner { * @return {@code true} If the {@code AccessControlManager} implementing this * interface can handle the specified {@code accessControlPolicy} at the given {@code path}. */ - boolean defines(String absPath, AccessControlPolicy accessControlPolicy); + boolean defines(@Nullable String absPath, @Nonnull AccessControlPolicy accessControlPolicy); } \ No newline at end of file Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/AggregatedPermissionProvider.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/AggregatedPermissionProvider.java?rev=1663623&r1=1663622&r2=1663623&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/AggregatedPermissionProvider.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/AggregatedPermissionProvider.java Tue Mar 3 10:51:54 2015 @@ -19,6 +19,7 @@ package org.apache.jackrabbit.oak.spi.se import javax.annotation.Nonnull; import org.apache.jackrabbit.oak.api.Tree; +import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits; /** * Extension of the {@link PermissionProvider} interface that allows it to be @@ -26,18 +27,9 @@ import org.apache.jackrabbit.oak.api.Tre */ public interface AggregatedPermissionProvider extends PermissionProvider { - /** - * Name of the configuration option that specifies the {@link org.apache.jackrabbit.oak.spi.security.authorization.permission.ControlFlag} - * of this provider instance. - */ - String PARAM_CONTROL_FLAG = "controlFlag"; - - @Nonnull - ControlFlag getFlag(); - boolean handles(@Nonnull String path, @Nonnull String jcrAction); - boolean handles(@Nonnull Tree tree); + boolean handles(@Nonnull Tree tree, @Nonnull PrivilegeBits privilegeBits); boolean handles(@Nonnull Tree tree, long permission); Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProvider.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProvider.java?rev=1663623&r1=1663622&r2=1663623&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProvider.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProvider.java Tue Mar 3 10:51:54 2015 @@ -30,8 +30,10 @@ 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.oak.api.Root; import org.apache.jackrabbit.oak.api.Tree; +import org.apache.jackrabbit.oak.api.Type; import org.apache.jackrabbit.oak.namepath.NameMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,6 +47,7 @@ public final class PrivilegeBitsProvider private static final Logger log = LoggerFactory.getLogger(PrivilegeBitsProvider.class); private final Map<PrivilegeBits, Set<String>> bitsToNames = new HashMap<PrivilegeBits, Set<String>>(); + private final Map<String, Set<String>> aggregation = new HashMap<String, Set<String>>(); private final Root root; @@ -134,7 +137,7 @@ public final class PrivilegeBitsProvider * Resolve the given privilege bits to a set of privilege names. * * @param privilegeBits An instance of privilege bits. - * @return The names of the registed privileges associated with the given + * @return The names of the registered privileges associated with the given * bits. Any bits that don't have a corresponding privilege definition will * be ignored. */ @@ -181,4 +184,55 @@ public final class PrivilegeBitsProvider return privilegeNames; } } + + /** + * TODO + * + * @param privilegeNames + * @return + */ + @Nonnull + public Iterable<String> getAggregatedPrivilegeNames(@Nonnull String... privilegeNames) { + if (privilegeNames.length == 0) { + return Collections.emptySet(); + } else { + Tree privilegesTree = getPrivilegesTree(); + if (!privilegesTree.exists()) { + return Collections.emptySet(); + } + + Set<String> aggregates = Sets.newHashSet(); + for (String privName : privilegeNames) { + if (aggregation.containsKey(privName)) { + aggregates.addAll(aggregation.get(privName)); + } else if (privilegesTree.hasChild(privName)) { + Tree privTree = privilegesTree.getChild(privName); + if (JCR_ALL.equals(privName)) { + // aggregation for jcr:all must not be cached + return fillAggregation(privTree, aggregates); + } else { + Set<String> aggSet = fillAggregation(privTree, Sets.<String>newHashSet()); + aggregation.put(privName, aggSet); + aggregates.addAll(aggSet); + } + } + } + return aggregates; + } + } + + private Set<String> fillAggregation(@Nonnull Tree privTree, @Nonnull Set<String> aggSet) { + if (privTree.hasProperty(REP_AGGREGATES)) { + for (String name : privTree.getProperty(REP_AGGREGATES).getValue(Type.NAMES)) { + if (aggregation.containsKey(name)) { + aggSet.addAll(aggregation.get(name)); + } else { + fillAggregation(privTree.getParent().getChild(name), aggSet); + } + } + } else { + aggSet.add(privTree.getName()); + } + return aggSet; + } } Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/TreeUtil.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/TreeUtil.java?rev=1663623&r1=1663622&r2=1663623&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/TreeUtil.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/TreeUtil.java Tue Mar 3 10:51:54 2015 @@ -38,6 +38,7 @@ import org.apache.jackrabbit.oak.commons import org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager; import org.apache.jackrabbit.oak.plugins.memory.PropertyStates; import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants; +import org.apache.jackrabbit.oak.plugins.tree.impl.ImmutableTree; import org.apache.jackrabbit.util.ISO8601; import static com.google.common.collect.Iterables.contains; @@ -431,4 +432,19 @@ public final class TreeUtil { return false; } + + + /** + * Returns {@code true} if the specified {@code tree} is a read-only tree + * such as obtained through {@link org.apache.jackrabbit.oak.plugins.tree.TreeFactory} + * or a {@link org.apache.jackrabbit.oak.plugins.tree.RootFactory read-only Root}. + * + * @param tree The tree object to be tested. + * @return {@code true} if the specified tree is an immutable read-only tree. + * @see org.apache.jackrabbit.oak.plugins.tree.TreeFactory#createReadOnlyTree(org.apache.jackrabbit.oak.spi.state.NodeState) + * @see org.apache.jackrabbit.oak.plugins.tree.RootFactory#createReadOnlyRoot(org.apache.jackrabbit.oak.spi.state.NodeState) + */ + public static boolean isReadOnlyTree(@Nonnull Tree tree) { + return tree instanceof ImmutableTree; + } } \ No newline at end of file Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/CompositeTokenConfigurationTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/CompositeTokenConfigurationTest.java?rev=1663623&r1=1663622&r2=1663623&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/CompositeTokenConfigurationTest.java (original) +++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/CompositeTokenConfigurationTest.java Tue Mar 3 10:51:54 2015 @@ -35,7 +35,7 @@ public class CompositeTokenConfiguration @Override public void before() throws Exception { super.before(); - setCompositeConfiguration(new CompositeTokenConfiguration(getSecurityProvider())); + compositeConfiguration = new CompositeTokenConfiguration(getSecurityProvider()); } @Test @@ -102,7 +102,7 @@ public class CompositeTokenConfiguration @Test public void testGetTokenProvider() { - CompositeTokenConfiguration ctc = (CompositeTokenConfiguration) getCompositeConfiguration(); + CompositeTokenConfiguration ctc = (CompositeTokenConfiguration) compositeConfiguration; TokenProvider tp = ctc.getTokenProvider(root); assertNotNull(tp); Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAccessControlManagerTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAccessControlManagerTest.java?rev=1663623&r1=1663622&r2=1663623&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAccessControlManagerTest.java (original) +++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAccessControlManagerTest.java Tue Mar 3 10:51:54 2015 @@ -29,6 +29,7 @@ import javax.jcr.security.Privilege; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import org.apache.jackrabbit.commons.iterator.AccessControlPolicyIteratorAdapter; +import org.apache.jackrabbit.oak.AbstractSecurityTest; import org.apache.jackrabbit.oak.namepath.NamePathMapper; import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants; import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.PolicyOwner; @@ -40,7 +41,7 @@ import static org.junit.Assert.assertSam import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -public class CompositeAccessControlManagerTest extends AbstractCompositeTest { +public class CompositeAccessControlManagerTest extends AbstractSecurityTest { private static final String TEST_PATH = "/test"; Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAuthorizationConfigurationTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAuthorizationConfigurationTest.java?rev=1663623&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAuthorizationConfigurationTest.java (added) +++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAuthorizationConfigurationTest.java Tue Mar 3 10:51:54 2015 @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.oak.security.authorization.composite; + +import java.security.Principal; +import java.util.Collections; + +import org.apache.jackrabbit.oak.AbstractSecurityTest; +import org.apache.jackrabbit.oak.namepath.NamePathMapper; +import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider; +import org.junit.Test; + +import static org.junit.Assert.assertSame; + +public class CompositeAuthorizationConfigurationTest extends AbstractSecurityTest { + + private CompositeAuthorizationConfiguration compositeConfiguration; + + @Override + public void before() throws Exception { + super.before(); + compositeConfiguration = new CompositeAuthorizationConfiguration(getSecurityProvider()); + } + + @Test(expected = IllegalStateException.class) + public void testEmptyGetAccessControlManager() { + compositeConfiguration.getAccessControlManager(root, NamePathMapper.DEFAULT); + } + + @Test(expected = IllegalStateException.class) + public void testEmptyGetPermissionProvider() { + compositeConfiguration.getPermissionProvider(root, adminSession.getWorkspaceName(), Collections.<Principal>emptySet()); + } + + @Test + public void testEmptyGetRestrictionProvider() { + assertSame(RestrictionProvider.EMPTY, compositeConfiguration.getRestrictionProvider()); + } +} \ No newline at end of file Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProviderTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProviderTest.java?rev=1663623&r1=1663622&r2=1663623&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProviderTest.java (original) +++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProviderTest.java Tue Mar 3 10:51:54 2015 @@ -16,7 +16,9 @@ */ package org.apache.jackrabbit.oak.security.authorization.composite; -public class CompositePermissionProviderTest extends AbstractCompositeTest { +import org.apache.jackrabbit.oak.AbstractSecurityTest; + +public class CompositePermissionProviderTest extends AbstractSecurityTest { // TODO } \ No newline at end of file Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/AbstractCompositeConfigurationTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/AbstractCompositeConfigurationTest.java?rev=1663623&r1=1663622&r2=1663623&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/AbstractCompositeConfigurationTest.java (original) +++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/AbstractCompositeConfigurationTest.java Tue Mar 3 10:51:54 2015 @@ -22,15 +22,7 @@ import org.apache.jackrabbit.oak.Abstrac public abstract class AbstractCompositeConfigurationTest<T extends SecurityConfiguration> extends AbstractSecurityTest { - private CompositeConfiguration<T> compositeConfiguration; - - public void setCompositeConfiguration(CompositeConfiguration<T> compositeConfiguration) { - this.compositeConfiguration = compositeConfiguration; - } - - public CompositeConfiguration getCompositeConfiguration() { - return compositeConfiguration; - } + protected CompositeConfiguration<T> compositeConfiguration; public List<T> getConfigurations() { return compositeConfiguration.getConfigurations(); Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/CompositeConfigurationTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/CompositeConfigurationTest.java?rev=1663623&r1=1663622&r2=1663623&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/CompositeConfigurationTest.java (original) +++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/CompositeConfigurationTest.java Tue Mar 3 10:51:54 2015 @@ -16,11 +16,81 @@ */ package org.apache.jackrabbit.oak.spi.security; -/** - * CompositeConfigurationTest... TODO - */ +import java.util.List; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + public class CompositeConfigurationTest extends AbstractCompositeConfigurationTest { - // TODO + private static final String NAME = "test"; + + @Override + public void before() throws Exception { + super.before(); + + compositeConfiguration = new CompositeConfiguration("test", getSecurityProvider()) {}; + } + + @Test + public void testGetName() { + assertEquals(NAME, compositeConfiguration.getName()); + } + + @Test + public void testEmpty() { + assertSame(ConfigurationParameters.EMPTY, compositeConfiguration.getParameters()); + assertTrue(compositeConfiguration.getConfigurations().isEmpty()); + } + + @Test + public void testSetDefaultConfig() { + SecurityConfiguration sc = new SecurityConfiguration.Default(); + compositeConfiguration.setDefaultConfig(sc); + + List<SecurityConfiguration> configurations = compositeConfiguration.getConfigurations(); + assertFalse(configurations.isEmpty()); + assertEquals(1, configurations.size()); + assertEquals(sc, configurations.iterator().next()); + } + + @Test + public void testAddConfiguration() { + compositeConfiguration.addConfiguration(new SecurityConfiguration.Default()); + compositeConfiguration.addConfiguration(new SecurityConfiguration.Default()); + + List<SecurityConfiguration> configurations = getConfigurations(); + assertFalse(configurations.isEmpty()); + assertEquals(2, configurations.size()); + + SecurityConfiguration def = new SecurityConfiguration.Default(); + compositeConfiguration.setDefaultConfig(def); + + configurations = getConfigurations(); + assertEquals(2, configurations.size()); + assertFalse(configurations.contains(def)); + } + + @Test + public void testRemoveConfiguration() { + SecurityConfiguration def = new SecurityConfiguration.Default(); + compositeConfiguration.setDefaultConfig(def); + + SecurityConfiguration sc = new SecurityConfiguration.Default(); + compositeConfiguration.addConfiguration(sc); + + compositeConfiguration.removeConfiguration(def); + List<SecurityConfiguration> configurations = compositeConfiguration.getConfigurations(); + assertEquals(1, configurations.size()); + assertEquals(sc, configurations.iterator().next()); + compositeConfiguration.removeConfiguration(sc); + configurations = compositeConfiguration.getConfigurations(); + assertEquals(1, configurations.size()); + assertEquals(def, configurations.iterator().next()); + } } \ No newline at end of file Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProviderTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProviderTest.java?rev=1663623&r1=1663622&r2=1663623&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProviderTest.java (original) +++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProviderTest.java Tue Mar 3 10:51:54 2015 @@ -148,4 +148,9 @@ public class PrivilegeBitsProviderTest e } assertEquals(all, bits.unmodifiable()); } + + @Test + public void testGetAggregatedNames() throws Exception { + // TODO + } } \ No newline at end of file
