RM-812 (Unable to audit for events that happened on a single day only, that is, date from and to being the same)

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@53938 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Tuna Aksoy
2013-08-12 11:28:15 +00:00
parent 026cc3035c
commit 9714ce7727

View File

@@ -26,6 +26,7 @@ import java.io.OutputStreamWriter;
import java.io.Serializable; import java.io.Serializable;
import java.io.Writer; import java.io.Writer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -71,6 +72,7 @@ import org.alfresco.util.PropertyCheck;
import org.alfresco.util.PropertyMap; import org.alfresco.util.PropertyMap;
import org.alfresco.util.TempFileProvider; import org.alfresco.util.TempFileProvider;
import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.json.JSONArray; import org.json.JSONArray;
@@ -228,11 +230,11 @@ public class RecordsManagementAuditServiceImpl
{ {
this.rmActionService = rmActionService; this.rmActionService = rmActionService;
} }
/** /**
* @param filePlanService file plan service * @param filePlanService file plan service
*/ */
public void setFilePlanService(FilePlanService filePlanService) public void setFilePlanService(FilePlanService filePlanService)
{ {
this.filePlanService = filePlanService; this.filePlanService = filePlanService;
} }
@@ -329,9 +331,9 @@ public class RecordsManagementAuditServiceImpl
new AuditEvent("unfreeze", MSG_UNFREEZE)); new AuditEvent("unfreeze", MSG_UNFREEZE));
this.auditEvents.put("reject", this.auditEvents.put("reject",
new AuditEvent("reject", MSG_REJECT_RECORD)); new AuditEvent("reject", MSG_REJECT_RECORD));
// Added for DOD compliance // Added for DOD compliance
this.auditEvents.put("createPerson", this.auditEvents.put("createPerson",
new AuditEvent("createPerson", "User Created")); new AuditEvent("createPerson", "User Created"));
} }
@@ -352,11 +354,11 @@ public class RecordsManagementAuditServiceImpl
policyComponent.bindClassBehaviour( policyComponent.bindClassBehaviour(
BeforeDeleteNodePolicy.QNAME, BeforeDeleteNodePolicy.QNAME,
RecordsManagementModel.ASPECT_RECORD_COMPONENT_ID, RecordsManagementModel.ASPECT_RECORD_COMPONENT_ID,
new JavaBehaviour(this, "beforeDeleteNode")); new JavaBehaviour(this, "beforeDeleteNode"));
policyComponent.bindClassBehaviour( policyComponent.bindClassBehaviour(
OnCreateNodePolicy.QNAME, OnCreateNodePolicy.QNAME,
ContentModel.TYPE_PERSON, ContentModel.TYPE_PERSON,
new JavaBehaviour(this, "onCreatePersonNode")); new JavaBehaviour(this, "onCreatePersonNode"));
} }
@Override @Override
@@ -364,11 +366,11 @@ public class RecordsManagementAuditServiceImpl
{ {
shutdown = true; shutdown = true;
} }
/*** TODO remove this when we support multiple file plans ****/ /*** TODO remove this when we support multiple file plans ****/
private NodeRef defaultFilePlan; private NodeRef defaultFilePlan;
private NodeRef getDefaultFilePlan() private NodeRef getDefaultFilePlan()
{ {
if (defaultFilePlan == null) if (defaultFilePlan == null)
@@ -381,7 +383,7 @@ public class RecordsManagementAuditServiceImpl
} }
return defaultFilePlan; return defaultFilePlan;
} }
/*** TODO end ***/ /*** TODO end ***/
/** /**
@@ -389,19 +391,19 @@ public class RecordsManagementAuditServiceImpl
*/ */
@Override @Override
@Deprecated @Deprecated
public boolean isEnabled() public boolean isEnabled()
{ {
return isAuditLogEnabled(getDefaultFilePlan()); return isAuditLogEnabled(getDefaultFilePlan());
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public boolean isAuditLogEnabled(NodeRef filePlan) public boolean isAuditLogEnabled(NodeRef filePlan)
{ {
ParameterCheck.mandatory("filePlan", filePlan); ParameterCheck.mandatory("filePlan", filePlan);
// TODO use file plan to scope audit log // TODO use file plan to scope audit log
return auditService.isAuditEnabled( return auditService.isAuditEnabled(
RecordsManagementAuditService.RM_AUDIT_APPLICATION_NAME, RecordsManagementAuditService.RM_AUDIT_APPLICATION_NAME,
RecordsManagementAuditService.RM_AUDIT_PATH_ROOT); RecordsManagementAuditService.RM_AUDIT_PATH_ROOT);
@@ -415,19 +417,19 @@ public class RecordsManagementAuditServiceImpl
{ {
startAuditLog(getDefaultFilePlan()); startAuditLog(getDefaultFilePlan());
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public void startAuditLog(NodeRef filePlan) public void startAuditLog(NodeRef filePlan)
{ {
ParameterCheck.mandatory("filePlan", filePlan); ParameterCheck.mandatory("filePlan", filePlan);
// TODO use file plan to scope audit log // TODO use file plan to scope audit log
auditService.enableAudit( auditService.enableAudit(
RecordsManagementAuditService.RM_AUDIT_APPLICATION_NAME, RecordsManagementAuditService.RM_AUDIT_APPLICATION_NAME,
RecordsManagementAuditService.RM_AUDIT_PATH_ROOT); RecordsManagementAuditService.RM_AUDIT_PATH_ROOT);
if (logger.isInfoEnabled()) if (logger.isInfoEnabled())
{ {
logger.info("Started Records Management auditing"); logger.info("Started Records Management auditing");
@@ -442,22 +444,22 @@ public class RecordsManagementAuditServiceImpl
{ {
stopAuditLog(getDefaultFilePlan()); stopAuditLog(getDefaultFilePlan());
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public void stopAuditLog(NodeRef filePlan) public void stopAuditLog(NodeRef filePlan)
{ {
ParameterCheck.mandatory("filePlan", filePlan); ParameterCheck.mandatory("filePlan", filePlan);
// TODO use file plan to scope audit log // TODO use file plan to scope audit log
auditService.disableAudit( auditService.disableAudit(
RecordsManagementAuditService.RM_AUDIT_APPLICATION_NAME, RecordsManagementAuditService.RM_AUDIT_APPLICATION_NAME,
RecordsManagementAuditService.RM_AUDIT_PATH_ROOT); RecordsManagementAuditService.RM_AUDIT_PATH_ROOT);
if (logger.isInfoEnabled()) if (logger.isInfoEnabled())
logger.info("Stopped Records Management auditing"); logger.info("Stopped Records Management auditing");
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -472,9 +474,9 @@ public class RecordsManagementAuditServiceImpl
*/ */
public void clearAuditLog(NodeRef filePlan) public void clearAuditLog(NodeRef filePlan)
{ {
ParameterCheck.mandatory("filePlan", filePlan); ParameterCheck.mandatory("filePlan", filePlan);
// TODO use file plan to scope audit log // TODO use file plan to scope audit log
auditService.clearAudit(RecordsManagementAuditService.RM_AUDIT_APPLICATION_NAME, null, null); auditService.clearAudit(RecordsManagementAuditService.RM_AUDIT_APPLICATION_NAME, null, null);
if (logger.isInfoEnabled()) if (logger.isInfoEnabled())
logger.debug("Records Management audit log has been cleared"); logger.debug("Records Management audit log has been cleared");
@@ -488,19 +490,19 @@ public class RecordsManagementAuditServiceImpl
{ {
return getDateAuditLogLastStarted(getDefaultFilePlan()); return getDateAuditLogLastStarted(getDefaultFilePlan());
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public Date getDateAuditLogLastStarted(NodeRef filePlan) public Date getDateAuditLogLastStarted(NodeRef filePlan)
{ {
ParameterCheck.mandatory("filePlan", filePlan); ParameterCheck.mandatory("filePlan", filePlan);
// TODO use file plan to scope audit log // TODO use file plan to scope audit log
// TODO: return proper date, for now it's today's date // TODO: return proper date, for now it's today's date
return new Date(); return getStartOfDay(new Date());
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -515,11 +517,11 @@ public class RecordsManagementAuditServiceImpl
*/ */
public Date getDateAuditLogLastStopped(NodeRef filePlan) public Date getDateAuditLogLastStopped(NodeRef filePlan)
{ {
ParameterCheck.mandatory("filePlan", filePlan); ParameterCheck.mandatory("filePlan", filePlan);
// TODO use file plan to scope audit log // TODO use file plan to scope audit log
// TODO: return proper date, for now it's today's date // TODO: return proper date, for now it's today's date
return new Date(); return getEndOfDay(new Date());
} }
/** /**
@@ -579,12 +581,12 @@ public class RecordsManagementAuditServiceImpl
{ {
auditRMEvent(childAssocRef.getChildRef(), RM_AUDIT_EVENT_CREATE_RM_OBJECT, null, null); auditRMEvent(childAssocRef.getChildRef(), RM_AUDIT_EVENT_CREATE_RM_OBJECT, null, null);
} }
public void onCreatePersonNode(ChildAssociationRef childAssocRef) public void onCreatePersonNode(ChildAssociationRef childAssocRef)
{ {
auditRMEvent(childAssocRef.getChildRef(), "createPerson", null, null); auditRMEvent(childAssocRef.getChildRef(), "createPerson", null, null);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
* @since 3.2 * @since 3.2
@@ -618,7 +620,7 @@ public class RecordsManagementAuditServiceImpl
// be extracted now and the audit entry needs to be created now. // be extracted now and the audit entry needs to be created now.
Map<String, Serializable> auditMap = buildAuditMap(nodeRef, eventName); Map<String, Serializable> auditMap = buildAuditMap(nodeRef, eventName);
auditMap = auditComponent.recordAuditValues(RecordsManagementAuditService.RM_AUDIT_PATH_ROOT, auditMap); auditMap = auditComponent.recordAuditValues(RecordsManagementAuditService.RM_AUDIT_PATH_ROOT, auditMap);
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
{ {
logger.debug("RM Audit: Audited node deletion: \n" + auditMap); logger.debug("RM Audit: Audited node deletion: \n" + auditMap);
@@ -656,10 +658,10 @@ public class RecordsManagementAuditServiceImpl
// That is it. The values are queued for the end of the transaction. // That is it. The values are queued for the end of the transaction.
} }
} }
/** /**
* Helper method to build audit map * Helper method to build audit map
* *
* @param nodeRef * @param nodeRef
* @param eventName * @param eventName
* @return * @return
@@ -678,8 +680,8 @@ public class RecordsManagementAuditServiceImpl
AuditApplication.buildPath( AuditApplication.buildPath(
RecordsManagementAuditService.RM_AUDIT_SNIPPET_EVENT, RecordsManagementAuditService.RM_AUDIT_SNIPPET_EVENT,
RecordsManagementAuditService.RM_AUDIT_SNIPPET_NODE), RecordsManagementAuditService.RM_AUDIT_SNIPPET_NODE),
nodeRef); nodeRef);
return auditMap; return auditMap;
} }
/** /**
@@ -743,11 +745,11 @@ public class RecordsManagementAuditServiceImpl
// Action description // Action description
String eventName = auditedNode.getEventName(); String eventName = auditedNode.getEventName();
Map<String, Serializable> auditMap = buildAuditMap(nodeRef, eventName); Map<String, Serializable> auditMap = buildAuditMap(nodeRef, eventName);
// TODO do we care if the before and after are null?? // TODO do we care if the before and after are null??
// Property changes // Property changes
Map<QName, Serializable> propertiesBefore = auditedNode.getNodePropertiesBefore(); Map<QName, Serializable> propertiesBefore = auditedNode.getNodePropertiesBefore();
Map<QName, Serializable> propertiesAfter = auditedNode.getNodePropertiesAfter(); Map<QName, Serializable> propertiesAfter = auditedNode.getNodePropertiesAfter();
@@ -767,7 +769,7 @@ public class RecordsManagementAuditServiceImpl
RecordsManagementAuditService.RM_AUDIT_SNIPPET_CHANGES, RecordsManagementAuditService.RM_AUDIT_SNIPPET_CHANGES,
RecordsManagementAuditService.RM_AUDIT_SNIPPET_AFTER), RecordsManagementAuditService.RM_AUDIT_SNIPPET_AFTER),
(Serializable) deltaPair.getSecond()); (Serializable) deltaPair.getSecond());
// Audit it // Audit it
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
{ {
@@ -905,7 +907,7 @@ public class RecordsManagementAuditServiceImpl
return false; return false;
} }
Date timestamp = new Date(time); Date timestamp = new Date(time);
String eventName = null; String eventName = null;
String fullName = null; String fullName = null;
@@ -974,15 +976,15 @@ public class RecordsManagementAuditServiceImpl
// skip it // skip it
return true; return true;
} }
if (params.getProperty() != null && if (params.getProperty() != null &&
getChangedProperties(beforeProperties, afterProperties).contains(params.getProperty()) == false) getChangedProperties(beforeProperties, afterProperties).contains(params.getProperty()) == false)
{ {
// skip it // skip it
return false; return false;
} }
// TODO: Refactor this to use the builder pattern // TODO: Refactor this to use the builder pattern
RecordsManagementAuditEntry entry = new RecordsManagementAuditEntry( RecordsManagementAuditEntry entry = new RecordsManagementAuditEntry(
timestamp, timestamp,
@@ -1018,7 +1020,7 @@ public class RecordsManagementAuditServiceImpl
private List<QName> getChangedProperties(Map<QName, Serializable> beforeProperties, Map<QName, Serializable> afterProperties) private List<QName> getChangedProperties(Map<QName, Serializable> beforeProperties, Map<QName, Serializable> afterProperties)
{ {
List<QName> changedProperties = new ArrayList<QName>(21); List<QName> changedProperties = new ArrayList<QName>(21);
if (beforeProperties != null && afterProperties != null) if (beforeProperties != null && afterProperties != null)
{ {
// add all the properties present before the audited action // add all the properties present before the audited action
@@ -1026,7 +1028,7 @@ public class RecordsManagementAuditServiceImpl
{ {
changedProperties.add(valuePropName); changedProperties.add(valuePropName);
} }
// add all the properties present after the audited action that // add all the properties present after the audited action that
// have not already been added // have not already been added
for (QName valuePropName : afterProperties.keySet()) for (QName valuePropName : afterProperties.keySet())
@@ -1037,10 +1039,10 @@ public class RecordsManagementAuditServiceImpl
} }
} }
} }
return changedProperties; return changedProperties;
} }
private void writeEntryToFile(RecordsManagementAuditEntry entry) private void writeEntryToFile(RecordsManagementAuditEntry entry)
{ {
if (writer == null) if (writer == null)
@@ -1081,8 +1083,8 @@ public class RecordsManagementAuditServiceImpl
}; };
String user = params.getUser(); String user = params.getUser();
Long fromTime = (params.getDateFrom() == null ? null : new Long(params.getDateFrom().getTime())); Long fromTime = getFromDateTime(params.getDateFrom());
Long toTime = (params.getDateTo() == null ? null : new Long(params.getDateTo().getTime())); Long toTime = getToDateTime(params.getDateTo());
NodeRef nodeRef = params.getNodeRef(); NodeRef nodeRef = params.getNodeRef();
int maxEntries = params.getMaxEntries(); int maxEntries = params.getMaxEntries();
boolean forward = maxEntries > 0 ? false : true; // Reverse order if the results are limited boolean forward = maxEntries > 0 ? false : true; // Reverse order if the results are limited
@@ -1113,6 +1115,90 @@ public class RecordsManagementAuditServiceImpl
writeAuditTrailFooter(writer, reportFormat); writeAuditTrailFooter(writer, reportFormat);
} }
/**
* Calculates the start of the given date.
* For example, if you had the date time of 12 Aug 2013 12:10:15.158
* the result would be 12 Aug 2013 00:00:00.000.
*
* @param date The date for which the start should be calculated.
* @return Returns the start of the given date.
*/
private Date getStartOfDay(Date date)
{
return DateUtils.truncate(date == null ? new Date() : date, Calendar.DATE);
}
/**
* Gets the start of the from date
* @see org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditServiceImpl.getStartOfDay()
*
* @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.
*/
private Date getFromDate(Date date)
{
return date == null ? null : getStartOfDay(date);
}
/**
* Returns the number of milliseconds for the "from date".
*
* @param date The date for which the number of milliseconds should retrieved.
* @return Returns null if the given date is null, otherwise the number of milliseconds for the given date.
*/
private Long getFromDateTime(Date date)
{
Long fromDateTime = null;
Date fromDate = getFromDate(date);
if (fromDate != null)
{
fromDateTime = new Long(fromDate.getTime());
}
return fromDateTime;
}
/**
* Calculates the end of the given date.
* For example, if you had the date time of 12 Aug 2013 12:10:15.158
* the result would be 12 Aug 2013 23:59:59.999.
*
* @param date The date for which the end should be calculated.
* @return Returns the end of the given date.
*/
private Date getEndOfDay(Date date)
{
return DateUtils.addMilliseconds(DateUtils.ceiling(date == null ? new Date() : date, Calendar.DATE), -1);
}
/**
* Gets the end of the from date
* @see org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditServiceImpl.getEndOfDay()
*
* @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.
*/
private Date getToDate(Date date)
{
return date == null ? null : getEndOfDay(date);
}
/**
* Returns the number of milliseconds for the "to date".
*
* @param date The date for which the number of milliseconds should retrieved.
* @return Returns null if the given date is null, otherwise the number of milliseconds for the given date.
*/
private Long getToDateTime(Date date)
{
Long toDateTime = null;
Date toDate = getToDate(date);
if (toDate != null)
{
toDateTime = new Long(toDate.getTime());
}
return toDateTime;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -1255,9 +1341,9 @@ public class RecordsManagementAuditServiceImpl
// write header as JSON // write header as JSON
writer.write("{\n\t\"data\":\n\t{"); writer.write("{\n\t\"data\":\n\t{");
writer.write("\n\t\t\"started\": \""); writer.write("\n\t\t\"started\": \"");
writer.write(ISO8601DateFormat.format(getDateLastStarted())); writer.write(ISO8601DateFormat.format(getStartOfDay(params.getDateFrom())));
writer.write("\",\n\t\t\"stopped\": \""); writer.write("\",\n\t\t\"stopped\": \"");
writer.write(ISO8601DateFormat.format(getDateLastStopped())); writer.write(ISO8601DateFormat.format(getEndOfDay(params.getDateTo())));
writer.write("\",\n\t\t\"enabled\": "); writer.write("\",\n\t\t\"enabled\": ");
writer.write(Boolean.toString(isEnabled())); writer.write(Boolean.toString(isEnabled()));
writer.write(",\n\t\t\"entries\":["); writer.write(",\n\t\t\"entries\":[");
@@ -1378,7 +1464,7 @@ public class RecordsManagementAuditServiceImpl
json.put("userRole", entry.getUserRole() == null ? "": entry.getUserRole()); json.put("userRole", entry.getUserRole() == null ? "": entry.getUserRole());
json.put("fullName", entry.getFullName() == null ? "": entry.getFullName()); json.put("fullName", entry.getFullName() == null ? "": entry.getFullName());
json.put("nodeRef", entry.getNodeRef() == null ? "": entry.getNodeRef()); json.put("nodeRef", entry.getNodeRef() == null ? "": entry.getNodeRef());
if (entry.getEvent().equals("createPerson") == true && entry.getNodeRef() != null) if (entry.getEvent().equals("createPerson") == true && entry.getNodeRef() != null)
{ {
NodeRef nodeRef = entry.getNodeRef(); NodeRef nodeRef = entry.getNodeRef();
@@ -1389,7 +1475,7 @@ public class RecordsManagementAuditServiceImpl
{ {
json.put("nodeName", entry.getNodeName() == null ? "": entry.getNodeName()); json.put("nodeName", entry.getNodeName() == null ? "": entry.getNodeName());
} }
json.put("nodeType", entry.getNodeType() == null ? "": entry.getNodeType()); json.put("nodeType", entry.getNodeType() == null ? "": entry.getNodeType());
json.put("event", entry.getEvent() == null ? "": getAuditEventLabel(entry.getEvent())); json.put("event", entry.getEvent() == null ? "": getAuditEventLabel(entry.getEvent()));
json.put("identifier", entry.getIdentifier() == null ? "": entry.getIdentifier()); json.put("identifier", entry.getIdentifier() == null ? "": entry.getIdentifier());