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/05/19 08:31:18 UTC
svn commit: r1795596 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/core/
test/java/org/apache/jackrabbit/oak/core/
Author: angela
Date: Fri May 19 08:31:18 2017
New Revision: 1795596
URL: http://svn.apache.org/viewvc?rev=1795596&view=rev
Log:
OAK-5355 : Too eager refreshing of tree permissions in SecureNodeBuilder
Added:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/MutableRootTest.java (with props)
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/SecureNodeBuilderTest.java (with props)
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/TestPermissionProvider.java (with props)
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/SecureNodeBuilder.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/SecureNodeBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/SecureNodeBuilder.java?rev=1795596&r1=1795595&r2=1795596&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/SecureNodeBuilder.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/SecureNodeBuilder.java Fri May 19 08:31:18 2017
@@ -158,9 +158,8 @@ class SecureNodeBuilder implements NodeB
public void baseChanged() {
checkState(parent == null);
- treePermission = null; // trigger re-evaluation of the context
+ treePermission = null; // trigger re-evaluation
rootPermission = null;
- getTreePermission(); // sets both tree permissions and root node permissions
}
@Override
@@ -174,11 +173,11 @@ class SecureNodeBuilder implements NodeB
return exists() && builder.moveTo(newParent, newName);
}
- @Override @CheckForNull
+ @CheckForNull
+ @Override
public PropertyState getProperty(String name) {
PropertyState property = builder.getProperty(name);
- if (property != null
- && new ReadablePropertyPredicate().apply(property)) {
+ if (new ReadablePropertyPredicate().apply(property)) {
return property;
} else {
return null;
@@ -201,7 +200,8 @@ class SecureNodeBuilder implements NodeB
}
}
- @Override @Nonnull
+ @Nonnull
+ @Override
public Iterable<? extends PropertyState> getProperties() {
if (getTreePermission().canReadProperties() || isNew()) {
return builder.getProperties();
@@ -215,61 +215,66 @@ class SecureNodeBuilder implements NodeB
@Override
public boolean getBoolean(@Nonnull String name) {
PropertyState property = getProperty(name);
- return property != null
- && property.getType() == BOOLEAN
- && property.getValue(BOOLEAN);
+ return isType(property, BOOLEAN) && property.getValue(BOOLEAN);
}
- @Override @CheckForNull
+ @CheckForNull
+ @Override
public String getString(@Nonnull String name) {
PropertyState property = getProperty(name);
- if (property != null && property.getType() == STRING) {
+ if (isType(property, STRING)) {
return property.getValue(STRING);
} else {
return null;
}
}
- @Override @CheckForNull
+ @CheckForNull
+ @Override
public String getName(@Nonnull String name) {
PropertyState property = getProperty(name);
- if (property != null && property.getType() == NAME) {
+ if (isType(property, NAME)) {
return property.getValue(NAME);
} else {
return null;
}
}
- @Override @Nonnull
+ @Nonnull
+ @Override
public Iterable<String> getNames(@Nonnull String name) {
PropertyState property = getProperty(name);
- if (property != null && property.getType() == NAMES) {
+ if (isType(property, NAMES)) {
return property.getValue(NAMES);
} else {
return emptyList();
}
}
- @Override @Nonnull
+ @Nonnull
+ @Override
public NodeBuilder setProperty(@Nonnull PropertyState property) {
builder.setProperty(property);
return this;
}
- @Override @Nonnull
+ @Nonnull
+ @Override
public <T> NodeBuilder setProperty(String name, @Nonnull T value) {
builder.setProperty(name, value);
return this;
}
- @Override @Nonnull
+ @Nonnull
+ @Override
public <T> NodeBuilder setProperty(
String name, @Nonnull T value, Type<T> type) {
builder.setProperty(name, value, type);
return this;
}
- @Override @Nonnull
+ @Nonnull
+ @Override
public NodeBuilder removeProperty(String name) {
if (hasProperty(name)) { // only remove properties that we can see
builder.removeProperty(name);
@@ -277,16 +282,12 @@ class SecureNodeBuilder implements NodeB
return this;
}
- @Override @Nonnull
+ @Nonnull
+ @Override
public Iterable<String> getChildNodeNames() {
return filter(
builder.getChildNodeNames(),
- new Predicate<String>() {
- @Override
- public boolean apply(@Nullable String input) {
- return input != null && getChildNode(input).exists();
- }
- });
+ input -> input != null && getChildNode(input).exists());
}
@Override
@@ -298,7 +299,8 @@ class SecureNodeBuilder implements NodeB
}
}
- @Override @Nonnull
+ @Nonnull
+ @Override
public NodeBuilder child(@Nonnull String name) {
if (hasChildNode(name)) {
return getChildNode(name);
@@ -307,13 +309,15 @@ class SecureNodeBuilder implements NodeB
}
}
- @Override @Nonnull
+ @Nonnull
+ @Override
public NodeBuilder setChildNode(@Nonnull String name) {
builder.setChildNode(name);
return new SecureNodeBuilder(this, name);
}
- @Override @Nonnull
+ @Nonnull
+ @Override
public NodeBuilder setChildNode(@Nonnull String name, @Nonnull NodeState nodeState) {
builder.setChildNode(name, nodeState);
return new SecureNodeBuilder(this, name);
@@ -344,6 +348,7 @@ class SecureNodeBuilder implements NodeB
*
* @return The permissions for this tree.
*/
+ @Nonnull
private TreePermission getTreePermission() {
if (treePermission == null
|| rootPermission != rootBuilder.treePermission) {
@@ -360,6 +365,11 @@ class SecureNodeBuilder implements NodeB
return treePermission;
}
+ private static boolean isType(@CheckForNull PropertyState property, Type<?> type) {
+ Type<?> t = (property == null) ? null : property.getType();
+ return t == type;
+ }
+
//------------------------------------------------------< inner classes >---
/**
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/MutableRootTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/MutableRootTest.java?rev=1795596&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/MutableRootTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/MutableRootTest.java Fri May 19 08:31:18 2017
@@ -0,0 +1,106 @@
+/*
+ * 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.core;
+
+import java.security.Principal;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.security.auth.Subject;
+
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore;
+import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
+import org.apache.jackrabbit.oak.spi.security.OpenSecurityProvider;
+import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
+import org.apache.jackrabbit.oak.spi.security.authentication.AuthInfoImpl;
+import org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
+import org.apache.jackrabbit.oak.spi.security.authorization.OpenAuthorizationConfiguration;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.TreePermission;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+public class MutableRootTest {
+
+ private final NodeStore store = new MemoryNodeStore();
+ private final TestPermissionProvider permissionProvider = new TestPermissionProvider();
+
+ private MutableRoot root;
+
+ @Before
+ public void before() {
+ SecurityProvider sp = new OpenSecurityProvider() {
+ @Nonnull
+ @Override
+ public <T> T getConfiguration(@Nonnull Class<T> configClass) {
+ if (AuthorizationConfiguration.class == configClass) {
+ return (T) new OpenAuthorizationConfiguration() {
+ @Nonnull
+ @Override
+ public PermissionProvider getPermissionProvider(@Nonnull Root root, @Nonnull String workspaceName, @Nonnull Set<Principal> principals) {
+ return permissionProvider;
+ }
+ };
+ } else {
+ return super.getConfiguration(configClass);
+ }
+ }
+ };
+ ContentSessionImpl cs = Mockito.mock(ContentSessionImpl.class);
+ when(cs.toString()).thenReturn("contentSession");
+ when(cs.getAuthInfo()).thenReturn(AuthInfoImpl.EMPTY);
+ when(cs.getWorkspaceName()).thenReturn("default");
+ root = new MutableRoot(store, new EmptyHook(), "default", new Subject(), sp, null, null, cs);
+ }
+
+ /**
+ * @see <a href"https://issues.apache.org/jira/browse/OAK-5355">OAK-5355</a>
+ */
+ @Test
+ public void testCommit() throws Exception {
+ MutableTree t = root.getTree(PathUtils.ROOT_PATH);
+ NodeBuilder nb = t.getNodeBuilder();
+ assertTrue(nb instanceof SecureNodeBuilder);
+
+ assertEquals(canReadRootTree(t), nb.exists());
+
+ // commit resets the permissionprovider, which in our test scenario alters
+ // the 'denyAll' flag.
+ root.commit();
+
+ assertEquals(canReadRootTree(t), nb.exists());
+
+ MutableTree t2 = root.getTree(PathUtils.ROOT_PATH);
+ NodeBuilder nb2 = t.getNodeBuilder();
+
+ assertEquals(canReadRootTree(t2), nb.exists());
+ assertEquals(nb2.exists(), nb.exists());
+ }
+
+ private boolean canReadRootTree(@Nonnull Tree t) {
+ return permissionProvider.getTreePermission(t, TreePermission.EMPTY).canRead();
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/MutableRootTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/SecureNodeBuilderTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/SecureNodeBuilderTest.java?rev=1795596&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/SecureNodeBuilderTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/SecureNodeBuilderTest.java Fri May 19 08:31:18 2017
@@ -0,0 +1,435 @@
+/*
+ * 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.core;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore;
+import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.apache.jackrabbit.oak.core.TestPermissionProvider.NAME_ACCESSIBLE;
+import static org.apache.jackrabbit.oak.core.TestPermissionProvider.NAME_NON_ACCESSIBLE;
+import static org.apache.jackrabbit.oak.core.TestPermissionProvider.NAME_NON_EXISTING;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+public class SecureNodeBuilderTest {
+
+ private final NodeStore store = new MemoryNodeStore();
+ private final TestPermissionProvider permissionProvider = new TestPermissionProvider();
+
+ private SecureNodeBuilder secureNodeBuilder;
+
+ @Before
+ public void before() throws Exception {
+ NodeBuilder rootBuilder = store.getRoot().builder();
+ rootBuilder.setProperty("prop", "value").setProperty(NAME_NON_ACCESSIBLE, "value");
+ rootBuilder.child(NAME_ACCESSIBLE).setProperty("prop", "value").setProperty(NAME_NON_ACCESSIBLE, "value");
+ rootBuilder.child(NAME_NON_ACCESSIBLE).setProperty("prop", "value").setProperty(NAME_NON_ACCESSIBLE, "value");
+ store.merge(rootBuilder, new EmptyHook(), new CommitInfo("id", null));
+
+ rootBuilder = store.getRoot().builder();
+ secureNodeBuilder = new SecureNodeBuilder(rootBuilder, new LazyValue<PermissionProvider>() {
+ @Override
+ protected PermissionProvider createValue() {
+ return permissionProvider;
+ }
+ });
+ }
+
+ @Test
+ public void testGetChildNodeNonExisting() {
+ NodeBuilder child = secureNodeBuilder.getChildNode(NAME_NON_EXISTING);
+ assertTrue(child instanceof SecureNodeBuilder);
+ }
+
+ @Test
+ public void testGetChildNode() {
+ NodeBuilder child = secureNodeBuilder.getChildNode(NAME_ACCESSIBLE);
+ assertTrue(child instanceof SecureNodeBuilder);
+ assertTrue(child.exists());
+ }
+
+ @Test
+ public void testGetChildNodeNonAccessible() {
+ NodeBuilder child = secureNodeBuilder.getChildNode(NAME_NON_ACCESSIBLE);
+ assertTrue(child instanceof SecureNodeBuilder);
+ }
+
+ @Test
+ public void testExists() {
+ assertTrue(secureNodeBuilder.exists());
+ }
+
+ @Test
+ public void testExistsNonExisting() {
+ assertFalse(secureNodeBuilder.getChildNode(NAME_NON_EXISTING).exists());
+ }
+
+ @Test
+ public void testExistsAccessible() {
+ assertTrue(secureNodeBuilder.getChildNode(NAME_ACCESSIBLE).exists());
+ }
+
+ @Test
+ public void testExistsNonAccessible() {
+ assertFalse(secureNodeBuilder.getChildNode(NAME_NON_ACCESSIBLE).exists());
+ }
+
+ @Test
+ public void testGetBaseState() {
+ NodeState ns = secureNodeBuilder.getBaseState();
+
+ assertTrue(ns instanceof SecureNodeState);
+ }
+
+ @Test
+ public void testGetBaseStateNonExisting() {
+ NodeState ns = secureNodeBuilder.getChildNode(NAME_NON_EXISTING).getBaseState();
+
+ assertTrue(ns instanceof SecureNodeState);
+ }
+
+ @Test
+ public void testGetBaseStateNonAccessible() {
+ NodeState ns = secureNodeBuilder.getChildNode(NAME_NON_ACCESSIBLE).getBaseState();
+
+ assertTrue(ns instanceof SecureNodeState);
+ }
+
+ @Test
+ public void testGetNodeState() {
+ NodeState ns = secureNodeBuilder.getNodeState();
+
+ assertTrue(ns instanceof SecureNodeState);
+ }
+
+ @Test
+ public void testGetNodeStateNonExisting() {
+ NodeState ns = secureNodeBuilder.getChildNode(NAME_NON_EXISTING).getNodeState();
+
+ assertTrue(ns instanceof SecureNodeState);
+ }
+
+ @Test
+ public void testGetNodeStateNonAccessible() {
+ NodeState ns = secureNodeBuilder.getChildNode(NAME_NON_ACCESSIBLE).getNodeState();
+
+ assertTrue(ns instanceof SecureNodeState);
+ }
+
+ /**
+ * Illustrating usage of {@link SecureNodeBuilder#baseChanged()} as it is
+ * currently present with {@link MutableRoot#commit()}, {@link MutableRoot#rebase()}
+ * and {@link MutableRoot#refresh()}: baseChanged is call <strong>before</strong>
+ * the permission provider is refreshed, which depending on the implementation
+ * may lead to a stale {@code TreePermission} being obtained with the non-lazy
+ * refresh as described in OAK-5355.
+ *
+ * @see <a href"https://issues.apache.org/jira/browse/OAK-5355">OAK-5355</a>
+ */
+ @Test
+ public void testBaseChanged() {
+ secureNodeBuilder.baseChanged();
+ // change the behavior of the permission provider to assure that subsequent
+ // calls are always reading the most up to date information
+ try {
+ permissionProvider.denyAll = true;
+ assertFalse(secureNodeBuilder.exists());
+ assertFalse(secureNodeBuilder.hasChildNode(NAME_ACCESSIBLE));
+ assertFalse(secureNodeBuilder.hasProperty("prop"));
+ assertFalse(secureNodeBuilder.isNew());
+ assertFalse(secureNodeBuilder.getBaseState().exists());
+ assertFalse(secureNodeBuilder.getNodeState().exists());
+ } finally {
+ permissionProvider.denyAll = false;
+ }
+ }
+
+ @Test
+ public void testHasProperty() {
+ assertTrue(secureNodeBuilder.hasProperty("prop"));
+ assertTrue(secureNodeBuilder.getChildNode(NAME_ACCESSIBLE).hasProperty("prop"));
+ assertTrue(secureNodeBuilder.getChildNode(NAME_NON_ACCESSIBLE).hasProperty("prop"));
+ assertFalse(secureNodeBuilder.getChildNode(NAME_NON_EXISTING).hasProperty("prop"));
+ }
+
+ @Test
+ public void testHasPropertyNonAccessible() {
+ assertFalse(secureNodeBuilder.hasProperty(NAME_NON_ACCESSIBLE));
+ assertFalse(secureNodeBuilder.getChildNode(NAME_ACCESSIBLE).hasProperty(NAME_NON_ACCESSIBLE));
+ assertFalse(secureNodeBuilder.getChildNode(NAME_NON_ACCESSIBLE).hasProperty(NAME_NON_ACCESSIBLE));
+ assertFalse(secureNodeBuilder.getChildNode(NAME_NON_EXISTING).hasProperty(NAME_NON_ACCESSIBLE));
+ }
+
+ @Test
+ public void testHasPropertyNonExisting() {
+ assertFalse(secureNodeBuilder.hasProperty(NAME_NON_EXISTING));
+ assertFalse(secureNodeBuilder.getChildNode(NAME_ACCESSIBLE).hasProperty(NAME_NON_EXISTING));
+ assertFalse(secureNodeBuilder.getChildNode(NAME_NON_ACCESSIBLE).hasProperty(NAME_NON_EXISTING));
+ assertFalse(secureNodeBuilder.getChildNode(NAME_NON_EXISTING).hasProperty(NAME_NON_EXISTING));
+ }
+
+ @Test
+ public void testGetProperty() {
+ assertNotNull(secureNodeBuilder.getProperty("prop"));
+ assertNotNull(secureNodeBuilder.getChildNode(NAME_ACCESSIBLE).getProperty("prop"));
+ assertNotNull(secureNodeBuilder.getChildNode(NAME_NON_ACCESSIBLE).getProperty("prop"));
+ assertNull(secureNodeBuilder.getChildNode(NAME_NON_EXISTING).getProperty("prop"));
+ }
+
+ @Test
+ public void testGetPropertyNonAccessible() {
+ assertNull(secureNodeBuilder.getProperty(NAME_NON_ACCESSIBLE));
+ assertNull(secureNodeBuilder.getChildNode(NAME_ACCESSIBLE).getProperty(NAME_NON_ACCESSIBLE));
+ assertNull(secureNodeBuilder.getChildNode(NAME_NON_ACCESSIBLE).getProperty(NAME_NON_ACCESSIBLE));
+ assertNull(secureNodeBuilder.getChildNode(NAME_NON_EXISTING).getProperty(NAME_NON_ACCESSIBLE));
+ }
+
+ @Test
+ public void testGetPropertyNonExisting() {
+ assertNull(secureNodeBuilder.getProperty(NAME_NON_EXISTING));
+ assertNull(secureNodeBuilder.getChildNode(NAME_ACCESSIBLE).getProperty(NAME_NON_EXISTING));
+ assertNull(secureNodeBuilder.getChildNode(NAME_NON_ACCESSIBLE).getProperty(NAME_NON_EXISTING));
+ assertNull(secureNodeBuilder.getChildNode(NAME_NON_EXISTING).getProperty(NAME_NON_EXISTING));
+ }
+
+ @Test
+ public void testGetPropertyCount() {
+ assertEquals(1, secureNodeBuilder.getPropertyCount());
+ assertEquals(1, secureNodeBuilder.getChildNode(NAME_ACCESSIBLE).getPropertyCount());
+ assertEquals(1, secureNodeBuilder.getChildNode(NAME_NON_ACCESSIBLE).getPropertyCount());
+ assertEquals(0, secureNodeBuilder.getChildNode(NAME_NON_EXISTING).getPropertyCount());
+ }
+
+ @Test
+ public void testGetPropertyCountCanReadProperties() {
+ try {
+ permissionProvider.canReadProperties = true;
+ assertEquals(2, secureNodeBuilder.getPropertyCount());
+ assertEquals(2, secureNodeBuilder.getChildNode(NAME_ACCESSIBLE).getPropertyCount());
+ assertEquals(2, secureNodeBuilder.getChildNode(NAME_NON_ACCESSIBLE).getPropertyCount());
+ assertEquals(0, secureNodeBuilder.getChildNode(NAME_NON_EXISTING).getPropertyCount());
+ } finally {
+ permissionProvider.canReadProperties = false;
+ }
+ }
+
+ @Test
+ public void testGetProperties() {
+ assertEquals(1, Iterables.size(secureNodeBuilder.getProperties()));
+ assertEquals(1, Iterables.size(secureNodeBuilder.getChildNode(NAME_ACCESSIBLE).getProperties()));
+ assertEquals(1, Iterables.size(secureNodeBuilder.getChildNode(NAME_NON_ACCESSIBLE).getProperties()));
+ assertEquals(0, Iterables.size(secureNodeBuilder.getChildNode(NAME_NON_EXISTING).getProperties()));
+ }
+
+ @Test
+ public void testGetPropertiesCanReadProperties() {
+ try {
+ permissionProvider.canReadProperties = true;
+ assertEquals(2, Iterables.size(secureNodeBuilder.getProperties()));
+ assertEquals(2, Iterables.size(secureNodeBuilder.getChildNode(NAME_ACCESSIBLE).getProperties()));
+ assertEquals(2, Iterables.size(secureNodeBuilder.getChildNode(NAME_NON_ACCESSIBLE).getProperties()));
+ assertEquals(0, Iterables.size(secureNodeBuilder.getChildNode(NAME_NON_EXISTING).getProperties()));
+ } finally {
+ permissionProvider.canReadProperties = false;
+ }
+ }
+
+ @Test
+ public void testGetPropertiesAfterSet() {
+ secureNodeBuilder.setProperty(PropertyStates.createProperty("another", ImmutableList.of("v", "v2"), Type.STRINGS));
+ assertEquals(2, Iterables.size(secureNodeBuilder.getProperties()));
+ }
+
+ @Test
+ public void testGetPropertiesAfterRemoval() {
+ secureNodeBuilder.removeProperty("prop");
+ assertEquals(0, Iterables.size(secureNodeBuilder.getProperties()));
+ }
+
+ @Test
+ public void testGetBoolean() {
+ assertFalse(secureNodeBuilder.getBoolean("prop"));
+ assertFalse(secureNodeBuilder.getBoolean(NAME_NON_EXISTING));
+ assertFalse(secureNodeBuilder.getBoolean(NAME_NON_ACCESSIBLE));
+ }
+
+ @Test
+ public void testGetBooleanTypeBoolean() {
+ secureNodeBuilder.setProperty("boolean", true, Type.BOOLEAN);
+ assertTrue(secureNodeBuilder.getBoolean("boolean"));
+ }
+
+ @Test
+ public void testGetBooleanTypeBooleans() {
+ secureNodeBuilder.setProperty("booleans", ImmutableList.of(true, false), Type.BOOLEANS);
+ assertFalse(secureNodeBuilder.getBoolean("booleans"));
+ }
+
+ @Test
+ public void testGetString() {
+ assertEquals("value", secureNodeBuilder.getString("prop"));
+ assertNull(secureNodeBuilder.getString(NAME_NON_EXISTING));
+ assertNull(secureNodeBuilder.getString(NAME_NON_ACCESSIBLE));
+ }
+
+ @Test
+ public void testGetStringTypeStrings() {
+ secureNodeBuilder.setProperty("strings", ImmutableList.of("a", "b"), Type.STRINGS);
+ assertNull(secureNodeBuilder.getString("strings"));
+ }
+
+ @Test
+ public void testGetStringTypeLong() {
+ secureNodeBuilder.setProperty("long", Long.MAX_VALUE, Type.LONG);
+ assertNull(secureNodeBuilder.getString("long"));
+ }
+
+ @Test
+ public void testGetName() {
+ assertNull(secureNodeBuilder.getName("prop"));
+ assertNull(secureNodeBuilder.getName(NAME_NON_EXISTING));
+ assertNull(secureNodeBuilder.getName(NAME_NON_ACCESSIBLE));
+ }
+
+ @Test
+ public void testGetNameTypeNames() {
+ secureNodeBuilder.setProperty("names", ImmutableList.of("a", "b"), Type.NAMES);
+ assertNull(secureNodeBuilder.getName("names"));
+ }
+
+ @Test
+ public void testGetNameTypeName() {
+ secureNodeBuilder.setProperty("name", "value", Type.NAME);
+ assertEquals("value", secureNodeBuilder.getName("name"));
+ }
+
+ @Test
+ public void testGetNames() {
+ assertEquals(0, Iterables.size(secureNodeBuilder.getNames("prop")));
+ assertEquals(0, Iterables.size(secureNodeBuilder.getNames(NAME_NON_EXISTING)));
+ assertEquals(0, Iterables.size(secureNodeBuilder.getNames(NAME_NON_ACCESSIBLE)));
+ }
+
+ @Test
+ public void testGetNamesTypeNames() {
+ Iterable<String> names = ImmutableList.of("a", "b");
+ secureNodeBuilder.setProperty("names", names, Type.NAMES);
+ assertTrue(Iterables.elementsEqual(names, secureNodeBuilder.getNames("names")));
+ }
+
+ @Test
+ public void testGetNamesTypeName() {
+ secureNodeBuilder.setProperty("name", "value", Type.NAME);
+ assertEquals(0, Iterables.size(secureNodeBuilder.getNames("name")));
+ }
+
+ @Test
+ public void testSetProperty() {
+ secureNodeBuilder.setProperty("another", "value");
+ assertTrue(secureNodeBuilder.hasProperty("another"));
+ }
+
+ @Test
+ public void testSetPropertyReturnsSame() {
+ assertSame(secureNodeBuilder, secureNodeBuilder.setProperty("another", "value"));
+ }
+
+ @Test
+ public void testSetPropertyModifiedNonAccessible() {
+ secureNodeBuilder.setProperty(NAME_NON_ACCESSIBLE, "anothervalue");
+ // modified property must exist irrespective of permission eval
+ assertTrue(secureNodeBuilder.hasProperty(NAME_NON_ACCESSIBLE));
+ }
+
+ @Test
+ public void testSetPropertyNewNonAccessible() {
+ String name = NAME_NON_ACCESSIBLE+"-new";
+ secureNodeBuilder.setProperty(name, "value");
+ // new property must exist irrespective of permission eval
+ assertTrue(secureNodeBuilder.hasProperty(name));
+ }
+
+ @Test
+ public void testRemoveProperty() {
+ secureNodeBuilder.removeProperty("prop");
+ assertFalse(secureNodeBuilder.hasProperty("prop"));
+ }
+
+ @Test
+ public void testRemovePropertyNonAccessible() {
+ secureNodeBuilder.removeProperty(NAME_NON_ACCESSIBLE);
+
+ // verify that property has not been removed
+ try {
+ permissionProvider.canReadProperties = true;
+ assertTrue(secureNodeBuilder.hasProperty(NAME_NON_ACCESSIBLE));
+ } finally {
+ permissionProvider.canReadProperties = false;
+ }
+ }
+
+ @Test
+ public void testRemovePropertyReturnsSame() {
+ assertSame(secureNodeBuilder, secureNodeBuilder.removeProperty("prop"));
+ }
+
+ @Test
+ public void testHasChildNode() {
+ assertTrue(secureNodeBuilder.hasChildNode(NAME_ACCESSIBLE));
+ }
+
+ @Test
+ public void testHasChildNodeNonAccessible() {
+ assertFalse(secureNodeBuilder.hasChildNode(NAME_NON_ACCESSIBLE));
+ }
+
+ @Test
+ public void testHasChildNodeNonExisting() {
+ assertFalse(secureNodeBuilder.hasChildNode(NAME_NON_EXISTING));
+ }
+
+ @Test
+ public void testGetChildNodeCount() {
+ assertEquals(1, secureNodeBuilder.getChildNodeCount(Long.MAX_VALUE));
+ }
+
+ @Test
+ public void testGetChildNodeCountCanReadAll() {
+ try {
+ permissionProvider.canReadAll = true;
+ assertEquals(2, secureNodeBuilder.getChildNodeCount(Long.MAX_VALUE));
+ } finally {
+ permissionProvider.canReadAll = false;
+ }
+ }
+
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/SecureNodeBuilderTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/TestPermissionProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/TestPermissionProvider.java?rev=1795596&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/TestPermissionProvider.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/TestPermissionProvider.java Fri May 19 08:31:18 2017
@@ -0,0 +1,110 @@
+package org.apache.jackrabbit.oak.core;
+
+import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.RepositoryPermission;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.TreePermission;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+/**
+ * Dummy permission provider implementation that grants read access to all trees
+ * that have a name that isn't equal to {@link #NAME_NON_ACCESSIBLE}.
+ */
+final class TestPermissionProvider implements PermissionProvider {
+
+ static final String NAME_ACCESSIBLE = "accessible";
+ static final String NAME_NON_ACCESSIBLE = "notAccessible";
+ static final String NAME_NON_EXISTING = "nonExisting";
+
+ boolean canReadAll = false;
+ boolean canReadProperties = false;
+
+ boolean denyAll;
+
+ private TreePermission getTreePermission(@Nonnull String name) {
+ if (denyAll) {
+ return TreePermission.EMPTY;
+ } else {
+ return new TreePermission() {
+ @Nonnull
+ @Override
+ public TreePermission getChildPermission(@Nonnull String childName, @Nonnull NodeState childState) {
+ return getTreePermission(childName);
+ }
+
+ @Override
+ public boolean canRead() {
+ return canReadAll || !name.contains(NAME_NON_ACCESSIBLE);
+ }
+
+ @Override
+ public boolean canRead(@Nonnull PropertyState property) {
+ return canReadProperties || !property.getName().contains(NAME_NON_ACCESSIBLE);
+ }
+
+ @Override
+ public boolean canReadAll() {
+ return canReadAll;
+ }
+
+ @Override
+ public boolean canReadProperties() {
+ return canReadProperties;
+ }
+
+ @Override
+ public boolean isGranted(long permissions) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isGranted(long permissions, @Nonnull PropertyState property) {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+ }
+
+ @Override
+ public void refresh() {
+ denyAll = !denyAll;
+ }
+
+ @Nonnull
+ @Override
+ public Set<String> getPrivileges(@Nullable Tree tree) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean hasPrivileges(@Nullable Tree tree, @Nonnull String... privilegeNames) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Nonnull
+ @Override
+ public RepositoryPermission getRepositoryPermission() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Nonnull
+ @Override
+ public TreePermission getTreePermission(@Nonnull Tree tree, @Nonnull TreePermission parentPermission) {
+ return getTreePermission(tree.getName());
+ }
+
+ @Override
+ public boolean isGranted(@Nonnull Tree tree, @Nullable PropertyState property, long permissions) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isGranted(@Nonnull String oakPath, @Nonnull String jcrActions) {
+ throw new UnsupportedOperationException();
+ }
+}
Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/TestPermissionProvider.java
------------------------------------------------------------------------------
svn:eol-style = native