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 2019/02/01 16:33:35 UTC
svn commit: r1852758 - in /jackrabbit/oak/trunk:
oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/
oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/tree/impl/
oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/eva...
Author: angela
Date: Fri Feb 1 16:33:35 2019
New Revision: 1852758
URL: http://svn.apache.org/viewvc?rev=1852758&view=rev
Log:
OAK-7997 : Adding restrictions to ACLs yields empty results for queries in Jackrabbit Oak
Added:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/AbstractQueryTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/IndexedQueryMixinTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/IndexedQueryTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/TraversingQueryMixinTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/TraversingQueryTest.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/tree/impl/TreeUtilTest.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/NodeImpl.java
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/plugins/tree/TreeUtil.java
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/plugins/tree/package-info.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java?rev=1852758&r1=1852757&r2=1852758&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java Fri Feb 1 16:33:35 2019
@@ -20,11 +20,7 @@ package org.apache.jackrabbit.oak.query.
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Lists.newArrayList;
-import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
-import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
import static org.apache.jackrabbit.JcrConstants.NT_BASE;
-import static org.apache.jackrabbit.oak.api.Type.NAME;
-import static org.apache.jackrabbit.oak.api.Type.NAMES;
import java.util.ArrayList;
import java.util.List;
@@ -36,8 +32,11 @@ import org.apache.jackrabbit.oak.api.Pro
import org.apache.jackrabbit.oak.api.Result.SizePrecision;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.commons.LazyValue;
import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.core.ImmutableRoot;
import org.apache.jackrabbit.oak.plugins.memory.PropertyBuilder;
+import org.apache.jackrabbit.oak.plugins.tree.TreeUtil;
import org.apache.jackrabbit.oak.query.QueryImpl;
import org.apache.jackrabbit.oak.query.QueryOptions;
import org.apache.jackrabbit.oak.spi.query.fulltext.FullTextExpression;
@@ -171,6 +170,8 @@ public class SelectorImpl extends Source
private String planIndexName;
private TimerStats timerDuration;
+ private LazyValue<Tree> lastReadOnlyTree;
+
public SelectorImpl(NodeTypeInfo nodeTypeInfo, String selectorName) {
this.nodeTypeInfo = checkNotNull(nodeTypeInfo);
this.selectorName = checkNotNull(selectorName);
@@ -566,24 +567,20 @@ public class SelectorImpl extends Source
}
private boolean evaluateTypeMatch() {
- Tree tree = getTree(currentRow.getPath());
+ String path = currentRow.getPath();
+ Tree tree = getTree(path);
if (tree == null || !tree.exists()) {
return false;
}
- PropertyState primary = tree.getProperty(JCR_PRIMARYTYPE);
- if (primary != null && primary.getType() == NAME) {
- String name = primary.getValue(NAME);
- if (primaryTypes.contains(name)) {
- return true;
- }
+ LazyValue<Tree> readOnly = getReadOnlyTree(path);
+ String primaryTypeName = TreeUtil.getPrimaryTypeName(tree, readOnly);
+ if (primaryTypeName != null && primaryTypes.contains(primaryTypeName)) {
+ return true;
}
- PropertyState mixins = tree.getProperty(JCR_MIXINTYPES);
- if (mixins != null && mixins.getType() == NAMES) {
- for (String name : mixins.getValue(NAMES)) {
- if (mixinTypes.contains(name)) {
- return true;
- }
+ for (String mixinName : TreeUtil.getMixinTypeNames(tree, readOnly)) {
+ if (mixinTypes.contains(mixinName)) {
+ return true;
}
}
// no matches found
@@ -622,10 +619,23 @@ public class SelectorImpl extends Source
if (lastPath == null || !path.equals(lastPath)) {
lastTree = query.getTree(path);
lastPath = path;
+ lastReadOnlyTree = null;
}
return lastTree;
}
+ private LazyValue<Tree> getReadOnlyTree(@NotNull String path) {
+ if (lastReadOnlyTree == null) {
+ lastReadOnlyTree = new LazyValue<Tree>() {
+ @Override
+ protected Tree createValue() {
+ return new ImmutableRoot(query.getExecutionContext().getBaseState()).getTree(path);
+ }
+ };
+ }
+ return lastReadOnlyTree;
+ }
+
/**
* The value for the given selector for the current node.
*
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/tree/impl/TreeUtilTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/tree/impl/TreeUtilTest.java?rev=1852758&r1=1852757&r2=1852758&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/tree/impl/TreeUtilTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/tree/impl/TreeUtilTest.java Fri Feb 1 16:33:35 2019
@@ -16,17 +16,27 @@
*/
package org.apache.jackrabbit.oak.plugins.tree.impl;
+import com.google.common.collect.Iterables;
import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.api.ContentSession;
import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.api.Tree;
-import org.apache.jackrabbit.oak.AbstractSecurityTest;
import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.commons.LazyValue;
import org.apache.jackrabbit.oak.plugins.tree.TreeUtil;
import org.apache.jackrabbit.oak.spi.nodetype.NodeTypeConstants;
import org.junit.Test;
+import org.mockito.Mockito;
+
+import javax.jcr.GuestCredentials;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
public class TreeUtilTest extends AbstractSecurityTest {
@@ -65,4 +75,133 @@ public class TreeUtilTest extends Abstra
assertNotNull(ps);
assertEquals("", ps.getValue(Type.STRING));
}
+
+ @Test
+ public void testGetPrimaryTypeNameAccessible() throws Exception {
+ Tree tree = root.getTree("/");
+ String expected = TreeUtil.getPrimaryTypeName(tree);
+ assertEquals(expected, TreeUtil.getPrimaryTypeName(tree, new LazyValue<Tree>() {
+ @Override
+ protected Tree createValue() {
+ return tree;
+ }
+ }));
+ }
+
+ @Test
+ public void testGetPrimaryTypeNameNotAccessible() throws Exception {
+ Tree tree = root.getTree("/");
+ String expected = TreeUtil.getPrimaryTypeName(tree);
+ try (ContentSession cs = login(new GuestCredentials())) {
+ Root r = cs.getLatestRoot();
+ assertNull(TreeUtil.getPrimaryTypeName(r.getTree("/")));
+ assertEquals(expected, TreeUtil.getPrimaryTypeName(r.getTree("/"), new LazyValue<Tree>() {
+ @Override
+ protected Tree createValue() {
+ return tree;
+ }
+ }));
+ }
+ }
+
+ @Test
+ public void testGetPrimaryTypeNameNotAccessibleNew() throws Exception {
+ Tree testTree = TreeUtil.addChild(root.getTree("/"), "test", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+
+ Tree t = Mockito.mock(Tree.class);
+ when(t.hasProperty(JcrConstants.JCR_PRIMARYTYPE)).thenReturn(false);
+ when(t.getStatus()).thenReturn(Tree.Status.NEW);
+
+ assertNull(TreeUtil.getPrimaryTypeName(t, new LazyValue<Tree>() {
+ @Override
+ protected Tree createValue() {
+ return testTree;
+ }
+ }));
+ }
+
+ @Test
+ public void testGetMixinTypeNamesMissingAccessible() {
+ assertTrue(Iterables.isEmpty(TreeUtil.getMixinTypeNames(root.getTree("/"))));
+ assertTrue(Iterables.isEmpty(TreeUtil.getMixinTypeNames(root.getTree("/"), new LazyValue<Tree>() {
+ @Override
+ protected Tree createValue() {
+ return root.getTree("/");
+ }
+ })));
+ }
+
+ @Test
+ public void testGetMixinTypeNamesMissingNotAccessible() throws Exception {
+ Tree tree = root.getTree("/");
+ assertTrue(Iterables.isEmpty(TreeUtil.getMixinTypeNames(tree)));
+
+ try (ContentSession cs = login(new GuestCredentials())) {
+ Root guestRoot = cs.getLatestRoot();
+ assertTrue(Iterables.isEmpty(TreeUtil.getMixinTypeNames(guestRoot.getTree("/"))));
+ assertTrue(Iterables.isEmpty(TreeUtil.getMixinTypeNames(guestRoot.getTree("/"), new LazyValue<Tree>() {
+ @Override
+ protected Tree createValue() {
+ return tree;
+ }
+ })));
+ }
+ }
+
+ @Test
+ public void testGetMixinTypeNamesPresentAccessible() throws Exception {
+ Tree testTree = TreeUtil.addChild(root.getTree("/"), "test", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+ TreeUtil.addMixin(testTree, "mix:title", root.getTree(NodeTypeConstants.NODE_TYPES_PATH), "uid");
+
+ String path = testTree.getPath();
+ Iterable<String> expected = TreeUtil.getMixinTypeNames(root.getTree(path));
+ assertTrue(Iterables.contains(expected, "mix:title"));
+
+ assertTrue(Iterables.elementsEqual(expected, TreeUtil.getMixinTypeNames(testTree, new LazyValue<Tree>() {
+ @Override
+ protected Tree createValue() {
+ return testTree;
+ }
+ })));
+ }
+
+ @Test
+ public void testGetMixinTypeNamesPresentNotAccessible() throws Exception {
+ Tree testTree = TreeUtil.addChild(root.getTree("/"), "test", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+ TreeUtil.addMixin(testTree, "mix:title", root.getTree(NodeTypeConstants.NODE_TYPES_PATH), "uid");
+ root.commit();
+
+ String path = testTree.getPath();
+ Iterable<String> expected = TreeUtil.getMixinTypeNames(root.getTree(path));
+ assertTrue(Iterables.contains(expected, "mix:title"));
+
+ try (ContentSession cs = login(new GuestCredentials())) {
+ Root guestRoot = cs.getLatestRoot();
+ assertTrue(Iterables.isEmpty(TreeUtil.getMixinTypeNames(guestRoot.getTree(path))));
+ assertTrue(Iterables.elementsEqual(expected, TreeUtil.getMixinTypeNames(guestRoot.getTree(path), new LazyValue<Tree>() {
+ @Override
+ protected Tree createValue() {
+ return testTree;
+ }
+ })));
+ }
+ }
+
+ @Test
+ public void testGetMixinTypeNamesPresentNotAccessibleNew() throws Exception {
+ Tree testTree = TreeUtil.addChild(root.getTree("/"), "test", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+ TreeUtil.addMixin(testTree, "mix:title", root.getTree(NodeTypeConstants.NODE_TYPES_PATH), "uid");
+ root.commit();
+
+ Tree t = Mockito.mock(Tree.class);
+ when(t.hasProperty(JcrConstants.JCR_MIXINTYPES)).thenReturn(false);
+ when(t.getStatus()).thenReturn(Tree.Status.NEW);
+
+ assertTrue(Iterables.isEmpty(TreeUtil.getMixinTypeNames(t, new LazyValue<Tree>() {
+ @Override
+ protected Tree createValue() {
+ return testTree;
+ }
+ })));
+ }
}
\ No newline at end of file
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/AbstractQueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/AbstractQueryTest.java?rev=1852758&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/AbstractQueryTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/AbstractQueryTest.java Fri Feb 1 16:33:35 2019
@@ -0,0 +1,164 @@
+/*
+ * 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.evaluation;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
+import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
+import org.apache.jackrabbit.oak.api.Result;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.plugins.tree.TreeUtil;
+import org.apache.jackrabbit.oak.spi.nodetype.NodeTypeConstants;
+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.PermissionProvider;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+import javax.jcr.query.Query;
+import javax.jcr.security.AccessControlManager;
+import java.util.Collections;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public abstract class AbstractQueryTest extends AbstractOakCoreTest {
+
+ Tree node;
+ Tree subnode;
+
+ @Before
+ public void before() throws Exception {
+ super.before();
+
+ createIndexDefinition();
+
+ node = TreeUtil.addChild(root.getTree("/"), "node", JcrConstants.NT_UNSTRUCTURED);
+ subnode = TreeUtil.addChild(node, "subnode", JcrConstants.NT_UNSTRUCTURED);
+ root.commit();
+ }
+
+ void grantPropertyReadAccess(@NotNull String propertyName) throws Exception {
+ AccessControlManager acMgr = getAccessControlManager(root);
+ JackrabbitAccessControlList acl = AccessControlUtils.getAccessControlList(acMgr, "/");
+ if (acl != null) {
+ Map<String, Value[]> restrictions = ImmutableMap.of(AccessControlConstants.REP_ITEM_NAMES, new Value[] {getValueFactory(root).createValue(propertyName, PropertyType.NAME)});
+ acl.addEntry(testPrincipal, AccessControlUtils.privilegesFromNames(acMgr, PrivilegeConstants.REP_READ_PROPERTIES), true, null, restrictions);
+ acMgr.setPolicy(acl.getPath(), acl);
+ }
+ }
+
+ void createIndexDefinition() throws RepositoryException {};
+ abstract String getStatement();
+
+ @Test
+ public void testQueryWithEmptyGlobRestriction() throws Exception {
+ // setup permissions for testuser using rep:glob restriction such that
+ // - access to /node is granted
+ // - access to /node/subnode is denied
+ AccessControlManager acm = getAccessControlManager(root);
+ JackrabbitAccessControlList acl = AccessControlUtils.getAccessControlList(acm, node.getPath());
+ if (acl != null) {
+ Map<String, Value> restrictions = ImmutableMap.of(AccessControlConstants.REP_GLOB, getValueFactory(root).createValue(""));
+ acl.addEntry(testPrincipal, AccessControlUtils.privilegesFromNames(acm, PrivilegeConstants.JCR_ALL), true, restrictions);
+ acm.setPolicy(acl.getPath(), acl);
+ root.commit();
+ }
+
+ assertAccess(node.getPath(), subnode.getPath(), false);
+
+ // test that query result corresponds to the direct access (node readable, subnode not readable)
+ Result result = getTestRoot().getQueryEngine().executeQuery(getStatement(), Query.JCR_SQL2, Collections.emptyMap(), Collections.emptyMap());
+
+ Iterable<String> expected = ImmutableSet.of(node.getPath());
+ assertTrue(Iterables.elementsEqual(expected, Iterables.transform(result.getRows(), row -> row.getPath())));
+ }
+
+ @Test
+ public void testQueryWithEmptyGlobRestrictionAndPropertyRead() throws Exception {
+ // setup permissions for testuser using rep:glob restriction such that
+ // - access to /node is granted
+ // - access to /node/subnode is denied
+ AccessControlManager acm = getAccessControlManager(root);
+ JackrabbitAccessControlList acl = AccessControlUtils.getAccessControlList(acm, node.getPath());
+ if (acl != null) {
+ Map<String, Value> restrictions = ImmutableMap.of(AccessControlConstants.REP_GLOB, getValueFactory(root).createValue(""));
+ acl.addEntry(testPrincipal, privilegesFromNames(PrivilegeConstants.JCR_ALL), true, restrictions);
+
+ restrictions = ImmutableMap.of(AccessControlConstants.REP_GLOB, getValueFactory(root).createValue("/"+NodeTypeConstants.JCR_PRIMARYTYPE));
+ acl.addEntry(testPrincipal, privilegesFromNames(PrivilegeConstants.REP_READ_PROPERTIES), true, restrictions);
+
+ acm.setPolicy(acl.getPath(), acl);
+ root.commit();
+ }
+
+ assertAccess(node.getPath(), subnode.getPath(), true);
+
+ // test that query result corresponds to the direct access (node readable, subnode not readable)
+ Result result = getTestRoot().getQueryEngine().executeQuery(getStatement(), Query.JCR_SQL2, Collections.emptyMap(), Collections.emptyMap());
+
+ Iterable<String> expected = ImmutableSet.of(node.getPath());
+ assertTrue(Iterables.elementsEqual(expected, Iterables.transform(result.getRows(), row -> row.getPath())));
+ }
+
+ @Test
+ public void testQueryWithAllowNodeAndDenySubNode() throws Exception {
+ // setup permissions for testuser using 2 aces such that
+ // - access to /node is granted
+ // - access to /node/subnode is denied
+ setupPermission(node.getPath(), testPrincipal, true, PrivilegeConstants.JCR_ALL);
+ setupPermission(subnode.getPath(), testPrincipal, false, PrivilegeConstants.JCR_ALL);
+
+ assertAccess(node.getPath(), subnode.getPath(), true);
+
+ // test that query result corresponds to the direct access (node readable, subnode not readable)
+ Result result = getTestRoot().getQueryEngine().executeQuery(getStatement(), Query.JCR_SQL2, Collections.emptyMap(), Collections.emptyMap());
+
+ Iterable<String> expected = ImmutableSet.of(node.getPath());
+ assertTrue(Iterables.elementsEqual(expected, Iterables.transform(result.getRows(), row -> row.getPath())));
+ }
+
+ private void assertAccess(@NotNull String nodePath, @NotNull String subnodePath, boolean canReadPrimaryType) throws Exception {
+ // verify access control setup
+ assertTrue(getTestRoot().getTree(nodePath).exists());
+ assertFalse(getTestRoot().getTree(subnodePath).exists());
+
+ // verify PermissionProvider.isGranted(String, String) as it is used inside
+ // the query code base (FilterImpl.isAccessible)
+ PermissionProvider pp = getConfig(AuthorizationConfiguration.class).getPermissionProvider(getTestRoot(), getTestSession().getWorkspaceName(), getTestSession().getAuthInfo().getPrincipals());
+ assertTrue(pp.isGranted(nodePath, Session.ACTION_READ));
+
+ assertEquals(canReadPrimaryType, pp.isGranted(nodePath + '/' + JcrConstants.JCR_PRIMARYTYPE, Session.ACTION_READ));
+ assertEquals(canReadPrimaryType, pp.isGranted(nodePath + '/' + JcrConstants.JCR_PRIMARYTYPE, Permissions.getString(Permissions.READ_PROPERTY)));
+
+ assertFalse(pp.isGranted(subnodePath, Session.ACTION_READ));
+ assertFalse(pp.isGranted(subnodePath + '/' + JcrConstants.JCR_PRIMARYTYPE, Session.ACTION_READ));
+ assertFalse(pp.isGranted(subnodePath + '/' + JcrConstants.JCR_PRIMARYTYPE, Permissions.getString(Permissions.READ_PROPERTY)));
+ }
+}
\ No newline at end of file
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/IndexedQueryMixinTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/IndexedQueryMixinTest.java?rev=1852758&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/IndexedQueryMixinTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/IndexedQueryMixinTest.java Fri Feb 1 16:33:35 2019
@@ -0,0 +1,55 @@
+/*
+ * 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.evaluation;
+
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
+import org.apache.jackrabbit.oak.plugins.index.IndexUtils;
+import org.apache.jackrabbit.oak.plugins.tree.TreeUtil;
+import org.apache.jackrabbit.oak.spi.nodetype.NodeTypeConstants;
+
+import javax.jcr.RepositoryException;
+
+import static org.junit.Assert.assertTrue;
+
+public class IndexedQueryMixinTest extends AbstractQueryTest {
+
+ @Override
+ public void before() throws Exception {
+ super.before();
+
+ TreeUtil.addMixin(node, "mix:title", root.getTree(NodeTypeConstants.NODE_TYPES_PATH), "userId");
+ node.setProperty("jcr:title", "title");
+ TreeUtil.addMixin(subnode, "mix:title", root.getTree(NodeTypeConstants.NODE_TYPES_PATH), "userId");
+ subnode.setProperty("jcr:title", "title");
+
+ grantPropertyReadAccess("jcr:title");
+
+ root.commit();
+ }
+
+ @Override
+ void createIndexDefinition() throws RepositoryException {
+ Tree oakIndex = root.getTree("/"+IndexConstants.INDEX_DEFINITIONS_NAME);
+ assertTrue(oakIndex.exists());
+ IndexUtils.createIndexDefinition(oakIndex, "test-index", false, new String[] {"jcr:title"}, "mix:title");
+ }
+
+ String getStatement() {
+ return "SELECT * FROM [mix:title] WHERE [jcr:title] is not null";
+ }
+}
\ No newline at end of file
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/IndexedQueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/IndexedQueryTest.java?rev=1852758&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/IndexedQueryTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/IndexedQueryTest.java Fri Feb 1 16:33:35 2019
@@ -0,0 +1,51 @@
+/*
+ * 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.evaluation;
+
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
+import org.apache.jackrabbit.oak.plugins.index.IndexUtils;
+
+import javax.jcr.RepositoryException;
+
+import static org.junit.Assert.assertTrue;
+
+public class IndexedQueryTest extends AbstractQueryTest {
+
+ @Override
+ public void before() throws Exception {
+ super.before();
+
+ node.setProperty("title", "a");
+ subnode.setProperty("title", "b");
+
+ grantPropertyReadAccess("title");
+
+ root.commit();
+ }
+
+ @Override
+ void createIndexDefinition() throws RepositoryException {
+ Tree oakIndex = root.getTree("/"+IndexConstants.INDEX_DEFINITIONS_NAME);
+ assertTrue(oakIndex.exists());
+ IndexUtils.createIndexDefinition(oakIndex, "test-index", false, new String[] {"title"}, "nt:unstructured");
+ }
+
+ String getStatement() {
+ return "SELECT * FROM [nt:unstructured] WHERE [title] is not null";
+ }
+}
\ No newline at end of file
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/TraversingQueryMixinTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/TraversingQueryMixinTest.java?rev=1852758&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/TraversingQueryMixinTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/TraversingQueryMixinTest.java Fri Feb 1 16:33:35 2019
@@ -0,0 +1,38 @@
+/*
+ * 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.evaluation;
+
+import org.apache.jackrabbit.oak.plugins.tree.TreeUtil;
+import org.apache.jackrabbit.oak.spi.nodetype.NodeTypeConstants;
+
+import javax.jcr.RepositoryException;
+
+public class TraversingQueryMixinTest extends AbstractQueryTest {
+
+ @Override
+ public void before() throws Exception {
+ super.before();
+
+ TreeUtil.addMixin(node, "mix:title", root.getTree(NodeTypeConstants.NODE_TYPES_PATH), "userId");
+ TreeUtil.addMixin(subnode, "mix:title", root.getTree(NodeTypeConstants.NODE_TYPES_PATH), "userId");
+ root.commit();
+ }
+
+ String getStatement() {
+ return "SELECT * FROM [mix:title] option (traversal ok)";
+ }
+}
\ No newline at end of file
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/TraversingQueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/TraversingQueryTest.java?rev=1852758&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/TraversingQueryTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/TraversingQueryTest.java Fri Feb 1 16:33:35 2019
@@ -0,0 +1,55 @@
+/*
+ * 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.evaluation;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
+import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
+import org.apache.jackrabbit.oak.api.QueryEngine;
+import org.apache.jackrabbit.oak.api.Result;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.plugins.tree.TreeUtil;
+import org.apache.jackrabbit.oak.spi.nodetype.NodeTypeConstants;
+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.PermissionProvider;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.jcr.Session;
+import javax.jcr.Value;
+import javax.jcr.query.Query;
+import javax.jcr.security.AccessControlManager;
+import java.util.Collections;
+import java.util.Map;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class TraversingQueryTest extends AbstractQueryTest {
+
+ String getStatement() {
+ return "SELECT * FROM [nt:unstructured] option (traversal ok)";
+ }
+}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/NodeImpl.java?rev=1852758&r1=1852757&r2=1852758&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/NodeImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/NodeImpl.java Fri Feb 1 16:33:35 2019
@@ -79,6 +79,7 @@ import org.apache.jackrabbit.oak.api.Pro
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Tree.Status;
import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.commons.LazyValue;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.jcr.delegate.NodeDelegate;
import org.apache.jackrabbit.oak.jcr.delegate.PropertyDelegate;
@@ -1281,30 +1282,26 @@ public class NodeImpl<T extends NodeDele
//------------------------------------------------------------< internal >---
@Nullable
private String getPrimaryTypeName(@NotNull Tree tree) {
- String primaryTypeName = null;
- if (tree.hasProperty(JcrConstants.JCR_PRIMARYTYPE)) {
- primaryTypeName = TreeUtil.getPrimaryTypeName(tree);
- } else if (tree.getStatus() != Status.NEW) {
- // OAK-2441: for backwards compatibility with Jackrabbit 2.x try to
- // read the primary type from the underlying node state.
- primaryTypeName = TreeUtil.getPrimaryTypeName(RootFactory.createReadOnlyRoot(sessionDelegate.getRoot()).getTree(tree.getPath()));
- }
- return primaryTypeName;
+ return TreeUtil.getPrimaryTypeName(tree, getReadOnlyTree(tree));
}
@NotNull
private Iterator<String> getMixinTypeNames(@NotNull Tree tree) throws RepositoryException {
- Iterator<String> mixinNames = Collections.emptyIterator();
if (tree.hasProperty(JcrConstants.JCR_MIXINTYPES) || canReadMixinTypes(tree)) {
- mixinNames = TreeUtil.getNames(tree, JcrConstants.JCR_MIXINTYPES).iterator();
- } else if (tree.getStatus() != Status.NEW) {
- // OAK-2441: for backwards compatibility with Jackrabbit 2.x try to
- // read the primary type from the underlying node state.
- mixinNames = TreeUtil.getNames(
- RootFactory.createReadOnlyRoot(sessionDelegate.getRoot()).getTree(tree.getPath()),
- JcrConstants.JCR_MIXINTYPES).iterator();
+ return TreeUtil.getMixinTypeNames(tree).iterator();
+ } else {
+ return TreeUtil.getMixinTypeNames(tree, getReadOnlyTree(tree)).iterator();
}
- return mixinNames;
+ }
+
+ @NotNull
+ private LazyValue<Tree> getReadOnlyTree(@NotNull Tree tree) {
+ return new LazyValue<Tree>() {
+ @Override
+ protected Tree createValue() {
+ return RootFactory.createReadOnlyRoot(sessionDelegate.getRoot()).getTree(tree.getPath());
+ }
+ };
}
private boolean canReadMixinTypes(@NotNull Tree tree) throws RepositoryException {
Modified: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/plugins/tree/TreeUtil.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/plugins/tree/TreeUtil.java?rev=1852758&r1=1852757&r2=1852758&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/plugins/tree/TreeUtil.java (original)
+++ jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/plugins/tree/TreeUtil.java Fri Feb 1 16:33:35 2019
@@ -34,6 +34,7 @@ import org.apache.jackrabbit.JcrConstant
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.commons.LazyValue;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.commons.UUIDUtils;
import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
@@ -88,6 +89,37 @@ public final class TreeUtil {
}
@Nullable
+ public static String getPrimaryTypeName(@NotNull Tree tree, @NotNull LazyValue<Tree> readOnlyTree) {
+ String primaryTypeName = null;
+ if (tree.hasProperty(JcrConstants.JCR_PRIMARYTYPE)) {
+ primaryTypeName = TreeUtil.getPrimaryTypeName(tree);
+ } else if (tree.getStatus() != Tree.Status.NEW) {
+ // OAK-2441: for backwards compatibility with Jackrabbit 2.x try to
+ // read the primary type from the underlying node state.
+ primaryTypeName = TreeUtil.getPrimaryTypeName(readOnlyTree.get());
+ }
+ return primaryTypeName;
+ }
+
+ @NotNull
+ public static Iterable<String> getMixinTypeNames(@NotNull Tree tree) {
+ return TreeUtil.getNames(tree, JcrConstants.JCR_MIXINTYPES);
+ }
+
+ @NotNull
+ public static Iterable<String> getMixinTypeNames(@NotNull Tree tree, @NotNull LazyValue<Tree> readOnlyTree) {
+ Iterable<String> mixinNames = emptyList();
+ if (tree.hasProperty(JcrConstants.JCR_MIXINTYPES)) {
+ mixinNames = getMixinTypeNames(tree);
+ } else if (tree.getStatus() != Tree.Status.NEW) {
+ // OAK-2441: for backwards compatibility with Jackrabbit 2.x try to
+ // read the primary type from the underlying node state.
+ mixinNames = TreeUtil.getNames(readOnlyTree.get(), JcrConstants.JCR_MIXINTYPES);
+ }
+ return mixinNames;
+ }
+
+ @Nullable
public static Iterable<String> getStrings(@NotNull Tree tree, @NotNull String propertyName) {
PropertyState property = tree.getProperty(propertyName);
if (property == null) {
Modified: jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/plugins/tree/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/plugins/tree/package-info.java?rev=1852758&r1=1852757&r2=1852758&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/plugins/tree/package-info.java (original)
+++ jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/plugins/tree/package-info.java Fri Feb 1 16:33:35 2019
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@Version("3.1.0")
+@Version("3.2.0")
package org.apache.jackrabbit.oak.plugins.tree;
import org.osgi.annotation.versioning.Version;