From 03a0a0d5614c25930e059d038e099fb2c446b889 Mon Sep 17 00:00:00 2001 From: "Daniel\\dll" Date: Tue, 28 Jan 2020 14:45:29 +0200 Subject: [PATCH 1/2] make stampable of custom type --- .../orm/auditable/AuditLogListener.groovy | 49 ++++++++++++------- .../plugins/orm/auditable/Stampable.groovy | 6 +-- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/plugin/src/main/groovy/grails/plugins/orm/auditable/AuditLogListener.groovy b/plugin/src/main/groovy/grails/plugins/orm/auditable/AuditLogListener.groovy index 17c2b8cc..9ec6a316 100755 --- a/plugin/src/main/groovy/grails/plugins/orm/auditable/AuditLogListener.groovy +++ b/plugin/src/main/groovy/grails/plugins/orm/auditable/AuditLogListener.groovy @@ -85,8 +85,7 @@ class AuditLogListener extends AbstractPersistenceEventListener { catch (Exception e) { if (AuditLogContext.context.failOnError) { throw e - } - else { + } else { log.error("Error creating audit log for event ${event.eventType} and domain ${event.entityObject}", e) } } @@ -95,8 +94,8 @@ class AuditLogListener extends AbstractPersistenceEventListener { @Override boolean supportsEventType(Class eventType) { return eventType.isAssignableFrom(PostInsertEvent) || - eventType.isAssignableFrom(PreUpdateEvent) || - eventType.isAssignableFrom(PreDeleteEvent) + eventType.isAssignableFrom(PreUpdateEvent) || + eventType.isAssignableFrom(PreDeleteEvent) } /** @@ -121,7 +120,7 @@ class AuditLogListener extends AbstractPersistenceEventListener { if (map || !verbose) { if (auditEventType == AuditEventType.DELETE) { map = map.collectEntries { String property, Object value -> - // Accessing a hibernate PersistentCollection of a deleted entity yields a NPE in Grails 3.3.x. + // Accessing a hibernate PersistentCollection of a deleted entity yields a NPE in Grails 3.3.x. // We can't filter hibernate classes because this plugin is ORM-agnostic and has no dependency to any ORM implementation. // This is a workaround. We might not log some other ORM collection implementation even if it would be possible to log them. // (see #153) @@ -129,11 +128,10 @@ class AuditLogListener extends AbstractPersistenceEventListener { if (value instanceof Collection) { return [:] } - return [(property):value] + return [(property): value] } as Map logChanges(domain, [:], map, auditEventType) - } - else { + } else { logChanges(domain, map, [:], auditEventType) } } @@ -189,7 +187,22 @@ class AuditLogListener extends AbstractPersistenceEventListener { // Use a single date for all audit_log entries in this transaction // Note, this will be ignored unless the audit_log domin has 'autoTimestamp false' - Date dateCreated = new Date() + Object dateCreated + + if (eventType == AuditEventType.DELETE) { + if (oldMap.hasProperty("dateCreated")) { + Class dateCreatedClass = oldMap.get("dateCreated").getClass() + dateCreated = dateCreatedClass.newInstance() + } + } else { + if (newMap.hasProperty("dateCreated")) { + Class dateCreatedClass = newMap.get("dateCreated").getClass() + dateCreated = dateCreatedClass.newInstance() + } + } + if (dateCreated == null) { + dateCreated = new Date() + } // This handles insert, delete, and update with any property level logging enabled if (newMap || oldMap) { @@ -208,24 +221,24 @@ class AuditLogListener extends AbstractPersistenceEventListener { oldValueAsString = conditionallyMaskAndTruncate(domain, propertyName, domain.convertLoggedPropertyToString(propertyName, oldVal), truncateLength) } + // Create a new entity for each property GormEntity audit = createAuditLogDomainInstance( - actor: domain.logCurrentUserName, uri: domain.logURI, className: domain.logClassName, eventName: eventType.name(), - persistedObjectId: domain.logEntityId, persistedObjectVersion: persistedObjectVersion, - propertyName: propertyName, oldValue: oldValueAsString, newValue: newValueAsString, - dateCreated: dateCreated, lastUpdated: dateCreated + actor: domain.logCurrentUserName, uri: domain.logURI, className: domain.logClassName, eventName: eventType.name(), + persistedObjectId: domain.logEntityId, persistedObjectVersion: persistedObjectVersion, + propertyName: propertyName, oldValue: oldValueAsString, newValue: newValueAsString, + dateCreated: dateCreated, lastUpdated: dateCreated ) if (domain.beforeSaveLog(audit)) { audit.save(failOnError: true) } } - } - else { + } else { // Create a single entity for this event GormEntity audit = createAuditLogDomainInstance( - actor: domain.logCurrentUserName, uri: domain.logURI, className: domain.logClassName, eventName: eventType.name(), - persistedObjectId: domain.logEntityId, persistedObjectVersion: persistedObjectVersion, - dateCreated: dateCreated, lastUpdated: dateCreated + actor: domain.logCurrentUserName, uri: domain.logURI, className: domain.logClassName, eventName: eventType.name(), + persistedObjectId: domain.logEntityId, persistedObjectVersion: persistedObjectVersion, + dateCreated: dateCreated, lastUpdated: dateCreated ) if (domain.beforeSaveLog(audit)) { audit.save(failOnError: true) diff --git a/plugin/src/main/groovy/grails/plugins/orm/auditable/Stampable.groovy b/plugin/src/main/groovy/grails/plugins/orm/auditable/Stampable.groovy index 2c80da8f..e3de4197 100644 --- a/plugin/src/main/groovy/grails/plugins/orm/auditable/Stampable.groovy +++ b/plugin/src/main/groovy/grails/plugins/orm/auditable/Stampable.groovy @@ -5,10 +5,10 @@ import org.grails.datastore.gorm.GormEntity /** * Entities should implement this trait to provide automatic stamping of date and user information */ -trait Stampable extends GormEntity { +trait Stampable extends GormEntity { // Grails will automatically populate these - Date dateCreated - Date lastUpdated + T dateCreated + T lastUpdated // We initialize these to non-null to they pass initial validation, they are set on insert/update String createdBy = "N/A" From 8992a313e719ac4ca27c1f5e77f9c83e9076bbf8 Mon Sep 17 00:00:00 2001 From: "Daniel\\dll" Date: Tue, 28 Jan 2020 14:57:42 +0200 Subject: [PATCH 2/2] update test examples to work with custom stampable types --- examples/audit-test/grails-app/domain/test/Coach.groovy | 2 +- examples/audit-test/grails-app/domain/test/Train.groovy | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/audit-test/grails-app/domain/test/Coach.groovy b/examples/audit-test/grails-app/domain/test/Coach.groovy index 010d5d8c..593908c8 100644 --- a/examples/audit-test/grails-app/domain/test/Coach.groovy +++ b/examples/audit-test/grails-app/domain/test/Coach.groovy @@ -2,7 +2,7 @@ package test import grails.plugins.orm.auditable.Stampable -class Coach implements Stampable { +class Coach implements Stampable { static constraints = { } diff --git a/examples/audit-test/grails-app/domain/test/Train.groovy b/examples/audit-test/grails-app/domain/test/Train.groovy index 9bfc26c6..e90a8843 100644 --- a/examples/audit-test/grails-app/domain/test/Train.groovy +++ b/examples/audit-test/grails-app/domain/test/Train.groovy @@ -2,9 +2,9 @@ package test import grails.plugins.orm.auditable.Stampable -class Train implements Stampable { - String number - +class Train implements Stampable { + String number + static constraints = { } }