diff --git a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditAddToHoldTests.java b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditAddToHoldTests.java
index 6a291f1e87..d911e81585 100644
--- a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditAddToHoldTests.java
+++ b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditAddToHoldTests.java
@@ -151,21 +151,6 @@ public class AuditAddToHoldTests extends BaseRMRestTest
};
}
- /**
- * Data provider with invalid users that can not add content to a hold
- *
- * @return the userModel
- */
- @DataProvider (name = "invalidUsersForAddToHold")
- public Object[][] getInvalidUsersForAddToHold()
- {
- return new UserModel[][]
- {
- { rmManagerNoReadOnHold },
- { rmManagerNoReadOnNode }
- };
- }
-
/**
* Given a document/record/record folder is added to a hold
* When I view the audit log
@@ -269,11 +254,11 @@ public class AuditAddToHoldTests extends BaseRMRestTest
/**
* Given a document is added to a hold
- * When I view the audit log as an user with no Read permissions over the hold or the document
+ * When I view the audit log as an user with no Read permissions over the document
* Then the add to hold entry isn't visible
*/
- @Test (dataProvider = "invalidUsersForAddToHold")
- public void addToHoldAuditEntryNotVisible(UserModel user)
+ @Test
+ public void addToHoldAuditEntryNotVisible()
{
STEP("Create a new file");
FileModel contentToBeAdded = dataContent.usingAdmin().usingSite(privateSite)
@@ -285,7 +270,33 @@ public class AuditAddToHoldTests extends BaseRMRestTest
STEP("Check that an user with no Read permissions can't see the entry for the add to hold event.");
assertTrue("The list of events should not contain Add to Hold entry ",
- rmAuditService.getAuditEntriesFilteredByEvent(user, ADD_TO_HOLD).isEmpty());
+ rmAuditService.getAuditEntriesFilteredByEvent(rmManagerNoReadOnNode, ADD_TO_HOLD).isEmpty());
+ }
+
+ /**
+ * Given a document is added to a hold
+ * When I view the audit log as an user with no Read permissions over the hold
+ * Then the the hold name is replaced in the add to hold entry
+ */
+ @Test
+ public void addToHoldAuditEntryHoldNameNotVisible()
+ {
+ STEP("Create a new file");
+ FileModel contentToBeAdded = dataContent.usingAdmin().usingSite(privateSite)
+ .createContent(CMISUtil.DocumentType.TEXT_PLAIN);
+ rmAuditService.clearAuditLog();
+
+ STEP("Add file to hold.");
+ holdsAPI.addItemToHold(rmAdmin.getUsername(), rmAdmin.getPassword(), contentToBeAdded.getNodeRefWithoutVersion(), HOLD1);
+
+ auditEntries = rmAuditService.getAuditEntriesFilteredByEvent(rmManagerNoReadOnHold, ADD_TO_HOLD);
+
+ STEP("Check that an user with no Read permissions can't see the hold name in the add to hold event.");
+ String replacementHoldName = "You don't have permission to view this hold.";
+ assertEquals("The list of events should contain the Add to Hold entry", 1, auditEntries.size());
+ assertTrue("The hold name should not be visible in the Add to Hold entry ",
+ auditEntries.stream().anyMatch(entry -> entry.getChangedValues().contains(
+ ImmutableMap.of("new", replacementHoldName, "previous", "", "name", "Hold Name"))));
}
@AfterClass (alwaysRun = true)
diff --git a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditRemoveFromHoldTests.java b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditRemoveFromHoldTests.java
index 2aa77a25ff..1f5b6c2d69 100644
--- a/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditRemoveFromHoldTests.java
+++ b/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditRemoveFromHoldTests.java
@@ -162,21 +162,6 @@ public class AuditRemoveFromHoldTests extends BaseRMRestTest
};
}
- /**
- * Data provider with invalid users that can not remove content from a hold
- *
- * @return the userModel
- */
- @DataProvider (name = "invalidUsersForRemoveFromHold")
- public Object[][] getInvalidUsersForRemoveFromHold()
- {
- return new UserModel[][]
- {
- { rmManagerNoReadOnHold },
- { rmManagerNoReadOnNode }
- };
- }
-
/**
* Given a document/record/record folder is removed from a hold
* When I view the audit log
@@ -280,11 +265,11 @@ public class AuditRemoveFromHoldTests extends BaseRMRestTest
/**
* Given a document/record/record folder is removed from a hold
- * When I view the audit log as an user with no Read permissions over the hold or the node
+ * When I view the audit log as an user with no Read permissions over the node
* Then the remove from hold entry isn't visible
*/
- @Test (dataProvider = "invalidUsersForRemoveFromHold")
- public void removeFromHoldAuditEntryNotVisible(UserModel user)
+ @Test
+ public void removeFromHoldAuditEntryNotVisible()
{
STEP("Add content to a hold.");
FileModel heldFile = dataContent.usingAdmin().usingSite(privateSite)
@@ -298,7 +283,35 @@ public class AuditRemoveFromHoldTests extends BaseRMRestTest
STEP("Check that an user with no Read permissions can't see the entry for the remove from hold event.");
assertTrue("The list of events should not contain Remove from Hold entry ",
- rmAuditService.getAuditEntriesFilteredByEvent(user, REMOVE_FROM_HOLD).isEmpty());
+ rmAuditService.getAuditEntriesFilteredByEvent(rmManagerNoReadOnNode, REMOVE_FROM_HOLD).isEmpty());
+ }
+
+ /**
+ * Given a document/record/record folder is removed from a hold
+ * When I view the audit log as an user with no Read permissions over the hold
+ * Then the the hold name is replaced in the remove from hold entry
+ */
+ @Test
+ public void removeFromHoldAuditEntryHoldNameNotVisible()
+ {
+ STEP("Add content to a hold.");
+ FileModel heldFile = dataContent.usingAdmin().usingSite(privateSite)
+ .createContent(CMISUtil.DocumentType.TEXT_PLAIN);
+ holdsAPI.addItemToHold(rmAdmin.getUsername(), rmAdmin.getPassword(), heldFile.getNodeRefWithoutVersion(), HOLD1);
+
+ rmAuditService.clearAuditLog();
+
+ STEP("Remove held content from the hold.");
+ holdsAPI.removeItemFromHold(rmAdmin.getUsername(), rmAdmin.getPassword(), heldFile.getNodeRefWithoutVersion(), HOLD1);
+
+ auditEntries = rmAuditService.getAuditEntriesFilteredByEvent(rmManagerNoReadOnHold, REMOVE_FROM_HOLD);
+
+ STEP("Check that an user with no Read permissions can't see the hold name in the remove from hold event.");
+ String replacementHoldName = "You don't have permission to view this hold.";
+ assertEquals("The list of events should contain the Remove from Hold entry", 1, auditEntries.size());
+ assertTrue("The hold name should not be visible in the Remove from Hold entry ",
+ auditEntries.stream().anyMatch(entry -> entry.getChangedValues().contains(
+ ImmutableMap.of("new", "", "previous", replacementHoldName, "name", "Hold Name"))));
}
@AfterClass (alwaysRun = true)
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/messages/audit-service.properties b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/messages/audit-service.properties
index b5e7c4079c..acafc32979 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/messages/audit-service.properties
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/messages/audit-service.properties
@@ -17,6 +17,7 @@ rm.audit.createHold=Create Hold
rm.audit.deleteHold=Delete Hold
rm.audit.addToHold=Add To Hold
rm.audit.removeFromHold=Remove From Hold
+rm.audit.holdPermission-Error=You don't have permission to view this hold.
rm.audit.audit-start=Audit Start
rm.audit.audit-stop=Audit Stop
rm.audit.audit-clear=Audit Clear
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
index ccaba88ffc..3b5c7eee06 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
@@ -941,6 +941,7 @@
+
cm:lastThumbnailModification
@@ -1533,7 +1534,6 @@
-
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/RecordsManagementAuditServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/RecordsManagementAuditServiceImpl.java
index 72cb924a53..924c4ec25d 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/RecordsManagementAuditServiceImpl.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/RecordsManagementAuditServiceImpl.java
@@ -61,6 +61,8 @@ import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementAction
import org.alfresco.module.org_alfresco_module_rm.audit.event.AuditEvent;
import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
+import org.alfresco.module.org_alfresco_module_rm.hold.HoldService;
+import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.repo.audit.AuditComponent;
import org.alfresco.repo.audit.model.AuditApplication;
import org.alfresco.repo.content.MimetypeMap;
@@ -195,6 +197,10 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
private static final String AUDIT_EVENT_VIEW = "audit.view";
private static final String MSG_AUDIT_VIEW = "rm.audit.audit-view";
+ private static final QName PROPERTY_HOLD_NAME = QName.createQName(RecordsManagementModel.RM_URI, "Hold Name");
+ private static final QName PROPERTY_HOLD_NODEREF = QName.createQName(RecordsManagementModel.RM_URI, "Hold NodeRef");
+ private static final String HOLD_PERMISSION_DENIED_MSG = "rm.audit.holdPermission-Error";
+
private PolicyComponent policyComponent;
private DictionaryService dictionaryService;
private TransactionService transactionService;
@@ -208,6 +214,7 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
private NamespaceService namespaceService;
protected CapabilityService capabilityService;
protected PermissionService permissionService;
+ protected HoldService holdService;
private boolean shutdown = false;
@@ -333,6 +340,15 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
this.permissionService = permissionService;
}
+ /**
+ *
+ * @param holdService
+ */
+ public void setHoldService(HoldService holdService)
+ {
+ this.holdService = holdService;
+ }
+
/**
* @see org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditService#registerAuditEvent(java.lang.String, java.lang.String)
*/
@@ -687,7 +703,8 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
/**
* Helper method to remove system properties from maps
*
- * @param properties
+ * @param before properties before event
+ * @param after properties after event
*/
private void removeAuditProperties(Map before, Map after)
{
@@ -864,220 +881,7 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
}
// define the callback
- AuditQueryCallback callback = new AuditQueryCallback()
- {
- private boolean firstEntry = true;
-
-
- @Override
- public boolean valuesRequired()
- {
- return true;
- }
-
- /**
- * Just log the error, but continue
- */
- @Override
- public boolean handleAuditEntryError(Long entryId, String errorMsg, Throwable error)
- {
- logger.warn(errorMsg, error);
- return true;
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public boolean handleAuditEntry(
- Long entryId,
- String applicationName,
- String user,
- long time,
- Map values)
- {
- // Check for context shutdown
- if (shutdown)
- {
- return false;
- }
-
-
- Date timestamp = new Date(time);
- String eventName = null;
- String fullName = null;
- String userRoles = null;
- NodeRef nodeRef = null;
- String nodeName = null;
- String nodeType = null;
- String nodeIdentifier = null;
- String namePath = null;
- Map beforeProperties = null;
- Map afterProperties = null;
-
- if (values.containsKey(RM_AUDIT_DATA_EVENT_NAME))
- {
- // This data is /RM/event/...
- eventName = (String) values.get(RM_AUDIT_DATA_EVENT_NAME);
- fullName = (String) values.get(RM_AUDIT_DATA_PERSON_FULLNAME);
- userRoles = (String) values.get(RM_AUDIT_DATA_PERSON_ROLES);
- nodeRef = (NodeRef) values.get(RM_AUDIT_DATA_NODE_NODEREF);
- nodeName = (String) values.get(RM_AUDIT_DATA_NODE_NAME);
- QName nodeTypeQname = (QName) values.get(RM_AUDIT_DATA_NODE_TYPE);
- nodeIdentifier = (String) values.get(RM_AUDIT_DATA_NODE_IDENTIFIER);
- namePath = (String) values.get(RM_AUDIT_DATA_NODE_NAMEPATH);
- beforeProperties = (Map) values.get(RM_AUDIT_DATA_NODE_CHANGES_BEFORE);
- afterProperties = (Map) values.get(RM_AUDIT_DATA_NODE_CHANGES_AFTER);
-
- // Convert some of the values to recognizable forms
- nodeType = null;
- if (nodeTypeQname != null)
- {
- TypeDefinition typeDef = dictionaryService.getType(nodeTypeQname);
- nodeType = (typeDef != null) ? typeDef.getTitle(dictionaryService) : null;
- }
- }
- else if (values.containsKey(DOD5015_AUDIT_DATA_EVENT_NAME))
- {
- // This data is /RM/event/...
- eventName = (String) values.get(DOD5015_AUDIT_DATA_EVENT_NAME);
- fullName = (String) values.get(DOD5015_AUDIT_DATA_PERSON_FULLNAME);
- userRoles = (String) values.get(DOD5015_AUDIT_DATA_PERSON_ROLES);
- nodeRef = (NodeRef) values.get(DOD5015_AUDIT_DATA_NODE_NODEREF);
- nodeName = (String) values.get(DOD5015_AUDIT_DATA_NODE_NAME);
- QName nodeTypeQname = (QName) values.get(DOD5015_AUDIT_DATA_NODE_TYPE);
- nodeIdentifier = (String) values.get(DOD5015_AUDIT_DATA_NODE_IDENTIFIER);
- namePath = (String) values.get(DOD5015_AUDIT_DATA_NODE_NAMEPATH);
- beforeProperties = (Map) values.get( DOD5015_AUDIT_DATA_NODE_CHANGES_BEFORE);
- afterProperties = (Map) values.get(DOD5015_AUDIT_DATA_NODE_CHANGES_AFTER);
-
- // Convert some of the values to recognizable forms
- nodeType = null;
- if (nodeTypeQname != null)
- {
- TypeDefinition typeDef = dictionaryService.getType(nodeTypeQname);
- nodeType = (typeDef != null) ? typeDef.getTitle(dictionaryService) : null;
- }
- }
- else if (values.containsKey(RM_AUDIT_DATA_LOGIN_USERNAME))
- {
- user = (String) values.get(RM_AUDIT_DATA_LOGIN_USERNAME);
- if (values.containsKey(RM_AUDIT_DATA_LOGIN_ERROR))
- {
- eventName = RM_AUDIT_EVENT_LOGIN_FAILURE;
- // The user didn't log in
- fullName = user;
- }
- else
- {
- eventName = RM_AUDIT_EVENT_LOGIN_SUCCESS;
- fullName = (String) values.get(RM_AUDIT_DATA_LOGIN_FULLNAME);
- }
- }
- else if (values.containsKey(DOD5015_AUDIT_DATA_LOGIN_USERNAME))
- {
- user = (String) values.get(DOD5015_AUDIT_DATA_LOGIN_USERNAME);
- if (values.containsKey(DOD5015_AUDIT_DATA_LOGIN_ERROR))
- {
- eventName = RM_AUDIT_EVENT_LOGIN_FAILURE;
- // The user didn't log in
- fullName = user;
- }
- else
- {
- eventName = RM_AUDIT_EVENT_LOGIN_SUCCESS;
- fullName = (String) values.get(DOD5015_AUDIT_DATA_LOGIN_FULLNAME);
- }
- }
- else
- {
- // This is not recognisable data
- logger.warn(
- "Unable to process audit entry for RM. Unexpected data: \n" +
- " Entry: " + entryId + "\n" +
- " Data: " + values);
- // Skip it
- return true;
- }
-
- if (nodeRef != null && nodeService.exists(nodeRef) &&
- ((filePlanService.isFilePlanComponent(nodeRef) &&
- !AccessStatus.ALLOWED.equals(
- capabilityService.getCapabilityAccessState(nodeRef, ACCESS_AUDIT_CAPABILITY)))
- || (!AccessStatus.ALLOWED.equals(permissionService.hasPermission(nodeRef, PermissionService.READ)))))
- {
- return true;
- }
-
- // TODO: Refactor this to use the builder pattern
- RecordsManagementAuditEntry entry = new RecordsManagementAuditEntry(
- timestamp,
- user,
- fullName,
- // A concatenated string of roles
- userRoles,
- nodeRef,
- nodeName,
- nodeType,
- eventName,
- nodeIdentifier,
- namePath,
- beforeProperties,
- afterProperties);
-
- // write out the entry to the file in requested format
- writeEntryToFile(entry);
-
- if (results != null)
- {
- results.add(entry);
- }
-
- if (logger.isDebugEnabled())
- {
- logger.debug(" " + entry);
- }
-
- // Keep going
- return true;
- }
-
- private void writeEntryToFile(RecordsManagementAuditEntry entry)
- {
- if (writer == null)
- {
- return;
- }
- try
- {
- if (!firstEntry)
- {
- if (reportFormat == ReportFormat.HTML)
- {
- writer.write("\n");
- }
- else
- {
- writer.write(",");
- }
- }
- else
- {
- firstEntry = false;
- }
-
- // write the entry to the file
- if (reportFormat == ReportFormat.JSON)
- {
- writer.write("\n\t\t");
- }
-
- writeAuditTrailEntry(writer, entry, reportFormat);
- }
- catch (IOException ioe)
- {
- throw new AlfrescoRuntimeException(MSG_TRAIL_FILE_FAIL, ioe);
- }
- }
- };
+ AuditQueryCallback callback = new AuditTrailQueryCallback(results, writer, reportFormat);
String user = params.getUser();
Long fromTime = getFromDateTime(params.getDateFrom());
@@ -1174,7 +978,7 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
/**
* Gets the start of the from date
- * @see org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditServiceImpl.getStartOfDay()
+ * @see org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditServiceImpl#getStartOfDay(java.util.Date)
*
* @param date The date for which the start should be retrieved.
* @return Returns null if the given date is null, otherwise the start of the given day.
@@ -1216,7 +1020,7 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
/**
* Gets the end of the from date
- * @see org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditServiceImpl.getEndOfDay()
+ * @see org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditServiceImpl#getEndOfDay(java.util.Date)
*
* @param date The date for which the end should be retrieved.
* @return Returns null if the given date is null, otherwise the end of the given day.
@@ -1912,4 +1716,270 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
{
auditEvent(nodeRef, action.getName());
}
+
+ private class AuditTrailQueryCallback implements AuditQueryCallback
+ {
+ private final List results;
+ private final Writer writer;
+ private final ReportFormat reportFormat;
+ private boolean firstEntry;
+
+ public AuditTrailQueryCallback(List results, Writer writer, ReportFormat reportFormat)
+ {
+ this.results = results;
+ this.writer = writer;
+ this.reportFormat = reportFormat;
+ firstEntry = true;
+ }
+
+
+ @Override
+ public boolean valuesRequired()
+ {
+ return true;
+ }
+
+ /**
+ * Just log the error, but continue
+ */
+ @Override
+ public boolean handleAuditEntryError(Long entryId, String errorMsg, Throwable error)
+ {
+ logger.warn(errorMsg, error);
+ return true;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public boolean handleAuditEntry(
+ Long entryId,
+ String applicationName,
+ String user,
+ long time,
+ Map values)
+ {
+ // Check for context shutdown
+ if (shutdown)
+ {
+ return false;
+ }
+
+
+ Date timestamp = new Date(time);
+ String eventName = null;
+ String fullName = null;
+ String userRoles = null;
+ NodeRef nodeRef = null;
+ String nodeName = null;
+ String nodeType = null;
+ String nodeIdentifier = null;
+ String namePath = null;
+ Map beforeProperties = null;
+ Map afterProperties = null;
+
+ if (values.containsKey(RM_AUDIT_DATA_EVENT_NAME))
+ {
+ // This data is /RM/event/...
+ eventName = (String) values.get(RM_AUDIT_DATA_EVENT_NAME);
+ fullName = (String) values.get(RM_AUDIT_DATA_PERSON_FULLNAME);
+ userRoles = (String) values.get(RM_AUDIT_DATA_PERSON_ROLES);
+ nodeRef = (NodeRef) values.get(RM_AUDIT_DATA_NODE_NODEREF);
+ nodeName = (String) values.get(RM_AUDIT_DATA_NODE_NAME);
+ QName nodeTypeQname = (QName) values.get(RM_AUDIT_DATA_NODE_TYPE);
+ nodeIdentifier = (String) values.get(RM_AUDIT_DATA_NODE_IDENTIFIER);
+ namePath = (String) values.get(RM_AUDIT_DATA_NODE_NAMEPATH);
+ beforeProperties = (Map) values.get(RM_AUDIT_DATA_NODE_CHANGES_BEFORE);
+ afterProperties = (Map) values.get(RM_AUDIT_DATA_NODE_CHANGES_AFTER);
+
+ // Convert some of the values to recognizable forms
+ if (nodeTypeQname != null)
+ {
+ TypeDefinition typeDef = dictionaryService.getType(nodeTypeQname);
+ nodeType = (typeDef != null) ? typeDef.getTitle(dictionaryService) : null;
+ }
+ }
+ else if (values.containsKey(DOD5015_AUDIT_DATA_EVENT_NAME))
+ {
+ // This data is /DOD5015/event/...
+ eventName = (String) values.get(DOD5015_AUDIT_DATA_EVENT_NAME);
+ fullName = (String) values.get(DOD5015_AUDIT_DATA_PERSON_FULLNAME);
+ userRoles = (String) values.get(DOD5015_AUDIT_DATA_PERSON_ROLES);
+ nodeRef = (NodeRef) values.get(DOD5015_AUDIT_DATA_NODE_NODEREF);
+ nodeName = (String) values.get(DOD5015_AUDIT_DATA_NODE_NAME);
+ QName nodeTypeQname = (QName) values.get(DOD5015_AUDIT_DATA_NODE_TYPE);
+ nodeIdentifier = (String) values.get(DOD5015_AUDIT_DATA_NODE_IDENTIFIER);
+ namePath = (String) values.get(DOD5015_AUDIT_DATA_NODE_NAMEPATH);
+ beforeProperties = (Map) values.get( DOD5015_AUDIT_DATA_NODE_CHANGES_BEFORE);
+ afterProperties = (Map) values.get(DOD5015_AUDIT_DATA_NODE_CHANGES_AFTER);
+
+ // Convert some of the values to recognizable forms
+ if (nodeTypeQname != null)
+ {
+ TypeDefinition typeDef = dictionaryService.getType(nodeTypeQname);
+ nodeType = (typeDef != null) ? typeDef.getTitle(dictionaryService) : null;
+ }
+ }
+ else if (values.containsKey(RM_AUDIT_DATA_LOGIN_USERNAME))
+ {
+ user = (String) values.get(RM_AUDIT_DATA_LOGIN_USERNAME);
+ if (values.containsKey(RM_AUDIT_DATA_LOGIN_ERROR))
+ {
+ eventName = RM_AUDIT_EVENT_LOGIN_FAILURE;
+ // The user didn't log in
+ fullName = user;
+ }
+ else
+ {
+ eventName = RM_AUDIT_EVENT_LOGIN_SUCCESS;
+ fullName = (String) values.get(RM_AUDIT_DATA_LOGIN_FULLNAME);
+ }
+ }
+ else if (values.containsKey(DOD5015_AUDIT_DATA_LOGIN_USERNAME))
+ {
+ user = (String) values.get(DOD5015_AUDIT_DATA_LOGIN_USERNAME);
+ if (values.containsKey(DOD5015_AUDIT_DATA_LOGIN_ERROR))
+ {
+ eventName = RM_AUDIT_EVENT_LOGIN_FAILURE;
+ // The user didn't log in
+ fullName = user;
+ }
+ else
+ {
+ eventName = RM_AUDIT_EVENT_LOGIN_SUCCESS;
+ fullName = (String) values.get(DOD5015_AUDIT_DATA_LOGIN_FULLNAME);
+ }
+ }
+ else
+ {
+ // This is not recognisable data
+ logger.warn(
+ "Unable to process audit entry for RM. Unexpected data: \n" +
+ " Entry: " + entryId + "\n" +
+ " Data: " + values);
+ // Skip it
+ return true;
+ }
+
+ if (nodeRef != null && nodeService.exists(nodeRef))
+ {
+ if ((filePlanService.isFilePlanComponent(nodeRef) &&
+ !AccessStatus.ALLOWED.equals(
+ capabilityService.getCapabilityAccessState(nodeRef, ACCESS_AUDIT_CAPABILITY))) ||
+ (!AccessStatus.ALLOWED.equals(permissionService.hasPermission(nodeRef, PermissionService.READ))))
+ {
+ return true;
+ }
+
+ checkPermissionIfHoldInProperties(beforeProperties);
+ checkPermissionIfHoldInProperties(afterProperties);
+ }
+
+ // remove any hold node refs from view
+ removeHoldNodeRefIfPresent(beforeProperties);
+ removeHoldNodeRefIfPresent(afterProperties);
+
+ // TODO: Refactor this to use the builder pattern
+ RecordsManagementAuditEntry entry = new RecordsManagementAuditEntry(
+ timestamp,
+ user,
+ fullName,
+ // A concatenated string of roles
+ userRoles,
+ nodeRef,
+ nodeName,
+ nodeType,
+ eventName,
+ nodeIdentifier,
+ namePath,
+ beforeProperties,
+ afterProperties);
+
+ // write out the entry to the file in requested format
+ writeEntryToFile(entry);
+
+ if (results != null)
+ {
+ results.add(entry);
+ }
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug(" " + entry);
+ }
+
+ // Keep going
+ return true;
+ }
+
+ /**
+ * Helper method to check permission on the hold, if any, from the given event properties
+ * @param eventProperties event properties
+ */
+ private void checkPermissionIfHoldInProperties(Map eventProperties)
+ {
+ NodeRef holdNodeRef = eventProperties != null ? (NodeRef) eventProperties.get(PROPERTY_HOLD_NODEREF) : null;
+ if (holdNodeRef != null)
+ {
+ if (!AccessStatus.ALLOWED.equals(
+ permissionService.hasPermission(holdNodeRef, PermissionService.READ)))
+ {
+ eventProperties.replace(PROPERTY_HOLD_NAME, I18NUtil.getMessage(HOLD_PERMISSION_DENIED_MSG));
+ }
+ }
+ }
+
+ /**
+ * Helper method to remove the hold node ref, if any, from the given event properties
+ * @param eventProperties event properties
+ */
+ private void removeHoldNodeRefIfPresent(Map eventProperties)
+ {
+ if (eventProperties != null)
+ {
+ eventProperties.remove(PROPERTY_HOLD_NODEREF);
+ }
+ }
+
+ /**
+ * Helper method to write the audit entry to file
+ * @param entry audit entry
+ */
+ private void writeEntryToFile(RecordsManagementAuditEntry entry)
+ {
+ if (writer == null)
+ {
+ return;
+ }
+ try
+ {
+ if (!firstEntry)
+ {
+ if (reportFormat == ReportFormat.HTML)
+ {
+ writer.write("\n");
+ }
+ else
+ {
+ writer.write(",");
+ }
+ }
+ else
+ {
+ firstEntry = false;
+ }
+
+ // write the entry to the file
+ if (reportFormat == ReportFormat.JSON)
+ {
+ writer.write("\n\t\t");
+ }
+
+ writeAuditTrailEntry(writer, entry, reportFormat);
+ }
+ catch (IOException ioe)
+ {
+ throw new AlfrescoRuntimeException(MSG_TRAIL_FILE_FAIL, ioe);
+ }
+ }
+ }
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/HoldUtils.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/HoldUtils.java
index 641b7f016d..d8faecc72e 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/HoldUtils.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/HoldUtils.java
@@ -47,18 +47,22 @@ class HoldUtils
{
/** A QName to display for the hold name. */
public static final QName HOLD_NAME = QName.createQName(RecordsManagementModel.RM_URI, "Hold Name");
+ /** A QName to display for the hold node ref. */
+ public static final QName HOLD_NODEREF = QName.createQName(RecordsManagementModel.RM_URI, "Hold NodeRef");
+
/**
- * Create a properties map containing the hold name for the given hold.
+ * Create a properties map containing the hold name and node ref for the given hold.
*
* @param nodeRef The nodeRef of the hold.
* @param nodeService The node service.
- * @return A map containing the name of the hold.
+ * @return A map containing the name and noderef of the hold.
*/
static Map makePropertiesMap(NodeRef nodeRef, NodeService nodeService)
{
Map auditProperties = new HashMap<>();
auditProperties.put(HOLD_NAME, nodeService.getProperty(nodeRef, ContentModel.PROP_NAME));
+ auditProperties.put(HOLD_NODEREF, nodeRef);
return auditProperties;
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/hold/HoldServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/hold/HoldServiceImpl.java
index 869da2ca2d..141b25cee1 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/hold/HoldServiceImpl.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/hold/HoldServiceImpl.java
@@ -43,7 +43,6 @@ import java.util.stream.Stream;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
-import org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditService;
import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
@@ -119,9 +118,6 @@ public class HoldServiceImpl extends ServiceBaseImpl
/** Permission service */
private PermissionService permissionService;
- /** records management audit service */
- private RecordsManagementAuditService recordsManagementAuditService;
-
/** Capability service */
private CapabilityService capabilityService;
@@ -168,14 +164,6 @@ public class HoldServiceImpl extends ServiceBaseImpl
this.permissionService = permissionService;
}
- /**
- * @param recordsManagementAuditService records management audit service
- */
- public void setRecordsManagementAuditService(RecordsManagementAuditService recordsManagementAuditService)
- {
- this.recordsManagementAuditService = recordsManagementAuditService;
- }
-
/**
* @param capabilityService capability service
*/