Index: oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionHookTest.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionHookTest.java (revision 1853004) +++ oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionHookTest.java (date 1549372641000) @@ -45,6 +45,7 @@ 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.principal.EveryonePrincipal; +import org.apache.jackrabbit.oak.spi.security.privilege.JcrAllUtil; import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBitsProvider; import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants; import org.apache.jackrabbit.oak.util.NodeUtil; @@ -382,7 +383,7 @@ assertTrue(allEntry.exists()); PropertyState ps = allEntry.getProperty(PermissionConstants.REP_PRIVILEGE_BITS); assertEquals(1, ps.count()); - assertEquals(PermissionStore.DYNAMIC_ALL_BITS, ps.getValue(Type.LONG, 0).longValue()); + assertTrue(JcrAllUtil.denotesDynamicJcrAll(ps)); // verify that the permission provider still exposes the correct privilege // (jcr:all) for the given childPath irrespective of the dynamic nature of Index: oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionStoreImplTest.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionStoreImplTest.java (revision 1853004) +++ oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionStoreImplTest.java (date 1549372641000) @@ -31,6 +31,7 @@ import org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration; import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionConstants; import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal; +import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits; import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants; import org.apache.jackrabbit.oak.util.NodeUtil; import org.jetbrains.annotations.NotNull; @@ -39,6 +40,7 @@ import org.junit.Before; import org.junit.Test; +import static org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants.REP_READ_NODES; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -116,7 +118,7 @@ Tree collision = TreeUtil.addChild(child, "c_"+child.getName(), NT_REP_PERMISSION_STORE); collision.setProperty(REP_ACCESS_CONTROLLED_PATH, "/another/path"); Tree entry = TreeUtil.addChild(collision, "1", NT_REP_PERMISSIONS); - entry.setProperty(REP_PRIVILEGE_BITS, PermissionStore.DYNAMIC_ALL_BITS); + entry.setProperty(PrivilegeBits.BUILT_IN.get(REP_READ_NODES).asPropertyState(REP_PRIVILEGE_BITS)); entry.setProperty(REP_IS_ALLOW, false); break; } Index: oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/JcrAllUtilTest.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/JcrAllUtilTest.java (date 1549372641000) +++ oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/JcrAllUtilTest.java (date 1549372641000) @@ -0,0 +1,141 @@ +/* + * 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.privilege; + +import com.google.common.collect.Lists; +import com.google.common.primitives.Longs; +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.api.Type; +import org.apache.jackrabbit.oak.plugins.memory.PropertyStates; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import static org.apache.jackrabbit.oak.spi.security.privilege.JcrAllUtil.DYNAMIC_JCR_ALL_VALUE; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.when; + +public class JcrAllUtilTest implements PrivilegeConstants { + + private static final Long ALL = Long.valueOf(Long.MAX_VALUE); + + private static final PropertyState ALL_PROPERTY = PropertyStates.createProperty(REP_BITS, Longs.asList(Long.MAX_VALUE), Type.LONGS); + private final PrivilegeBits ALL_BITS = PrivilegeBits.getInstance(ALL_PROPERTY); + + private static final PropertyState DYNAMIC_ALL_PROPERTY = PropertyStates.createProperty("anyName", Longs.asList(DYNAMIC_JCR_ALL_VALUE), Type.LONGS); + + private Tree privTree; + private Tree jcrAllDefTree; + private Root root; + private PrivilegeBitsProvider bitsProvider; + + @Before + public void before() { + jcrAllDefTree = Mockito.mock(Tree.class); + when(jcrAllDefTree.exists()).thenReturn(true); + when(jcrAllDefTree.getName()).thenReturn(JCR_ALL); + when(jcrAllDefTree.getProperty(REP_BITS)).thenReturn(ALL_PROPERTY); + + privTree = Mockito.mock(Tree.class); + when(privTree.exists()).thenReturn(true); + when(privTree.hasChild(JCR_ALL)).thenReturn(true); + when(privTree.getChild(JCR_ALL)).thenReturn(jcrAllDefTree); + + root = Mockito.mock(Root.class); + when(root.getTree(PRIVILEGES_PATH)).thenReturn(privTree); + + bitsProvider = new PrivilegeBitsProvider(root); + } + + @Test + public void testGetInstanceBuiltin() { + PrivilegeBits readBits = PrivilegeBits.BUILT_IN.get(REP_READ_NODES); + PropertyState propState = readBits.asPropertyState(("anyName")); + + assertSame(readBits, JcrAllUtil.getPrivilegeBits(propState, bitsProvider)); + } + + @Test + public void testAsPropertyStateBuiltin() { + PrivilegeBits readBits = PrivilegeBits.BUILT_IN.get(REP_READ_NODES); + PropertyState propertyState = JcrAllUtil.getPropertyState("anyName", readBits, bitsProvider); + + assertEquals(readBits.asPropertyState("anyName"), propertyState); + } + + @Test + public void testGetInstanceCombined() { + PrivilegeBits bits = PrivilegeBits.getInstance(); + bits.add(PrivilegeBits.BUILT_IN.get(REP_READ_NODES)); + bits.add(PrivilegeBits.BUILT_IN.get(REP_WRITE)); + PropertyState propState = bits.asPropertyState("anyName"); + + assertEquals(bits.unmodifiable(), JcrAllUtil.getPrivilegeBits(propState, bitsProvider)); + } + + @Test + public void testAsPropertyStateCombined() { + PrivilegeBits bits = PrivilegeBits.getInstance(); + bits.add(PrivilegeBits.BUILT_IN.get(REP_READ_NODES)); + bits.add(PrivilegeBits.BUILT_IN.get(REP_WRITE)); + PropertyState expected = bits.asPropertyState("anyName"); + + assertEquals(expected, JcrAllUtil.getPropertyState("anyName", bits, bitsProvider)); + } + + @Test + public void testGetInstanceDynamicAll() { + assertEquals(ALL_BITS, JcrAllUtil.getPrivilegeBits(DYNAMIC_ALL_PROPERTY, bitsProvider)); + } + + @Test + public void testAsPropertyStateDynamicAll() { + assertEquals(DYNAMIC_ALL_PROPERTY, JcrAllUtil.getPropertyState("anyName", ALL_BITS, bitsProvider)); + } + + @Test + public void testDenotesDynamicAllNullPropertyState() { + assertFalse(JcrAllUtil.denotesDynamicJcrAll(null)); + } + + @Test + public void testDenotesDynamicAllNotLongsPropertyState() { + assertFalse(JcrAllUtil.denotesDynamicJcrAll(PropertyStates.createProperty("any", "String"))); + assertFalse(JcrAllUtil.denotesDynamicJcrAll(PropertyStates.createProperty("any", Lists.newArrayList("mv", "strings"), Type.STRINGS))); + assertFalse(JcrAllUtil.denotesDynamicJcrAll(PropertyStates.createProperty("any", "-1"))); + } + + @Test + public void testDenotesDynamicAllMVLongPropertyState() { + assertFalse(JcrAllUtil.denotesDynamicJcrAll(PropertyStates.createProperty("any", Lists.newArrayList(-1, 2, 3), Type.LONGS))); + } + + @Test + public void testDenotesDynamicAllSingleLongPropertyState() { + assertFalse(JcrAllUtil.denotesDynamicJcrAll(PropertyStates.createProperty("any", DYNAMIC_JCR_ALL_VALUE))); + } + + @Test + public void testDenotesDynamicAll() { + assertTrue(JcrAllUtil.denotesDynamicJcrAll(PropertyStates.createProperty("any", Lists.newArrayList(DYNAMIC_JCR_ALL_VALUE), Type.LONGS))); + } +} \ No newline at end of file Index: oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProviderTest.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProviderTest.java (revision 1853004) +++ oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProviderTest.java (date 1549034443000) @@ -16,10 +16,6 @@ */ package org.apache.jackrabbit.oak.spi.security.privilege; -import java.util.Set; -import javax.jcr.RepositoryException; -import javax.jcr.security.Privilege; - import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; @@ -34,12 +30,19 @@ import org.junit.Test; import org.mockito.Mockito; +import javax.jcr.security.Privilege; +import java.util.Set; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class PrivilegeBitsProviderTest implements PrivilegeConstants { @@ -56,15 +59,19 @@ @Before public void before() { + pTree = Mockito.mock(Tree.class); + when(pTree.getName()).thenReturn(KNOWN_PRIV_NAME); + when(pTree.getProperty(REP_BITS)).thenReturn(ps); + privTree = Mockito.mock(Tree.class); + when(privTree.exists()).thenReturn(true); + when(privTree.hasChild(KNOWN_PRIV_NAME)).thenReturn(true); + when(privTree.getChild(KNOWN_PRIV_NAME)).thenReturn(pTree); + when(privTree.getChildren()).thenReturn(ImmutableSet.of(pTree)); root = Mockito.mock(Root.class); when(root.getTree(PRIVILEGES_PATH)).thenReturn(privTree); - pTree = Mockito.mock(Tree.class); - when(pTree.getName()).thenReturn(KNOWN_PRIV_NAME); - when(pTree.getProperty(REP_BITS)).thenReturn(ps); - bitsProvider = new PrivilegeBitsProvider(root); } @@ -86,7 +93,7 @@ @Test public void testGetBitsEmptyArray() { - assertEquals(PrivilegeBits.EMPTY, bitsProvider.getBits()); + assertEquals(PrivilegeBits.EMPTY, bitsProvider.getBits(new String[0])); } @Test @@ -150,6 +157,72 @@ assertEquals(bits.unmodifiable(), bitsProvider.getBits(KNOWN_PRIV_NAME)); } + @Test + public void testGetBitsTwiceSingleBuiltIn() { + Iterable names = ImmutableList.of(JCR_ADD_CHILD_NODES); + PrivilegeBits bits1 = bitsProvider.getBits(names); + PrivilegeBits bits2 = bitsProvider.getBits(names); + + assertSame(bits1, bits2); + assertEquals(bits1, bits2); + + verify(root, never()).getTree(PRIVILEGES_PATH); + verify(privTree, never()).getChild(KNOWN_PRIV_NAME); + } + + @Test + public void testGetBitsTwiceMultipleBuiltIn() { + Iterable names = ImmutableList.of(JCR_ADD_CHILD_NODES, JCR_REMOVE_CHILD_NODES); + PrivilegeBits bits1 = bitsProvider.getBits(names); + PrivilegeBits bits2 = bitsProvider.getBits(names); + + assertNotSame(bits1, bits2); + assertEquals(bits1, bits2); + + verify(root, never()).getTree(PRIVILEGES_PATH); + verify(privTree, never()).getChild(KNOWN_PRIV_NAME); + } + + @Test + public void testGetBitsTwiceKnown() { + Iterable names = ImmutableList.of(KNOWN_PRIV_NAME); + PrivilegeBits bits1 = bitsProvider.getBits(names); + PrivilegeBits bits2 = bitsProvider.getBits(names); + + assertNotSame(bits1, bits2); + assertEquals(bits1, bits2); + + verify(root, times(1)).getTree(PRIVILEGES_PATH); + verify(privTree, times(1)).getChild(KNOWN_PRIV_NAME); + } + + @Test + public void testGetBitsTwiceBuitInKnown() { + Iterable names = ImmutableList.of(KNOWN_PRIV_NAME, JCR_ADD_CHILD_NODES); + PrivilegeBits bits1 = bitsProvider.getBits(names); + PrivilegeBits bits2 = bitsProvider.getBits(names); + + assertNotSame(bits1, bits2); + assertEquals(bits1, bits2); + + verify(root, times(1)).getTree(PRIVILEGES_PATH); + verify(privTree, times(1)).getChild(KNOWN_PRIV_NAME); + } + + @Test + public void testGetBitsTwiceKnownUnknown() { + Iterable names = ImmutableList.of(KNOWN_PRIV_NAME, "unknown"); + PrivilegeBits bits1 = bitsProvider.getBits(names); + PrivilegeBits bits2 = bitsProvider.getBits(names); + + assertNotSame(bits1, bits2); + assertEquals(bits1, bits2); + assertEquals(bitsProvider.getBits(KNOWN_PRIV_NAME), bits1); + + verify(root, times(2)).getTree(PRIVILEGES_PATH); + verify(privTree, times(1)).getChild(KNOWN_PRIV_NAME); + } + @Test public void testGetBitsFromEmptyPrivileges() { assertSame(PrivilegeBits.EMPTY, bitsProvider.getBits(new Privilege[0], NamePathMapper.DEFAULT)); @@ -192,9 +265,6 @@ @Test public void testGetPrivilegeNames() { - when(privTree.exists()).thenReturn(true); - when(privTree.getChildren()).thenReturn(ImmutableSet.of(pTree)); - Set names = bitsProvider.getPrivilegeNames(bits); assertFalse(names.isEmpty()); assertEquals(ImmutableSet.of(KNOWN_PRIV_NAME), names); @@ -202,18 +272,12 @@ @Test public void testGetPrivilegeNamesFromCache() { - when(privTree.exists()).thenReturn(true); - when(privTree.getChildren()).thenReturn(ImmutableSet.of(pTree)); - Set names = bitsProvider.getPrivilegeNames(bits); assertSame(names, bitsProvider.getPrivilegeNames(bits)); } @Test public void testGetPrivilegeNamesWithAggregation() { - when(privTree.exists()).thenReturn(true); - when(privTree.getChildren()).thenReturn(ImmutableSet.of(pTree)); - Tree anotherPriv = Mockito.mock(Tree.class); when(anotherPriv.exists()).thenReturn(true); when(anotherPriv.getName()).thenReturn("name2"); Index: oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsTest.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsTest.java (revision 1853004) +++ oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsTest.java (date 1549029443000) @@ -205,6 +205,39 @@ } } + @Test + public void testBuiltIn() { + for (PrivilegeBits bits : PrivilegeBits.BUILT_IN.values()) { + assertTrue(bits.isBuiltin()); + assertTrue(PrivilegeBits.getInstance(bits).isBuiltin()); + } + } + + @Test + public void testCombinationNotBuiltIn() { + PrivilegeBits combination = PrivilegeBits.getInstance(); + for (PrivilegeBits bits : PrivilegeBits.BUILT_IN.values()) { + combination.add(bits); + } + assertFalse(combination.isBuiltin()); + } + + @Test + public void testNextNotBuiltIn() { + assertFalse(PrivilegeBits.getInstance(PrivilegeBits.NEXT_AFTER_BUILT_INS).isBuiltin()); + } + + @Test + public void testCombinationWithNextNotBuiltIn() { + PrivilegeBits bits = PrivilegeBits.NEXT_AFTER_BUILT_INS; + PrivilegeBits toTest = PrivilegeBits.getInstance(PrivilegeBits.BUILT_IN.get(PrivilegeConstants.JCR_READ)); + + for (int i = 0; i<100; i++) { + bits = bits.nextBits(); + assertFalse(toTest.add(bits).isBuiltin()); + } + } + @Test public void testIsEmpty() { // empty