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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 86131fd51439ffb0e1e16fd0b3bdd770c0cdf6de5bc8df5f234377d9ef0aeddb
4
- data.tar.gz: 4729941ef95dc9e6e542eb705ac12ff4876999c61f210a50d8ef460a02d71078
3
+ metadata.gz: 051f76b7a9cfbc91222643f2e0ddaa7738d2e446c00ec079dcf0b5d64d7146d3
4
+ data.tar.gz: 70ef8ed6c1473ca9d2ac21dc444ae66c0b8d42280e5a3c6bf4d1fe46c07f0e60
5
5
  SHA512:
6
- metadata.gz: 27d6c2bd685eaca06093e7b8352aa942b83163a09be96fade16cc39ac46502697ca264a54f7a99a4390afe6cc07fbca0d345cb4ad35d7a11d98fa8da9aa262dd
7
- data.tar.gz: 615ffae5d0fe3a44ffde034ddd60a2074cdff6679b1a8d59b23adfa2fed557023ffd786516997627aaf3de7916c39666d85abd24b38b1562976678472bbc85a9
6
+ metadata.gz: e085b0764b5feb96dc88cb5db4361f07148550368bde350a45fe21aba47ed80bfa38bb5683437bf3ad7cd983d7dbfe5f4980a80a7da0f1bf76dabea037323b58
7
+ data.tar.gz: d55bbe1f1f139efd63ac97281d954bfac440b091e292ad57b23668a456f4e389f4401c9a6e6e4ebb9627d4556a9460cb94d2d71c0f0f2f5174b0e62cb2c10968
@@ -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 = (Rails::VERSION::MAJOR >= 6) ? self.class.unscoped : self.class
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
@@ -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 = respond_to?(:changes_to_save) ? changes_to_save : 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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Audited
4
- VERSION = "5.2.0"
4
+ VERSION = "5.3.1"
5
5
  end
@@ -1,6 +1,9 @@
1
1
  require "spec_helper"
2
2
 
3
- SingleCov.covered! uncovered: 9 # not testing proxy_respond_to? hack / 2 methods / deprecation of `version`
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.2.0
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-01-23 00:00:00.000000000 Z
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.3.7
255
+ rubygems_version: 3.4.6
256
256
  signing_key:
257
257
  specification_version: 4
258
258
  summary: Log all changes to your models