Merge branch 'feature/RM-7028_Add_Add_To_Hold_ToAudit' into 'master'

RM-7028 Audit add to hold

Closes RM-7028

See merge request records-management/records-management!1296
This commit is contained in:
Sara Aspery
2019-11-19 18:21:37 +00:00
11 changed files with 483 additions and 185 deletions

View File

@@ -15,6 +15,7 @@ rm.audit.copyTo=Copy to
rm.audit.fileTo=File to rm.audit.fileTo=File to
rm.audit.createHold=Create Hold rm.audit.createHold=Create Hold
rm.audit.deleteHold=Delete Hold rm.audit.deleteHold=Delete Hold
rm.audit.addToHold=Add To Hold
rm.audit.audit-start=Audit Start rm.audit.audit-start=Audit Start
rm.audit.audit-stop=Audit Stop rm.audit.audit-stop=Audit Stop
rm.audit.audit-clear=Audit Clear rm.audit.audit-clear=Audit Clear

View File

@@ -14,11 +14,13 @@
<property name="filePlanRoleService" ref="filePlanRoleService" /> <property name="filePlanRoleService" ref="filePlanRoleService" />
</bean> </bean>
<bean id="org_alfresco_module_rm_namePathExtractor" class="org.alfresco.module.org_alfresco_module_rm.audit.extractor.FilePlanNamePathDataExtractor"> <bean id="org_alfresco_module_rm_namePathExtractor" class="org.alfresco.module.org_alfresco_module_rm.audit.extractor.NamePathDataExtractor">
<property name="registry" ref="auditModel.extractorRegistry" /> <property name="registry" ref="auditModel.extractorRegistry" />
<property name="nodeService" ref="nodeService" /> <property name="nodeService" ref="nodeService" />
<property name="filePlanService" ref="filePlanService" /> <property name="filePlanService" ref="filePlanService" />
<property name="ruleService" ref="RuleService" /> <property name="ruleService" ref="RuleService" />
<property name="permissionService" ref="PermissionService" />
<property name="dictionaryService" ref="DictionaryService" />
</bean> </bean>
<bean id="org_alfresco_module_rm_nodeRefPathExtractor" class="org.alfresco.module.org_alfresco_module_rm.audit.extractor.FilePlanNodeRefPathDataExtractor"> <bean id="org_alfresco_module_rm_nodeRefPathExtractor" class="org.alfresco.module.org_alfresco_module_rm.audit.extractor.FilePlanNodeRefPathDataExtractor">
@@ -138,4 +140,11 @@
<property name="name" value="Delete Hold"/> <property name="name" value="Delete Hold"/>
<property name="label" value="rm.audit.deleteHold"/> <property name="label" value="rm.audit.deleteHold"/>
</bean> </bean>
<bean id="audit-event.addToHold" parent="audit-event" class="org.alfresco.module.org_alfresco_module_rm.audit.event.AddToHoldAuditEvent">
<property name="nodeService" ref="nodeService" />
<property name="name" value="Add To Hold"/>
<property name="label" value="rm.audit.addToHold"/>
</bean>
</beans> </beans>

View File

@@ -0,0 +1,85 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2019 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* 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/>.
* #L%
*/
package org.alfresco.module.org_alfresco_module_rm.audit.event;
import static org.alfresco.repo.policy.Behaviour.NotificationFrequency.EVERY_EVENT;
import java.io.Serializable;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.hold.HoldServicePolicies;
import org.alfresco.repo.policy.annotation.Behaviour;
import org.alfresco.repo.policy.annotation.BehaviourBean;
import org.alfresco.repo.policy.annotation.BehaviourKind;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName;
/**
* Add to hold audit event.
*
* @author Sara Aspery
* @since 3.3
*/
@BehaviourBean
public class AddToHoldAuditEvent extends AuditEvent implements HoldServicePolicies.OnAddToHoldPolicy
{
/**
* Node Service
*/
private NodeService nodeService;
/**
* Sets the node service
*
* @param nodeService nodeService to set
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.hold.HoldServicePolicies.OnAddToHoldPolicy#onAddToHold(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
@Behaviour
(
kind = BehaviourKind.CLASS,
type = "rma:hold",
notificationFrequency = EVERY_EVENT
)
public void onAddToHold(NodeRef holdNodeRef, NodeRef contentNodeRef)
{
Map<QName, Serializable> auditProperties = HoldUtils.makePropertiesMap(holdNodeRef, nodeService);
auditProperties.put(ContentModel.PROP_NAME, nodeService.getProperty(contentNodeRef, ContentModel.PROP_NAME));
recordsManagementAuditService.auditEvent(contentNodeRef, getName(), null, auditProperties, true, false);
}
}

View File

@@ -35,25 +35,33 @@ import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.repo.audit.extractor.AbstractDataExtractor; import org.alfresco.repo.audit.extractor.AbstractDataExtractor;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.Path;
import org.alfresco.service.cmr.rule.RuleService; import org.alfresco.service.cmr.rule.RuleService;
import org.alfresco.service.cmr.security.PermissionService;
/** /**
* An extractor that extracts the <b>cm:name</b> path from the RM root down to * An extractor that extracts the <b>cm:name</b> path from the RM root down to
* - and including - the node's own name. This will only extract data if the * - and including - the node's own name. This will only extract data if the
* node is a {@link RecordsManagementModel#ASPECT_FILE_PLAN_COMPONENT fileplan component}. * node is a {@link RecordsManagementModel#ASPECT_FILE_PLAN_COMPONENT fileplan component}
* or is a subtype of content.
* *
* @see FilePlanService#getNodeRefPath(NodeRef) * @see FilePlanService#getNodeRefPath(NodeRef)
* *
* @author Derek Hulley * @author Derek Hulley
* @since 3.2 * @since 3.2
* @author Sara Aspery
* @since AGS 3.3
*/ */
public final class FilePlanNamePathDataExtractor extends AbstractDataExtractor public final class NamePathDataExtractor extends AbstractDataExtractor
{ {
private NodeService nodeService; private NodeService nodeService;
private FilePlanService filePlanService; private FilePlanService filePlanService;
private RuleService ruleService; private RuleService ruleService;
private PermissionService permissionService;
private DictionaryService dictionaryService;
/** /**
* Used to check that the node in the context is a fileplan component * Used to check that the node in the context is a fileplan component
@@ -68,8 +76,8 @@ public final class FilePlanNamePathDataExtractor extends AbstractDataExtractor
*/ */
public void setFilePlanService(FilePlanService filePlanService) public void setFilePlanService(FilePlanService filePlanService)
{ {
this.filePlanService = filePlanService; this.filePlanService = filePlanService;
} }
/** /**
* @param ruleService the ruleService to set * @param ruleService the ruleService to set
@@ -80,8 +88,24 @@ public final class FilePlanNamePathDataExtractor extends AbstractDataExtractor
} }
/** /**
* @return Returns <tt>true</tt> if the data is a NodeRef and it represents * @param permissionService permission service
* a fileplan component */
public void setPermissionService(PermissionService permissionService)
{
this.permissionService = permissionService;
}
/**
* @param dictionaryService dictionary service
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
/**
* @return Returns <tt>true</tt> if the data is a NodeRef and it either represents
* a fileplan component or is frozen
*/ */
public boolean isSupported(Serializable data) public boolean isSupported(Serializable data)
{ {
@@ -89,7 +113,9 @@ public final class FilePlanNamePathDataExtractor extends AbstractDataExtractor
{ {
return false; return false;
} }
return nodeService.hasAspect((NodeRef)data, RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT); NodeRef nodeRef = (NodeRef) data;
return nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT) ||
dictionaryService.isSubClass(nodeService.getType(nodeRef), ContentModel.TYPE_CONTENT);
} }
/** /**
@@ -97,25 +123,34 @@ public final class FilePlanNamePathDataExtractor extends AbstractDataExtractor
*/ */
public Serializable extractData(Serializable value) public Serializable extractData(Serializable value)
{ {
String extractedData = null; String extractedData;
ruleService.disableRules(); ruleService.disableRules();
try try
{ {
NodeRef nodeRef = (NodeRef) value; NodeRef nodeRef = (NodeRef) value;
StringBuilder sb = new StringBuilder(128); StringBuilder sb = new StringBuilder(128);
if (nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT)) if (nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT))
{ {
// Get path from the RM root // Get path from the RM root
List<NodeRef> nodeRefPath = filePlanService.getNodeRefPath(nodeRef); List<NodeRef> nodeRefPath = filePlanService.getNodeRefPath(nodeRef);
for (NodeRef pathNodeRef : nodeRefPath) for (NodeRef pathNodeRef : nodeRefPath)
{ {
String name = (String)nodeService.getProperty(pathNodeRef, ContentModel.PROP_NAME); String name = (String) nodeService.getProperty(pathNodeRef, ContentModel.PROP_NAME);
sb.append("/").append(name); sb.append("/").append(name);
} }
} }
else if (dictionaryService.isSubClass(nodeService.getType(nodeRef), ContentModel.TYPE_CONTENT))
{
// Get path from the DM root
Path nodeRefPath = nodeService.getPath(nodeRef);
sb.append(nodeRefPath.toDisplayPath(nodeService, permissionService));
// Get node name
String name = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
sb.append("/").append(name);
}
// Done // Done
extractedData = sb.toString(); extractedData = sb.toString();
@@ -143,9 +178,9 @@ public final class FilePlanNamePathDataExtractor extends AbstractDataExtractor
{ {
return false; return false;
} }
FilePlanNamePathDataExtractor that = (FilePlanNamePathDataExtractor) o; NamePathDataExtractor that = (NamePathDataExtractor) o;
return Objects.equals(nodeService, that.nodeService) && Objects.equals(filePlanService, that.filePlanService) return Objects.equals(nodeService, that.nodeService) && Objects.equals(filePlanService, that.filePlanService)
&& Objects.equals(ruleService, that.ruleService); && Objects.equals(ruleService, that.ruleService);
} }
@Override @Override
@@ -154,3 +189,4 @@ public final class FilePlanNamePathDataExtractor extends AbstractDataExtractor
return Objects.hash(nodeService, filePlanService, ruleService); return Objects.hash(nodeService, filePlanService, ruleService);
} }
} }

View File

@@ -100,7 +100,6 @@ public class HoldServiceImpl extends ServiceBaseImpl
private static Log logger = LogFactory.getLog(HoldServiceImpl.class); private static Log logger = LogFactory.getLog(HoldServiceImpl.class);
/** Audit event keys */ /** Audit event keys */
private static final String AUDIT_ADD_TO_HOLD = "addToHold";
private static final String AUDIT_REMOVE_FROM_HOLD = "removeFromHold"; private static final String AUDIT_REMOVE_FROM_HOLD = "removeFromHold";
/** I18N */ /** I18N */
@@ -225,7 +224,6 @@ public class HoldServiceImpl extends ServiceBaseImpl
@Override @Override
public Void doWork() throws Exception public Void doWork() throws Exception
{ {
recordsManagementAuditService.registerAuditEvent(new AuditEvent(AUDIT_ADD_TO_HOLD, "capability.AddToHold.title"));
recordsManagementAuditService.registerAuditEvent(new AuditEvent(AUDIT_REMOVE_FROM_HOLD, "capability.RemoveFromHold.title")); recordsManagementAuditService.registerAuditEvent(new AuditEvent(AUDIT_REMOVE_FROM_HOLD, "capability.RemoveFromHold.title"));
return null; return null;
} }
@@ -667,9 +665,6 @@ public class HoldServiceImpl extends ServiceBaseImpl
transactionalResourceHelper.getSet("frozen").add(nodeRef); transactionalResourceHelper.getSet("frozen").add(nodeRef);
nodeService.addChild(hold, nodeRef, ASSOC_FROZEN_CONTENT, ASSOC_FROZEN_CONTENT); nodeService.addChild(hold, nodeRef, ASSOC_FROZEN_CONTENT, ASSOC_FROZEN_CONTENT);
// audit item being added to the hold
recordsManagementAuditService.auditEvent(nodeRef, AUDIT_ADD_TO_HOLD);
// Mark all the folders contents as frozen // Mark all the folders contents as frozen
if (isRecordFolder(nodeRef)) if (isRecordFolder(nodeRef))
{ {

View File

@@ -109,7 +109,11 @@ public class DeleteHoldTest extends BaseRMTestCase implements BeforeDeleteHoldPo
public NodeRef run() throws Exception public NodeRef run() throws Exception
{ {
// create test holds // create test holds
return createAndCheckHold(); NodeRef newHold = createAndCheckHold();
// add the record folder to hold1
holdService.addToHold(newHold, rmFolder);
return newHold;
} }
}); });
//Splitting transaction to fix onCreateNodePolicy issue where there was a node not found exception //Splitting transaction to fix onCreateNodePolicy issue where there was a node not found exception
@@ -118,9 +122,6 @@ public class DeleteHoldTest extends BaseRMTestCase implements BeforeDeleteHoldPo
@Override @Override
public Void run() throws Exception public Void run() throws Exception
{ {
// add the record folder to hold1
holdService.addToHold(hold1, rmFolder);
// assert that the folder and records are frozen // assert that the folder and records are frozen
assertTrue(freezeService.isFrozen(rmFolder)); assertTrue(freezeService.isFrozen(rmFolder));
assertTrue(freezeService.isFrozen(recordOne)); assertTrue(freezeService.isFrozen(recordOne));
@@ -162,33 +163,44 @@ public class DeleteHoldTest extends BaseRMTestCase implements BeforeDeleteHoldPo
//Splitting transaction to fix onCreateNodePolicy issue where there was a node not found exception //Splitting transaction to fix onCreateNodePolicy issue where there was a node not found exception
doTestInTransaction(new Test<Void>() doTestInTransaction(new Test<Void>()
{ {
@Override @Override
public Void run() throws Exception public Void run() throws Exception
{ {
NodeRef hold1 = holds.get(0); NodeRef hold1 = holds.get(0);
NodeRef hold2 = holds.get(1); NodeRef hold2 = holds.get(1);
// add the record folder to hold1 // add the record folder to hold1
holdService.addToHold(hold1, rmFolder); holdService.addToHold(hold1, rmFolder);
// assert that the folder and records are frozen // assert that the folder and records are frozen
assertTrue(freezeService.isFrozen(rmFolder)); assertTrue(freezeService.isFrozen(rmFolder));
assertTrue(freezeService.isFrozen(recordOne)); assertTrue(freezeService.isFrozen(recordOne));
assertTrue(freezeService.isFrozen(recordDeclaredOne)); assertTrue(freezeService.isFrozen(recordDeclaredOne));
// check the contents of the hold // check the contents of the hold
List<NodeRef> frozenNodes = holdService.getHeld(hold1); List<NodeRef> frozenNodes = holdService.getHeld(hold1);
assertNotNull(frozenNodes); assertNotNull(frozenNodes);
assertEquals(1, frozenNodes.size()); assertEquals(1, frozenNodes.size());
assertEquals(rmFolder, frozenNodes.get(0)); assertEquals(rmFolder, frozenNodes.get(0));
holdService.addToHold(hold2, recordOne); holdService.addToHold(hold2, recordOne);
// assert that the folder and records are frozen // assert that the folder and records are frozen
assertTrue(freezeService.isFrozen(rmFolder)); assertTrue(freezeService.isFrozen(rmFolder));
assertTrue(freezeService.isFrozen(recordOne)); assertTrue(freezeService.isFrozen(recordOne));
assertTrue(freezeService.isFrozen(recordDeclaredOne)); assertTrue(freezeService.isFrozen(recordDeclaredOne));
return null;
}
});
doTestInTransaction(new Test<Void>()
{
@Override
public Void run() throws Exception
{
NodeRef hold1 = holds.get(0);
NodeRef hold2 = holds.get(1);
// delete the hold // delete the hold
holdService.deleteHold(hold1); holdService.deleteHold(hold1);

View File

@@ -62,7 +62,7 @@ public class RecordsManagementAuditServiceImplTest extends BaseRMTestCase
implements RMPermissionModel implements RMPermissionModel
{ {
/** A QName to display for the hold name. */ /** A QName to display for the hold name. */
public static final QName HOLD_NAME = QName.createQName(RecordsManagementModel.RM_URI, "Hold Name"); private static final QName HOLD_NAME = QName.createQName(RecordsManagementModel.RM_URI, "Hold Name");
/** Test record */ /** Test record */
private NodeRef record; private NodeRef record;
@@ -108,6 +108,15 @@ public class RecordsManagementAuditServiceImplTest extends BaseRMTestCase
return true; return true;
} }
/**
* @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase#isCollaborationSiteTest()
*/
@Override
protected boolean isCollaborationSiteTest()
{
return true;
}
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase#setupTestDataImpl() * @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase#setupTestDataImpl()
*/ */
@@ -574,61 +583,11 @@ public class RecordsManagementAuditServiceImplTest extends BaseRMTestCase
}); });
} }
/**
* Given I have created a hold
* When I delete the hold and get the RM audit filter by delete hold event
* Then there will be an entry for the deleted hold, including the hold name
*/
@org.junit.Test
public void testAuditForDeleteHold()
{
doBehaviourDrivenTest(new BehaviourDrivenTest()
{
final static String DELETE_HOLD_AUDIT_EVENT = "Delete Hold";
String holdName = "Hold " + GUID.generate();
NodeRef hold;
Map<QName, Serializable> auditEventProperties;
@Override
public void given()
{
rmAuditService.clearAuditLog(filePlan);
hold = createHold(holdName, "Reason " + GUID.generate());
}
@Override
public void when()
{
deleteHold(hold);
auditEventProperties = getAuditEntry(DELETE_HOLD_AUDIT_EVENT).getBeforeProperties();
}
@Override
public void then()
{
// check delete hold audit event includes the hold name
assertEquals("Delete Hold event does not include hold name.", holdName,
auditEventProperties.get(HOLD_NAME));
}
@Override
public void after()
{
// Stop and delete all entries
rmAuditService.stopAuditLog(filePlan);
rmAuditService.clearAuditLog(filePlan);
}
});
}
/** /**
* Given I have created a hold * Given I have created a hold
* When I will get the RM audit filter by create hold event * When I will get the RM audit filter by create hold event
* Then there will be an entry for the created hold, including the hold name and reason * Then there will be an entry for the created hold, including the hold name and reason
*/ */
@org.junit.Test
public void testAuditForCreateHold() public void testAuditForCreateHold()
{ {
doBehaviourDrivenTest(new BehaviourDrivenTest() doBehaviourDrivenTest(new BehaviourDrivenTest()
@@ -638,14 +597,13 @@ public class RecordsManagementAuditServiceImplTest extends BaseRMTestCase
String holdName = "Hold " + GUID.generate(); String holdName = "Hold " + GUID.generate();
String holdReason = "Reason " + GUID.generate(); String holdReason = "Reason " + GUID.generate();
NodeRef hold;
Map<QName, Serializable> auditEventProperties; Map<QName, Serializable> auditEventProperties;
@Override @Override
public void given() public void given()
{ {
rmAuditService.clearAuditLog(filePlan); rmAuditService.clearAuditLog(filePlan);
hold = createHold(holdName, holdReason); utils.createHold(filePlan, holdName, holdReason);
} }
@Override @Override
@@ -676,6 +634,107 @@ public class RecordsManagementAuditServiceImplTest extends BaseRMTestCase
}); });
} }
/**
* Given I have created a hold
* When I delete the hold and get the RM audit filter by delete hold event
* Then there will be an entry for the deleted hold, including the hold name
*/
public void testAuditForDeleteHold()
{
doBehaviourDrivenTest(new BehaviourDrivenTest()
{
final static String DELETE_HOLD_AUDIT_EVENT = "Delete Hold";
String holdName = "Hold " + GUID.generate();
NodeRef hold;
Map<QName, Serializable> auditEventProperties;
@Override
public void given()
{
rmAuditService.clearAuditLog(filePlan);
hold = utils.createHold(filePlan, holdName, "Reason " + GUID.generate());
}
@Override
public void when()
{
utils.deleteHold(hold);
auditEventProperties = getAuditEntry(DELETE_HOLD_AUDIT_EVENT).getBeforeProperties();
}
@Override
public void then()
{
// check delete hold audit event includes the hold name
assertEquals("Delete Hold event does not include hold name.", holdName,
auditEventProperties.get(HOLD_NAME));
}
@Override
public void after()
{
// Stop and delete all entries
rmAuditService.stopAuditLog(filePlan);
rmAuditService.clearAuditLog(filePlan);
}
});
}
/**
* Given I have added an item of content to a hold
* When I get the RM audit filter by add to hold event
* Then there will be an entry for the item added to the hold, including both the item name and hold name
*/
public void testAuditForAddContentToHold()
{
doBehaviourDrivenTest(new BehaviourDrivenTest()
{
final static String ADD_TO_HOLD_AUDIT_EVENT = "Add To Hold";
String holdName = "Hold " + GUID.generate();
NodeRef hold;
Map<QName, Serializable> auditEventProperties;
@Override
public void given()
{
rmAuditService.clearAuditLog(filePlan);
hold = utils.createHold(filePlan, holdName, "Reason " + GUID.generate());
utils.addItemToHold(hold, dmDocument);
}
@Override
public void when()
{
auditEventProperties = getAuditEntry(ADD_TO_HOLD_AUDIT_EVENT).getAfterProperties();
}
@Override
public void then()
{
// check add to hold audit event includes the hold name
assertEquals("Add To Hold event does not include hold name.", holdName,
auditEventProperties.get(HOLD_NAME));
// check add to hold audit event includes the content name
String contentName = (String) nodeService.getProperty(dmDocument, PROP_NAME);
assertEquals("Add To Hold event does not include content name.", contentName,
auditEventProperties.get(PROP_NAME));
}
@Override
public void after()
{
// Stop and delete all entries
rmAuditService.stopAuditLog(filePlan);
rmAuditService.clearAuditLog(filePlan);
}
});
}
/** === Helper methods === */ /** === Helper methods === */
private List<RecordsManagementAuditEntry> getAuditTrail(String asUser) private List<RecordsManagementAuditEntry> getAuditTrail(String asUser)

View File

@@ -92,8 +92,6 @@ import org.alfresco.util.GUID;
import org.alfresco.util.RetryingTransactionHelperTestCase; import org.alfresco.util.RetryingTransactionHelperTestCase;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import static org.alfresco.util.GUID.generate;
/** /**
* Base test case class to use for RM unit tests. * Base test case class to use for RM unit tests.
* *
@@ -709,26 +707,6 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
return createPerson(userName, true); return createPerson(userName, true);
} }
/**
* Util method to create a hold.
* @param holdName hold name
* @param holdReason hold reason
* @return NodeRef hold node reference
*/
protected NodeRef createHold(String holdName, String holdReason)
{
return holdService.createHold(filePlan, holdName, holdReason, generate());
}
/**
* Util method to delete a hold.
* @param nodeRef hold node reference
*/
protected void deleteHold(NodeRef nodeRef)
{
holdService.deleteHold(nodeRef);
}
/** /**
* Setup multi hierarchy test data * Setup multi hierarchy test data
*/ */

View File

@@ -27,6 +27,8 @@
package org.alfresco.module.org_alfresco_module_rm.test.util; package org.alfresco.module.org_alfresco_module_rm.test.util;
import static org.alfresco.util.GUID.generate;
import java.io.InputStream; import java.io.InputStream;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
@@ -48,6 +50,7 @@ import org.alfresco.module.org_alfresco_module_rm.capability.Capability;
import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService; import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
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.disposition.DispositionService; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService;
import org.alfresco.module.org_alfresco_module_rm.hold.HoldService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.module.org_alfresco_module_rm.model.security.ModelSecurityService; import org.alfresco.module.org_alfresco_module_rm.model.security.ModelSecurityService;
import org.alfresco.module.org_alfresco_module_rm.record.RecordService; import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
@@ -72,16 +75,9 @@ import org.springframework.context.ApplicationContext;
*/ */
public class CommonRMTestUtils implements RecordsManagementModel public class CommonRMTestUtils implements RecordsManagementModel
{ {
private DispositionService dispositionService; /**
private NodeService nodeService; * test values
private ContentService contentService; */
private RecordsManagementActionService actionService;
private ModelSecurityService modelSecurityService;
private FilePlanRoleService filePlanRoleService;
private CapabilityService capabilityService;
private RecordService recordService;
/** test values */
public static final String DEFAULT_DISPOSITION_AUTHORITY = "disposition authority"; public static final String DEFAULT_DISPOSITION_AUTHORITY = "disposition authority";
public static final String DEFAULT_DISPOSITION_INSTRUCTIONS = "disposition instructions"; public static final String DEFAULT_DISPOSITION_INSTRUCTIONS = "disposition instructions";
public static final String DEFAULT_DISPOSITION_DESCRIPTION = "disposition action description"; public static final String DEFAULT_DISPOSITION_DESCRIPTION = "disposition action description";
@@ -91,22 +87,32 @@ public class CommonRMTestUtils implements RecordsManagementModel
public static final String PERIOD_ONE_WEEK = "week|1"; public static final String PERIOD_ONE_WEEK = "week|1";
public static final String PERIOD_ONE_YEAR = "year|1"; public static final String PERIOD_ONE_YEAR = "year|1";
public static final String PERIOD_THREE_YEARS = "year|3"; public static final String PERIOD_THREE_YEARS = "year|3";
private DispositionService dispositionService;
private NodeService nodeService;
private ContentService contentService;
private RecordsManagementActionService actionService;
private ModelSecurityService modelSecurityService;
private FilePlanRoleService filePlanRoleService;
private CapabilityService capabilityService;
private RecordService recordService;
private HoldService holdService;
/** /**
* Constructor * Constructor
* *
* @param applicationContext application context * @param applicationContext application context
*/ */
public CommonRMTestUtils(ApplicationContext applicationContext) public CommonRMTestUtils(ApplicationContext applicationContext)
{ {
dispositionService = (DispositionService)applicationContext.getBean("DispositionService"); dispositionService = (DispositionService) applicationContext.getBean("DispositionService");
nodeService = (NodeService)applicationContext.getBean("NodeService"); nodeService = (NodeService) applicationContext.getBean("NodeService");
contentService = (ContentService)applicationContext.getBean("ContentService"); contentService = (ContentService) applicationContext.getBean("ContentService");
actionService = (RecordsManagementActionService)applicationContext.getBean("RecordsManagementActionService"); actionService = (RecordsManagementActionService) applicationContext.getBean("RecordsManagementActionService");
modelSecurityService = (ModelSecurityService)applicationContext.getBean("ModelSecurityService"); modelSecurityService = (ModelSecurityService) applicationContext.getBean("ModelSecurityService");
filePlanRoleService = (FilePlanRoleService)applicationContext.getBean("FilePlanRoleService"); filePlanRoleService = (FilePlanRoleService) applicationContext.getBean("FilePlanRoleService");
capabilityService = (CapabilityService)applicationContext.getBean("CapabilityService"); capabilityService = (CapabilityService) applicationContext.getBean("CapabilityService");
recordService = (RecordService)applicationContext.getBean("RecordService"); recordService = (RecordService) applicationContext.getBean("RecordService");
holdService = (HoldService) applicationContext.getBean("HoldService");
} }
/** /**
@@ -123,26 +129,26 @@ public class CommonRMTestUtils implements RecordsManagementModel
/** /**
* Create test disposition schedule * Create test disposition schedule
*/ */
public DispositionSchedule createBasicDispositionSchedule( public DispositionSchedule createBasicDispositionSchedule(
NodeRef container, NodeRef container,
String dispositionInstructions, String dispositionInstructions,
String dispositionAuthority, String dispositionAuthority,
boolean isRecordLevel, boolean isRecordLevel,
boolean defaultDispositionActions) boolean defaultDispositionActions)
{ {
return createDispositionSchedule(container, dispositionInstructions, dispositionAuthority, isRecordLevel, defaultDispositionActions, false); return createDispositionSchedule(container, dispositionInstructions, dispositionAuthority, isRecordLevel, defaultDispositionActions, false);
} }
/** /**
* Create test disposition schedule * Create test disposition schedule
*/ */
public DispositionSchedule createDispositionSchedule( public DispositionSchedule createDispositionSchedule(
NodeRef container, NodeRef container,
String dispositionInstructions, String dispositionInstructions,
String dispositionAuthority, String dispositionAuthority,
boolean isRecordLevel, boolean isRecordLevel,
boolean defaultDispositionActions, boolean defaultDispositionActions,
boolean extendedDispositionSchedule) boolean extendedDispositionSchedule)
{ {
return createDispositionSchedule( return createDispositionSchedule(
container, container,
@@ -158,13 +164,13 @@ public class CommonRMTestUtils implements RecordsManagementModel
* Create test disposition schedule * Create test disposition schedule
*/ */
public DispositionSchedule createDispositionSchedule( public DispositionSchedule createDispositionSchedule(
NodeRef container, NodeRef container,
String dispositionInstructions, String dispositionInstructions,
String dispositionAuthority, String dispositionAuthority,
boolean isRecordLevel, boolean isRecordLevel,
boolean defaultDispositionActions, boolean defaultDispositionActions,
boolean extendedDispositionSchedule, boolean extendedDispositionSchedule,
String defaultEvent) String defaultEvent)
{ {
Map<QName, Serializable> dsProps = new HashMap<>(3); Map<QName, Serializable> dsProps = new HashMap<>(3);
dsProps.put(PROP_DISPOSITION_AUTHORITY, dispositionAuthority); dsProps.put(PROP_DISPOSITION_AUTHORITY, dispositionAuthority);
@@ -180,7 +186,7 @@ public class CommonRMTestUtils implements RecordsManagementModel
List<String> events = new ArrayList<>(1); List<String> events = new ArrayList<>(1);
events.add(defaultEvent); events.add(defaultEvent);
adParams.put(PROP_DISPOSITION_EVENT, (Serializable)events); adParams.put(PROP_DISPOSITION_EVENT, (Serializable) events);
dispositionService.addDispositionActionDefinition(dispositionSchedule, adParams); dispositionService.addDispositionActionDefinition(dispositionSchedule, adParams);
@@ -209,8 +215,8 @@ public class CommonRMTestUtils implements RecordsManagementModel
/** /**
* Helper method to create a record in a record folder. * Helper method to create a record in a record folder.
* *
* @param recordFolder record folder * @param recordFolder record folder
* @param name name of record * @param name name of record
* @return {@link NodeRef} record node reference * @return {@link NodeRef} record node reference
*/ */
public NodeRef createRecord(NodeRef recordFolder, String name) public NodeRef createRecord(NodeRef recordFolder, String name)
@@ -221,9 +227,9 @@ public class CommonRMTestUtils implements RecordsManagementModel
/** /**
* Helper method to create a record in a record folder. * Helper method to create a record in a record folder.
* *
* @param recordFolder record folder * @param recordFolder record folder
* @param name name of the record * @param name name of the record
* @param title title of the record * @param title title of the record
* @return {@link NodeRef} record node reference * @return {@link NodeRef} record node reference
*/ */
public NodeRef createRecord(NodeRef recordFolder, String name, String title) public NodeRef createRecord(NodeRef recordFolder, String name, String title)
@@ -236,10 +242,10 @@ public class CommonRMTestUtils implements RecordsManagementModel
/** /**
* Helper method to create a record in a record folder. * Helper method to create a record in a record folder.
* *
* @param recordFolder record folder * @param recordFolder record folder
* @param name name of record * @param name name of record
* @param properties properties of the record * @param properties properties of the record
* @param content content of the record * @param content content of the record
* @return {@link NodeRef} record node reference * @return {@link NodeRef} record node reference
*/ */
public NodeRef createRecord(NodeRef recordFolder, String name, Map<QName, Serializable> properties, String content) public NodeRef createRecord(NodeRef recordFolder, String name, Map<QName, Serializable> properties, String content)
@@ -259,10 +265,10 @@ public class CommonRMTestUtils implements RecordsManagementModel
/** /**
* Helper method to create a record in a record folder. * Helper method to create a record in a record folder.
* *
* @param recordFolder record folder * @param recordFolder record folder
* @param name name of record * @param name name of record
* @param properties properties of the record * @param properties properties of the record
* @param content content of the record * @param content content of the record
* @return {@link NodeRef} record node reference * @return {@link NodeRef} record node reference
*/ */
public NodeRef createRecord(NodeRef recordFolder, String name, Map<QName, Serializable> properties, String mimetype, InputStream content) public NodeRef createRecord(NodeRef recordFolder, String name, Map<QName, Serializable> properties, String mimetype, InputStream content)
@@ -373,7 +379,7 @@ public class CommonRMTestUtils implements RecordsManagementModel
}, AuthenticationUtil.getAdminUserName()); }, AuthenticationUtil.getAdminUserName());
} }
public Role createRole(NodeRef filePlan, String roleName, String ... capabilityNames) public Role createRole(NodeRef filePlan, String roleName, String... capabilityNames)
{ {
Set<Capability> capabilities = new HashSet<>(capabilityNames.length); Set<Capability> capabilities = new HashSet<>(capabilityNames.length);
for (String name : capabilityNames) for (String name : capabilityNames)
@@ -392,8 +398,8 @@ public class CommonRMTestUtils implements RecordsManagementModel
/** /**
* Helper method to complete event on disposable item * Helper method to complete event on disposable item
* *
* @param disposableItem disposable item (record or record folder) * @param disposableItem disposable item (record or record folder)
* @param eventName event name * @param eventName event name
*/ */
public void completeEvent(NodeRef disposableItem, String eventName) public void completeEvent(NodeRef disposableItem, String eventName)
{ {
@@ -404,4 +410,37 @@ public class CommonRMTestUtils implements RecordsManagementModel
// complete event // complete event
actionService.executeRecordsManagementAction(disposableItem, CompleteEventAction.NAME, params); actionService.executeRecordsManagementAction(disposableItem, CompleteEventAction.NAME, params);
} }
/**
* Helper method to create a hold.
*
* @param holdName hold name
* @param holdReason hold reason
* @return NodeRef hold node reference
*/
public NodeRef createHold(NodeRef filePlan, String holdName, String holdReason)
{
return holdService.createHold(filePlan, holdName, holdReason, generate());
}
/**
* Helper method to delete a hold.
*
* @param nodeRef hold node reference
*/
public void deleteHold(NodeRef nodeRef)
{
holdService.deleteHold(nodeRef);
}
/**
* Util method to add content to a hold.
*
* @param holdNodeRef hold node reference
* @param contentNodeRef content node reference
*/
public void addItemToHold(NodeRef holdNodeRef, NodeRef contentNodeRef)
{
holdService.addToHold(holdNodeRef, contentNodeRef);
}
} }

View File

@@ -0,0 +1,92 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2019 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* 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/>.
* #L%
*/
package org.alfresco.module.org_alfresco_module_rm.audit.event;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.util.GUID;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import java.util.Map;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
/**
* Unit tests for {@link AddToHoldAuditEvent}.
*
* @author Sara Aspery
* @since 3.3
*/
public class AddToHoldAuditEventUnitTest extends BaseUnitTest
{
@InjectMocks
private AddToHoldAuditEvent addToHoldAuditEvent;
@Mock
private NodeService mockedNodeService;
private NodeRef holdNodeRef;
private NodeRef contentNodeRef;
/** Set up the mocks. */
@Before
public void setUp()
{
initMocks(this);
holdNodeRef = generateNodeRef();
String holdName = "Hold " + GUID.generate();
contentNodeRef = generateNodeRef();
String contentName = "Content " + GUID.generate();
when(mockedNodeService.getProperty(holdNodeRef, PROP_NAME)).thenReturn(holdName);
when(mockedNodeService.getProperty(contentNodeRef, PROP_NAME)).thenReturn(contentName);
}
/**
* Check that the add to hold event calls an audit event.
*
*/
@Test
public void testAddToHoldCausesAuditEvent()
{
addToHoldAuditEvent.onAddToHold(holdNodeRef, contentNodeRef);
verify(mockedRecordsManagementAuditService, times(1)).auditEvent(eq(contentNodeRef), any(String.class), isNull(Map.class), any(Map.class), eq(true), eq(false));
}
}

View File

@@ -346,18 +346,15 @@ public class HoldServiceImplUnitTest extends BaseUnitTest
verify(mockedNodeService).addChild(hold, recordFolder, ASSOC_FROZEN_CONTENT, ASSOC_FROZEN_CONTENT); verify(mockedNodeService).addChild(hold, recordFolder, ASSOC_FROZEN_CONTENT, ASSOC_FROZEN_CONTENT);
verify(mockedNodeService).addAspect(eq(recordFolder), eq(ASPECT_FROZEN), any(Map.class)); verify(mockedNodeService).addAspect(eq(recordFolder), eq(ASPECT_FROZEN), any(Map.class));
verify(mockedNodeService).addAspect(eq(record), eq(ASPECT_FROZEN), any(Map.class)); verify(mockedNodeService).addAspect(eq(record), eq(ASPECT_FROZEN), any(Map.class));
verify(mockedRecordsManagementAuditService).auditEvent(eq(recordFolder), anyString());
holdService.addToHold(hold, record); holdService.addToHold(hold, record);
verify(mockedNodeService).addChild(hold, record, ASSOC_FROZEN_CONTENT, ASSOC_FROZEN_CONTENT); verify(mockedNodeService).addChild(hold, record, ASSOC_FROZEN_CONTENT, ASSOC_FROZEN_CONTENT);
verify(mockedNodeService).addAspect(eq(recordFolder), eq(ASPECT_FROZEN), any(Map.class)); verify(mockedNodeService).addAspect(eq(recordFolder), eq(ASPECT_FROZEN), any(Map.class));
verify(mockedNodeService, times(2)).addAspect(eq(record), eq(ASPECT_FROZEN), any(Map.class)); verify(mockedNodeService, times(2)).addAspect(eq(record), eq(ASPECT_FROZEN), any(Map.class));
verify(mockedRecordsManagementAuditService).auditEvent(eq(record), anyString());
holdService.addToHold(hold, activeContent); holdService.addToHold(hold, activeContent);
verify(mockedNodeService).addChild(hold, activeContent, ASSOC_FROZEN_CONTENT, ASSOC_FROZEN_CONTENT); verify(mockedNodeService).addChild(hold, activeContent, ASSOC_FROZEN_CONTENT, ASSOC_FROZEN_CONTENT);
verify(mockedNodeService).addAspect(eq(activeContent), eq(ASPECT_FROZEN), any(Map.class)); verify(mockedNodeService).addAspect(eq(activeContent), eq(ASPECT_FROZEN), any(Map.class));
verify(mockedRecordsManagementAuditService).auditEvent(eq(activeContent), anyString());
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@@ -371,13 +368,11 @@ public class HoldServiceImplUnitTest extends BaseUnitTest
verify(mockedNodeService, never()).addChild(hold, recordFolder, ASSOC_FROZEN_CONTENT, ASSOC_FROZEN_CONTENT); verify(mockedNodeService, never()).addChild(hold, recordFolder, ASSOC_FROZEN_CONTENT, ASSOC_FROZEN_CONTENT);
verify(mockedNodeService, never()).addAspect(eq(recordFolder), eq(ASPECT_FROZEN), any(Map.class)); verify(mockedNodeService, never()).addAspect(eq(recordFolder), eq(ASPECT_FROZEN), any(Map.class));
verify(mockedNodeService, never()).addAspect(eq(record), eq(ASPECT_FROZEN), any(Map.class)); verify(mockedNodeService, never()).addAspect(eq(record), eq(ASPECT_FROZEN), any(Map.class));
verify(mockedRecordsManagementAuditService, never()).auditEvent(eq(recordFolder), anyString());
holdService.addToHold(hold, activeContent); holdService.addToHold(hold, activeContent);
verify(mockedNodeService, never()).addChild(hold, activeContent, ASSOC_FROZEN_CONTENT, ASSOC_FROZEN_CONTENT); verify(mockedNodeService, never()).addChild(hold, activeContent, ASSOC_FROZEN_CONTENT, ASSOC_FROZEN_CONTENT);
verify(mockedNodeService, never()).addAspect(eq(activeContent), eq(ASPECT_FROZEN), any(Map.class)); verify(mockedNodeService, never()).addAspect(eq(activeContent), eq(ASPECT_FROZEN), any(Map.class));
verify(mockedRecordsManagementAuditService, never()).auditEvent(eq(activeContent), anyString());
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@@ -395,12 +390,10 @@ public class HoldServiceImplUnitTest extends BaseUnitTest
verify(mockedNodeService).addChild(hold, recordFolder, ASSOC_FROZEN_CONTENT, ASSOC_FROZEN_CONTENT); verify(mockedNodeService).addChild(hold, recordFolder, ASSOC_FROZEN_CONTENT, ASSOC_FROZEN_CONTENT);
verify(mockedNodeService, never()).addAspect(eq(recordFolder), eq(ASPECT_FROZEN), any(Map.class)); verify(mockedNodeService, never()).addAspect(eq(recordFolder), eq(ASPECT_FROZEN), any(Map.class));
verify(mockedNodeService, never()).addAspect(eq(record), eq(ASPECT_FROZEN), any(Map.class)); verify(mockedNodeService, never()).addAspect(eq(record), eq(ASPECT_FROZEN), any(Map.class));
verify(mockedRecordsManagementAuditService).auditEvent(eq(recordFolder), anyString());
holdService.addToHold(hold, activeContent); holdService.addToHold(hold, activeContent);
verify(mockedNodeService).addChild(hold, activeContent, ASSOC_FROZEN_CONTENT, ASSOC_FROZEN_CONTENT); verify(mockedNodeService).addChild(hold, activeContent, ASSOC_FROZEN_CONTENT, ASSOC_FROZEN_CONTENT);
verify(mockedNodeService, never()).addAspect(eq(activeContent), eq(ASPECT_FROZEN), any(Map.class)); verify(mockedNodeService, never()).addAspect(eq(activeContent), eq(ASPECT_FROZEN), any(Map.class));
verify(mockedRecordsManagementAuditService).auditEvent(eq(activeContent), anyString());
} }
@Test (expected = AccessDeniedException.class) @Test (expected = AccessDeniedException.class)
@@ -466,7 +459,6 @@ public class HoldServiceImplUnitTest extends BaseUnitTest
verify(mockedNodeService, times(1)).addChild(hold2, recordFolder, ASSOC_FROZEN_CONTENT, ASSOC_FROZEN_CONTENT); verify(mockedNodeService, times(1)).addChild(hold2, recordFolder, ASSOC_FROZEN_CONTENT, ASSOC_FROZEN_CONTENT);
verify(mockedNodeService, times(1)).addAspect(eq(recordFolder), eq(ASPECT_FROZEN), any(Map.class)); verify(mockedNodeService, times(1)).addAspect(eq(recordFolder), eq(ASPECT_FROZEN), any(Map.class));
verify(mockedNodeService, times(1)).addAspect(eq(record), eq(ASPECT_FROZEN), any(Map.class)); verify(mockedNodeService, times(1)).addAspect(eq(record), eq(ASPECT_FROZEN), any(Map.class));
verify(mockedRecordsManagementAuditService, times(2)).auditEvent(eq(recordFolder), anyString());
} }
@Test (expected = IntegrityException.class) @Test (expected = IntegrityException.class)