/*
* 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.core.security.authorization;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
import org.apache.jackrabbit.test.NotExecutableException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jcr.AccessDeniedException;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.security.AccessControlEntry;
import javax.jcr.security.Privilege;
import javax.jcr.version.Version;
/** <code>AbstractVersionAccessTest</code>... */
public abstract class AbstractVersionManagementTest extends AbstractEvaluationTest {
private static Logger log = LoggerFactory.getLogger(AbstractVersionManagementTest.class);
protected Node createVersionableNode(Node parent) throws RepositoryException, NotExecutableException {
Node n = parent.addNode(nodeName1);
if (n.canAddMixin(mixVersionable)) {
n.addMixin(mixVersionable);
} else {
throw new NotExecutableException();
}
parent.save();
return n;
}
public void testAddMixVersionable() throws RepositoryException, NotExecutableException {
Node trn = getTestNode();
modifyPrivileges(trn.getPath(), PrivilegeRegistry.REP_WRITE, true);
modifyPrivileges(trn.getPath(), Privilege.JCR_VERSION_MANAGEMENT, false);
Node n = trn.addNode(nodeName1);
try {
if (n.canAddMixin(mixVersionable)) {
n.addMixin(mixVersionable);
} else {
throw new NotExecutableException();
}
trn.save();
fail("Test session does not have write permission in the version storage -> adding mixin must fail.");
} catch (AccessDeniedException e) {
// success
log.debug(e.getMessage());
// ... but autocreated versionable node properties must not be present
assertFalse(n.isNodeType(mixVersionable));
assertFalse(n.hasProperty("jcr:isCheckedOut"));
assertFalse(n.hasProperty(jcrVersionHistory));
}
}
public void testAddMixVersionable2() throws RepositoryException, NotExecutableException {
Node trn = getTestNode();
modifyPrivileges(trn.getPath(), PrivilegeRegistry.REP_WRITE, true);
modifyPrivileges(trn.getPath(), Privilege.JCR_NODE_TYPE_MANAGEMENT, true);
modifyPrivileges(trn.getPath(), Privilege.JCR_VERSION_MANAGEMENT, true);
Node n = createVersionableNode(trn);
n.checkin();
n.checkout();
}
public void testWriteVersionStore() throws RepositoryException, NotExecutableException {
Node trn = getTestNode();
modifyPrivileges(trn.getPath(), PrivilegeRegistry.REP_WRITE, true);
modifyPrivileges(trn.getPath(), Privilege.JCR_VERSION_MANAGEMENT, false);
Node n = createVersionableNode(testRootNode);
try {
Node n2 = trn.getNode(nodeName1);
n2.checkin();
fail("No write permission in the version storage.");
} catch (AccessDeniedException e) {
// success
log.debug(e.getMessage());
// ... but the property must not be modified nor indicating
// checkedIn status
Property p = n.getProperty("jcr:isCheckedOut");
assertFalse(p.isModified());
assertTrue(n.getProperty("jcr:isCheckedOut").getValue().getBoolean());
}
}
public void testRemoveVersion() throws RepositoryException, NotExecutableException {
Node trn = getTestNode();
Node n = createVersionableNode(testRootNode);
modifyPrivileges(trn.getPath(), Privilege.JCR_VERSION_MANAGEMENT, true);
// test session should now be able to create versionable nodes, checkout
// and checkin them, read the version/v-histories.
Node testNode = trn.getNode(nodeName1);
Version v = testNode.checkin();
testNode.checkout();
testNode.checkin();
// remove ability to edit version information
// -> VersionHistory.removeVersion must not be allowed.
modifyPrivileges(trn.getPath(), Privilege.JCR_VERSION_MANAGEMENT, false);
try {
testNode.getVersionHistory().removeVersion(v.getName());
fail("TestSession without remove privilege on the v-storage must not be able to remove a version.");
} catch (AccessDeniedException e) {
// success
log.debug(e.getMessage());
}
}
public void testRemoveVersion2() throws RepositoryException, NotExecutableException {
Node trn = getTestNode();
Node n = createVersionableNode(testRootNode);
modifyPrivileges(trn.getPath(), Privilege.JCR_VERSION_MANAGEMENT, true);
Node testNode = trn.getNode(nodeName1);
Version v = testNode.checkin();
testNode.checkout();
testNode.checkin();
// -> VersionHistory.removeVersion must not be allowed.
try {
testNode.getVersionHistory().removeVersion(v.getName());
fail("TestSession without remove privilege on the v-storage must not be able to remove a version.");
} catch (AccessDeniedException e) {
// success
log.debug(e.getMessage());
}
}
public void testRemoveVersion3() throws RepositoryException, NotExecutableException {
Node trn = getTestNode();
Node n = createVersionableNode(testRootNode);
String path = getTestSession().getRootNode().getPath();
JackrabbitAccessControlList tmpl = getPolicy(acMgr, path, testUser.getPrincipal());
AccessControlEntry entry;
try {
// NOTE: don't use 'modifyPrivileges' in order not to have the
// root-policy cleared on tear-down.
tmpl.addEntry(testUser.getPrincipal(), privilegesFromName(Privilege.JCR_VERSION_MANAGEMENT), true, getRestrictions(superuser, path));
acMgr.setPolicy(tmpl.getPath(), tmpl);
superuser.save();
Node testNode = trn.getNode(nodeName1);
Version v = testNode.checkin();
testNode.checkout();
testNode.checkin();
// -> VersionHistory.removeVersion must be allowed
testNode.getVersionHistory().removeVersion(v.getName());
} finally {
// revert privilege modification (manually remove the ACE added)
AccessControlEntry[] entries = tmpl.getAccessControlEntries();
for (AccessControlEntry entry1 : entries) {
if (entry1.getPrincipal().equals(testUser.getPrincipal())) {
tmpl.removeAccessControlEntry(entry1);
}
}
acMgr.setPolicy(tmpl.getPath(), tmpl);
superuser.save();
}
}
}