audited 5.2.0 → 5.3.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of audited might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +11 -5
- data/CHANGELOG.md +19 -0
- data/README.md +1 -0
- data/lib/audited/audit.rb +1 -1
- data/lib/audited/auditor.rb +25 -3
- data/lib/audited/version.rb +1 -1
- data/spec/audited/auditor_spec.rb +92 -4
- data/spec/support/active_record/models.rb +7 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 051f76b7a9cfbc91222643f2e0ddaa7738d2e446c00ec079dcf0b5d64d7146d3
|
4
|
+
data.tar.gz: 70ef8ed6c1473ca9d2ac21dc444ae66c0b8d42280e5a3c6bf4d1fe46c07f0e60
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e085b0764b5feb96dc88cb5db4361f07148550368bde350a45fe21aba47ed80bfa38bb5683437bf3ad7cd983d7dbfe5f4980a80a7da0f1bf76dabea037323b58
|
7
|
+
data.tar.gz: d55bbe1f1f139efd63ac97281d954bfac440b091e292ad57b23668a456f4e389f4401c9a6e6e4ebb9627d4556a9460cb94d2d71c0f0f2f5174b0e62cb2c10968
|
data/.github/workflows/ci.yml
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
name: CI
|
2
2
|
|
3
3
|
on:
|
4
|
-
pull_request
|
5
|
-
push
|
6
|
-
branches:
|
7
|
-
- main
|
4
|
+
- pull_request
|
5
|
+
- push
|
8
6
|
|
9
7
|
jobs:
|
10
8
|
build:
|
@@ -12,7 +10,7 @@ jobs:
|
|
12
10
|
strategy:
|
13
11
|
fail-fast: false
|
14
12
|
matrix:
|
15
|
-
ruby: [2.3, 2.4, 2.5, 2.6, 2.7, 3.0, 3.1]
|
13
|
+
ruby: [2.3, 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2]
|
16
14
|
appraisal:
|
17
15
|
- rails50
|
18
16
|
- rails51
|
@@ -43,6 +41,8 @@ jobs:
|
|
43
41
|
ruby: 3.0
|
44
42
|
- appraisal: rails50
|
45
43
|
ruby: 3.1
|
44
|
+
- appraisal: rails50
|
45
|
+
ruby: 3.2
|
46
46
|
|
47
47
|
# Rails 5.1 supports Ruby 2.2-2.5
|
48
48
|
- appraisal: rails51
|
@@ -53,6 +53,8 @@ jobs:
|
|
53
53
|
ruby: 3.0
|
54
54
|
- appraisal: rails51
|
55
55
|
ruby: 3.1
|
56
|
+
- appraisal: rails51
|
57
|
+
ruby: 3.2
|
56
58
|
|
57
59
|
# Rails 5.2 supports Ruby 2.2-2.5
|
58
60
|
- appraisal: rails52
|
@@ -63,6 +65,8 @@ jobs:
|
|
63
65
|
ruby: 3.0
|
64
66
|
- appraisal: rails52
|
65
67
|
ruby: 3.1
|
68
|
+
- appraisal: rails52
|
69
|
+
ruby: 3.2
|
66
70
|
|
67
71
|
# Rails 6.0 supports Ruby 2.5-2.7
|
68
72
|
- appraisal: rails60
|
@@ -73,6 +77,8 @@ jobs:
|
|
73
77
|
ruby: 3.0
|
74
78
|
- appraisal: rails60
|
75
79
|
ruby: 3.1
|
80
|
+
- appraisal: rails60
|
81
|
+
ruby: 3.2
|
76
82
|
|
77
83
|
# Rails 6.1 supports Ruby 2.5+
|
78
84
|
- appraisal: rails61
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,24 @@
|
|
1
1
|
# Audited ChangeLog
|
2
2
|
|
3
|
+
## 5.3.1 (2023-02-21)
|
4
|
+
|
5
|
+
- Ensure touch support doesn't cause double audits - @mcyoung
|
6
|
+
[#660](https://github.com/collectiveidea/audited/pull/660)
|
7
|
+
- Testing Improvements - @vlad-psh
|
8
|
+
[#628](https://github.com/collectiveidea/audited/pull/628)
|
9
|
+
- Testing Improvements - @mcyoung
|
10
|
+
[#658](https://github.com/collectiveidea/audited/pull/658)
|
11
|
+
|
12
|
+
## 5.3.0 (2023-02-14)
|
13
|
+
|
14
|
+
- Audit touch calls - @mcyoung
|
15
|
+
[#657](https://github.com/collectiveidea/audited/pull/657)
|
16
|
+
- Allow using with Padrino and other non-Rails projects - @nicduke38degrees
|
17
|
+
[#655](https://github.com/collectiveidea/audited/pull/655)
|
18
|
+
- Testing updates - @jdufresne
|
19
|
+
[#652](https://github.com/collectiveidea/audited/pull/652)
|
20
|
+
[#653](https://github.com/collectiveidea/audited/pull/653)
|
21
|
+
|
3
22
|
## 5.2.0 (2023-01-23)
|
4
23
|
|
5
24
|
Improved
|
data/README.md
CHANGED
@@ -24,6 +24,7 @@ Audited supports and is [tested against](https://github.com/collectiveidea/audit
|
|
24
24
|
* 2.7
|
25
25
|
* 3.0
|
26
26
|
* 3.1
|
27
|
+
* 3.2
|
27
28
|
|
28
29
|
Audited may work just fine with a Ruby version not listed above, but we can't guarantee that it will. If you'd like to maintain a Ruby that isn't listed, please let us know with a [pull request](https://github.com/collectiveidea/audited/pulls).
|
29
30
|
|
data/lib/audited/audit.rb
CHANGED
@@ -174,7 +174,7 @@ module Audited
|
|
174
174
|
if action == "create"
|
175
175
|
self.version = 1
|
176
176
|
else
|
177
|
-
collection = (
|
177
|
+
collection = (ActiveRecord::VERSION::MAJOR >= 6) ? self.class.unscoped : self.class
|
178
178
|
max = collection.auditable_finder(auditable_id, auditable_type).maximum(:version) || 0
|
179
179
|
self.version = max + 1
|
180
180
|
end
|
data/lib/audited/auditor.rb
CHANGED
@@ -84,6 +84,7 @@ module Audited
|
|
84
84
|
|
85
85
|
after_create :audit_create if audited_options[:on].include?(:create)
|
86
86
|
before_update :audit_update if audited_options[:on].include?(:update)
|
87
|
+
after_touch :audit_touch if audited_options[:on].include?(:touch) && ::ActiveRecord::VERSION::MAJOR >= 6
|
87
88
|
before_destroy :audit_destroy if audited_options[:on].include?(:destroy)
|
88
89
|
|
89
90
|
# Define and set after_audit and around_audit callbacks. This might be useful if you want
|
@@ -230,8 +231,15 @@ module Audited
|
|
230
231
|
|
231
232
|
private
|
232
233
|
|
233
|
-
def audited_changes
|
234
|
-
all_changes =
|
234
|
+
def audited_changes(for_touch: false)
|
235
|
+
all_changes = if for_touch
|
236
|
+
previous_changes
|
237
|
+
elsif respond_to?(:changes_to_save)
|
238
|
+
changes_to_save
|
239
|
+
else
|
240
|
+
changes
|
241
|
+
end
|
242
|
+
|
235
243
|
filtered_changes = \
|
236
244
|
if audited_options[:only].present?
|
237
245
|
all_changes.slice(*self.class.audited_columns)
|
@@ -239,6 +247,13 @@ module Audited
|
|
239
247
|
all_changes.except(*self.class.non_audited_columns)
|
240
248
|
end
|
241
249
|
|
250
|
+
if for_touch
|
251
|
+
filtered_changes.reject! do |k, v|
|
252
|
+
audits.last.audited_changes[k].to_json == v.to_json ||
|
253
|
+
audits.last.audited_changes[k].to_json == v[1].to_json
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
242
257
|
filtered_changes = redact_values(filtered_changes)
|
243
258
|
filtered_changes = filter_encrypted_attrs(filtered_changes)
|
244
259
|
filtered_changes = normalize_enum_changes(filtered_changes)
|
@@ -324,6 +339,13 @@ module Audited
|
|
324
339
|
end
|
325
340
|
end
|
326
341
|
|
342
|
+
def audit_touch
|
343
|
+
unless (changes = audited_changes(for_touch: true)).empty?
|
344
|
+
write_audit(action: "update", audited_changes: changes,
|
345
|
+
comment: audit_comment)
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
327
349
|
def audit_destroy
|
328
350
|
unless new_record?
|
329
351
|
write_audit(action: "destroy", audited_changes: audited_attributes,
|
@@ -474,7 +496,7 @@ module Audited
|
|
474
496
|
|
475
497
|
def normalize_audited_options
|
476
498
|
audited_options[:on] = Array.wrap(audited_options[:on])
|
477
|
-
audited_options[:on] = [:create, :update, :destroy] if audited_options[:on].empty?
|
499
|
+
audited_options[:on] = [:create, :update, :touch, :destroy] if audited_options[:on].empty?
|
478
500
|
audited_options[:only] = Array.wrap(audited_options[:only]).map(&:to_s)
|
479
501
|
audited_options[:except] = Array.wrap(audited_options[:except]).map(&:to_s)
|
480
502
|
max_audits = audited_options[:max_audits] || Audited.max_audits
|
data/lib/audited/version.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
|
3
|
+
# not testing proxy_respond_to? hack / 2 methods / deprecation of `version`
|
4
|
+
# also, an additional 5 around `after_touch` for Versions before 6.
|
5
|
+
uncovered = ActiveRecord::VERSION::MAJOR < 6 ? 14 : 9
|
6
|
+
SingleCov.covered! uncovered: uncovered
|
4
7
|
|
5
8
|
class ConditionalPrivateCompany < ::ActiveRecord::Base
|
6
9
|
self.table_name = "companies"
|
@@ -143,7 +146,7 @@ describe Audited::Auditor do
|
|
143
146
|
end
|
144
147
|
|
145
148
|
it "should be configurable which attributes are not audited via ignored_attributes" do
|
146
|
-
Audited.ignored_attributes = ["delta", "top_secret", "created_at"]
|
149
|
+
Audited.ignored_attributes = ["delta", "top_secret", "created_at", "updated_at"]
|
147
150
|
|
148
151
|
expect(Secret.non_audited_columns).to include("delta", "top_secret", "created_at")
|
149
152
|
end
|
@@ -215,17 +218,25 @@ describe Audited::Auditor do
|
|
215
218
|
redacted = Audited::Auditor::AuditedInstanceMethods::REDACTED
|
216
219
|
user =
|
217
220
|
Models::ActiveRecord::UserMultipleRedactedAttributes.create(
|
218
|
-
password: "password"
|
219
|
-
ssn: 123456789
|
221
|
+
password: "password"
|
220
222
|
)
|
221
223
|
user.save!
|
222
224
|
expect(user.audits.last.audited_changes["password"]).to eq(redacted)
|
225
|
+
# Saving '[REDACTED]' value for 'ssn' even if value wasn't set explicitly when record was created
|
223
226
|
expect(user.audits.last.audited_changes["ssn"]).to eq(redacted)
|
227
|
+
|
224
228
|
user.password = "new_password"
|
225
229
|
user.ssn = 987654321
|
226
230
|
user.save!
|
227
231
|
expect(user.audits.last.audited_changes["password"]).to eq([redacted, redacted])
|
228
232
|
expect(user.audits.last.audited_changes["ssn"]).to eq([redacted, redacted])
|
233
|
+
|
234
|
+
# If we haven't changed any attrs from 'redacted' list, audit should not contain these keys
|
235
|
+
user.name = "new name"
|
236
|
+
user.save!
|
237
|
+
expect(user.audits.last.audited_changes).to have_key('name')
|
238
|
+
expect(user.audits.last.audited_changes).not_to have_key('password')
|
239
|
+
expect(user.audits.last.audited_changes).not_to have_key('ssn')
|
229
240
|
end
|
230
241
|
|
231
242
|
it "should redact columns in 'redacted' column with custom option" do
|
@@ -414,6 +425,83 @@ describe Audited::Auditor do
|
|
414
425
|
end
|
415
426
|
end
|
416
427
|
|
428
|
+
if ::ActiveRecord::VERSION::MAJOR >= 6
|
429
|
+
describe "on touch" do
|
430
|
+
before do
|
431
|
+
@user = create_user(name: "Brandon", status: :active)
|
432
|
+
end
|
433
|
+
|
434
|
+
it "should save an audit" do
|
435
|
+
expect { @user.touch(:suspended_at) }.to change(Audited::Audit, :count).by(1)
|
436
|
+
end
|
437
|
+
|
438
|
+
it "should set the action to 'update'" do
|
439
|
+
@user.touch(:suspended_at)
|
440
|
+
expect(@user.audits.last.action).to eq("update")
|
441
|
+
expect(Audited::Audit.updates.order(:id).last).to eq(@user.audits.last)
|
442
|
+
expect(@user.audits.updates.last).to eq(@user.audits.last)
|
443
|
+
end
|
444
|
+
|
445
|
+
it "should store the changed attributes" do
|
446
|
+
@user.touch(:suspended_at)
|
447
|
+
expect(@user.audits.last.audited_changes["suspended_at"][0]).to be_nil
|
448
|
+
expect(Time.parse(@user.audits.last.audited_changes["suspended_at"][1].to_s)).to be_within(2.seconds).of(Time.current)
|
449
|
+
end
|
450
|
+
|
451
|
+
it "should store audit comment" do
|
452
|
+
@user.audit_comment = "Here exists a touch comment"
|
453
|
+
@user.touch(:suspended_at)
|
454
|
+
expect(@user.audits.last.action).to eq("update")
|
455
|
+
expect(@user.audits.last.comment).to eq("Here exists a touch comment")
|
456
|
+
end
|
457
|
+
|
458
|
+
it "should not save an audit if only specified on create/destroy" do
|
459
|
+
on_create_destroy = Models::ActiveRecord::OnCreateDestroyUser.create(name: "Bart")
|
460
|
+
expect {
|
461
|
+
on_create_destroy.touch(:suspended_at)
|
462
|
+
}.to_not change(Audited::Audit, :count)
|
463
|
+
end
|
464
|
+
|
465
|
+
context "don't double audit" do
|
466
|
+
let(:user) { Models::ActiveRecord::Owner.create(name: "OwnerUser", suspended_at: 1.month.ago, companies_attributes: [{ name: "OwnedCompany" }]) }
|
467
|
+
let(:company) { user.companies.first }
|
468
|
+
|
469
|
+
it "should only create 1 (create) audit for object" do
|
470
|
+
expect(user.audits.count).to eq(1)
|
471
|
+
expect(user.audits.first.action).to eq("create")
|
472
|
+
end
|
473
|
+
|
474
|
+
it "should only create 1 (create) audit for nested resource" do
|
475
|
+
expect(company.audits.count).to eq(1)
|
476
|
+
expect(company.audits.first.action).to eq("create")
|
477
|
+
end
|
478
|
+
|
479
|
+
context "after creating" do
|
480
|
+
it "updating / touching nested resource shouldn't save touch audit on parent object" do
|
481
|
+
expect { company.touch(:type) }.not_to change(user.audits, :count)
|
482
|
+
expect { company.update(type: "test") }.not_to change(user.audits, :count)
|
483
|
+
end
|
484
|
+
|
485
|
+
it "updating / touching parent object shouldn't save previous data" do
|
486
|
+
expect { user.touch(:suspended_at) }.to change(user.audits, :count).from(1).to(2)
|
487
|
+
expect(user.audits.last.action).to eq("update")
|
488
|
+
expect(user.audits.last.audited_changes.keys).to eq(%w[suspended_at])
|
489
|
+
end
|
490
|
+
end
|
491
|
+
|
492
|
+
context "after updating" do
|
493
|
+
it "changing nested resource shouldn't audit owner" do
|
494
|
+
expect { user.update(username: "test") }.to change(user.audits, :count).from(1).to(2)
|
495
|
+
expect { company.update(type: "test") }.not_to change(user.audits, :count)
|
496
|
+
|
497
|
+
expect { user.touch(:suspended_at) }.to change(user.audits, :count).from(2).to(3)
|
498
|
+
expect { company.update(type: "another_test") }.not_to change(user.audits, :count)
|
499
|
+
end
|
500
|
+
end
|
501
|
+
end
|
502
|
+
end
|
503
|
+
end
|
504
|
+
|
417
505
|
describe "on destroy" do
|
418
506
|
before do
|
419
507
|
@user = create_user(status: :active)
|
@@ -124,11 +124,12 @@ module Models
|
|
124
124
|
audited
|
125
125
|
has_associated_audits
|
126
126
|
has_many :companies, class_name: "OwnedCompany", dependent: :destroy
|
127
|
+
accepts_nested_attributes_for :companies
|
127
128
|
end
|
128
129
|
|
129
130
|
class OwnedCompany < ::ActiveRecord::Base
|
130
131
|
self.table_name = "companies"
|
131
|
-
belongs_to :owner, class_name: "Owner"
|
132
|
+
belongs_to :owner, class_name: "Owner", touch: true
|
132
133
|
attr_accessible :name, :owner if respond_to?(:attr_accessible) # declare attr_accessible before calling aaa
|
133
134
|
audited associated_with: :owner
|
134
135
|
end
|
@@ -146,6 +147,11 @@ module Models
|
|
146
147
|
audited on: [:create, :destroy]
|
147
148
|
end
|
148
149
|
|
150
|
+
class OnCreateDestroyUser < ::ActiveRecord::Base
|
151
|
+
self.table_name = "users"
|
152
|
+
audited on: [:create, :destroy]
|
153
|
+
end
|
154
|
+
|
149
155
|
class OnCreateDestroyExceptName < ::ActiveRecord::Base
|
150
156
|
self.table_name = "companies"
|
151
157
|
audited except: :name, on: [:create, :destroy]
|
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.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brandon Keepers
|
@@ -13,7 +13,7 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date: 2023-
|
16
|
+
date: 2023-02-21 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: activerecord
|
@@ -252,7 +252,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
252
252
|
- !ruby/object:Gem::Version
|
253
253
|
version: '0'
|
254
254
|
requirements: []
|
255
|
-
rubygems_version: 3.
|
255
|
+
rubygems_version: 3.4.6
|
256
256
|
signing_key:
|
257
257
|
specification_version: 4
|
258
258
|
summary: Log all changes to your models
|