RM-1315: Manage Permissions is not working for folder inside Holds/Unfiled Records

* unit tests to show unfiled and holds permissions working correctly
 * fixed issues exposed by above
 * minor refactor for FilePlanPermissionService implementation to reduce complexity
 * added unit test execution to local build target



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@66102 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2014-04-01 23:53:16 +00:00
parent c7facab5a9
commit 09648f9829
10 changed files with 478 additions and 180 deletions

View File

@@ -0,0 +1,263 @@
/*
* Copyright (C) 2005-2014 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.module.org_alfresco_module_rm.security;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Spy;
/**
* File plan permission service implementation unit test.
* <p>
* Primarily tests the file plan permission service interaction with the
* permission service.
*
* @author Roy Wetherall
* @since 2.2
*/
public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
{
/** test authority */
protected static final String AUTHORITY = "anAuthority";
/** unfiled nodes */
protected NodeRef unfiledRecordContainer;
protected NodeRef unfiledRecordFolder;
protected NodeRef unfiledRecordFolderChild;
protected NodeRef unfiledRecord;
/** held nodes */
protected NodeRef holdContainer;
protected NodeRef hold;
protected NodeRef heldRecord;
/** file plan permission service implementation */
@Spy @InjectMocks FilePlanPermissionServiceImpl filePlanPermissionService;
/**
* @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest#before()
*/
@Override
public void before()
{
super.before();
// mock up run as methods
mockRunAsMethods(filePlanPermissionService);
// initialize node's
unfiledRecordContainer = generateContainerNodeRef(TYPE_UNFILED_RECORD_CONTAINER);
unfiledRecordFolder = generateContainerNodeRef(TYPE_UNFILED_RECORD_FOLDER);
unfiledRecordFolderChild = generateContainerNodeRef(TYPE_UNFILED_RECORD_FOLDER);
unfiledRecord = generateRecord();
holdContainer = generateContainerNodeRef(TYPE_HOLD_CONTAINER);
hold = generateHoldNodeRef("my test hold");
heldRecord = generateRecord();
// setup parent hierarchy
makePrimaryParentOf(filePlan, generateNodeRef(ContentModel.TYPE_FOLDER));
makePrimaryParentOf(unfiledRecordFolder, unfiledRecordContainer);
makePrimaryParentOf(unfiledRecordContainer, filePlan);
makePrimaryParentOf(hold, holdContainer);
makePrimaryParentOf(holdContainer, filePlan);
// setup child hierarchy
makeChildrenOf(unfiledRecordFolder, unfiledRecordFolderChild);
makeChildrenOf(unfiledRecordFolderChild, unfiledRecord);
makeChildrenOf(hold, heldRecord);
}
/**
* Helper method to generate a container node ref of a perticular type.
*
* @param type type of node reference
* @return {@link NodeRef} node reference that behaves like a container of the type given.
*/
private NodeRef generateContainerNodeRef(QName type)
{
NodeRef nodeRef = generateNodeRef(type);
setupAsFilePlanComponent(nodeRef);
doReturn(true).when(filePlanPermissionService).isFilePlanContainer(nodeRef);
return nodeRef;
}
/**
* Set read permission on unfiled record folder.
*/
@Test
public void setReadPermissionOnUnfiledRecordFolder()
{
// set read permission on unfiled record folder
filePlanPermissionService.setPermission(unfiledRecordFolder, AUTHORITY, RMPermissionModel.READ_RECORDS);
// verify permission set on target node
verify(mockedPermissionService, times(1)).setPermission(unfiledRecordFolder, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
// verify READ permission set up hierarchy
verify(mockedPermissionService, times(1)).setPermission(unfiledRecordContainer, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
verify(mockedPermissionService, times(1)).setPermission(filePlan, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
// verify READ permission set down hierarchy
verify(mockedPermissionService, times(1)).setPermission(unfiledRecordFolderChild, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
verify(mockedPermissionService, times(1)).setPermission(unfiledRecord, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
}
/**
* Set filling permission on unfiled record folder
*/
@Test
public void setReadAndFilePermissionOnUnfileRecordFolder()
{
// set read permission on unfiled record folder
filePlanPermissionService.setPermission(unfiledRecordFolder, AUTHORITY, RMPermissionModel.FILING);
// verify permission set on target node
verify(mockedPermissionService, times(1)).setPermission(unfiledRecordFolder, AUTHORITY, RMPermissionModel.FILING, true);
// verify READ permission set up hierarchy
verify(mockedPermissionService, times(1)).setPermission(unfiledRecordContainer, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
verify(mockedPermissionService, times(1)).setPermission(filePlan, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
// verify FILING permission set down hierarchy
verify(mockedPermissionService, times(1)).setPermission(unfiledRecordFolderChild, AUTHORITY, RMPermissionModel.FILING, true);
verify(mockedPermissionService, times(1)).setPermission(unfiledRecord, AUTHORITY, RMPermissionModel.FILING, true);
}
/**
* Remove permission from unfiled record folders.
*/
@Test
public void deletePermissionFromUnfiledRecordFolder()
{
// delete read permission from unfiled record folder
filePlanPermissionService.deletePermission(unfiledRecordFolder, AUTHORITY, RMPermissionModel.READ_RECORDS);
// verify permission deleted on target node
verify(mockedPermissionService, times(1)).deletePermission(unfiledRecordFolder, AUTHORITY, RMPermissionModel.READ_RECORDS);
// verify no permissions deleted up the hierarchy
verify(mockedPermissionService, never()).deletePermission(eq(unfiledRecordContainer), eq(AUTHORITY), anyString());
verify(mockedPermissionService, never()).deletePermission(eq(filePlan), eq(AUTHORITY), anyString());
// verify READ permission removed down hierarchy
verify(mockedPermissionService, times(1)).deletePermission(unfiledRecordFolderChild, AUTHORITY, RMPermissionModel.READ_RECORDS);
verify(mockedPermissionService, times(1)).deletePermission(unfiledRecord, AUTHORITY, RMPermissionModel.READ_RECORDS);
}
/**
* Set read permission on hold container
*/
public void setReadPermissionOnHoldContainer()
{
// set read permission on hold
filePlanPermissionService.setPermission(holdContainer, AUTHORITY, RMPermissionModel.READ_RECORDS);
// verify permission set on target node
verify(mockedPermissionService, times(1)).setPermission(holdContainer, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
// verify READ permission set up hierarchy
verify(mockedPermissionService, times(1)).setPermission(filePlan, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
// verify READ permission set on hold
verify(mockedPermissionService, times(1)).setPermission(hold, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
// verify permission not set on child of hold
verify(mockedPermissionService, never()).setPermission(eq(heldRecord), eq(AUTHORITY), anyString(), eq(true));
}
/**
* Set filing permission on hold container
*/
public void setFilingPermissionOnHoldContainer()
{
// set read permission on hold
filePlanPermissionService.setPermission(holdContainer, AUTHORITY, RMPermissionModel.FILING);
// verify permission set on target node
verify(mockedPermissionService, times(1)).setPermission(holdContainer, AUTHORITY, RMPermissionModel.FILING, true);
// verify READ permission set up hierarchy
verify(mockedPermissionService, times(1)).setPermission(filePlan, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
// verify FILING permission set on hold
verify(mockedPermissionService, times(1)).setPermission(hold, AUTHORITY, RMPermissionModel.FILING, true);
// verify permission not set on child of hold
verify(mockedPermissionService, never()).setPermission(eq(heldRecord), eq(AUTHORITY), anyString(), eq(true));
}
/**
* Set read permission on hold.
*/
@Test
public void setReadPermissionOnHold()
{
// set read permission on hold
filePlanPermissionService.setPermission(hold, AUTHORITY, RMPermissionModel.READ_RECORDS);
// verify permission set on target node
verify(mockedPermissionService, times(1)).setPermission(hold, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
// verify READ permission set up hierarchy
verify(mockedPermissionService, times(1)).setPermission(holdContainer, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
verify(mockedPermissionService, times(1)).setPermission(filePlan, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
// verify permission not set on child of hold
verify(mockedPermissionService, never()).setPermission(eq(heldRecord), eq(AUTHORITY), anyString(), eq(true));
}
/**
* Set filing permission on hold.
*/
@Test
public void setFilingPermissionOnHold()
{
// set filing permission on hold
filePlanPermissionService.setPermission(hold, AUTHORITY, RMPermissionModel.FILING);
// verify permission set on target node
verify(mockedPermissionService, times(1)).setPermission(hold, AUTHORITY, RMPermissionModel.FILING, true);
// verify READ permission set up hierarchy
verify(mockedPermissionService, times(1)).setPermission(holdContainer, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
verify(mockedPermissionService, times(1)).setPermission(filePlan, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
// verify permission not set on child of hold
verify(mockedPermissionService, never()).setPermission(eq(heldRecord), eq(AUTHORITY), anyString(), eq(true));
}
}

View File

@@ -26,6 +26,7 @@ import org.alfresco.module.org_alfresco_module_rm.record.RecordServiceImplUnitTe
import org.alfresco.module.org_alfresco_module_rm.script.hold.HoldPostUnitTest;
import org.alfresco.module.org_alfresco_module_rm.script.hold.HoldPutUnitTest;
import org.alfresco.module.org_alfresco_module_rm.script.hold.HoldsGetUnitTest;
import org.alfresco.module.org_alfresco_module_rm.security.FilePlanPermissionServiceImplUnitTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@@ -46,7 +47,8 @@ import org.junit.runners.Suite.SuiteClasses;
TransferEvaluatorUnitTest.class,
HoldsGetUnitTest.class,
HoldPostUnitTest.class,
HoldPutUnitTest.class
HoldPutUnitTest.class,
FilePlanPermissionServiceImplUnitTest.class
})
public class AllUnitTestSuite
{

View File

@@ -19,7 +19,9 @@
package org.alfresco.module.org_alfresco_module_rm.test.util;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
@@ -34,14 +36,18 @@ import org.alfresco.module.org_alfresco_module_rm.identifier.IdentifierService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService;
import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.cmr.dictionary.DictionaryService;
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.security.PermissionService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.QNamePattern;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.util.GUID;
import org.alfresco.util.collections.CollectionUtils;
import org.junit.Before;
@@ -49,6 +55,9 @@ import org.junit.Rule;
import org.junit.rules.ExpectedException;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.context.ApplicationContext;
/**
* Base unit test.
@@ -72,12 +81,17 @@ public class BaseUnitTest implements RecordsManagementModel
@Mock(name="dictionaryService") protected DictionaryService mockedDictionaryService;
@Mock(name="namespaceService") protected NamespaceService mockedNamespaceService;
@Mock(name="identifierService") protected IdentifierService mockedIdentifierService;
@Mock(name="permissionService") protected PermissionService mockedPermissionService;
/** rm service mocks */
@Mock(name="filePlanService") protected FilePlanService mockedFilePlanService;
@Mock(name="recordFolderService") protected RecordFolderService mockedRecordFolderService;
@Mock(name="recordService") protected RecordService mockedRecordService;
@Mock(name="holdService") protected HoldService mockedHoldService;
/** application context mock */
@Mock(name="applicationContext") protected ApplicationContext mockedApplicationContext;
/** expected exception rule */
@Rule
public ExpectedException exception = ExpectedException.none();
@@ -89,9 +103,13 @@ public class BaseUnitTest implements RecordsManagementModel
public void before()
{
MockitoAnnotations.initMocks(this);
// setup application context
doReturn(mockedNodeService).when(mockedApplicationContext).getBean("nodeService");
// setup file plan
filePlan = generateNodeRef(TYPE_FILE_PLAN);
setupAsFilePlanComponent(filePlan);
doReturn(true).when(mockedFilePlanService).isFilePlan(filePlan);
// setup basic file plan component
@@ -112,8 +130,7 @@ public class BaseUnitTest implements RecordsManagementModel
doReturn(result).when(mockedNodeService).getChildAssocs(eq(recordFolder), eq(ContentModel.ASSOC_CONTAINS), any(QNamePattern.class));
doReturn(result).when(mockedNodeService).getParentAssocs(record);
doReturn(Collections.singletonList(recordFolder)).when(mockedRecordFolderService).getRecordFolders(record);
doReturn(Collections.singletonList(record)).when(mockedRecordService).getRecords(recordFolder);
doReturn(Collections.singletonList(record)).when(mockedRecordService).getRecords(recordFolder);
}
/**
@@ -179,7 +196,7 @@ public class BaseUnitTest implements RecordsManagementModel
doReturn(filePlan).when(mockedFilePlanService).getFilePlan(nodeRef);
doReturn(filePlan).when(mockedNodeService).getProperty(nodeRef, PROP_ROOT_NODEREF);
}
/**
* Helper method to generate a node reference.
*
@@ -207,4 +224,72 @@ public class BaseUnitTest implements RecordsManagementModel
}
return nodeRef;
}
/**
* Helper method to make one node the primary parent of the other.
* <p>
* Assumes the cm:contains assoc type.
*
* @param child
* @param parent
*/
protected void makePrimaryParentOf(NodeRef child, NodeRef parent)
{
doReturn(new ChildAssociationRef(ContentModel.ASSOC_CONTAINS, parent, generateQName(), child))
.when(mockedNodeService)
.getPrimaryParent(child);
}
/**
* Helper method to make a number of nodes children of another.
* <p>
* Assumes the cm:contains assoc type.
*
* @param parent
* @param children
*/
protected void makeChildrenOf(NodeRef parent, NodeRef ... children)
{
List<ChildAssociationRef> assocs = new ArrayList<ChildAssociationRef>(children.length);
for (NodeRef child : children)
{
assocs.add(new ChildAssociationRef(ContentModel.ASSOC_CONTAINS, parent, generateQName(), child));
}
doReturn(assocs).when(mockedNodeService).getChildAssocs(parent, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
}
/**
* Helper method to mock up calls to 'run as' methods
* on base service implementation.
*
* @param service
*/
@SuppressWarnings("unchecked")
protected void mockRunAsMethods(ServiceBaseImpl service)
{
doAnswer(new Answer<Object>()
{
@SuppressWarnings("rawtypes")
@Override
public Object answer(InvocationOnMock invocation) throws Throwable
{
RunAsWork work = (RunAsWork)invocation.getArguments()[0];
return work.doWork();
}
}).when(service).runAsSystem(any(RunAsWork.class));
doAnswer(new Answer<Object>()
{
@SuppressWarnings("rawtypes")
@Override
public Object answer(InvocationOnMock invocation) throws Throwable
{
RunAsWork work = (RunAsWork)invocation.getArguments()[0];
return work.doWork();
}
}).when(service).runAs(any(RunAsWork.class), anyString());
}
}