Using the audit trail system
As of v10.7.0, Preside comes with an audit trail system that allows you to log the activity of your admin users and display that activity in the admin:
Creating log entries
You can log an activity in one of two ways:
// in a handler
event.audit(
action = "datamanager_translate_record"
, type = "datamanager"
, recordId = recordId
, detail = updatedData
);
// from a service using Preside Super class
$audit(
action = "slack_command_executed"
, type = "slackcommands"
, detail = { command="deploy", commandArgs=commandArgs }
);
Both of these methods proxy to the log() method of the Audit Service (see links for docs).
Rendering log entries
For an audit log entry to appear in a useful way for the user, you will want to:
- Provide i18n properties file entries to describe the audit type and action
- Provide a custom renderer context for either your audit type or action
i18n
Each audit "type" should have its own .properties
file that lives at /i18n/auditlog/{type}.properties
, e.g. /i18n/auditlog/datamanager.properties
. At a minimum, it should contain a title
and iconClass
entry:
title=Data manager
iconClass=fa-puzzle-piece
In addition, for each audit action within the type, you should supply a {action}.title
, {action}.message
and {action}.iconClass
entry:
title=Data manager
iconClass=fa-puzzle-piece
datamanager_add_record.title=Add record (Data manager)
datamanager_add_record.message={1} created a new {2}, {3}
datamanager_add_record.iconClass=fa-plus-circle green
datamanager_delete_record.title=Delete record (Data manager)
datamanager_delete_record.message={1} deleted {2}, {3}
datamanager_delete_record.iconClass=fa-trash red
Audit log entry renderer
When audit log entries are rendered, the system uses the AuditLogEntry
content renderer. It uses the audit log type and/or action as the context for the renderer. This means that the audit log entry will be rendered by one of the following viewlets (whichever exists):
renderers.content.AuditLogEntry.{action}
renderers.content.AuditLogEntry.{type}
renderers.content.AuditLogEntry.default
The default context renderer looks like this:
<cfparam name="args.type" type="string"/>
<cfparam name="args.action" type="string"/>
<cfparam name="args.datecreated" type="date"/>
<cfparam name="args.known_as" type="string"/>
<cfparam name="args.userLink" type="string"/>
<cfscript>
userLink = '<a href="#args.userLink#">#args.known_as#</a>';
message = translateResource( uri="auditlog.#args.type#:#args.action#.message", data=[ userLink ] );
</cfscript>
<cfoutput>
#message#
</cfoutput>
This means that you can use the default renderer if your audit message could look like this:
myaction.message={1} did some really cool action
If you need a more detailed message, for example: you'd like to replay the slack command that was entered in a slack command hook, then you can create a custom context for either your audit type or category. e.g.
<!-- /views/renderers/content/auditLogEntry/slackcommand.cfm -->
<cfscript>
action = args.action ?: "";
known_as = args.known_as ?: "";
detail = args.detail ?: {};
userLink = '<a href="#( args.userLink ?: '' )#">#args.known_as#</a>';
command = '<code>/#( detail.command ?: '' )# #( detail.commandArgs ?: '' )#</code>';
message = translateResource( uri="auditlog.slackcommand:#args.action#.message", data=[ userLink, command ] );
</cfscript>
<cfoutput>#message#</cfoutput>
# /i18n/auditlog/slackcommand.properties
title=Slack commands
iconClass=fa-slack
command_sent.title=Slack command issued
command_sent.message={1} has issued a command from Slack: {2}
command_sent.iconClass=fa-slack blue