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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c2f155f1c224559a215a6098e8dad58c4a807e87d38cb99e9b09b21e570db0ac
4
- data.tar.gz: 572d605d910cf1d0a6c9a3904ba9ccc95979b189fabf3912a66adb590fc40bf7
3
+ metadata.gz: 4d9407750d2b70edd5e934c0b0544ba52230a3e3ac4955194029b6b7370c8fe7
4
+ data.tar.gz: 863fc4f2e8d1cc188664f4a346db886f7dfdd4bf6c6b56f3371eacb4d75497dd
5
5
  SHA512:
6
- metadata.gz: 22f44786ceff2b8dd4f22f97ad2b874b5fe8e9fb99d97519a47e68e272ca0409ec20ed042ed38e706defffc6ffb9bb2e12f95ee9d508dcd2ff731e9e24a598b3
7
- data.tar.gz: dd24d3d0f51e90f683003f831d9907403e369aad7db2146f56dc8169d7feb5d83e6ff408693eef12e620e7b759a5bc7929c04d41d0ec5f3f36f79f953b6bc341
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.x) works with Rails 7.1, 7.0, 6.1, 6.0, 5.2, 5.1, and 5.0.
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/gem_helper"
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.version >= "7.1"
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
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Audited
4
- VERSION = "5.4.2"
4
+ VERSION = "5.5.0"
5
5
  end
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
@@ -16,7 +16,7 @@ module Audited
16
16
  private
17
17
 
18
18
  def timestamped_migrations?
19
- (Rails.version >= "7.0") ?
19
+ (Rails.gem_version >= Gem::Version.new("7.0")) ?
20
20
  ::ActiveRecord.timestamped_migrations :
21
21
  ::ActiveRecord::Base.timestamped_migrations
22
22
  end
@@ -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.version >= "7.1"
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.version >= "5.1"
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.version >= "7.1"
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.version >= "5.1"
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.2
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: 2023-11-08 00:00:00.000000000 Z
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.4.7
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: []