blob: 1c86c6437d4fe75a1420b6955965f0bf6b10153c [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.jcr.security.authorization;
import javax.jcr.AccessDeniedException;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.security.Privilege;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
import org.junit.Before;
import org.junit.Test;
/**
* Permission evaluation tests for move operations.
*/
public abstract class AbstractMoveTest extends AbstractEvaluationTest {
protected String nodePath3;
protected String destPath;
protected String siblingDestPath;
protected Privilege[] modifyChildCollection;
@Override
@Before
protected void setUp() throws Exception {
super.setUp();
Node node3 = superuser.getNode(childNPath).addNode(nodeName3);
node3.setProperty("movedProp", "val");
nodePath3 = node3.getPath();
superuser.save();
testSession.refresh(false);
destPath = path + "/destination";
siblingDestPath = siblingPath + "/destination";
modifyChildCollection = privilegesFromNames(new String[] {
Privilege.JCR_ADD_CHILD_NODES,
Privilege.JCR_REMOVE_CHILD_NODES});
}
abstract protected void move(String source, String dest) throws RepositoryException;
abstract protected void move(String source, String dest, Session session) throws RepositoryException;
@Test
public void testMove() throws Exception {
// give 'add_child_nodes' and 'nt-management' privilege
// -> not sufficient privileges for a move
allow(path, privilegesFromNames(new String[] {
Privilege.JCR_ADD_CHILD_NODES,
Privilege.JCR_NODE_TYPE_MANAGEMENT}));
try {
move(childNPath, destPath);
fail("Move requires addChildNodes and removeChildNodes privilege.");
} catch (AccessDeniedException e) {
// success.
}
}
@Test
public void testMove2() throws Exception {
// grant 'add_child_nodes', 'remove_child_nodes' at 'path'
// -> not sufficient for a move since 'remove_node' privilege is missing
// on the move-target
allow(path, modifyChildCollection);
try {
move(childNPath, destPath);
fail("Move requires addChildNodes and removeChildNodes privilege.");
} catch (AccessDeniedException e) {
// success.
}
}
@Test
public void testMove2b() throws Exception {
// grant 'add_child_nodes', 'remove_child_nodes' and 'nt_mgt' at 'path'
// -> not sufficient for a move since 'remove_node' privilege is missing
// on the move-target
allow(path, privilegesFromNames(new String[] {
Privilege.JCR_ADD_CHILD_NODES,
Privilege.JCR_REMOVE_CHILD_NODES,
Privilege.JCR_NODE_TYPE_MANAGEMENT}));
try {
move(childNPath, destPath);
fail("Move requires addChildNodes and removeChildNodes privilege.");
} catch (AccessDeniedException e) {
// success.
}
}
@Test
public void testMove3() throws Exception {
allow(path, privilegesFromNames(new String[] {
Privilege.JCR_ADD_CHILD_NODES,
Privilege.JCR_REMOVE_CHILD_NODES,
Privilege.JCR_NODE_TYPE_MANAGEMENT}));
// allow 'remove_node' at childNPath
// -> now move must succeed
allow(childNPath, privilegesFromName(Privilege.JCR_REMOVE_NODE));
move(childNPath, destPath);
}
@Test
public void testMove4() throws Exception {
allow(path, privilegesFromName(PrivilegeConstants.REP_WRITE));
move(childNPath, destPath);
// withdraw 'add_child_nodes' privilege on former src-parent
// -> moving child-node back must fail
deny(path, privilegesFromName(Privilege.JCR_ADD_CHILD_NODES));
try {
move(destPath, childNPath);
fail("Move requires addChildNodes and removeChildNodes privilege.");
} catch (AccessDeniedException e) {
// success.
}
}
@Test
public void testMissingJcrAddChildNodesAtDestParent() throws Exception {
allow(path, privilegesFromNames(new String[] {
Privilege.JCR_ADD_CHILD_NODES,
Privilege.JCR_REMOVE_CHILD_NODES}));
try {
move(childNPath, siblingDestPath);
fail("Move requires addChildNodes privilege at dest parent");
} catch (AccessDeniedException e) {
// success.
}
}
@Test
public void testDifferentDestParent() throws Exception {
allow(path, privilegesFromName(Privilege.JCR_REMOVE_CHILD_NODES));
allow(siblingPath, privilegesFromNames(new String[] {
Privilege.JCR_ADD_CHILD_NODES, Privilege.JCR_NODE_TYPE_MANAGEMENT
}));
allow(childNPath, privilegesFromName(Privilege.JCR_REMOVE_NODE));
move(childNPath, siblingDestPath);
}
@Test
public void testMoveAccessControlledNode() throws Exception {
// permissions defined @ childNode
// -> revoke read permission
deny(childNPath, readPrivileges);
assertFalse(testSession.nodeExists(childNPath));
assertHasPrivileges(childNPath, readPrivileges, false);
assertFalse(testSession.nodeExists(nodePath3));
assertHasPrivileges(nodePath3, readPrivileges, false);
// move the ancestor node
String movedChildNPath = path + "/movedNode";
String movedNode3Path = movedChildNPath + '/' + nodeName3;
move(childNPath, movedChildNPath, superuser);
// expected behavior:
// the AC-content present on childNode is still enforced both on
// the node itself and on the subtree.
assertFalse(testSession.nodeExists(movedChildNPath));
assertHasPrivileges(movedChildNPath, readPrivileges, false);
assertFalse(testSession.nodeExists(movedNode3Path));
assertHasPrivileges(movedNode3Path, readPrivileges, false);
}
@Test
public void testMoveAccessControlledNodeInSubtree() throws Exception {
// permissions defined @ node3Path
// -> revoke read permission
deny(nodePath3, readPrivileges);
assertFalse(testSession.nodeExists(nodePath3));
assertHasPrivileges(nodePath3, readPrivileges, false);
// move the ancestor node
String movedChildNPath = path + "/movedNode";
String movedNode3Path = movedChildNPath + '/' + nodeName3;
move(childNPath, movedChildNPath, superuser);
// expected behavior:
// the AC-content present on node3 is still enforced
assertFalse(testSession.nodeExists(movedNode3Path));
assertHasPrivileges(movedNode3Path, readPrivileges, false);
}
@Test
public void testMoveWithDifferentEffectiveAc() throws Exception {
// @path read is denied, @childNode its allowed again
deny(path, readPrivileges);
allow(childNPath, readPrivileges);
assertTrue(testSession.nodeExists(nodePath3));
assertTrue(testAcMgr.hasPrivileges(nodePath3, readPrivileges));
// move the ancestor node
String movedPath = path + "/movedNode";
move(nodePath3, movedPath, superuser);
// expected behavior:
// due to move node3 should not e visible any more
assertFalse(testSession.nodeExists(movedPath));
assertHasPrivileges(movedPath, readPrivileges, false);
}
@Test
public void testMoveNodeWithGlobRestriction() throws Exception {
// permissions defined @ path
// restriction: remove read priv to nodeName3 node
deny(childNPath, readPrivileges, createGlobRestriction('/' +nodeName3));
assertFalse(testSession.nodeExists(nodePath3));
assertHasPrivileges(nodePath3, readPrivileges, false);
String movedChildNPath = path + "/movedNode";
String movedNode3Path = movedChildNPath + '/' + nodeName3;
move(childNPath, movedChildNPath, superuser);
assertFalse(testSession.nodeExists(movedNode3Path));
assertHasPrivileges(movedNode3Path, readPrivileges, false);
}
@Test
public void testMoveNodeWithGlobRestriction2() throws Exception {
// permissions defined @ path
// restriction: remove read priv to nodeName3 node
deny(childNPath, readPrivileges, createGlobRestriction('/' + nodeName3));
assertHasPrivileges(nodePath3, readPrivileges, false);
String movedChildNPath = path + "/movedNode";
String movedNode3Path = movedChildNPath + '/' + nodeName3;
move(childNPath, movedChildNPath, superuser);
assertFalse(testSession.nodeExists(movedNode3Path));
assertHasPrivileges(movedNode3Path, readPrivileges, false);
}
}