Skip to content

Commit

Permalink
Add snapshot_on_deletion feature to AuditLog (#28)
Browse files Browse the repository at this point in the history
### Summary

Because the `changes` hash is always empty on deletion, we would like the option to create a snapshot by default on deletes, to ensure that we know what it was exactly that was deleted. (This is particularly useful for models that existed prior to the introduction of this framework.)

### Other Information

I'm defaulting it to `false` because ... I guess it felt extra confusing to have a feature that defaults to only partially being enabled. But I could be convinced that `true` is actually a better default 🤷
  • Loading branch information
smudge authored Oct 13, 2022
1 parent 8a0db84 commit dd4adb8
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 2 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Gemfile.lock
log/*.log
pkg/
spec/examples.txt
spec/dummy/log/*.log
spec/dummy/tmp/
/gemfiles/*.gemfile.lock
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,15 @@ Journaled::AuditLog.with_snapshots do
end
```

Snapshots can also be enabled globally for all _deletion_ operations. Since
`changes` will be empty on deletion, you should consider using this if you care
about the contents of any records being deleted (and/or don't have a full audit
trail from their time of creation):

```ruby
Journaled::AuditLog.snapshot_on_deletion = true
```

Events with snapshots will continue to populate the `changes` field, but will
additionally contain a snapshot with the full state of the user:

Expand Down
3 changes: 2 additions & 1 deletion app/models/journaled/audit_log/event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ def changes
end

def snapshot
filtered_attributes if record._log_snapshot || AuditLog.snapshots_enabled
filtered_attributes if record._log_snapshot || AuditLog.snapshots_enabled ||
(database_operation == 'delete' && AuditLog.snapshot_on_deletion)
end

def actor
Expand Down
1 change: 1 addition & 0 deletions lib/journaled/audit_log.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ module AuditLog
mattr_accessor(:default_enqueue_opts) { {} }
mattr_accessor(:excluded_classes) { DEFAULT_EXCLUDED_CLASSES.dup }
thread_mattr_accessor(:snapshots_enabled) { false }
thread_mattr_accessor(:snapshot_on_deletion) { false }
thread_mattr_accessor(:_disabled) { false }
thread_mattr_accessor(:_force) { false }

Expand Down
2 changes: 1 addition & 1 deletion lib/journaled/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Journaled
VERSION = "5.1.1".freeze
VERSION = "5.2.0".freeze
end
17 changes: 17 additions & 0 deletions spec/lib/journaled/audit_log_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,23 @@ def assign_attrs(**attrs)
end
end
end

context 'and snapshotting is enabled only on deletion' do
subject { MyModel.new(name: 'bob') }

before do
described_class.snapshot_on_deletion = true
end

it 'emits snapshots through the lifecycle of the object, and filters the expected fields' do
expect { subject.save }
.to not_journal_event_including(snapshot: { all: 'attributes', password: '[FILTERED]' })
expect { subject.update(name: 'robert') }
.to not_journal_event_including(snapshot: { all: 'attributes', password: '[FILTERED]' })
expect { subject.destroy }
.to journal_event_including(snapshot: { all: 'attributes', password: '[FILTERED]' })
end
end
end

context 'and a field is ignored' do
Expand Down
1 change: 1 addition & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
mocks.verify_partial_doubles = true
end

config.example_status_persistence_file_path = 'spec/examples.txt'
config.order = :random
end

Expand Down

0 comments on commit dd4adb8

Please sign in to comment.