audited 5.4.2 → 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/publish_gem.yml +28 -0
- data/CHANGELOG.md +15 -0
- data/README.md +10 -3
- data/Rakefile +1 -3
- data/lib/audited/audit.rb +1 -1
- data/lib/audited/auditor.rb +8 -5
- data/lib/audited/version.rb +1 -1
- data/lib/audited.rb +2 -0
- data/lib/generators/audited/migration.rb +1 -1
- data/spec/audited/auditor_spec.rb +45 -0
- data/spec/audited_spec_helpers.rb +4 -0
- data/spec/rails_app/config/application.rb +1 -1
- data/spec/support/active_record/models.rb +10 -3
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d9407750d2b70edd5e934c0b0544ba52230a3e3ac4955194029b6b7370c8fe7
|
4
|
+
data.tar.gz: 863fc4f2e8d1cc188664f4a346db886f7dfdd4bf6c6b56f3371eacb4d75497dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cb853e42fb4e6ff1493f3864a0c5833e730b27e90f14d8b8529ad11c3dd66052c8bd3739433e4c08decd84ecb5525a244ab8a831bf70a7a21654c398e220b8c7
|
7
|
+
data.tar.gz: 36d1acab56d4011d8766f0a3f0126ecae8fff5a7469a3ac00a43d6ccc3e1f09eee5c8e8054d30367dbdf69caab3f49135020861ca16d10a76e5f44349e14a57f
|
@@ -0,0 +1,28 @@
|
|
1
|
+
name: Publish Gem
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
tags:
|
6
|
+
- v*
|
7
|
+
|
8
|
+
jobs:
|
9
|
+
push:
|
10
|
+
if: github.repository == 'collectiveidea/audited'
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
environment: publishing
|
13
|
+
|
14
|
+
permissions:
|
15
|
+
contents: write
|
16
|
+
id-token: write
|
17
|
+
|
18
|
+
steps:
|
19
|
+
# Set up
|
20
|
+
- uses: actions/checkout@v4
|
21
|
+
- name: Set up Ruby
|
22
|
+
uses: ruby/setup-ruby@v1
|
23
|
+
with:
|
24
|
+
bundler-cache: true
|
25
|
+
ruby-version: ruby
|
26
|
+
|
27
|
+
# Release
|
28
|
+
- uses: rubygems/release-gem@v1
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
# Audited ChangeLog
|
2
2
|
|
3
|
+
### 5.5.0 (2024-04-02)
|
4
|
+
|
5
|
+
- Removed support for Rails 5.0 and 5.1.
|
6
|
+
- Replace RequestStore with ActiveSupport::CurrentAttributes - @punkisdead
|
7
|
+
[#702](https://github.com/collectiveidea/audited/pull/702)
|
8
|
+
|
9
|
+
### 5.4.3 (2024-01-11)
|
10
|
+
|
11
|
+
- Ignore readonly columns in audit - @sriddbs
|
12
|
+
[#692](https://github.com/collectiveidea/audited/pull/692)
|
13
|
+
- Robustify Rails version checks - @blaet
|
14
|
+
[#689](https://github.com/collectiveidea/audited/pull/689)
|
15
|
+
- Ignore callbacks if not specifed on the model
|
16
|
+
[#679](https://github.com/collectiveidea/audited/pull/679)
|
17
|
+
|
3
18
|
## 5.4.2 (2023-11-30)
|
4
19
|
|
5
20
|
- Revert replacing RequetStore with ActiveSupport::CurrentAttributes until it is fully tested.
|
data/README.md
CHANGED
@@ -8,8 +8,9 @@ Audited
|
|
8
8
|
**Audited** (previously acts_as_audited) is an ORM extension that logs all changes to your models. Audited can also record who made those changes, save comments and associate models related to the changes.
|
9
9
|
|
10
10
|
|
11
|
-
Audited currently (5.
|
11
|
+
Audited currently (5.5) works with Rails 7.1, 7.0, 6.1, 6.0, 5.2.
|
12
12
|
|
13
|
+
For Rails 5.0 & 5.1, use gem version 5.4.3
|
13
14
|
For Rails 4, use gem version 4.x
|
14
15
|
For Rails 3, use gem version 3.0 or see the [3.0-stable branch](https://github.com/collectiveidea/audited/tree/3.0-stable).
|
15
16
|
|
@@ -133,18 +134,24 @@ end
|
|
133
134
|
|
134
135
|
### Specifying callbacks
|
135
136
|
|
136
|
-
By default, a new audit is created for any Create, Update or Destroy action. You can, however, limit the actions audited.
|
137
|
+
By default, a new audit is created for any Create, Update, Touch (Rails 6+) or Destroy action. You can, however, limit the actions audited.
|
137
138
|
|
138
139
|
```ruby
|
139
140
|
class User < ActiveRecord::Base
|
140
141
|
# All fields and actions
|
141
142
|
# audited
|
142
143
|
|
143
|
-
# Single field, only audit Update and Destroy (not Create)
|
144
|
+
# Single field, only audit Update and Destroy (not Create or Touch)
|
144
145
|
# audited only: :name, on: [:update, :destroy]
|
145
146
|
end
|
146
147
|
```
|
147
148
|
|
149
|
+
You can ignore the default callbacks globally unless the callback action is specified in your model using the `:on` option. To configure default callback exclusion, put the following in an initializer file (`config/initializers/audited.rb`):
|
150
|
+
|
151
|
+
```ruby
|
152
|
+
Audited.ignored_default_callbacks = [:create, :update] # ignore callbacks create and update
|
153
|
+
```
|
154
|
+
|
148
155
|
### Comments
|
149
156
|
|
150
157
|
You can attach comments to each audit using an `audit_comment` attribute on your model.
|
data/Rakefile
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
2
|
|
3
|
-
require "bundler/
|
3
|
+
require "bundler/gem_tasks"
|
4
4
|
require "rspec/core/rake_task"
|
5
5
|
require "rake/testtask"
|
6
6
|
require "appraisal"
|
7
7
|
|
8
|
-
Bundler::GemHelper.install_tasks(name: "audited")
|
9
|
-
|
10
8
|
RSpec::Core::RakeTask.new(:spec)
|
11
9
|
|
12
10
|
Rake::TestTask.new do |t|
|
data/lib/audited/audit.rb
CHANGED
@@ -49,7 +49,7 @@ module Audited
|
|
49
49
|
cattr_accessor :audited_class_names
|
50
50
|
self.audited_class_names = Set.new
|
51
51
|
|
52
|
-
if Rails.
|
52
|
+
if Rails.gem_version >= Gem::Version.new("7.1")
|
53
53
|
serialize :audited_changes, coder: YAMLIfTextColumnType
|
54
54
|
else
|
55
55
|
serialize :audited_changes, YAMLIfTextColumnType
|
data/lib/audited/auditor.rb
CHANGED
@@ -231,7 +231,7 @@ module Audited
|
|
231
231
|
|
232
232
|
private
|
233
233
|
|
234
|
-
def audited_changes(for_touch: false)
|
234
|
+
def audited_changes(for_touch: false, exclude_readonly_attrs: false)
|
235
235
|
all_changes = if for_touch
|
236
236
|
previous_changes
|
237
237
|
elsif respond_to?(:changes_to_save)
|
@@ -240,6 +240,8 @@ module Audited
|
|
240
240
|
changes
|
241
241
|
end
|
242
242
|
|
243
|
+
all_changes = all_changes.except(*self.class.readonly_attributes.to_a) if exclude_readonly_attrs
|
244
|
+
|
243
245
|
filtered_changes = \
|
244
246
|
if audited_options[:only].present?
|
245
247
|
all_changes.slice(*self.class.audited_columns)
|
@@ -247,6 +249,8 @@ module Audited
|
|
247
249
|
all_changes.except(*self.class.non_audited_columns)
|
248
250
|
end
|
249
251
|
|
252
|
+
filtered_changes = normalize_enum_changes(filtered_changes)
|
253
|
+
|
250
254
|
if for_touch && (last_audit = audits.last&.audited_changes)
|
251
255
|
filtered_changes.reject! do |k, v|
|
252
256
|
last_audit[k].to_json == v.to_json ||
|
@@ -256,7 +260,6 @@ module Audited
|
|
256
260
|
|
257
261
|
filtered_changes = redact_values(filtered_changes)
|
258
262
|
filtered_changes = filter_encrypted_attrs(filtered_changes)
|
259
|
-
filtered_changes = normalize_enum_changes(filtered_changes)
|
260
263
|
filtered_changes.to_hash
|
261
264
|
end
|
262
265
|
|
@@ -333,14 +336,14 @@ module Audited
|
|
333
336
|
end
|
334
337
|
|
335
338
|
def audit_update
|
336
|
-
unless (changes = audited_changes).empty? && (audit_comment.blank? || audited_options[:update_with_comment_only] == false)
|
339
|
+
unless (changes = audited_changes(exclude_readonly_attrs: true)).empty? && (audit_comment.blank? || audited_options[:update_with_comment_only] == false)
|
337
340
|
write_audit(action: "update", audited_changes: changes,
|
338
341
|
comment: audit_comment)
|
339
342
|
end
|
340
343
|
end
|
341
344
|
|
342
345
|
def audit_touch
|
343
|
-
unless (changes = audited_changes(for_touch: true)).empty?
|
346
|
+
unless (changes = audited_changes(for_touch: true, exclude_readonly_attrs: true)).empty?
|
344
347
|
write_audit(action: "update", audited_changes: changes,
|
345
348
|
comment: audit_comment)
|
346
349
|
end
|
@@ -496,7 +499,7 @@ module Audited
|
|
496
499
|
|
497
500
|
def normalize_audited_options
|
498
501
|
audited_options[:on] = Array.wrap(audited_options[:on])
|
499
|
-
audited_options[:on] = [:create, :update, :touch, :destroy] if audited_options[:on].empty?
|
502
|
+
audited_options[:on] = ([:create, :update, :touch, :destroy] - Audited.ignored_default_callbacks) if audited_options[:on].empty?
|
500
503
|
audited_options[:only] = Array.wrap(audited_options[:only]).map(&:to_s)
|
501
504
|
audited_options[:except] = Array.wrap(audited_options[:except]).map(&:to_s)
|
502
505
|
max_audits = audited_options[:max_audits] || Audited.max_audits
|
data/lib/audited/version.rb
CHANGED
data/lib/audited.rb
CHANGED
@@ -9,6 +9,7 @@ module Audited
|
|
9
9
|
:auditing_enabled,
|
10
10
|
:current_user_method,
|
11
11
|
:ignored_attributes,
|
12
|
+
:ignored_default_callbacks,
|
12
13
|
:max_audits,
|
13
14
|
:store_synthesized_enums
|
14
15
|
attr_writer :audit_class
|
@@ -35,6 +36,7 @@ module Audited
|
|
35
36
|
end
|
36
37
|
|
37
38
|
@ignored_attributes = %w[lock_version created_at updated_at created_on updated_on]
|
39
|
+
@ignored_default_callbacks = []
|
38
40
|
|
39
41
|
@current_user_method = :current_user
|
40
42
|
@auditing_enabled = true
|
@@ -245,6 +245,27 @@ describe Audited::Auditor do
|
|
245
245
|
expect(user.audits.last.audited_changes["password"]).to eq(["My", "Custom", "Value", 7])
|
246
246
|
end
|
247
247
|
|
248
|
+
context "when ignored_default_callbacks is set" do
|
249
|
+
before { Audited.ignored_default_callbacks = [:create] }
|
250
|
+
after { Audited.ignored_default_callbacks = [] }
|
251
|
+
|
252
|
+
it "should remove create callback" do
|
253
|
+
class DefaultCallback < ::ActiveRecord::Base
|
254
|
+
audited
|
255
|
+
end
|
256
|
+
|
257
|
+
expect(DefaultCallback.audited_options[:on]).to eq([:update, :touch, :destroy])
|
258
|
+
end
|
259
|
+
|
260
|
+
it "should keep create callback if specified" do
|
261
|
+
class CallbacksSpecified < ::ActiveRecord::Base
|
262
|
+
audited on: [:create, :update, :destroy]
|
263
|
+
end
|
264
|
+
|
265
|
+
expect(CallbacksSpecified.audited_options[:on]).to eq([:create, :update, :destroy])
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
248
269
|
if ::ActiveRecord::VERSION::MAJOR >= 7
|
249
270
|
it "should filter encrypted attributes" do
|
250
271
|
user = Models::ActiveRecord::UserWithEncryptedPassword.create(password: "password")
|
@@ -358,6 +379,12 @@ describe Audited::Auditor do
|
|
358
379
|
Models::ActiveRecord::OnUpdateDestroy.create!(name: "Bart")
|
359
380
|
}.to_not change(Audited::Audit, :count)
|
360
381
|
end
|
382
|
+
|
383
|
+
it "should save readonly columns" do
|
384
|
+
expect {
|
385
|
+
Models::ActiveRecord::UserWithReadOnlyAttrs.create!(name: "Bart")
|
386
|
+
}.to change(Audited::Audit, :count)
|
387
|
+
end
|
361
388
|
end
|
362
389
|
|
363
390
|
describe "on update" do
|
@@ -409,6 +436,16 @@ describe Audited::Auditor do
|
|
409
436
|
expect { @user.update_attribute :activated, "1" }.to_not change(Audited::Audit, :count)
|
410
437
|
end
|
411
438
|
|
439
|
+
context "with readonly attributes" do
|
440
|
+
before do
|
441
|
+
@user = create_user_with_readonly_attrs(status: "active")
|
442
|
+
end
|
443
|
+
|
444
|
+
it "should not save readonly columns" do
|
445
|
+
expect { @user.update! status: "banned" }.to_not change(Audited::Audit, :count)
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
412
449
|
describe "with no dirty changes" do
|
413
450
|
it "does not create an audit if the record is not changed" do
|
414
451
|
expect {
|
@@ -503,6 +540,14 @@ describe Audited::Auditor do
|
|
503
540
|
expect(user.audits.last.action).to eq("update")
|
504
541
|
expect(user.audits.last.audited_changes.keys).to eq(%w[suspended_at])
|
505
542
|
end
|
543
|
+
|
544
|
+
it "updating nested resource through parent while changing an enum on parent shouldn't double audit" do
|
545
|
+
user.status = :reliable
|
546
|
+
user.companies_attributes = [{name: "test"}]
|
547
|
+
expect { user.save }.to change(user.audits, :count).from(1).to(2)
|
548
|
+
expect(user.audits.last.action).to eq("update")
|
549
|
+
expect(user.audits.last.audited_changes.keys).to eq(%w[status])
|
550
|
+
end
|
506
551
|
end
|
507
552
|
|
508
553
|
context "after updating" do
|
@@ -3,6 +3,10 @@ module AuditedSpecHelpers
|
|
3
3
|
Models::ActiveRecord::User.create({name: "Brandon", username: "brandon", password: "password", favourite_device: "Android Phone"}.merge(attrs))
|
4
4
|
end
|
5
5
|
|
6
|
+
def create_user_with_readonly_attrs(attrs = {})
|
7
|
+
Models::ActiveRecord::UserWithReadOnlyAttrs.create({name: "Brandon", username: "brandon", password: "password", favourite_device: "Android Phone"}.merge(attrs))
|
8
|
+
end
|
9
|
+
|
6
10
|
def build_user(attrs = {})
|
7
11
|
Models::ActiveRecord::User.new({name: "darth", username: "darth", password: "noooooooo"}.merge(attrs))
|
8
12
|
end
|
@@ -30,7 +30,7 @@ module RailsApp
|
|
30
30
|
ActiveSupport::TimeWithZone ActiveSupport::TimeZone ActiveSupport::HashWithIndifferentAccess]
|
31
31
|
end
|
32
32
|
|
33
|
-
if Rails.
|
33
|
+
if Rails.gem_version >= Gem::Version.new("7.1")
|
34
34
|
config.active_support.cache_format_version = 7.1
|
35
35
|
end
|
36
36
|
end
|
@@ -5,11 +5,11 @@ module Models
|
|
5
5
|
module ActiveRecord
|
6
6
|
class User < ::ActiveRecord::Base
|
7
7
|
audited except: :password
|
8
|
-
attribute :non_column_attr if Rails.
|
8
|
+
attribute :non_column_attr if Rails.gem_version >= Gem::Version.new("5.1")
|
9
9
|
attr_protected :logins if respond_to?(:attr_protected)
|
10
10
|
enum status: {active: 0, reliable: 1, banned: 2}
|
11
11
|
|
12
|
-
if Rails.
|
12
|
+
if Rails.gem_version >= Gem::Version.new("7.1")
|
13
13
|
serialize :phone_numbers, type: Array
|
14
14
|
else
|
15
15
|
serialize :phone_numbers, Array
|
@@ -27,7 +27,7 @@ module Models
|
|
27
27
|
|
28
28
|
class UserOnlyPassword < ::ActiveRecord::Base
|
29
29
|
self.table_name = :users
|
30
|
-
attribute :non_column_attr if Rails.
|
30
|
+
attribute :non_column_attr if Rails.gem_version >= Gem::Version.new("5.1")
|
31
31
|
audited only: :password
|
32
32
|
end
|
33
33
|
|
@@ -54,6 +54,12 @@ module Models
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
+
class UserWithReadOnlyAttrs < ::ActiveRecord::Base
|
58
|
+
self.table_name = :users
|
59
|
+
audited
|
60
|
+
attr_readonly :status
|
61
|
+
end
|
62
|
+
|
57
63
|
class CommentRequiredUser < ::ActiveRecord::Base
|
58
64
|
self.table_name = :users
|
59
65
|
audited except: :password, comment_required: true
|
@@ -130,6 +136,7 @@ module Models
|
|
130
136
|
has_associated_audits
|
131
137
|
has_many :companies, class_name: "OwnedCompany", dependent: :destroy
|
132
138
|
accepts_nested_attributes_for :companies
|
139
|
+
enum status: {active: 0, reliable: 1, banned: 2}
|
133
140
|
end
|
134
141
|
|
135
142
|
class OwnedCompany < ::ActiveRecord::Base
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: audited
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brandon Keepers
|
@@ -10,10 +10,10 @@ authors:
|
|
10
10
|
- Brian Ryckbost
|
11
11
|
- Steve Richert
|
12
12
|
- Ryan Glover
|
13
|
-
autorequire:
|
13
|
+
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date:
|
16
|
+
date: 2024-04-02 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: activerecord
|
@@ -181,6 +181,7 @@ extra_rdoc_files: []
|
|
181
181
|
files:
|
182
182
|
- ".github/workflows/buildlight.yml"
|
183
183
|
- ".github/workflows/ci.yml"
|
184
|
+
- ".github/workflows/publish_gem.yml"
|
184
185
|
- ".gitignore"
|
185
186
|
- ".standard.yml"
|
186
187
|
- ".yardopts"
|
@@ -252,7 +253,7 @@ homepage: https://github.com/collectiveidea/audited
|
|
252
253
|
licenses:
|
253
254
|
- MIT
|
254
255
|
metadata: {}
|
255
|
-
post_install_message:
|
256
|
+
post_install_message:
|
256
257
|
rdoc_options: []
|
257
258
|
require_paths:
|
258
259
|
- lib
|
@@ -267,8 +268,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
267
268
|
- !ruby/object:Gem::Version
|
268
269
|
version: '0'
|
269
270
|
requirements: []
|
270
|
-
rubygems_version: 3.
|
271
|
-
signing_key:
|
271
|
+
rubygems_version: 3.5.3
|
272
|
+
signing_key:
|
272
273
|
specification_version: 4
|
273
274
|
summary: Log all changes to your models
|
274
275
|
test_files: []
|