/* * 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 javax.jcr.security.Privilege; import org.apache.jackrabbit.test.NotExecutableException; import javax.jcr.AccessDeniedException; import javax.jcr.Node; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.lock.Lock; import javax.jcr.lock.LockManager; /** <code>AbstractVersionAccessTest</code>... */ public abstract class AbstractLockManagementTest extends AbstractEvaluationTest { private Node createLockableNode(Node parent) throws RepositoryException, NotExecutableException { Node n = parent.addNode(nodeName1); if (!n.isNodeType(mixLockable)) { if (n.canAddMixin(mixLockable)) { n.addMixin(mixLockable); } else { throw new NotExecutableException(); } parent.save(); } return n; } private Node createLockedNode(Node parent) throws RepositoryException, NotExecutableException { Node n = createLockableNode(parent); // create a deep, session scoped lock n.lock(true, true); return n; } public void testReadLockContent() throws RepositoryException, NotExecutableException { Node n = createLockedNode(testRootNode); Node childN = n.addNode(nodeName2); modifyPrivileges(n.getPath(), Privilege.JCR_READ, false); modifyPrivileges(childN.getPath(), Privilege.JCR_READ, true); Node childN2 = (Node) getTestSession().getItem(childN.getPath()); try { childN2.getLock(); fail("TestUser doesn't have permission to read the jcr:lockIsDeep property."); } catch (AccessDeniedException e) { // success } } public void testLock2() throws RepositoryException, NotExecutableException { Node n = createLockableNode(testRootNode); modifyPrivileges(n.getPath(), PrivilegeRegistry.REP_WRITE, false); modifyPrivileges(n.getPath(), Privilege.JCR_LOCK_MANAGEMENT, true); Node n2 = getTestNode().getNode(nodeName1); // all lock operations must succeed Lock l = n2.lock(true, true); l.refresh(); n2.unlock(); } public void testLock3() throws RepositoryException, NotExecutableException { Node n = createLockableNode(testRootNode); Node trn = getTestNode(); modifyPrivileges(trn.getPath(), Privilege.JCR_READ, true); modifyPrivileges(trn.getPath(), PrivilegeRegistry.REP_WRITE, true); modifyPrivileges(trn.getPath(), Privilege.JCR_LOCK_MANAGEMENT, true); Node n2 = trn.getNode(n.getName()); n2.lock(true, true); Lock l = n2.getLock(); // withdraw lock-mgmt -> must not be able to refresh the lock or // unlock the node modifyPrivileges(trn.getPath(), Privilege.JCR_LOCK_MANAGEMENT, false); try { l.refresh(); fail("TestUser doesn't have permission to refresh the lock."); } catch (AccessDeniedException e) { // success } try { n2.unlock(); fail("TestUser doesn't have permission to unlock the node."); } catch (AccessDeniedException e) { // success } // make sure the lock can be removed upon session.logout. modifyPrivileges(trn.getPath(), Privilege.JCR_LOCK_MANAGEMENT, true); } public void testLock4() throws RepositoryException, NotExecutableException { Node n = createLockableNode(testRootNode); Node trn = getTestNode(); modifyPrivileges(trn.getPath(), Privilege.JCR_READ, true); modifyPrivileges(trn.getPath(), PrivilegeRegistry.REP_WRITE, true); modifyPrivileges(trn.getPath(), Privilege.JCR_LOCK_MANAGEMENT, true); Node n2 = trn.getNode(n.getName()); n2.lock(true, true); Lock l = n2.getLock(); String lt = l.getLockToken(); // withdraw lock-mgmt -> logout of session must still remove the lock modifyPrivileges(trn.getPath(), Privilege.JCR_LOCK_MANAGEMENT, false); getTestSession().logout(); boolean isLocked = n.isLocked(); assertFalse(isLocked); } public void testLockBreaking() throws RepositoryException, NotExecutableException { String locktoken = null; LockManager sulm = superuser.getWorkspace().getLockManager(); String lockedpath = null; try { Node trn = getTestNode(); modifyPrivileges(trn.getPath(), Privilege.JCR_READ, true); modifyPrivileges(trn.getPath(), PrivilegeRegistry.REP_WRITE, true); modifyPrivileges(trn.getPath(), Privilege.JCR_LOCK_MANAGEMENT, true); Session lockingSession = trn.getSession(); assertFalse("super user and test user should have different user ids: " + lockingSession.getUserID() + " vs " + superuser.getUserID(), lockingSession.getUserID().equals(superuser.getUserID())); trn.addNode("locktest", "nt:unstructured"); trn.addMixin("mix:lockable"); lockingSession.save(); // let the "other" user lock the node LockManager oulm = lockingSession.getWorkspace().getLockManager(); Lock l = oulm.lock(trn.getPath(), true, false, Long.MAX_VALUE, null); lockedpath = trn.getPath(); locktoken = l.getLockToken(); lockingSession.logout(); // transfer the lock token to the super user and try the unlock Node lockednode = superuser.getNode(lockedpath); assertTrue(lockednode.isLocked()); Lock sl = sulm.getLock(lockedpath); assertNotNull(sl.getLockToken()); sulm.addLockToken(sl.getLockToken()); sulm.unlock(lockedpath); locktoken = null; } finally { if (locktoken != null && lockedpath != null) { sulm.addLockToken(locktoken); sulm.unlock(lockedpath); } } } }