mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
91057: Merged V4.2-BUG-FIX (4.2.5) to HEAD-BUG-FIX (5.0/Cloud) 90986: MNT-11732: ephemeral locks have configurable threshold over which locks will be automatically made persistent instead. By setting the new property, administrators may control how ephemeral locks are created, for example: property alfresco.ephemeralLock.expiryThresh=30 This will mean that when a LockService client requests that an ephemeral lock is created with a timeout of greater than 30 seconds, the lock will be created as a persistent lock instead (the ephemeral lifetime request is vetoed). By setting this property to -1, ALL locks will be created as persistent locks (giving the old, pre-ephemeral locking behaviour). By leaving this at the default (48 hours) the newer locking behaviour is completely unaffected, e.g. ephemeral locks may be created with up to 48 hour expiry time and over this limit an exception is thrown (and the lock is not created). By setting the value to something in between these settings it is possible to have quite a nice balance of behaviour. Using the example of 30 seconds, as above, will mean that using Share's "Edit Online" to edit a document in MS Word will result in a persistent lock (as MS Word requests approx 1 hour for its locks). After Solr has performed its next incremental index, then the Word document may be seen in the "Document's I'm Editing" filter in Share, since this is a persistent (in-DB) lock. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@94765 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
1018 lines
43 KiB
Java
1018 lines
43 KiB
Java
/*
|
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
|
*
|
|
* This file is part of Alfresco
|
|
*
|
|
* Alfresco is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Alfresco is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
package org.alfresco.repo.lock;
|
|
|
|
import static org.junit.Assert.assertNotEquals;
|
|
|
|
import java.io.Serializable;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
import javax.transaction.NotSupportedException;
|
|
import javax.transaction.SystemException;
|
|
|
|
import org.alfresco.model.ContentModel;
|
|
import org.alfresco.repo.lock.mem.Lifetime;
|
|
import org.alfresco.repo.lock.mem.LockState;
|
|
import org.alfresco.repo.lock.mem.LockStore;
|
|
import org.alfresco.repo.search.IndexerAndSearcher;
|
|
import org.alfresco.repo.search.SearcherComponent;
|
|
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
|
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
|
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
|
|
import org.alfresco.service.cmr.lock.LockService;
|
|
import org.alfresco.service.cmr.lock.LockStatus;
|
|
import org.alfresco.service.cmr.lock.LockType;
|
|
import org.alfresco.service.cmr.lock.NodeLockedException;
|
|
import org.alfresco.service.cmr.lock.UnableToAquireLockException;
|
|
import org.alfresco.service.cmr.lock.UnableToReleaseLockException;
|
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
|
import org.alfresco.service.cmr.repository.NodeRef;
|
|
import org.alfresco.service.cmr.repository.NodeService;
|
|
import org.alfresco.service.cmr.repository.StoreRef;
|
|
import org.alfresco.service.cmr.search.ResultSet;
|
|
import org.alfresco.service.cmr.security.MutableAuthenticationService;
|
|
import org.alfresco.service.cmr.security.PermissionService;
|
|
import org.alfresco.service.namespace.QName;
|
|
import org.alfresco.test_category.BaseSpringTestsCategory;
|
|
import org.alfresco.test_category.OwnJVMTestsCategory;
|
|
import org.alfresco.util.BaseSpringTest;
|
|
import org.alfresco.util.TestWithUserUtils;
|
|
import org.junit.Test;
|
|
import org.junit.experimental.categories.Category;
|
|
|
|
/**
|
|
* Simple lock service test
|
|
*
|
|
* @author Roy Wetherall
|
|
*/
|
|
@Category(BaseSpringTestsCategory.class)
|
|
public class LockServiceImplTest extends BaseSpringTest
|
|
{
|
|
/**
|
|
* Services used in tests
|
|
*/
|
|
private NodeService nodeService;
|
|
private LockService lockService;
|
|
private MutableAuthenticationService authenticationService;
|
|
private CheckOutCheckInService cociService;
|
|
|
|
private PermissionService permissionService;
|
|
private LockService securedLockService;
|
|
/**
|
|
* Data used in tests
|
|
*/
|
|
private NodeRef parentNode;
|
|
private NodeRef childNode1;
|
|
private NodeRef childNode2;
|
|
private NodeRef noAspectNode;
|
|
private NodeRef checkedOutNode;
|
|
|
|
private static final String GOOD_USER_NAME = "goodUser";
|
|
private static final String BAD_USER_NAME = "badUser";
|
|
private static final String PWD = "password";
|
|
|
|
NodeRef rootNodeRef;
|
|
private StoreRef storeRef;
|
|
|
|
/**
|
|
* Called during the transaction setup
|
|
*/
|
|
protected void onSetUpInTransaction() throws Exception
|
|
{
|
|
this.nodeService = (NodeService)applicationContext.getBean("dbNodeService");
|
|
this.lockService = (LockService)applicationContext.getBean("lockService");
|
|
|
|
this.securedLockService = (LockService)applicationContext.getBean("LockService");
|
|
this.permissionService = (PermissionService)applicationContext.getBean("PermissionService");
|
|
|
|
this.authenticationService = (MutableAuthenticationService)applicationContext.getBean("authenticationService");
|
|
this.cociService = (CheckOutCheckInService) applicationContext.getBean("checkOutCheckInService");
|
|
|
|
// Set the authentication
|
|
AuthenticationComponent authComponent = (AuthenticationComponent)this.applicationContext.getBean("authenticationComponent");
|
|
authComponent.setSystemUserAsCurrentUser();
|
|
|
|
// Create the node properties
|
|
HashMap<QName, Serializable> nodeProperties = new HashMap<QName, Serializable>();
|
|
nodeProperties.put(QName.createQName("{test}property1"), "value1");
|
|
|
|
// Create a workspace that contains the 'live' nodes
|
|
storeRef = this.nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());
|
|
|
|
// Get a reference to the root node
|
|
rootNodeRef = this.nodeService.getRootNode(storeRef);
|
|
|
|
// Create node
|
|
this.parentNode = this.nodeService.createNode(
|
|
rootNodeRef,
|
|
ContentModel.ASSOC_CHILDREN,
|
|
QName.createQName("{}ParentNode"),
|
|
ContentModel.TYPE_CONTAINER,
|
|
nodeProperties).getChildRef();
|
|
this.nodeService.addAspect(this.parentNode, ContentModel.ASPECT_LOCKABLE, new HashMap<QName, Serializable>());
|
|
HashMap<QName, Serializable> audProps = new HashMap<QName, Serializable>();
|
|
audProps.put(ContentModel.PROP_CREATOR, "Monkey");
|
|
this.nodeService.addAspect(this.parentNode, ContentModel.ASPECT_AUDITABLE, audProps);
|
|
assertNotNull(this.parentNode);
|
|
|
|
// Add some children to the node
|
|
this.childNode1 = this.nodeService.createNode(
|
|
this.parentNode,
|
|
ContentModel.ASSOC_CHILDREN,
|
|
QName.createQName("{}ChildNode1"),
|
|
ContentModel.TYPE_CONTAINER,
|
|
nodeProperties).getChildRef();
|
|
this.nodeService.addAspect(this.childNode1, ContentModel.ASPECT_LOCKABLE, new HashMap<QName, Serializable>());
|
|
assertNotNull(this.childNode1);
|
|
this.childNode2 = this.nodeService.createNode(
|
|
this.parentNode,
|
|
ContentModel.ASSOC_CHILDREN,
|
|
QName.createQName("{}ChildNode2"),
|
|
ContentModel.TYPE_CONTAINER,
|
|
nodeProperties).getChildRef();
|
|
this.nodeService.addAspect(this.childNode2, ContentModel.ASPECT_LOCKABLE, new HashMap<QName, Serializable>());
|
|
assertNotNull(this.childNode2);
|
|
|
|
// Create a node with no lockAspect
|
|
this.noAspectNode = this.nodeService.createNode(
|
|
rootNodeRef,
|
|
ContentModel.ASSOC_CHILDREN,
|
|
QName.createQName("{}noAspectNode"),
|
|
ContentModel.TYPE_CONTAINER,
|
|
nodeProperties).getChildRef();
|
|
assertNotNull(this.noAspectNode);
|
|
|
|
// Create node with checkedOut
|
|
this.checkedOutNode = this.nodeService.createNode(
|
|
rootNodeRef,
|
|
ContentModel.ASSOC_CHILDREN,
|
|
QName.createQName("{}checkedOutNode"),
|
|
ContentModel.TYPE_CONTAINER,
|
|
nodeProperties).getChildRef();
|
|
assertNotNull(this.checkedOutNode);
|
|
|
|
// Check out test file
|
|
NodeRef fileWorkingCopyNodeRef = cociService.checkout(checkedOutNode);
|
|
assertNotNull(fileWorkingCopyNodeRef);
|
|
assertTrue(nodeService.hasAspect(checkedOutNode, ContentModel.ASPECT_CHECKED_OUT));
|
|
assertTrue(nodeService.hasAspect(checkedOutNode, ContentModel.ASPECT_LOCKABLE));
|
|
|
|
|
|
// Create the users
|
|
TestWithUserUtils.createUser(GOOD_USER_NAME, PWD, rootNodeRef, this.nodeService, this.authenticationService);
|
|
TestWithUserUtils.createUser(BAD_USER_NAME, PWD, rootNodeRef, this.nodeService, this.authenticationService);
|
|
|
|
this.permissionService.setPermission(rootNodeRef, GOOD_USER_NAME, PermissionService.ALL_PERMISSIONS, true);
|
|
this.permissionService.setPermission(rootNodeRef, BAD_USER_NAME, PermissionService.CHECK_OUT, true);
|
|
this.permissionService.setPermission(rootNodeRef, BAD_USER_NAME, PermissionService.WRITE, true);
|
|
this.permissionService.setPermission(rootNodeRef, BAD_USER_NAME, PermissionService.READ, true);
|
|
|
|
// Stash the user node ref's for later use
|
|
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
}
|
|
|
|
/**
|
|
* Test lock
|
|
*/
|
|
public void testLock()
|
|
{
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
// Check that the node is not currently locked
|
|
assertEquals(
|
|
LockStatus.NO_LOCK,
|
|
this.lockService.getLockStatus(this.parentNode));
|
|
|
|
|
|
// Test valid lock
|
|
this.lockService.lock(this.parentNode, LockType.WRITE_LOCK);
|
|
assertEquals(
|
|
LockStatus.LOCK_OWNER,
|
|
this.lockService.getLockStatus(this.parentNode));
|
|
|
|
// Check that we can retrieve LockState
|
|
LockState lockState = lockService.getLockState(parentNode);
|
|
assertEquals(parentNode, lockState.getNodeRef());
|
|
assertEquals(LockType.WRITE_LOCK, lockState.getLockType());
|
|
assertEquals(GOOD_USER_NAME, lockState.getOwner());
|
|
assertEquals(Lifetime.PERSISTENT, lockState.getLifetime());
|
|
assertEquals(null, lockState.getExpires());
|
|
assertEquals(null, lockState.getAdditionalInfo());
|
|
|
|
// Check the correct properties have been set
|
|
Map<QName, Serializable> props = nodeService.getProperties(parentNode);
|
|
assertEquals(GOOD_USER_NAME, props.get(ContentModel.PROP_LOCK_OWNER));
|
|
assertEquals(LockType.WRITE_LOCK.toString(), props.get(ContentModel.PROP_LOCK_TYPE));
|
|
assertEquals(Lifetime.PERSISTENT.toString(), props.get(ContentModel.PROP_LOCK_LIFETIME));
|
|
assertEquals(null, props.get(ContentModel.PROP_EXPIRY_DATE));
|
|
|
|
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
assertEquals(
|
|
LockStatus.LOCKED,
|
|
this.lockService.getLockStatus(this.parentNode));
|
|
|
|
// Test lock when already locked
|
|
try
|
|
{
|
|
this.lockService.lock(this.parentNode, LockType.WRITE_LOCK);
|
|
fail("The user should not be able to lock the node since it is already locked by another user.");
|
|
}
|
|
catch (UnableToAquireLockException exception)
|
|
{
|
|
System.out.println(exception.getMessage());
|
|
}
|
|
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
// Test already locked by this user
|
|
try
|
|
{
|
|
this.lockService.lock(this.parentNode, LockType.WRITE_LOCK);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
fail("No error should be thrown when a node is re-locked by the current lock owner.");
|
|
}
|
|
|
|
// Test with no apect node
|
|
this.lockService.lock(this.noAspectNode, LockType.WRITE_LOCK);
|
|
}
|
|
|
|
public void testPersistentLockMayStoreAdditionalInfo()
|
|
{
|
|
lockService.lock(noAspectNode, LockType.NODE_LOCK, 0, Lifetime.PERSISTENT, "additional info");
|
|
|
|
LockState lockState = lockService.getLockState(noAspectNode);
|
|
assertEquals("additional info", lockState.getAdditionalInfo());
|
|
}
|
|
|
|
public void testEphemeralLock()
|
|
{
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
// Check that the node is not currently locked
|
|
assertEquals(LockStatus.NO_LOCK, lockService.getLockStatus(noAspectNode));
|
|
|
|
// Check that there really is no lockable aspect
|
|
assertEquals(false, nodeService.hasAspect(noAspectNode, ContentModel.ASPECT_LOCKABLE));
|
|
|
|
// Lock the node
|
|
lockService.lock(noAspectNode, LockType.WRITE_LOCK, 86400, Lifetime.EPHEMERAL, "some extra data");
|
|
|
|
// Check additionalInfo has been stored
|
|
assertEquals("some extra data", lockService.getAdditionalInfo(noAspectNode));
|
|
|
|
// Check that we can retrieve LockState
|
|
LockState lockState = lockService.getLockState(noAspectNode);
|
|
assertEquals(noAspectNode, lockState.getNodeRef());
|
|
assertEquals(LockType.WRITE_LOCK, lockState.getLockType());
|
|
assertEquals(GOOD_USER_NAME, lockState.getOwner());
|
|
assertEquals(Lifetime.EPHEMERAL, lockState.getLifetime());
|
|
assertNotNull(lockState.getExpires());
|
|
assertEquals("some extra data", lockState.getAdditionalInfo());
|
|
|
|
// The node should be locked
|
|
assertEquals(LockStatus.LOCK_OWNER, lockService.getLockStatus(noAspectNode));
|
|
// The node must still not have the lockable aspect applied
|
|
assertEquals(false, nodeService.hasAspect(noAspectNode, ContentModel.ASPECT_LOCKABLE));
|
|
// ...though the full node service should report that it is present
|
|
NodeService fullNodeService = (NodeService) applicationContext.getBean("nodeService");
|
|
assertEquals(true, fullNodeService.hasAspect(noAspectNode, ContentModel.ASPECT_LOCKABLE));
|
|
|
|
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
assertEquals(LockStatus.LOCKED, lockService.getLockStatus(noAspectNode));
|
|
|
|
// Test lock when already locked
|
|
try
|
|
{
|
|
lockService.lock(noAspectNode, LockType.WRITE_LOCK);
|
|
fail("The user should not be able to lock the node since it is already locked by another user.");
|
|
}
|
|
catch (UnableToAquireLockException exception)
|
|
{
|
|
System.out.println(exception.getMessage());
|
|
}
|
|
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
assertEquals(LockStatus.LOCK_OWNER, lockService.getLockStatus(noAspectNode));
|
|
|
|
// Test already locked by this user - relock
|
|
try
|
|
{
|
|
lockService.lock(noAspectNode, LockType.WRITE_LOCK, 0, Lifetime.EPHEMERAL);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
fail("No error should be thrown when a node is re-locked by the current lock owner.");
|
|
}
|
|
|
|
// The node should be locked
|
|
assertEquals(LockStatus.LOCK_OWNER, lockService.getLockStatus(noAspectNode));
|
|
// If we remove the lock info directly from the memory store then the node should no longer
|
|
// be reported as locked (as it is an ephemeral lock)
|
|
LockStore lockStore = (LockStore) applicationContext.getBean("lockStore");
|
|
lockStore.clear();
|
|
// The node must no longer be reported as locked
|
|
assertEquals(LockStatus.NO_LOCK, lockService.getLockStatus(noAspectNode));
|
|
|
|
// Lock again, ready to test unlocking an ephemeral lock.
|
|
try
|
|
{
|
|
lockService.lock(noAspectNode, LockType.WRITE_LOCK, 0, Lifetime.EPHEMERAL);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
fail("No error should be thrown when a node is re-locked by the current lock owner.");
|
|
}
|
|
assertEquals(LockStatus.LOCK_OWNER, lockService.getLockStatus(noAspectNode));
|
|
lockService.unlock(noAspectNode);
|
|
assertEquals(LockStatus.NO_LOCK, lockService.getLockStatus(noAspectNode));
|
|
}
|
|
|
|
@Test
|
|
public void testEphemeralLockIndexing()
|
|
{
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, authenticationService);
|
|
|
|
IndexerAndSearcher indexerAndSearcher = (IndexerAndSearcher)
|
|
applicationContext.getBean("indexerAndSearcherFactory");
|
|
SearcherComponent searcher = new SearcherComponent();
|
|
searcher.setIndexerAndSearcherFactory(indexerAndSearcher);
|
|
|
|
// Create a lock (owned by the current user)
|
|
lockService.lock(noAspectNode, LockType.WRITE_LOCK, 86400, Lifetime.EPHEMERAL);
|
|
|
|
// Query for the user's locks
|
|
final String query = String.format("+@cm\\:lockOwner:\"%s\" +@cm\\:lockType:\"WRITE_LOCK\"", GOOD_USER_NAME);
|
|
ResultSet rs = searcher.query(storeRef, "lucene", query);
|
|
assertTrue(rs.getNodeRefs().contains(noAspectNode));
|
|
|
|
// Unlock the node
|
|
lockService.unlock(noAspectNode);
|
|
|
|
// Perform a new search, the index should reflect that it is not locked.
|
|
rs = searcher.query(storeRef, "lucene", query);
|
|
assertFalse(rs.getNodeRefs().contains(noAspectNode));
|
|
}
|
|
|
|
/* MNT-10477 related test */
|
|
@Test
|
|
public void testEphemeralLockModifyNode()
|
|
{
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
// Check that the node is not currently locked
|
|
assertEquals(LockStatus.NO_LOCK, lockService.getLockStatus(noAspectNode));
|
|
|
|
// Check that there really is no lockable aspect
|
|
assertEquals(false, nodeService.hasAspect(noAspectNode, ContentModel.ASPECT_LOCKABLE));
|
|
|
|
// Lock the node
|
|
lockService.lock(noAspectNode, LockType.WRITE_LOCK, 86400, Lifetime.EPHEMERAL, "some extra data");
|
|
|
|
// get bad user
|
|
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
assertEquals(LockStatus.LOCKED, lockService.getLockStatus(noAspectNode));
|
|
|
|
NodeService fullNodeService = (NodeService) applicationContext.getBean("nodeService");
|
|
|
|
/* addProperties test */
|
|
try
|
|
{
|
|
Map<QName, Serializable> props = new HashMap<QName, Serializable>();
|
|
props.put(ContentModel.PROP_DESCRIPTION, "descr" + System.currentTimeMillis());
|
|
props.put(ContentModel.PROP_TITLE, "title" + System.currentTimeMillis());
|
|
fullNodeService.addProperties(noAspectNode, props);
|
|
|
|
fail();
|
|
}
|
|
catch(NodeLockedException e)
|
|
{
|
|
// it's ok - node supposed to be locked
|
|
}
|
|
|
|
/* setProperty test */
|
|
try
|
|
{
|
|
fullNodeService.setProperty(noAspectNode, ContentModel.PROP_DESCRIPTION, "descr" + System.currentTimeMillis());
|
|
|
|
fail();
|
|
}
|
|
catch(NodeLockedException e)
|
|
{
|
|
// it's ok - node supposed to be locked
|
|
}
|
|
|
|
/* setProperties test */
|
|
try
|
|
{
|
|
Map<QName, Serializable> props = new HashMap<QName, Serializable>();
|
|
props.put(ContentModel.PROP_DESCRIPTION, "descr" + System.currentTimeMillis());
|
|
props.put(ContentModel.PROP_TITLE, "title" + System.currentTimeMillis());
|
|
fullNodeService.setProperties(noAspectNode, props);
|
|
|
|
fail();
|
|
}
|
|
catch(NodeLockedException e)
|
|
{
|
|
// it's ok - node supposed to be locked
|
|
}
|
|
|
|
/* removeProperty test */
|
|
try
|
|
{
|
|
fullNodeService.removeProperty(noAspectNode, ContentModel.PROP_DESCRIPTION);
|
|
|
|
fail();
|
|
}
|
|
catch(NodeLockedException e)
|
|
{
|
|
// it's ok - node supposed to be locked
|
|
}
|
|
|
|
/* addAspect test */
|
|
try
|
|
{
|
|
fullNodeService.addAspect(noAspectNode, ContentModel.ASPECT_AUTHOR , null);
|
|
|
|
fail();
|
|
}
|
|
catch(NodeLockedException e)
|
|
{
|
|
// it's ok - node supposed to be locked
|
|
}
|
|
|
|
/* removeAspect test */
|
|
try
|
|
{
|
|
fullNodeService.removeAspect(noAspectNode, ContentModel.ASPECT_AUTHOR);
|
|
|
|
fail();
|
|
}
|
|
catch(NodeLockedException e)
|
|
{
|
|
// it's ok - node supposed to be locked
|
|
}
|
|
|
|
/* setType test */
|
|
try
|
|
{
|
|
fullNodeService.setType(noAspectNode, ContentModel.TYPE_CMOBJECT);
|
|
|
|
fail();
|
|
}
|
|
catch(NodeLockedException e)
|
|
{
|
|
// it's ok - node supposed to be locked
|
|
}
|
|
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
lockService.unlock(noAspectNode);
|
|
assertEquals(LockStatus.NO_LOCK, lockService.getLockStatus(noAspectNode));
|
|
}
|
|
|
|
public void testLockRevertedOnRollback() throws NotSupportedException, SystemException
|
|
{
|
|
// Preconditions of test
|
|
assertEquals(LockStatus.NO_LOCK, lockService.getLockStatus(noAspectNode));
|
|
assertEquals(LockStatus.NO_LOCK, lockService.getLockStatus(rootNodeRef));
|
|
|
|
// Lock noAspectNode
|
|
lockService.lock(noAspectNode, LockType.WRITE_LOCK, 0, Lifetime.EPHEMERAL);
|
|
|
|
// Lock rootNodeRef
|
|
lockService.lock(rootNodeRef, LockType.NODE_LOCK, 0, Lifetime.EPHEMERAL);
|
|
|
|
// Sometime later, a refresh occurs (so this should not be reverted to unlocked, but to this state)
|
|
lockService.lock(rootNodeRef, LockType.NODE_LOCK, 3600, Lifetime.EPHEMERAL);
|
|
|
|
// Rollback
|
|
endTransaction();
|
|
|
|
// This lock should not be present.
|
|
assertEquals(LockStatus.NO_LOCK, lockService.getLockStatus(noAspectNode));
|
|
|
|
// This lock should still be present.
|
|
assertEquals(LockStatus.LOCK_OWNER, lockService.getLockStatus(rootNodeRef));
|
|
}
|
|
|
|
/**
|
|
* Test lock with lockChildren == true
|
|
*/
|
|
// TODO
|
|
public void testLockChildren()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Test lock with collection
|
|
*/
|
|
// TODO
|
|
public void testLockMany()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Test unlock node
|
|
*/
|
|
public void testUnlock()
|
|
{
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
// Lock the parent node
|
|
testLock();
|
|
|
|
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
// Try and unlock a locked node
|
|
try
|
|
{
|
|
this.lockService.unlock(this.parentNode);
|
|
// This will pass in the open workd
|
|
//fail("A user cannot unlock a node that is currently lock by another user.");
|
|
}
|
|
catch (UnableToReleaseLockException exception)
|
|
{
|
|
System.out.println(exception.getMessage());
|
|
}
|
|
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
// Unlock the node
|
|
this.lockService.unlock(this.parentNode);
|
|
assertEquals(
|
|
LockStatus.NO_LOCK,
|
|
this.lockService.getLockStatus(this.parentNode));
|
|
|
|
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
assertEquals(
|
|
LockStatus.NO_LOCK,
|
|
this.lockService.getLockStatus(this.parentNode));
|
|
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
// Try and unlock node with no lock
|
|
try
|
|
{
|
|
this.lockService.unlock(this.parentNode);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
fail("Unlocking an unlocked node should not result in an exception being raised.");
|
|
}
|
|
|
|
// Test with no apect node
|
|
this.lockService.unlock(this.noAspectNode);
|
|
}
|
|
|
|
// TODO
|
|
public void testUnlockChildren()
|
|
{
|
|
}
|
|
|
|
// TODO
|
|
public void testUnlockMany()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Test getLockStatus
|
|
*/
|
|
public void testGetLockStatus()
|
|
{
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
// Check an unlocked node
|
|
LockStatus lockStatus1 = this.lockService.getLockStatus(this.parentNode);
|
|
assertEquals(LockStatus.NO_LOCK, lockStatus1);
|
|
|
|
this.lockService.lock(this.parentNode, LockType.WRITE_LOCK);
|
|
|
|
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
// Check for locked status
|
|
LockStatus lockStatus2 = this.lockService.getLockStatus(this.parentNode);
|
|
assertEquals(LockStatus.LOCKED, lockStatus2);
|
|
|
|
// Check lockstore is not used for persistent locks
|
|
// Previously LockStore was doubling up as a cache - the change in requirements means a test
|
|
// is necessary to ensure the work has been implemented correctly (despite being an odd test)
|
|
LockStore lockStore = (LockStore) applicationContext.getBean("lockStore");
|
|
lockStore.clear();
|
|
LockState lockState = lockStore.get(parentNode);
|
|
// Nothing stored against node ref
|
|
assertNull(lockState);
|
|
lockService.getLockStatus(parentNode);
|
|
// In-memory store still empty - only used for ephemeral locks
|
|
lockState = lockStore.get(parentNode);
|
|
assertNull(lockState);
|
|
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
// Check for lock owner status
|
|
LockStatus lockStatus3 = this.lockService.getLockStatus(this.parentNode);
|
|
assertEquals(LockStatus.LOCK_OWNER, lockStatus3);
|
|
|
|
// Test with no apect node
|
|
this.lockService.getLockStatus(this.noAspectNode);
|
|
|
|
// Test method overload
|
|
LockStatus lockStatus4 = this.lockService.getLockStatus(this.parentNode);
|
|
assertEquals(LockStatus.LOCK_OWNER, lockStatus4);
|
|
}
|
|
|
|
public void testGetLocks()
|
|
{
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
LockServiceImpl lockService = (LockServiceImpl) this.lockService;
|
|
List<NodeRef> locked1 = lockService.getLocks(this.storeRef);
|
|
assertNotNull(locked1);
|
|
assertEquals(0, locked1.size());
|
|
|
|
this.lockService.lock(this.parentNode, LockType.WRITE_LOCK);
|
|
this.lockService.lock(this.childNode1, LockType.WRITE_LOCK);
|
|
this.lockService.lock(this.childNode2, LockType.READ_ONLY_LOCK);
|
|
|
|
List<NodeRef> locked2 = lockService.getLocks(this.storeRef);
|
|
assertNotNull(locked2);
|
|
assertEquals(3, locked2.size());
|
|
|
|
List<NodeRef> locked3 = lockService.getLocks(this.storeRef, LockType.WRITE_LOCK);
|
|
assertNotNull(locked3);
|
|
assertEquals(2, locked3.size());
|
|
|
|
List<NodeRef> locked4 = lockService.getLocks(this.storeRef, LockType.READ_ONLY_LOCK);
|
|
assertNotNull(locked4);
|
|
assertEquals(1, locked4.size());
|
|
|
|
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
List<NodeRef> locked5 = lockService.getLocks(this.storeRef);
|
|
assertNotNull(locked5);
|
|
assertEquals(0, locked5.size());
|
|
}
|
|
|
|
/**
|
|
* Test getLockType
|
|
*/
|
|
public void testGetLockType()
|
|
{
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
// Get the lock type (should be null since the object is not locked)
|
|
LockType lockType1 = this.lockService.getLockType(this.parentNode);
|
|
assertNull(lockType1);
|
|
|
|
// Lock the object for writing
|
|
this.lockService.lock(this.parentNode, LockType.WRITE_LOCK);
|
|
LockType lockType2 = this.lockService.getLockType(this.parentNode);
|
|
assertNotNull(lockType2);
|
|
assertEquals(LockType.WRITE_LOCK, lockType2);
|
|
|
|
// Unlock the node
|
|
this.lockService.unlock(this.parentNode);
|
|
LockType lockType3 = this.lockService.getLockType(this.parentNode);
|
|
assertNull(lockType3);
|
|
|
|
// Lock the object for read only
|
|
this.lockService.lock(this.parentNode, LockType.READ_ONLY_LOCK);
|
|
LockType lockType4 = this.lockService.getLockType(this.parentNode);
|
|
assertNotNull(lockType4);
|
|
assertEquals(LockType.READ_ONLY_LOCK, lockType4);
|
|
|
|
// Lock the object for node lock
|
|
this.lockService.lock(this.parentNode, LockType.NODE_LOCK);
|
|
LockType lockType5 = this.lockService.getLockType(this.parentNode);
|
|
assertNotNull(lockType5);
|
|
assertEquals(LockType.NODE_LOCK, lockType5);
|
|
|
|
// Unlock the node
|
|
this.lockService.unlock(this.parentNode);
|
|
LockType lockType6 = this.lockService.getLockType(this.parentNode);
|
|
assertNull(lockType6);
|
|
|
|
// Test with no apect node
|
|
LockType lockType7 = this.lockService.getLockType(this.noAspectNode);
|
|
assertTrue("lock type is not null", lockType7 == null);
|
|
}
|
|
|
|
public void testGetLockTypeEphemeral()
|
|
{
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
// Get the lock type (should be null since the object is not locked)
|
|
LockType lockType1 = this.lockService.getLockType(this.parentNode);
|
|
assertNull(lockType1);
|
|
|
|
// Lock the object for writing
|
|
this.lockService.lock(this.parentNode, LockType.WRITE_LOCK, 0, Lifetime.EPHEMERAL);
|
|
LockType lockType2 = this.lockService.getLockType(this.parentNode);
|
|
assertNotNull(lockType2);
|
|
assertEquals(LockType.WRITE_LOCK, lockType2);
|
|
|
|
// Unlock the node
|
|
this.lockService.unlock(this.parentNode);
|
|
LockType lockType3 = this.lockService.getLockType(this.parentNode);
|
|
assertNull(lockType3);
|
|
|
|
// Lock the object for read only
|
|
this.lockService.lock(this.parentNode, LockType.READ_ONLY_LOCK, 0, Lifetime.EPHEMERAL);
|
|
LockType lockType4 = this.lockService.getLockType(this.parentNode);
|
|
assertNotNull(lockType4);
|
|
assertEquals(LockType.READ_ONLY_LOCK, lockType4);
|
|
|
|
// Lock the object for node lock
|
|
this.lockService.lock(this.parentNode, LockType.NODE_LOCK, 0, Lifetime.EPHEMERAL);
|
|
LockType lockType5 = this.lockService.getLockType(this.parentNode);
|
|
assertNotNull(lockType5);
|
|
assertEquals(LockType.NODE_LOCK, lockType5);
|
|
|
|
// Unlock the node
|
|
this.lockService.unlock(this.parentNode);
|
|
LockType lockType6 = this.lockService.getLockType(this.parentNode);
|
|
assertNull(lockType6);
|
|
|
|
// Test with no apect node
|
|
LockType lockType7 = this.lockService.getLockType(this.noAspectNode);
|
|
assertTrue("lock type is not null", lockType7 == null);
|
|
}
|
|
|
|
public void testTimeToExpire()
|
|
{
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
this.lockService.lock(this.parentNode, LockType.WRITE_LOCK, 1);
|
|
assertEquals(LockStatus.LOCK_OWNER, this.lockService.getLockStatus(this.parentNode));
|
|
|
|
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
assertEquals(LockStatus.LOCKED, this.lockService.getLockStatus(this.parentNode));
|
|
|
|
// Wait for 2 second before re-testing the status
|
|
try {Thread.sleep(2*1000);} catch (Exception exception){};
|
|
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
assertEquals(LockStatus.LOCK_EXPIRED, this.lockService.getLockStatus(this.parentNode));
|
|
|
|
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
assertEquals(LockStatus.LOCK_EXPIRED, this.lockService.getLockStatus(this.parentNode));
|
|
|
|
// Re-lock and then update the time to expire before lock expires
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
this.lockService.lock(this.parentNode, LockType.WRITE_LOCK, 0);
|
|
try
|
|
{
|
|
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
this.lockService.lock(this.parentNode, LockType.WRITE_LOCK, 1);
|
|
fail("Can not update lock info if not lock owner");
|
|
}
|
|
catch (UnableToAquireLockException exception)
|
|
{
|
|
// Expected
|
|
}
|
|
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
this.lockService.lock(this.parentNode, LockType.WRITE_LOCK, 1);
|
|
assertEquals(LockStatus.LOCK_OWNER, this.lockService.getLockStatus(this.parentNode));
|
|
|
|
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
assertEquals(LockStatus.LOCKED, this.lockService.getLockStatus(this.parentNode));
|
|
|
|
// Wait for 2 second before re-testing the status
|
|
try {Thread.sleep(2*1000);} catch (Exception exception){};
|
|
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
assertEquals(LockStatus.LOCK_EXPIRED, this.lockService.getLockStatus(this.parentNode));
|
|
|
|
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
assertEquals(LockStatus.LOCK_EXPIRED, this.lockService.getLockStatus(this.parentNode));
|
|
}
|
|
|
|
public void testEphemeralExpiryThreshold()
|
|
{
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
final int origThresh = ((LockServiceImpl)lockService).getEphemeralExpiryThreshold();
|
|
// Check the default situation is that the threshold does not apply.
|
|
assertEquals(LockServiceImpl.MAX_EPHEMERAL_LOCK_SECONDS, origThresh);
|
|
try
|
|
{
|
|
// Set the ephemeral expiry threshold to a much smaller value than the default
|
|
// so that it takes effect.
|
|
lockService.setEphemeralExpiryThreshold(300);
|
|
|
|
// Check for an expiry time that should be unaffected by the threshold.
|
|
checkLifetimeForExpiry(Lifetime.EPHEMERAL, 0, Lifetime.EPHEMERAL);
|
|
checkLifetimeForExpiry(Lifetime.EPHEMERAL, 150, Lifetime.EPHEMERAL);
|
|
|
|
// Check the largest allowed ephemeral expiry time.
|
|
checkLifetimeForExpiry(Lifetime.EPHEMERAL, 300, Lifetime.EPHEMERAL);
|
|
|
|
// When the expiry is greater than the threshold, then the lock should be
|
|
// applied as a persistent lock.
|
|
checkLifetimeForExpiry(Lifetime.PERSISTENT, 301, Lifetime.EPHEMERAL);
|
|
|
|
// Switch off ephemeral locks entirely
|
|
lockService.setEphemeralExpiryThreshold(-1);
|
|
// Always persistent...
|
|
checkLifetimeForExpiry(Lifetime.PERSISTENT, 0, Lifetime.EPHEMERAL);
|
|
checkLifetimeForExpiry(Lifetime.PERSISTENT, 150, Lifetime.EPHEMERAL);
|
|
checkLifetimeForExpiry(Lifetime.PERSISTENT, 300, Lifetime.EPHEMERAL);
|
|
checkLifetimeForExpiry(Lifetime.PERSISTENT, 301, Lifetime.EPHEMERAL);
|
|
}
|
|
finally
|
|
{
|
|
lockService.setEphemeralExpiryThreshold(origThresh);
|
|
}
|
|
}
|
|
|
|
private void checkLifetimeForExpiry(Lifetime expectedLifetime, int expirySecs, Lifetime requestedLifetime)
|
|
{
|
|
lockService.unlock(parentNode);
|
|
assertNotEquals(LockStatus.LOCKED ,lockService.getLockStatus(parentNode));
|
|
lockService.lock(parentNode, LockType.WRITE_LOCK, expirySecs, requestedLifetime);
|
|
LockState lock = lockService.getLockState(parentNode);
|
|
assertEquals(expectedLifetime, lock.getLifetime());
|
|
|
|
// Check that for any timeouts we test, a request for a persistent lock always yields a persistent lock.
|
|
lockService.unlock(parentNode);
|
|
assertNotEquals(LockStatus.LOCKED ,lockService.getLockStatus(parentNode));
|
|
lockService.lock(parentNode, LockType.WRITE_LOCK, expirySecs, Lifetime.PERSISTENT);
|
|
lock = lockService.getLockState(parentNode);
|
|
assertEquals(Lifetime.PERSISTENT, lock.getLifetime());
|
|
}
|
|
|
|
/**
|
|
* Unit test to validate the behaviour of creating children of locked nodes.
|
|
* No lock - can create children
|
|
* READ_ONLY_LOCK - can't create children
|
|
* WRITE_LOCK - owner can create children
|
|
* non owner can't create children
|
|
* NODE_LOCK non owner can create children
|
|
* owner can create children
|
|
*/
|
|
public void testCreateChildrenOfLockedNodes() throws Exception
|
|
{
|
|
|
|
/**
|
|
* Check we can create a child of an unlocked node.
|
|
*/
|
|
assertEquals(
|
|
LockStatus.NO_LOCK,
|
|
this.lockService.getLockStatus(this.parentNode));
|
|
|
|
ChildAssociationRef child = nodeService.createNode(parentNode, ContentModel.ASSOC_CONTAINS, QName.createQName("ChildA"), ContentModel.TYPE_FOLDER);
|
|
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
this.lockService.lock(this.parentNode, LockType.WRITE_LOCK);
|
|
|
|
// Owner can create children
|
|
child = nodeService.createNode(parentNode, ContentModel.ASSOC_CONTAINS, QName.createQName("ChildB"), ContentModel.TYPE_FOLDER);
|
|
|
|
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
try
|
|
{
|
|
// Non owner can't create children with a write lock in place
|
|
child = nodeService.createNode(parentNode, ContentModel.ASSOC_CONTAINS, QName.createQName("ChildB"), ContentModel.TYPE_FOLDER);
|
|
fail("could create a child with a read only lock");
|
|
}
|
|
catch (NodeLockedException e)
|
|
{
|
|
logger.debug("exception while trying to create a child of a read only lock", e);
|
|
}
|
|
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
this.lockService.lock(this.parentNode, LockType.NODE_LOCK);
|
|
|
|
// owner can create children with a node lock
|
|
child = nodeService.createNode(parentNode, ContentModel.ASSOC_CONTAINS, QName.createQName("ChildD"), ContentModel.TYPE_FOLDER);
|
|
|
|
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
// Non owner can create children with a node lock
|
|
child = nodeService.createNode(parentNode, ContentModel.ASSOC_CONTAINS, QName.createQName("ChildC"), ContentModel.TYPE_FOLDER);
|
|
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
this.lockService.lock(this.parentNode, LockType.READ_ONLY_LOCK);
|
|
|
|
// owner should not be able to create children with a READ_ONLY_LOCK
|
|
try
|
|
{
|
|
child = nodeService.createNode(parentNode, ContentModel.ASSOC_CONTAINS, QName.createQName("ChildD"), ContentModel.TYPE_FOLDER);
|
|
fail("could create a child with a read only lock");
|
|
}
|
|
catch (NodeLockedException e)
|
|
{
|
|
logger.debug("exception while trying to create a child of a read only lock", e);
|
|
}
|
|
|
|
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
// Non owner should not be able to create children with READ_ONLY_LOCK
|
|
try
|
|
{
|
|
child = nodeService.createNode(parentNode, ContentModel.ASSOC_CONTAINS, QName.createQName("ChildE"), ContentModel.TYPE_FOLDER);
|
|
fail("could create a child with a read only lock");
|
|
}
|
|
catch (NodeLockedException e)
|
|
{
|
|
logger.debug("exception while trying to create a child of a read only lock", e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test that it is impossible to unlock a checked out node
|
|
*/
|
|
public void testUnlockCheckedOut() throws Exception
|
|
{
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
try
|
|
{
|
|
this.lockService.unlock(checkedOutNode);
|
|
fail("could unlock a checked out node");
|
|
}
|
|
catch (UnableToReleaseLockException e)
|
|
{
|
|
logger.debug("exception while trying to unlock a checked out node", e);
|
|
}
|
|
}
|
|
|
|
@SuppressWarnings("deprecation")
|
|
public void testUnlockNodeWithAdminUserAndAllPermissionsUser()
|
|
{
|
|
for (Lifetime lt : new Lifetime[]{Lifetime.EPHEMERAL, Lifetime.PERSISTENT})
|
|
{
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
/* create node */
|
|
final NodeRef testNode =
|
|
this.nodeService.createNode(parentNode, ContentModel.ASSOC_CONTAINS, QName.createQName("{}testNode"), ContentModel.TYPE_CONTAINER).getChildRef();
|
|
|
|
// lock it as GOOD user
|
|
this.securedLockService.lock(testNode, LockType.WRITE_LOCK, 2 * 86400, lt, null);
|
|
|
|
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
|
|
try
|
|
{
|
|
// try to unlock as bad user
|
|
this.securedLockService.unlock(testNode);
|
|
fail("BAD user shouldn't be able to unlock " + lt + " lock");
|
|
}
|
|
catch(AccessDeniedException e)
|
|
{
|
|
// expected expetion
|
|
}
|
|
|
|
TestWithUserUtils.authenticateUser(AuthenticationUtil.getAdminUserName(), "admin", rootNodeRef, this.authenticationService);
|
|
|
|
// try to unlock as ADMIN user
|
|
this.securedLockService.unlock(testNode);
|
|
|
|
// test that bad use able to lock/unlock node
|
|
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
this.securedLockService.lock(testNode, LockType.WRITE_LOCK, 2 * 86400, lt, null);
|
|
this.securedLockService.unlock(testNode);
|
|
|
|
this.securedLockService.lock(testNode, LockType.WRITE_LOCK, 2 * 86400, lt, null);
|
|
|
|
// user who has ALL PERMISSIONS is able to unlock another's user lock
|
|
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
|
|
this.securedLockService.unlock(testNode);
|
|
|
|
this.nodeService.deleteNode(testNode);
|
|
}
|
|
}
|
|
}
|