From 33bbeeaacac3b223f92968cec2d983c3e9a10f28 Mon Sep 17 00:00:00 2001 From: Dennie de Lange Date: Tue, 24 Jan 2017 01:26:45 +0100 Subject: [PATCH 1/2] Fixed issue with Hibernate stamping, stamping was ignored with dynamicUpdate = true and stamping was ignored on cascading saves. --- .../orm/auditable/AuditLogListener.groovy | 58 ++++++++++++++----- .../auditable/AuditLoggingGrailsPlugin.groovy | 5 +- version.txt | 2 +- 3 files changed, 48 insertions(+), 17 deletions(-) diff --git a/audit-logging/src/main/groovy/grails/plugins/orm/auditable/AuditLogListener.groovy b/audit-logging/src/main/groovy/grails/plugins/orm/auditable/AuditLogListener.groovy index 8ad244db..d14fefb1 100755 --- a/audit-logging/src/main/groovy/grails/plugins/orm/auditable/AuditLogListener.groovy +++ b/audit-logging/src/main/groovy/grails/plugins/orm/auditable/AuditLogListener.groovy @@ -19,6 +19,7 @@ package grails.plugins.orm.auditable import com.fasterxml.jackson.annotation.JsonIgnore +import org.apache.commons.lang.ArrayUtils import static grails.plugins.orm.auditable.AuditLogListenerUtil.* import groovy.util.logging.Commons @@ -69,6 +70,8 @@ class AuditLogListener extends AbstractPersistenceEventListener { @JsonIgnore Closure actorClosure + boolean usingHibernate = false + Boolean stampEnabled = true Boolean stampAlways = false String stampCreatedBy @@ -92,7 +95,7 @@ class AuditLogListener extends AbstractPersistenceEventListener { return } if (stampEnabled && (stampAlways || isStampable(event.entityObject, event.eventType))) { - stamp(event.entityObject, event.eventType); + stamp(event); } if (isAuditableEntity(event.entityObject, getEventName(event))) { log.trace "Audit logging: ${event.eventType.name()} for ${event.entityObject.class.name}" @@ -111,12 +114,15 @@ class AuditLogListener extends AbstractPersistenceEventListener { } } - void stamp(entity, EventType eventType) { - if (EventType.PreInsert == eventType) { - stampCreatedBy(entity) - stampLastUpdatedBy(entity) + void stamp(AbstractPersistenceEvent event) { + def entity = event.entityObject + def actor = getActor() + + if (EventType.PreInsert == event.eventType) { + stampCreatedBy(entity,actor,event) + stampLastUpdatedBy(entity,actor,event) } else { - stampLastUpdatedBy(entity) + stampLastUpdatedBy(entity,actor,event) } } @@ -149,12 +155,12 @@ class AuditLogListener extends AbstractPersistenceEventListener { actorClosure = null } } - // If we couldn't find an actor, use the configured default or just 'system' - if (!actor) { - actor = AuditLoggingConfigUtils.auditConfig.defaultActor ?: 'system' - } } - log.trace("Actor: $actor") + // If we couldn't find an actor, use the configured default or just 'system' + if (!actor) { + actor = AuditLoggingConfigUtils.auditConfig.defaultActor ?: 'system' + } + if(log.traceEnabled) log.trace("Actor: $actor") return actor?.toString() } @@ -268,14 +274,36 @@ class AuditLogListener extends AbstractPersistenceEventListener { return mask } - protected stampCreatedBy(entity) { - entity."${stampCreatedBy}" = getActor() + protected stampCreatedBy(entity,actor,event) { + entity."${stampCreatedBy}" = actor + + if(usingHibernate){ + String[] propertyNames = event.nativeEvent.getPersister().getEntityMetamodel().getPropertyNames(); + Object[] state = event.nativeEvent.state + + syncHibernateState(state,propertyNames,stampCreatedBy,actor) + } } - protected stampLastUpdatedBy(entity) { - entity."${stampLastUpdatedBy}" = getActor() + protected stampLastUpdatedBy(entity,actor,event) { + entity."${stampLastUpdatedBy}" = actor + + if(usingHibernate){ + String[] propertyNames = event.nativeEvent.getPersister().getEntityMetamodel().getPropertyNames(); + Object[] state = event.nativeEvent.state + + syncHibernateState(state,propertyNames,stampCreatedBy,entity."${stampCreatedBy}") + syncHibernateState(state,propertyNames,stampLastUpdatedBy,actor) + } } + private void syncHibernateState(Object[] state,String[] propertyNames,String propertyName,Object value){ + int index = ArrayUtils.indexOf(propertyNames, propertyName); + if(index>=0){ + state[index] = value + } + } + /** * We must use the preDelete event if we want to capture * what the old object was like. diff --git a/audit-logging/src/main/groovy/grails/plugins/orm/auditable/AuditLoggingGrailsPlugin.groovy b/audit-logging/src/main/groovy/grails/plugins/orm/auditable/AuditLoggingGrailsPlugin.groovy index f33a3e23..627bb486 100755 --- a/audit-logging/src/main/groovy/grails/plugins/orm/auditable/AuditLoggingGrailsPlugin.groovy +++ b/audit-logging/src/main/groovy/grails/plugins/orm/auditable/AuditLoggingGrailsPlugin.groovy @@ -93,6 +93,8 @@ When called, the event handlers have access to oldObj and newObj definitions tha boolean dataStoreDisabled = datastore.hasProperty("config") ? datastore.config.auditLog.disabled : false // Don't register the listener if we are disabled if (!disabled && !dataStoreDisabled) { + boolean isHibernateDataStore = datastore.class.simpleName == 'HibernateDatastore' + def listener = new AuditLogListener(datastore) listener.grailsApplication = application listener.stampEnabled = stampEnabled @@ -100,6 +102,7 @@ When called, the event handlers have access to oldObj and newObj definitions tha listener.stampCreatedBy = stampCreatedBy listener.stampLastUpdatedBy = stampLastUpdatedBy listener.verbose = verbose + listener.usingHibernate = isHibernateDataStore listener.nonVerboseDelete = nonVerboseDelete listener.logFullClassName = logFullClassName listener.transactional = transactional @@ -124,7 +127,7 @@ When called, the event handlers have access to oldObj and newObj definitions tha if (!conf || !conf.active) { return } - + log.trace 'onConfigChange' } } diff --git a/version.txt b/version.txt index b6539c1c..9226a700 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -2.0.3-SNAPSHOT +2.0.4-SNAPSHOT From 0b8e7d912517093ced188544f2164b659839bae3 Mon Sep 17 00:00:00 2001 From: Robert Oschwald Date: Wed, 1 Feb 2017 21:59:31 +0100 Subject: [PATCH 2/2] Update version.txt No need to bump further. We are on 2.0.3-SNAPSHOT to release 2.0.3, soon. --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 9226a700..b6539c1c 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -2.0.4-SNAPSHOT +2.0.3-SNAPSHOT