blob: f01936eeafeece7a9066f9123b2999e068049de0 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jackrabbit.oak.spi.security.authorization.principalbased.impl;
import org.apache.jackrabbit.guava.common.collect.ImmutableList;
import org.apache.jackrabbit.guava.common.collect.ImmutableMap;
import org.apache.jackrabbit.guava.common.collect.Iterables;
import org.apache.jackrabbit.guava.common.collect.Maps;
import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.plugins.tree.TreeUtil;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
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.principalbased.FilterProvider;
import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
import org.apache.jackrabbit.oak.spi.xml.ImportBehavior;
import org.apache.jackrabbit.oak.spi.xml.NodeInfo;
import org.apache.jackrabbit.oak.spi.xml.PropInfo;
import org.apache.jackrabbit.oak.spi.xml.ProtectedItemImporter;
import org.apache.jackrabbit.oak.spi.xml.ReferenceChangeTracker;
import org.apache.jackrabbit.oak.spi.xml.TextValue;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Test;
import javax.jcr.ImportUUIDBehavior;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.ValueFormatException;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.PropertyDefinition;
import javax.jcr.security.AccessControlException;
import javax.jcr.security.AccessControlPolicy;
import java.security.Principal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants.REP_GLOB;
import static org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants.REP_ITEM_NAMES;
import static org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants.REP_NODE_PATH;
import static org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants.REP_NT_NAMES;
import static org.apache.jackrabbit.oak.spi.security.authorization.principalbased.impl.Constants.NT_REP_PRINCIPAL_ENTRY;
import static org.apache.jackrabbit.oak.spi.security.authorization.principalbased.impl.Constants.NT_REP_PRINCIPAL_POLICY;
import static org.apache.jackrabbit.oak.spi.security.authorization.principalbased.impl.Constants.NT_REP_RESTRICTIONS;
import static org.apache.jackrabbit.oak.spi.security.authorization.principalbased.impl.Constants.REP_EFFECTIVE_PATH;
import static org.apache.jackrabbit.oak.spi.security.authorization.principalbased.impl.Constants.REP_PRINCIPAL_NAME;
import static org.apache.jackrabbit.oak.spi.security.authorization.principalbased.impl.Constants.REP_PRINCIPAL_POLICY;
import static org.apache.jackrabbit.oak.spi.security.authorization.principalbased.impl.Constants.REP_PRIVILEGES;
import static org.apache.jackrabbit.oak.spi.security.authorization.principalbased.impl.Constants.REP_RESTRICTIONS;
import static org.apache.jackrabbit.oak.spi.security.authorization.principalbased.impl.MockUtility.mockTree;
import static org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants.JCR_READ;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class PrincipalPolicyImporterTest extends AbstractPrincipalBasedTest {
private FilterProvider filterProvider;
private PrincipalPolicyImporter importer;
@Override
public void before() throws Exception {
super.before();
filterProvider = spy(getFilterProvider());
importer = new PrincipalPolicyImporter(filterProvider, getMgrProvider(root));
}
@Override
protected ConfigurationParameters getSecurityConfigParameters() {
ConfigurationParameters params = ConfigurationParameters.of(ProtectedItemImporter.PARAM_IMPORT_BEHAVIOR, ImportBehavior.NAME_BESTEFFORT);
return ConfigurationParameters.of(AuthorizationConfiguration.NAME, params);
}
private boolean init(boolean isWorkspaceImport, int uuidBehavior) {
return importer.init(mock(Session.class), root, getNamePathMapper(), isWorkspaceImport, uuidBehavior, new ReferenceChangeTracker(), getSecurityProvider());
}
private PropInfo mockPropInfo(@NotNull String jcrName) {
return when(mock(PropInfo.class).getName()).thenReturn(jcrName).getMock();
}
private PropInfo mockPropInfo(@NotNull Principal principal) throws RepositoryException {
TextValue tx = when(mock(TextValue.class).getString()).thenReturn(principal.getName()).getMock();
PropInfo propInfo = mockPropInfo(getJcrName(REP_PRINCIPAL_NAME));
when(propInfo.getTextValue()).thenReturn(tx);
return propInfo;
}
private List<PropInfo> mockPropInfos(@Nullable String effectivePath, @NotNull String... privNames) throws RepositoryException {
List<PropInfo> propInfos = new ArrayList();
if (effectivePath != null) {
TextValue tx = when(mock(TextValue.class).getString()).thenReturn(effectivePath).getMock();
PropInfo propInfo = mockPropInfo(getJcrName(REP_EFFECTIVE_PATH));
when(propInfo.getTextValue()).thenReturn(tx);
when(propInfo.getType()).thenReturn(PropertyType.PATH);
propInfos.add(propInfo);
}
List privTxtValues = new ArrayList();
for (String privName : privNames) {
TextValue tx = when(mock(TextValue.class).getString()).thenReturn(getJcrName(privName)).getMock();
privTxtValues.add(tx);
}
if (!privTxtValues.isEmpty()) {
PropInfo propInfo = mockPropInfo(getJcrName(REP_PRIVILEGES));
when(propInfo.getTextValues()).thenReturn(privTxtValues);
when(propInfo.getType()).thenReturn(PropertyType.NAME);
propInfos.add(propInfo);
}
return propInfos;
}
private List<PropInfo> mockPropInfos(@NotNull Map<String, String> restrictions, int propertyType) throws RepositoryException {
return mockPropInfos(Maps.transformValues(restrictions, string -> {
try {
return new Value[] {getValueFactory(root).createValue(string, propertyType)};
} catch (ValueFormatException e) {
throw new RuntimeException(e);
}
}));
}
private List<PropInfo> mockPropInfos(@NotNull Map<String, Value[]> restrictions) throws RepositoryException {
List<PropInfo> propInfos = new ArrayList();
for (Map.Entry<String,Value[]> r : restrictions.entrySet()) {
String jcrName = r.getKey();
List<Value> vs = ImmutableList.copyOf(r.getValue());
PropInfo propInfo = mockPropInfo(jcrName);
if (!vs.isEmpty()) {
TextValue first = when(mock(TextValue.class).getString()).thenReturn(vs.get(0).getString()).getMock();
when(propInfo.getTextValue()).thenReturn(first);
when(propInfo.getValues(anyInt())).thenReturn(vs);
}
propInfos.add(propInfo);
}
return propInfos;
}
private PropertyDefinition mockPropertyDefinition(@NotNull String jcrName) {
NodeType nt = when(mock(NodeType.class).getName()).thenReturn(jcrName).getMock();
return when(mock(PropertyDefinition.class).getDeclaringNodeType()).thenReturn(nt).getMock();
}
private NodeInfo mockNodeInfo(@NotNull String jcrName, @NotNull String jcrPrimaryType) {
NodeInfo ni = when(mock(NodeInfo.class).getName()).thenReturn(jcrName).getMock();
when(ni.getPrimaryTypeName()).thenReturn(jcrPrimaryType);
return ni;
}
private Tree createPolicyTree(@NotNull User user) throws RepositoryException {
Tree t = root.getTree(getNamePathMapper().getOakPath(user.getPath()));
return TreeUtil.getOrAddChild(t, REP_PRINCIPAL_POLICY, NT_REP_PRINCIPAL_POLICY);
}
private String getJcrName(@NotNull String oakName) {
return getNamePathMapper().getJcrName(oakName);
}
@Nullable
private static PrincipalPolicyImpl.EntryImpl assertPolicy(@NotNull AccessControlPolicy[] policies, int expectedEntries) {
assertEquals(1, policies.length);
assertTrue(policies[0] instanceof PrincipalPolicyImpl);
assertEquals(expectedEntries, (((PrincipalPolicyImpl) policies[0])).size());
if (expectedEntries > 0) {
return ((PrincipalPolicyImpl) policies[0]).getEntries().get(0);
} else {
return null;
}
}
@Test
public void testInitWorkspaceImport() {
assertTrue(init(true, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW));
}
@Test
public void testInitSessionImport() {
assertTrue(init(false, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING));
}
@Test(expected = IllegalStateException.class)
public void testInitTwice() {
assertTrue(init(true, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW));
init(false, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING);
}
@Test
public void testInitResetMgrProviderRoot() {
MgrProvider mp = when(mock(MgrProvider.class).getSecurityProvider()).thenReturn(getSecurityProvider()).getMock();
importer = new PrincipalPolicyImporter(filterProvider, mp);
init(true, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
verify(mp, times(1)).reset(root, getNamePathMapper());
}
@Test
public void testInitGetsFilter() {
init(false,ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW);
verify(filterProvider, times(1)).getFilter(getSecurityProvider(), root, getNamePathMapper());
}
@Test
public void testProcessReferencesIsNop() {
// no initialization required
importer.processReferences();
init(false, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW);
importer.processReferences();
}
@Test(expected = IllegalStateException.class)
public void testHandlePropInfoNotInitialized() throws Exception {
importer.handlePropInfo(mock(Tree.class), mock(PropInfo.class), mock(PropertyDefinition.class));
}
@Test
public void testHandlePropInfoNonExistingTree() throws Exception {
init(true, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING);
Tree tree = when(mock(Tree.class).exists()).thenReturn(false).getMock();
assertFalse(importer.handlePropInfo(tree, mock(PropInfo.class), mock(PropertyDefinition.class)));
}
@Test
public void testHandlePropInfoWrongTreeName() throws Exception {
init(true, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW);
// wrong policy name
Tree tree = mockTree(AccessControlConstants.REP_POLICY, NT_REP_PRINCIPAL_POLICY, true);
assertFalse(importer.handlePropInfo(tree, mock(PropInfo.class), mock(PropertyDefinition.class)));
}
@Test
public void testHandlePropInfoWrongTreeNt() throws Exception {
init(true, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW);
// wrong nt name
Tree tree = mockTree(REP_PRINCIPAL_POLICY, AccessControlConstants.NT_REP_ACL, true);
assertFalse(importer.handlePropInfo(tree, mock(PropInfo.class), mock(PropertyDefinition.class)));
}
@Test
public void testHandlePropInfoInvalidPropInfoName() throws Exception {
init(true, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW);
Tree tree = mockTree(REP_PRINCIPAL_POLICY, NT_REP_PRINCIPAL_POLICY, true);
assertFalse(importer.handlePropInfo(tree, mockPropInfo("wrongName"), mock(PropertyDefinition.class)));
}
@Test
public void testHandlePropInfoNullPropInfoName() throws Exception {
init(false, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING);
Tree tree = mockTree(REP_PRINCIPAL_POLICY, NT_REP_PRINCIPAL_POLICY, true);
assertFalse(importer.handlePropInfo(tree, mock(PropInfo.class), mock(PropertyDefinition.class)));
}
@Test
public void testHandlePropInfoOakPropInfoName() throws Exception {
init(false, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING);
Tree tree = mockTree(REP_PRINCIPAL_POLICY, NT_REP_PRINCIPAL_POLICY, true);
PropInfo propInfo = mockPropInfo(REP_PRINCIPAL_NAME);
assertFalse(importer.handlePropInfo(tree, propInfo, mock(PropertyDefinition.class)));
}
@Test
public void testHandlePropInfoDefinitionMultiple() throws Exception {
init(false, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING);
Tree tree = mockTree(REP_PRINCIPAL_POLICY, NT_REP_PRINCIPAL_POLICY, true);
PropInfo propInfo = mockPropInfo(getJcrName(REP_PRINCIPAL_NAME));
PropertyDefinition def = when(mock(PropertyDefinition.class).isMultiple()).thenReturn(true).getMock();
assertFalse(importer.handlePropInfo(tree, propInfo, def));
}
@Test
public void testHandlePropInfoInvalidDeclaringNtName() throws Exception {
init(false, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING);
Tree tree = mockTree(REP_PRINCIPAL_POLICY, NT_REP_PRINCIPAL_POLICY, true);
PropInfo propInfo = mockPropInfo(getJcrName(REP_PRINCIPAL_NAME));
PropertyDefinition def = mockPropertyDefinition("wrongDeclaringNtName");
assertFalse(importer.handlePropInfo(tree, propInfo, def));
}
@Test
public void testHandlePropInfoOakDeclaringNtName() throws Exception {
init(false, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING);
Tree tree = mockTree(REP_PRINCIPAL_POLICY, NT_REP_PRINCIPAL_POLICY, true);
PropInfo propInfo = mockPropInfo(getJcrName(REP_PRINCIPAL_NAME));
PropertyDefinition def = mockPropertyDefinition(NT_REP_PRINCIPAL_POLICY);
assertFalse(importer.handlePropInfo(tree, propInfo, def));
}
@Test
public void testHandlePropInfoUnsupportedPath() throws Exception {
init(false, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING);
Tree tree = mockTree(REP_PRINCIPAL_POLICY, NT_REP_PRINCIPAL_POLICY, "/some/unsupported/path");
PropInfo propInfo = mockPropInfo(getJcrName(REP_PRINCIPAL_NAME));
PropertyDefinition def = mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY));
assertFalse(importer.handlePropInfo(tree, propInfo, def));
}
@Test(expected = ConstraintViolationException.class)
public void testHandlePropInfoPrincipalNameMismatch() throws Exception {
init(true, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
importer.handlePropInfo(createPolicyTree(getTestSystemUser()), mockPropInfo(new PrincipalImpl("mismatch")), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY)));
}
@Test
public void testHandlePropInfoPrincipalNotHandled() throws Exception {
init(false, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING);
User testUser = getTestUser();
String wrongUserPath = PathUtils.concat(SUPPORTED_PATH , "testUser");
Tree tree = mockTree(REP_PRINCIPAL_POLICY, NT_REP_PRINCIPAL_POLICY, PathUtils.concat(wrongUserPath, REP_PRINCIPAL_POLICY));
assertFalse(importer.handlePropInfo(tree, mockPropInfo(testUser.getPrincipal()), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY))));
}
@Test
public void testHandlePropInfoPrincipalByNameReturnsNull() throws Exception {
init(false, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW);
String oakPath = PathUtils.concat(SUPPORTED_PATH, "unknownSystemUser", REP_PRINCIPAL_POLICY);
Tree tree = mockTree(REP_PRINCIPAL_POLICY, NT_REP_PRINCIPAL_POLICY, oakPath);
assertFalse(importer.handlePropInfo(tree, mockPropInfo(new PrincipalImpl("notFound")), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY))));
}
@Test
public void testHandlePropInfoValidPrincipal() throws Exception {
init(true, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING);
User user = getTestSystemUser();
assertTrue(importer.handlePropInfo(createPolicyTree(user), mockPropInfo(user.getPrincipal()), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY))));
}
@Test(expected = IllegalStateException.class)
public void testPropertiesCompletedNotInitialized() throws Exception {
importer.propertiesCompleted(mock(Tree.class));
}
@Test
public void testPropertiesCompletedNoPolicy() throws Exception {
init(false, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
importer.propertiesCompleted(mock(Tree.class));
assertFalse(root.hasPendingChanges());
}
@Test
public void testPropertiesCompletedWrongTree() throws Exception {
init(true, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
User user = getTestSystemUser();
importer.handlePropInfo(createPolicyTree(user), mockPropInfo(user.getPrincipal()), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY)));
importer.propertiesCompleted(mockTree("/another/path", true));
assertEquals(0, getAccessControlManager(root).getPolicies(user.getPrincipal()).length);
assertFalse(root.getTree(getNamePathMapper().getOakPath(user.getPath())).hasChild(REP_PRINCIPAL_POLICY));
}
@Test
public void testPropertiesCompletedSetsPolicy() throws Exception {
init(true, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW);
User user = getTestSystemUser();
Tree policyTree = createPolicyTree(user);
String oakPath = policyTree.getPath();
importer.handlePropInfo(policyTree, mockPropInfo(user.getPrincipal()), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY)));
importer.propertiesCompleted(policyTree);
assertTrue(root.getTree(oakPath).hasProperty(REP_PRINCIPAL_NAME));
assertPolicy(getAccessControlManager(root).getPolicies(user.getPrincipal()), 0);
}
@Test(expected = IllegalStateException.class)
public void testStartNotInitialized() {
importer.start(mock(Tree.class));
}
@Test
public void testStartWithoutPolicy() {
init(true, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW);
assertFalse(importer.start(mock(Tree.class)));
}
@Test
public void testStartWithPolicyAndValidTree() throws Exception {
init(false, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING);
User user = getTestSystemUser();
Tree policyTree = createPolicyTree(user);
importer.handlePropInfo(policyTree, mockPropInfo(user.getPrincipal()), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY)));
importer.propertiesCompleted(policyTree);
assertTrue(importer.start(policyTree));
}
@Test
public void testStartInvalidTree() throws Exception {
init(true, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW);
User user = getTestSystemUser();
Tree policyTree = createPolicyTree(user);
importer.handlePropInfo(policyTree, mockPropInfo(user.getPrincipal()), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY)));
importer.propertiesCompleted(policyTree);
assertFalse(importer.start(mockTree("/another/path", true)));
}
@Test(expected = IllegalStateException.class)
public void testEndWithoutPolicy() throws Exception {
importer.end(mock(Tree.class));
}
@Test
public void testEndWithInvalidTree() throws Exception {
init(true, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
User user = getTestSystemUser();
Tree policyTree = createPolicyTree(user);
importer.handlePropInfo(policyTree, mockPropInfo(user.getPrincipal()), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY)));
importer.propertiesCompleted(policyTree);
importer.end(mockTree("/another/path", true));
// end-call must have removed the policy due to the mismatch
assertFalse(root.getTree(policyTree.getPath()).exists());
}
@Test
public void testEndWithPolicyAndValidTree() throws Exception {
init(true, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
User user = getTestSystemUser();
Tree policyTree = createPolicyTree(user);
importer.handlePropInfo(policyTree, mockPropInfo(user.getPrincipal()), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY)));
importer.propertiesCompleted(policyTree);
importer.end(policyTree);
policyTree = root.getTree(policyTree.getPath());
assertTrue(policyTree.exists());
assertTrue(policyTree.hasProperty(REP_PRINCIPAL_NAME));
assertTrue(Iterables.isEmpty(policyTree.getChildren()));
}
@Test(expected = IllegalStateException.class)
public void testStartChildInfoWithoutPolicy() throws Exception {
importer.startChildInfo(mock(NodeInfo.class), mock(List.class));
}
@Test(expected = ConstraintViolationException.class)
public void testStartChildInfoInvalidPrimaryType() throws Exception {
init(true, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
User user = getTestSystemUser();
Tree policyTree = createPolicyTree(user);
importer.handlePropInfo(policyTree, mockPropInfo(user.getPrincipal()), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY)));
importer.startChildInfo(mockNodeInfo("invalidACE", getJcrName(AccessControlConstants.NT_REP_GRANT_ACE)), mock(List.class));
}
@Test(expected = ConstraintViolationException.class)
public void testStartChildInfoOakPrimaryType() throws Exception {
init(true, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW);
User user = getTestSystemUser();
Tree policyTree = createPolicyTree(user);
importer.handlePropInfo(policyTree, mockPropInfo(user.getPrincipal()), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY)));
importer.startChildInfo(mockNodeInfo("oakName", NT_REP_PRINCIPAL_ENTRY), mock(List.class));
}
@Test(expected = ConstraintViolationException.class)
public void testStartChildInfoNestedEntry() throws Exception {
init(true, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
User user = getTestSystemUser();
Tree policyTree = createPolicyTree(user);
importer.handlePropInfo(policyTree, mockPropInfo(user.getPrincipal()), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY)));
importer.startChildInfo(mockNodeInfo("entry", getJcrName(NT_REP_PRINCIPAL_ENTRY)), mockPropInfos("/anyPath", PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
importer.startChildInfo(mockNodeInfo("anotherEntry", getJcrName(NT_REP_PRINCIPAL_ENTRY)), mockPropInfos("/anyPath", PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
}
@Test(expected = ConstraintViolationException.class)
public void testStartChildInfoMissingPrivileges() throws Exception {
init(false, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
User user = getTestSystemUser();
Tree policyTree = createPolicyTree(user);
importer.handlePropInfo(policyTree, mockPropInfo(user.getPrincipal()), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY)));
importer.startChildInfo(mockNodeInfo("entry", getJcrName(NT_REP_PRINCIPAL_ENTRY)), mockPropInfos("/effective/path"));
}
@Test(expected = ConstraintViolationException.class)
public void testStartChildInfoRestrictionNotNestedInEntry() throws Exception {
init(false, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
User user = getTestSystemUser();
Tree policyTree = createPolicyTree(user);
importer.handlePropInfo(policyTree, mockPropInfo(user.getPrincipal()), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY)));
importer.startChildInfo(mockNodeInfo(getJcrName(REP_RESTRICTIONS), getJcrName(NT_REP_RESTRICTIONS)), mock(List.class));
}
@Test(expected = ConstraintViolationException.class)
public void testStartChildInfoUnsupportedProperty() throws Exception {
init(true, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING);
User user = getTestSystemUser();
Tree policyTree = createPolicyTree(user);
importer.handlePropInfo(policyTree, mockPropInfo(user.getPrincipal()), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY)));
List<PropInfo> propInfos = mockPropInfos("/effective/path", PrivilegeConstants.JCR_REMOVE_CHILD_NODES);
propInfos.add(mockPropInfo("unsupportedProperty"));
importer.startChildInfo(mockNodeInfo("entry", getJcrName(NT_REP_PRINCIPAL_ENTRY)), propInfos);
}
@Test(expected = ConstraintViolationException.class)
public void testStartChildInfoWrongEffectivePathPropertyType() throws Exception {
init(true, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING);
User user = getTestSystemUser();
Tree policyTree = createPolicyTree(user);
importer.handlePropInfo(policyTree, mockPropInfo(user.getPrincipal()), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY)));
List<PropInfo> propInfos = mockPropInfos(null, PrivilegeConstants.JCR_REMOVE_CHILD_NODES);
// effective path with wrong type
TextValue tx = when(mock(TextValue.class).getString()).thenReturn("/effective/path").getMock();
PropInfo propInfo = mockPropInfo(getJcrName(REP_EFFECTIVE_PATH));
when(propInfo.getTextValue()).thenReturn(tx);
when(propInfo.getType()).thenReturn(PropertyType.STRING);
propInfos.add(propInfo);
importer.startChildInfo(mockNodeInfo("entry", getJcrName(NT_REP_PRINCIPAL_ENTRY)), propInfos);
}
@Test(expected = ConstraintViolationException.class)
public void testStartChildInfoWrongPrivilegesPropertyType() throws Exception {
init(true, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING);
User user = getTestSystemUser();
Tree policyTree = createPolicyTree(user);
importer.handlePropInfo(policyTree, mockPropInfo(user.getPrincipal()), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY)));
List<PropInfo> propInfos = mockPropInfos("/effective/path");
// rep:privileges with wrong type
PropInfo propInfo = mockPropInfo(getJcrName(REP_PRIVILEGES));
TextValue tx = when(mock(TextValue.class).getString()).thenReturn(getJcrName(JCR_READ)).getMock();
List values = ImmutableList.of(tx);
when(propInfo.getTextValues()).thenReturn(values);
when(propInfo.getType()).thenReturn(PropertyType.STRING);
propInfos.add(propInfo);
importer.startChildInfo(mockNodeInfo("entry", getJcrName(NT_REP_PRINCIPAL_ENTRY)), propInfos);
}
@Test(expected = IllegalStateException.class)
public void testStartChildInfoNestedRestriction() throws Exception {
init(false, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
User user = getTestSystemUser();
Tree policyTree = createPolicyTree(user);
importer.handlePropInfo(policyTree, mockPropInfo(user.getPrincipal()), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY)));
importer.startChildInfo(mockNodeInfo("entry", getJcrName(NT_REP_PRINCIPAL_ENTRY)), mockPropInfos("/effective/path", PrivilegeConstants.REP_WRITE));
importer.startChildInfo(mockNodeInfo(getJcrName(REP_RESTRICTIONS), getJcrName(NT_REP_RESTRICTIONS)), mockPropInfos(ImmutableMap.of(getJcrName(REP_GLOB), "/some/glob"), PropertyType.STRING));
importer.startChildInfo(mockNodeInfo(getJcrName(REP_RESTRICTIONS), getJcrName(NT_REP_RESTRICTIONS)), mockPropInfos(ImmutableMap.of()));
}
@Test(expected = IllegalStateException.class)
public void testStartChildInfoNestedMvRestriction() throws Exception {
init(false, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
User user = getTestSystemUser();
Tree policyTree = createPolicyTree(user);
importer.handlePropInfo(policyTree, mockPropInfo(user.getPrincipal()), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY)));
importer.startChildInfo(mockNodeInfo("entry", getJcrName(NT_REP_PRINCIPAL_ENTRY)), mockPropInfos("/effective/path", PrivilegeConstants.REP_WRITE));
importer.startChildInfo(mockNodeInfo(getJcrName(REP_RESTRICTIONS), getJcrName(NT_REP_RESTRICTIONS)), mockPropInfos(ImmutableMap.of(getJcrName(REP_NT_NAMES), new Value[0])));
importer.startChildInfo(mockNodeInfo(getJcrName(REP_RESTRICTIONS), getJcrName(NT_REP_RESTRICTIONS)), mockPropInfos(ImmutableMap.of()));
}
@Test(expected = IllegalStateException.class)
public void testStartChildInfoRepNodeRestrictionOverwritesEffectivePath() throws Exception {
init(false, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
User user = getTestSystemUser();
Tree policyTree = createPolicyTree(user);
importer.handlePropInfo(policyTree, mockPropInfo(user.getPrincipal()), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY)));
importer.startChildInfo(mockNodeInfo("entry", getJcrName(NT_REP_PRINCIPAL_ENTRY)), mockPropInfos("/effective/path", PrivilegeConstants.REP_READ_PROPERTIES));
importer.startChildInfo(mockNodeInfo(getJcrName(REP_RESTRICTIONS), getJcrName(NT_REP_RESTRICTIONS)), mockPropInfos(ImmutableMap.of(
getJcrName(REP_NODE_PATH), "/effective/path"), PropertyType.STRING));
}
@Test
public void testStartChildInfoRepNodeRestriction() throws Exception {
init(true, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW);
User user = getTestSystemUser();
Tree policyTree = createPolicyTree(user);
importer.handlePropInfo(policyTree, mockPropInfo(user.getPrincipal()), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY)));
importer.start(policyTree);
importer.startChildInfo(mockNodeInfo("entry", getJcrName(NT_REP_PRINCIPAL_ENTRY)), mockPropInfos(null, PrivilegeConstants.REP_READ_PROPERTIES));
importer.startChildInfo(mockNodeInfo(getJcrName(REP_RESTRICTIONS), getJcrName(NT_REP_RESTRICTIONS)), mockPropInfos(ImmutableMap.of(
getJcrName(REP_NODE_PATH), "/effective/path"), PropertyType.STRING));
importer.endChildInfo();
importer.endChildInfo();
importer.end(policyTree);
PrincipalPolicyImpl.EntryImpl entry = assertPolicy(getAccessControlManager(root).getPolicies(user.getPrincipal()), 1);
assertEquals("/effective/path", entry.getEffectivePath());
}
@Test
public void testStartChildInfoMvRestrictions() throws Exception {
init(false, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
User user = getTestSystemUser();
Tree policyTree = createPolicyTree(user);
importer.handlePropInfo(policyTree, mockPropInfo(user.getPrincipal()), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY)));
importer.start(policyTree);
importer.startChildInfo(mockNodeInfo("entry", getJcrName(NT_REP_PRINCIPAL_ENTRY)), mockPropInfos("/effective/path", PrivilegeConstants.REP_WRITE));
ValueFactory vf = getValueFactory(root);
Value[] nameValues = new Value[] {vf.createValue(getJcrName("jcr:content"), PropertyType.NAME), vf.createValue(getJcrName("jcr:data"), PropertyType.NAME)};
importer.startChildInfo(mockNodeInfo(getJcrName(REP_RESTRICTIONS), getJcrName(NT_REP_RESTRICTIONS)), mockPropInfos(ImmutableMap.of(
getJcrName(REP_ITEM_NAMES), nameValues,
getJcrName(REP_GLOB), new Value[] {vf.createValue("/some/*/globbing")})
));
importer.endChildInfo();
importer.endChildInfo();
importer.end(policyTree);
PrincipalPolicyImpl.EntryImpl entry = assertPolicy(getAccessControlManager(root).getPolicies(user.getPrincipal()), 1);
assertNotNull(entry.getRestrictions(getJcrName(REP_ITEM_NAMES)));
assertNotNull(entry.getRestriction(getJcrName(REP_GLOB)));
}
@Test(expected = AccessControlException.class)
public void testStartChildInfoUnsupportedRestrictions() throws Exception {
init(false, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
User user = getTestSystemUser();
Tree policyTree = createPolicyTree(user);
importer.handlePropInfo(policyTree, mockPropInfo(user.getPrincipal()), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY)));
importer.start(policyTree);
importer.startChildInfo(mockNodeInfo("entry", getJcrName(NT_REP_PRINCIPAL_ENTRY)), mockPropInfos("/effective/path", PrivilegeConstants.REP_WRITE));
importer.startChildInfo(mockNodeInfo(getJcrName(REP_RESTRICTIONS), getJcrName(NT_REP_RESTRICTIONS)), mockPropInfos(ImmutableMap.of(
"unsupported", "x"), PropertyType.STRING));
// adding entry to policy must already throw the exception
importer.endChildInfo();
}
@Test(expected = IllegalStateException.class)
public void testEndChildInfoWithoutPolicyNorEntry() throws Exception {
importer.endChildInfo();
}
@Test(expected = ConstraintViolationException.class)
public void testEndChildInfoMissingEffectivePath() throws Exception {
init(false, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
User user = getTestSystemUser();
Tree policyTree = createPolicyTree(user);
importer.handlePropInfo(policyTree, mockPropInfo(user.getPrincipal()), mockPropertyDefinition(getJcrName(NT_REP_PRINCIPAL_POLICY)));
importer.startChildInfo(mockNodeInfo("entry", getJcrName(NT_REP_PRINCIPAL_ENTRY)), mockPropInfos(null, JCR_READ));
importer.endChildInfo();
}
}