audited 5.2.0 → 5.3.2

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: c9441d78ecdc47f146411573dbbba291449a94d062e2e564be52ff58548a2c25
4
+ data.tar.gz: e2843b1bfe94e4a19aa6666a98c01d23fd165240f96d2c602d5291383b68f4a1
5
5
  SHA512:
6
- metadata.gz: 27d6c2bd685eaca06093e7b8352aa942b83163a09be96fade16cc39ac46502697ca264a54f7a99a4390afe6cc07fbca0d345cb4ad35d7a11d98fa8da9aa262dd
7
- data.tar.gz: 615ffae5d0fe3a44ffde034ddd60a2074cdff6679b1a8d59b23adfa2fed557023ffd786516997627aaf3de7916c39666d85abd24b38b1562976678472bbc85a9
6
+ metadata.gz: fbee8a19b3da64248a2d2ea58bdac95f94431b4e57545ceae25897b50470a3adf7bc9b7497da58a7e85e466502d2baa3c0d9e9e96e070b2f48b8a0ebe506cd0d
7
+ data.tar.gz: e0093f598ceec9caade9d14c9fdba938e8ba92b3355bc164ba9587b1863230681586071ac5864ede9aaf361be58bdad38e08742a9f06e1093e89422c0a04e4ea
@@ -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,29 @@
1
1
  # Audited ChangeLog
2
2
 
3
+ ## 5.3.2 (2023-02-22)
4
+
5
+ - Touch audit bug fixes - @mcyoung
6
+ [#662](https://github.com/collectiveidea/audited/pull/662)
7
+
8
+ ## 5.3.1 (2023-02-21)
9
+
10
+ - Ensure touch support doesn't cause double audits - @mcyoung
11
+ [#660](https://github.com/collectiveidea/audited/pull/660)
12
+ - Testing Improvements - @vlad-psh
13
+ [#628](https://github.com/collectiveidea/audited/pull/628)
14
+ - Testing Improvements - @mcyoung
15
+ [#658](https://github.com/collectiveidea/audited/pull/658)
16
+
17
+ ## 5.3.0 (2023-02-14)
18
+
19
+ - Audit touch calls - @mcyoung
20
+ [#657](https://github.com/collectiveidea/audited/pull/657)
21
+ - Allow using with Padrino and other non-Rails projects - @nicduke38degrees
22
+ [#655](https://github.com/collectiveidea/audited/pull/655)
23
+ - Testing updates - @jdufresne
24
+ [#652](https://github.com/collectiveidea/audited/pull/652)
25
+ [#653](https://github.com/collectiveidea/audited/pull/653)
26
+
3
27
  ## 5.2.0 (2023-01-23)
4
28
 
5
29
  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,15 @@ 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
+ next unless audits.present?
253
+
254
+ audits.last.audited_changes[k].to_json == v.to_json ||
255
+ audits.last.audited_changes[k].to_json == v[1].to_json
256
+ end
257
+ end
258
+
242
259
  filtered_changes = redact_values(filtered_changes)
243
260
  filtered_changes = filter_encrypted_attrs(filtered_changes)
244
261
  filtered_changes = normalize_enum_changes(filtered_changes)
@@ -324,6 +341,13 @@ module Audited
324
341
  end
325
342
  end
326
343
 
344
+ def audit_touch
345
+ unless (changes = audited_changes(for_touch: true)).empty?
346
+ write_audit(action: "update", audited_changes: changes,
347
+ comment: audit_comment)
348
+ end
349
+ end
350
+
327
351
  def audit_destroy
328
352
  unless new_record?
329
353
  write_audit(action: "destroy", audited_changes: audited_attributes,
@@ -474,7 +498,7 @@ module Audited
474
498
 
475
499
  def normalize_audited_options
476
500
  audited_options[:on] = Array.wrap(audited_options[:on])
477
- audited_options[:on] = [:create, :update, :destroy] if audited_options[:on].empty?
501
+ audited_options[:on] = [:create, :update, :touch, :destroy] if audited_options[:on].empty?
478
502
  audited_options[:only] = Array.wrap(audited_options[:only]).map(&:to_s)
479
503
  audited_options[:except] = Array.wrap(audited_options[:except]).map(&:to_s)
480
504
  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.2"
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 6 around `after_touch` for Versions before 6.
5
+ uncovered = (ActiveRecord::VERSION::MAJOR < 6) ? 15 : 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,99 @@ 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
+ it "should store an audit if touch is the only audit" do
466
+ on_touch = Models::ActiveRecord::OnTouchOnly.create(name: "Bart")
467
+ expect {
468
+ on_touch.update(name: "NotBart")
469
+ }.to_not change(Audited::Audit, :count)
470
+ expect {
471
+ on_touch.touch(:suspended_at)
472
+ }.to change(on_touch.audits, :count).from(0).to(1)
473
+
474
+ @user.audits.destroy_all
475
+ expect(@user.audits).to be_empty
476
+ expect {
477
+ @user.touch(:suspended_at)
478
+ }.to change(@user.audits, :count).from(0).to(1)
479
+ end
480
+
481
+ context "don't double audit" do
482
+ let(:user) { Models::ActiveRecord::Owner.create(name: "OwnerUser", suspended_at: 1.month.ago, companies_attributes: [{name: "OwnedCompany"}]) }
483
+ let(:company) { user.companies.first }
484
+
485
+ it "should only create 1 (create) audit for object" do
486
+ expect(user.audits.count).to eq(1)
487
+ expect(user.audits.first.action).to eq("create")
488
+ end
489
+
490
+ it "should only create 1 (create) audit for nested resource" do
491
+ expect(company.audits.count).to eq(1)
492
+ expect(company.audits.first.action).to eq("create")
493
+ end
494
+
495
+ context "after creating" do
496
+ it "updating / touching nested resource shouldn't save touch audit on parent object" do
497
+ expect { company.touch(:type) }.not_to change(user.audits, :count)
498
+ expect { company.update(type: "test") }.not_to change(user.audits, :count)
499
+ end
500
+
501
+ it "updating / touching parent object shouldn't save previous data" do
502
+ expect { user.touch(:suspended_at) }.to change(user.audits, :count).from(1).to(2)
503
+ expect(user.audits.last.action).to eq("update")
504
+ expect(user.audits.last.audited_changes.keys).to eq(%w[suspended_at])
505
+ end
506
+ end
507
+
508
+ context "after updating" do
509
+ it "changing nested resource shouldn't audit owner" do
510
+ expect { user.update(username: "test") }.to change(user.audits, :count).from(1).to(2)
511
+ expect { company.update(type: "test") }.not_to change(user.audits, :count)
512
+
513
+ expect { user.touch(:suspended_at) }.to change(user.audits, :count).from(2).to(3)
514
+ expect { company.update(type: "another_test") }.not_to change(user.audits, :count)
515
+ end
516
+ end
517
+ end
518
+ end
519
+ end
520
+
417
521
  describe "on destroy" do
418
522
  before do
419
523
  @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]
@@ -155,5 +161,10 @@ module Models
155
161
  self.table_name = "companies"
156
162
  audited on: [:create, :update]
157
163
  end
164
+
165
+ class OnTouchOnly < ::ActiveRecord::Base
166
+ self.table_name = "users"
167
+ audited on: [:touch]
168
+ end
158
169
  end
159
170
  end
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.2
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-22 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