mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
RM-3074: Integration tests
* including fix for ghosted records being visible in collab sites
This commit is contained in:
@@ -260,7 +260,8 @@
|
|||||||
depends-on="rmDestroyRecordsScheduledForDestructionCapability">
|
depends-on="rmDestroyRecordsScheduledForDestructionCapability">
|
||||||
<property name="capabilityService" ref="CapabilityService" />
|
<property name="capabilityService" ref="CapabilityService" />
|
||||||
<property name="recordableVersionService" ref="RecordableVersionService" />
|
<property name="recordableVersionService" ref="RecordableVersionService" />
|
||||||
<property name="contentDestructionComponent" ref="contentDestructionComponent"/>
|
<property name="contentDestructionComponent" ref="contentDestructionComponent"/>
|
||||||
|
<property name="inplaceRecordService" ref="InplaceRecordService"/>
|
||||||
<property name="ghostingEnabled">
|
<property name="ghostingEnabled">
|
||||||
<value>${rm.ghosting.enabled}</value>
|
<value>${rm.ghosting.enabled}</value>
|
||||||
</property>
|
</property>
|
||||||
|
@@ -36,6 +36,7 @@ import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
|
|||||||
import org.alfresco.module.org_alfresco_module_rm.content.ContentDestructionComponent;
|
import org.alfresco.module.org_alfresco_module_rm.content.ContentDestructionComponent;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition;
|
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule;
|
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.record.InplaceRecordService;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionService;
|
import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionService;
|
||||||
import org.alfresco.service.cmr.action.Action;
|
import org.alfresco.service.cmr.action.Action;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
@@ -62,6 +63,9 @@ public class DestroyAction extends RMDispositionActionExecuterAbstractBase
|
|||||||
|
|
||||||
/** Recordable version service */
|
/** Recordable version service */
|
||||||
private RecordableVersionService recordableVersionService;
|
private RecordableVersionService recordableVersionService;
|
||||||
|
|
||||||
|
/** Inplace record service */
|
||||||
|
private InplaceRecordService inplaceRecordService;
|
||||||
|
|
||||||
/** Indicates if ghosting is enabled or not */
|
/** Indicates if ghosting is enabled or not */
|
||||||
private boolean ghostingEnabled = true;
|
private boolean ghostingEnabled = true;
|
||||||
@@ -89,6 +93,14 @@ public class DestroyAction extends RMDispositionActionExecuterAbstractBase
|
|||||||
{
|
{
|
||||||
this.recordableVersionService = recordableVersionService;
|
this.recordableVersionService = recordableVersionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param inplaceRecordService inplace record service
|
||||||
|
*/
|
||||||
|
public void setInplaceRecordService(InplaceRecordService inplaceRecordService)
|
||||||
|
{
|
||||||
|
this.inplaceRecordService = inplaceRecordService;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ghostingEnabled true if ghosting is enabled, false otherwise
|
* @param ghostingEnabled true if ghosting is enabled, false otherwise
|
||||||
@@ -171,6 +183,9 @@ public class DestroyAction extends RMDispositionActionExecuterAbstractBase
|
|||||||
|
|
||||||
// Add the ghosted aspect
|
// Add the ghosted aspect
|
||||||
getNodeService().addAspect(record, ASPECT_GHOSTED, null);
|
getNodeService().addAspect(record, ASPECT_GHOSTED, null);
|
||||||
|
|
||||||
|
// Hide from inplace users to give the impression of destruction
|
||||||
|
inplaceRecordService.hideRecord(record);
|
||||||
|
|
||||||
// destroy content
|
// destroy content
|
||||||
contentDestructionComponent.destroyContent(record);
|
contentDestructionComponent.destroyContent(record);
|
||||||
|
@@ -103,22 +103,26 @@ public class InplaceRecordServiceImpl extends ServiceBaseImpl implements Inplace
|
|||||||
{
|
{
|
||||||
// remove the child association
|
// remove the child association
|
||||||
NodeRef originatingLocation = (NodeRef) nodeService.getProperty(nodeRef, PROP_RECORD_ORIGINATING_LOCATION);
|
NodeRef originatingLocation = (NodeRef) nodeService.getProperty(nodeRef, PROP_RECORD_ORIGINATING_LOCATION);
|
||||||
List<ChildAssociationRef> parentAssocs = nodeService.getParentAssocs(nodeRef);
|
|
||||||
for (ChildAssociationRef childAssociationRef : parentAssocs)
|
if (originatingLocation != null)
|
||||||
{
|
{
|
||||||
if (!childAssociationRef.isPrimary() &&
|
List<ChildAssociationRef> parentAssocs = nodeService.getParentAssocs(nodeRef);
|
||||||
childAssociationRef.getParentRef().equals(originatingLocation) &&
|
for (ChildAssociationRef childAssociationRef : parentAssocs)
|
||||||
!nodeService.hasAspect(childAssociationRef.getChildRef(), ASPECT_PENDING_DELETE))
|
|
||||||
{
|
{
|
||||||
nodeService.removeChildAssociation(childAssociationRef);
|
if (!childAssociationRef.isPrimary() &&
|
||||||
break;
|
childAssociationRef.getParentRef().equals(originatingLocation) &&
|
||||||
|
!nodeService.hasAspect(childAssociationRef.getChildRef(), ASPECT_PENDING_DELETE))
|
||||||
|
{
|
||||||
|
nodeService.removeChildAssociation(childAssociationRef);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove the extended security from the node
|
||||||
|
// this prevents the users from continuing to see the record in searchs and other linked locations
|
||||||
|
extendedSecurityService.remove(nodeRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove the extended security from the node
|
|
||||||
// this prevents the users from continuing to see the record in searchs and other linked locations
|
|
||||||
extendedSecurityService.remove(nodeRef);
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@@ -34,15 +34,20 @@ import java.util.Map;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.action.impl.CutOffAction;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.action.impl.DeclareRecordAction;
|
import org.alfresco.module.org_alfresco_module_rm.action.impl.DeclareRecordAction;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.action.impl.DestroyAction;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.capability.Capability;
|
import org.alfresco.module.org_alfresco_module_rm.capability.Capability;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
|
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
|
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.test.util.CommonRMTestUtils;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.test.util.bdt.BehaviourTest;
|
import org.alfresco.module.org_alfresco_module_rm.test.util.bdt.BehaviourTest;
|
||||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.security.AccessStatus;
|
import org.alfresco.service.cmr.security.AccessStatus;
|
||||||
import org.alfresco.service.cmr.security.PermissionService;
|
import org.alfresco.service.cmr.security.PermissionService;
|
||||||
|
import org.alfresco.util.GUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In-place record permission integration test.
|
* In-place record permission integration test.
|
||||||
@@ -322,26 +327,253 @@ public class InplaceRecordPermissionTest extends BaseRMTestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a record
|
* Given an inplace record ready for destruction
|
||||||
* When it is destroyed
|
* When it is destroyed
|
||||||
* And it's metadata is maintained
|
* And it's metadata is maintained
|
||||||
* Then the inplace users still have access to the meta-data stub
|
* Then the inplace users will no longer see the record
|
||||||
*/
|
*/
|
||||||
// TODO
|
public void testDestroyedRecordInplacePermissions()
|
||||||
|
{
|
||||||
|
test()
|
||||||
|
.given()
|
||||||
|
|
||||||
|
// Given that a record is declared by a collaborator
|
||||||
|
.as(dmCollaborator)
|
||||||
|
.perform(() -> recordService.createRecord(filePlan, dmDocument))
|
||||||
|
.expect(true)
|
||||||
|
.from(() -> recordService.isRecord(dmDocument))
|
||||||
|
.because("Document is a record.")
|
||||||
|
|
||||||
|
// And it is filed into the file plan
|
||||||
|
// And eligible for destruction
|
||||||
|
.asAdmin()
|
||||||
|
.perform(() ->
|
||||||
|
{
|
||||||
|
// create record category and disposition schedule
|
||||||
|
NodeRef recordCategory = filePlanService.createRecordCategory(filePlan, GUID.generate());
|
||||||
|
utils.createBasicDispositionSchedule(recordCategory, GUID.generate(), GUID.generate(), true, true);
|
||||||
|
|
||||||
|
// create record folder and file record
|
||||||
|
NodeRef recordFolder = recordFolderService.createRecordFolder(recordCategory, GUID.generate());
|
||||||
|
fileFolderService.move(dmDocument, recordFolder, null);
|
||||||
|
|
||||||
|
// cut off record
|
||||||
|
rmActionService.executeRecordsManagementAction(dmDocument, DeclareRecordAction.NAME);
|
||||||
|
utils.completeEvent(dmDocument, CommonRMTestUtils.DEFAULT_EVENT_NAME);
|
||||||
|
rmActionService.executeRecordsManagementAction(dmDocument, CutOffAction.NAME);
|
||||||
|
})
|
||||||
|
.expect("destroy")
|
||||||
|
.from(() -> dispositionService.getNextDispositionAction(dmDocument).getName())
|
||||||
|
.because("The next action is destroy.")
|
||||||
|
.expect(true)
|
||||||
|
.from(() -> dispositionService.isNextDispositionActionEligible(dmDocument))
|
||||||
|
.because("The next action is eligible.")
|
||||||
|
|
||||||
|
// When the record is destroyed
|
||||||
|
.when(() -> rmActionService.executeRecordsManagementAction(dmDocument, DestroyAction.NAME))
|
||||||
|
|
||||||
|
.then()
|
||||||
|
.expect(true)
|
||||||
|
.from(() -> recordService.isMetadataStub(dmDocument))
|
||||||
|
.because("The record has been destroyed and the meta-stub remains.")
|
||||||
|
|
||||||
|
// Then the collaborator has no permissions or capabilities
|
||||||
|
.as(dmCollaborator)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And the consumer has no permissions or capabilities
|
||||||
|
.as(dmConsumer)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And a user that is not in the site has no permissions or capabilities
|
||||||
|
.as(userName)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)); // edit record metadata capability
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given an inplace user with write access
|
* Given an inplace record
|
||||||
* When a role is added to the inplace writers role
|
* And the collaborator has view and edit non-record capability
|
||||||
* Then then they receive that additional capability on the inplace record
|
* And doesn't have edit record capability
|
||||||
|
* When we add edit record metadata capability to the extended writer role
|
||||||
|
* Then the collaborator now has edit record metadata capability
|
||||||
*/
|
*/
|
||||||
// TODO
|
public void testAddUserToRole()
|
||||||
|
{
|
||||||
|
test()
|
||||||
|
.given()
|
||||||
|
.as(dmCollaborator)
|
||||||
|
|
||||||
|
// Given an inplace record
|
||||||
|
.perform(() -> recordService.createRecord(filePlan, dmDocument))
|
||||||
|
.expect(true)
|
||||||
|
.from(() -> recordService.isRecord(dmDocument))
|
||||||
|
.because("Document is a record.")
|
||||||
|
|
||||||
|
// And the collaborator has view and edit non-record capability
|
||||||
|
// And doesn't have edit record capability
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.ALLOWED, // read record permission
|
||||||
|
AccessStatus.ALLOWED, // filing permission
|
||||||
|
AccessStatus.ALLOWED, // view record capability
|
||||||
|
AccessStatus.ALLOWED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
.when()
|
||||||
|
.asAdmin()
|
||||||
|
|
||||||
|
// When we add edit record metadata capability to the extended writer role
|
||||||
|
.perform(() -> filePlanRoleService.updateRole(filePlan,
|
||||||
|
FilePlanRoleService.ROLE_EXTENDED_WRITERS,
|
||||||
|
"",
|
||||||
|
Stream
|
||||||
|
.of(viewRecordsCapability, editNonRecordMetadataCapability, editRecordMetadataCapability)
|
||||||
|
.collect(Collectors.toSet())))
|
||||||
|
|
||||||
|
.then()
|
||||||
|
.as(dmCollaborator)
|
||||||
|
|
||||||
|
// Then the collaborator now has edit record metadata capability
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.ALLOWED, // read record permission
|
||||||
|
AccessStatus.ALLOWED, // filing permission
|
||||||
|
AccessStatus.ALLOWED, // view record capability
|
||||||
|
AccessStatus.ALLOWED, // edit non record metadata capability
|
||||||
|
AccessStatus.ALLOWED)) // edit record metadata capability
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
// hide?
|
/**
|
||||||
// TODO
|
* Given an inplace record
|
||||||
|
* When the record is hidden
|
||||||
|
* Then the collaborator has no access to the record
|
||||||
|
* And the consumer has no access to the record
|
||||||
|
* And a user that is not in the site has no permissions or capabilities
|
||||||
|
*/
|
||||||
|
public void testNoPermissionsAfterHide()
|
||||||
|
{
|
||||||
|
test()
|
||||||
|
.given()
|
||||||
|
.as(dmCollaborator)
|
||||||
|
|
||||||
|
// Given an inplace record
|
||||||
|
.perform(() -> recordService.createRecord(filePlan, dmDocument))
|
||||||
|
.expect(true)
|
||||||
|
.from(() -> recordService.isRecord(dmDocument))
|
||||||
|
.because("Document is a record.")
|
||||||
|
.when()
|
||||||
|
.asAdmin()
|
||||||
|
|
||||||
|
// When the record is hidden
|
||||||
|
.perform(() -> inplaceRecordService.hideRecord(dmDocument))
|
||||||
|
|
||||||
|
.then()
|
||||||
|
|
||||||
|
// Then the collaborator has no access to the record
|
||||||
|
.as(dmCollaborator)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And the consumer has no access to the record
|
||||||
|
.as(dmConsumer)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And a user that is not in the site has no permissions or capabilities
|
||||||
|
.as(userName)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)); // edit record metadata capability
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
// reject?
|
/**
|
||||||
// TODO
|
* Given an inplace record
|
||||||
|
* When the record is rejected
|
||||||
// user added to group ?
|
* Then the collaborator has no access to the record
|
||||||
// TODO
|
* And the consumer has no access to the record
|
||||||
|
* And a user that is not in the site has no permissions or capabilities
|
||||||
|
*/
|
||||||
|
public void testNoPermissionsAfterReject()
|
||||||
|
{
|
||||||
|
test()
|
||||||
|
.given()
|
||||||
|
.as(dmCollaborator)
|
||||||
|
|
||||||
|
// Given an inplace record
|
||||||
|
.perform(() -> recordService.createRecord(filePlan, dmDocument))
|
||||||
|
.expect(true)
|
||||||
|
.from(() -> recordService.isRecord(dmDocument))
|
||||||
|
.because("Document is a record.")
|
||||||
|
.when()
|
||||||
|
.asAdmin()
|
||||||
|
|
||||||
|
// When the record is rejected
|
||||||
|
.perform(() -> recordService.rejectRecord(dmDocument, GUID.generate()))
|
||||||
|
|
||||||
|
.then()
|
||||||
|
|
||||||
|
// Then the collaborator has no access to the record
|
||||||
|
.as(dmCollaborator)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And the consumer has no access to the record
|
||||||
|
.as(dmConsumer)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And a user that is not in the site has no permissions or capabilities
|
||||||
|
.as(userName)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)); // edit record metadata capability
|
||||||
|
;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user