diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAuthorizationConfiguration.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAuthorizationConfiguration.java index ae97d097ee..0bba6cd9d5 100644 --- a/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAuthorizationConfiguration.java +++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAuthorizationConfiguration.java @@ -174,13 +174,10 @@ public class CompositeAuthorizationConfiguration extends CompositeConfiguration< case 1: return configurations.get(0).getPermissionProvider(root, workspaceName, principals); default: List aggrPermissionProviders = new ArrayList<>(configurations.size()); - CompositePermissionProvider composite = null; for (AuthorizationConfiguration conf : configurations) { PermissionProvider pProvider = conf.getPermissionProvider(root, workspaceName, principals); if (pProvider instanceof AggregatedPermissionProvider) { aggrPermissionProviders.add((AggregatedPermissionProvider) pProvider); - } else if (pProvider instanceof CompositePermissionProvider) { - composite = (CompositePermissionProvider) pProvider; } else { log.debug("Ignoring permission provider of '{}': Not an AggregatedPermissionProvider", conf.getClass().getName()); } @@ -188,11 +185,7 @@ public class CompositeAuthorizationConfiguration extends CompositeConfiguration< PermissionProvider pp; switch (aggrPermissionProviders.size()) { case 0 : - if (composite != null) { - pp = composite; - } else { - pp = EmptyPermissionProvider.getInstance(); - } + pp = EmptyPermissionProvider.getInstance(); break; case 1 : pp = aggrPermissionProviders.get(0); diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProvider.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProvider.java index 9cf8f27b69..1c2d5ce7de 100644 --- a/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProvider.java +++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProvider.java @@ -20,6 +20,7 @@ import static org.apache.jackrabbit.oak.security.authorization.composite.Composi import java.util.List; import java.util.Set; +import java.util.function.Function; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -29,6 +30,7 @@ import org.apache.jackrabbit.oak.api.Root; import org.apache.jackrabbit.oak.api.Tree; import org.apache.jackrabbit.oak.plugins.tree.RootFactory; import org.apache.jackrabbit.oak.plugins.tree.TreeLocation; +import org.apache.jackrabbit.oak.plugins.tree.TreeType; import org.apache.jackrabbit.oak.plugins.tree.TreeTypeProvider; import org.apache.jackrabbit.oak.plugins.tree.impl.ImmutableTree; import org.apache.jackrabbit.oak.security.authorization.composite.CompositeAuthorizationConfiguration.CompositionType; @@ -49,7 +51,7 @@ import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBitsProvider; * {@link org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregatedPermissionProvider} * interface. */ -class CompositePermissionProvider implements PermissionProvider { +class CompositePermissionProvider implements AggregatedPermissionProvider { private final Root root; private final AggregatedPermissionProvider[] pps; @@ -206,37 +208,7 @@ class CompositePermissionProvider implements PermissionProvider { boolean isAcContent = ctx.definesLocation(location); long permissions = Permissions.getPermissions(jcrActions, location, isAcContent); - - PropertyState property = location.getProperty(); - Tree tree = (property == null) ? location.getTree() : location.getParent().getTree(); - - if (tree != null) { - return isGranted(tree, property, permissions); - } else { - boolean isGranted = false; - long coveredPermissions = Permissions.NO_PERMISSION; - - for (AggregatedPermissionProvider aggregatedPermissionProvider : pps) { - long supportedPermissions = aggregatedPermissionProvider.supportedPermissions(location, permissions); - if (doEvaluate(supportedPermissions)) { - if (compositionType == AND) { - isGranted = aggregatedPermissionProvider.isGranted(location, supportedPermissions); - if (!isGranted) { - return false; - } - coveredPermissions |= supportedPermissions; - } else { - for (long p : Permissions.aggregates(permissions)) { - if (aggregatedPermissionProvider.isGranted(location, p)) { - coveredPermissions |= p; - isGranted = true; - } - } - } - } - } - return isGranted && coveredPermissions == permissions; - } + return isGranted(location, permissions); } //------------------------------------------------------------< private >--- @@ -293,4 +265,92 @@ class CompositePermissionProvider implements PermissionProvider { return isGranted && coveredPermissions == repositoryPermissions; } } + + //---------------------------------------< AggregatedPermissionProvider >--- + + @Nonnull + @Override + public PrivilegeBits supportedPrivileges(@Nullable Tree tree, @Nullable PrivilegeBits privilegeBits) { + PrivilegeBits result = PrivilegeBits.getInstance(); + for (AggregatedPermissionProvider aggregatedPermissionProvider : pps) { + PrivilegeBits supported = aggregatedPermissionProvider.supportedPrivileges(tree, privilegeBits); + result.add(supported); + } + return result; + } + + @Override + public long supportedPermissions(@Nullable Tree tree, @Nullable PropertyState property, long permissions) { + return supportedPermissions((aggregatedPermissionProvider) -> aggregatedPermissionProvider + .supportedPermissions(tree, property, permissions)); + } + + @Override + public long supportedPermissions(TreeLocation location, long permissions) { + return supportedPermissions((aggregatedPermissionProvider) -> aggregatedPermissionProvider + .supportedPermissions(location, permissions)); + } + + @Override + public long supportedPermissions(TreePermission treePermission, PropertyState property, long permissions) { + return supportedPermissions((aggregatedPermissionProvider) -> aggregatedPermissionProvider + .supportedPermissions(treePermission, property, permissions)); + } + + private long supportedPermissions(Function supported) { + long coveredPermissions = Permissions.NO_PERMISSION; + for (AggregatedPermissionProvider aggregatedPermissionProvider : pps) { + long supportedPermissions = supported.apply(aggregatedPermissionProvider); + coveredPermissions |= supportedPermissions; + } + return coveredPermissions; + } + + @Override + public boolean isGranted(@Nonnull TreeLocation location, long permissions) { + PropertyState property = location.getProperty(); + Tree tree = (property == null) ? location.getTree() : location.getParent().getTree(); + + if (tree != null) { + return isGranted(tree, property, permissions); + } else { + boolean isGranted = false; + long coveredPermissions = Permissions.NO_PERMISSION; + + for (AggregatedPermissionProvider aggregatedPermissionProvider : pps) { + long supportedPermissions = aggregatedPermissionProvider.supportedPermissions(location, permissions); + if (doEvaluate(supportedPermissions)) { + if (compositionType == AND) { + isGranted = aggregatedPermissionProvider.isGranted(location, supportedPermissions); + if (!isGranted) { + return false; + } + coveredPermissions |= supportedPermissions; + } else { + for (long p : Permissions.aggregates(permissions)) { + if (aggregatedPermissionProvider.isGranted(location, p)) { + coveredPermissions |= p; + isGranted = true; + } + } + } + } + } + return isGranted && coveredPermissions == permissions; + } + } + + @Nonnull + @Override + public TreePermission getTreePermission(@Nonnull Tree tree, @Nonnull TreeType type, + @Nonnull TreePermission parentPermission) { + ImmutableTree immutableTree = (ImmutableTree) PermissionUtil.getImmutableTree(tree, immutableRoot); + if (tree.isRoot()) { + return CompositeTreePermission.create(immutableTree, typeProvider, pps, compositionType); + } else if (parentPermission instanceof CompositeTreePermission) { + return CompositeTreePermission.create(immutableTree, ((CompositeTreePermission) parentPermission), type); + } else { + return parentPermission.getChildPermission(immutableTree.getName(), immutableTree.getNodeState()); + } + } } diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeTreePermission.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeTreePermission.java index bbaf835bdb..8ee183aa22 100644 --- a/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeTreePermission.java +++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeTreePermission.java @@ -19,6 +19,8 @@ package org.apache.jackrabbit.oak.security.authorization.composite; import static org.apache.jackrabbit.oak.security.authorization.composite.CompositeAuthorizationConfiguration.CompositionType.AND; import static org.apache.jackrabbit.oak.security.authorization.composite.CompositeAuthorizationConfiguration.CompositionType.OR; +import java.util.function.Supplier; + import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -85,15 +87,16 @@ final class CompositeTreePermission implements TreePermission { } static TreePermission create(@Nonnull final ImmutableTree tree, @Nonnull CompositeTreePermission parentPermission) { - return create(new LazyTree() { - @Override - ImmutableTree get() { - return tree; - } - }, tree.getName(), tree.getNodeState(), parentPermission); + return create(() -> tree, tree.getName(), tree.getNodeState(), parentPermission, null); } - private static TreePermission create(@Nonnull LazyTree lazyTree, @Nonnull String childName, @Nonnull NodeState childState, @Nonnull CompositeTreePermission parentPermission) { + static TreePermission create(@Nonnull final ImmutableTree tree, @Nonnull CompositeTreePermission parentPermission, + @Nullable TreeType treeType) { + return create(() -> tree, tree.getName(), tree.getNodeState(), parentPermission, treeType); + } + + private static TreePermission create(@Nonnull Supplier lazyTree, @Nonnull String childName, @Nonnull NodeState childState, @Nonnull CompositeTreePermission parentPermission, + @Nullable TreeType treeType) { switch (parentPermission.childSize) { case 0: return TreePermission.EMPTY; case 1: @@ -107,7 +110,12 @@ final class CompositeTreePermission implements TreePermission { return (parent == null) ? TreePermission.EMPTY : parent.getChildPermission(childName, childState); default: ImmutableTree tree = lazyTree.get(); - TreeType type = getType(tree, parentPermission); + TreeType type; + if (treeType != null) { + type = treeType; + } else { + type = getType(tree, parentPermission); + } AggregatedPermissionProvider[] pvds = new AggregatedPermissionProvider[parentPermission.childSize]; TreePermission[] tps = new TreePermission[parentPermission.childSize]; @@ -134,12 +142,7 @@ final class CompositeTreePermission implements TreePermission { @Nonnull @Override public TreePermission getChildPermission(@Nonnull final String childName, @Nonnull final NodeState childState) { - return create(new LazyTree() { - @Override - ImmutableTree get() { - return new ImmutableTree(tree, childName, childState); - } - }, childName, childState, this); + return create(() -> new ImmutableTree(tree, childName, childState), childName, childState, this, null); } @Override @@ -254,8 +257,4 @@ final class CompositeTreePermission implements TreePermission { private static TreeType getType(@Nonnull Tree tree, @Nonnull CompositeTreePermission parent) { return parent.typeProvider.getType(tree, parent.type); } - - private abstract static class LazyTree { - abstract ImmutableTree get(); - } } \ No newline at end of file