audited 5.0.2 → 5.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Appraisals +15 -2
- data/CHANGELOG.md +105 -1
- data/README.md +29 -11
- data/Rakefile +1 -3
- data/audited.gemspec +38 -0
- data/lib/audited/audit.rb +8 -4
- data/lib/audited/auditor.rb +81 -28
- data/lib/audited/version.rb +1 -1
- data/lib/audited.rb +18 -9
- data/lib/generators/audited/migration.rb +10 -2
- metadata +39 -57
- data/.github/workflows/ci.yml +0 -115
- data/.gitignore +0 -17
- data/.standard.yml +0 -5
- data/.yardopts +0 -3
- data/gemfiles/rails50.gemfile +0 -10
- data/gemfiles/rails51.gemfile +0 -10
- data/gemfiles/rails52.gemfile +0 -10
- data/gemfiles/rails60.gemfile +0 -10
- data/gemfiles/rails61.gemfile +0 -10
- data/gemfiles/rails70.gemfile +0 -10
- data/spec/audited/audit_spec.rb +0 -357
- data/spec/audited/auditor_spec.rb +0 -1097
- data/spec/audited/rspec_matchers_spec.rb +0 -69
- data/spec/audited/sweeper_spec.rb +0 -133
- data/spec/audited_spec.rb +0 -18
- data/spec/audited_spec_helpers.rb +0 -32
- data/spec/rails_app/app/assets/config/manifest.js +0 -2
- data/spec/rails_app/config/application.rb +0 -13
- data/spec/rails_app/config/database.yml +0 -26
- data/spec/rails_app/config/environment.rb +0 -5
- data/spec/rails_app/config/environments/test.rb +0 -47
- data/spec/rails_app/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/rails_app/config/initializers/inflections.rb +0 -2
- data/spec/rails_app/config/initializers/secret_token.rb +0 -3
- data/spec/rails_app/config/routes.rb +0 -3
- data/spec/spec_helper.rb +0 -24
- data/spec/support/active_record/models.rb +0 -151
- data/spec/support/active_record/postgres/1_change_audited_changes_type_to_json.rb +0 -11
- data/spec/support/active_record/postgres/2_change_audited_changes_type_to_jsonb.rb +0 -11
- data/spec/support/active_record/schema.rb +0 -90
- data/test/db/version_1.rb +0 -17
- data/test/db/version_2.rb +0 -18
- data/test/db/version_3.rb +0 -18
- data/test/db/version_4.rb +0 -19
- data/test/db/version_5.rb +0 -17
- data/test/db/version_6.rb +0 -19
- data/test/install_generator_test.rb +0 -62
- data/test/test_helper.rb +0 -18
- data/test/upgrade_generator_test.rb +0 -97
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6f68b2608cf53ed7087873504b4f29c97599bf31a79d284a3675c1725c91bfba
|
4
|
+
data.tar.gz: 62a32603313de542d0e9aa261110d0be63ba50c56e3073bd828e8492681ec7cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: de9505c3076a24b043ba3128f526709def0c4c9dbe2a6ac56dab7163b252efa20e94c84f9481fb7c3e5673eee822e18654949736693e42e4e00285149cc639f0
|
7
|
+
data.tar.gz: 88d44336e6e2e61952a973d9b44957d68375cc18e009ac0fc410638b9748dcd4a331dcb15224f073e28077c84ee0f50c8d5e848f559925ebedca77696ca35f32
|
data/Appraisals
CHANGED
@@ -6,6 +6,8 @@ appraise "rails50" do
|
|
6
6
|
gem "mysql2", ">= 0.3.18", "< 0.6.0"
|
7
7
|
gem "pg", ">= 0.18", "< 2.0"
|
8
8
|
gem "sqlite3", "~> 1.3.6"
|
9
|
+
gem "psych", "~> 3.1"
|
10
|
+
gem "loofah", "2.20.0"
|
9
11
|
end
|
10
12
|
|
11
13
|
appraise "rails51" do
|
@@ -13,13 +15,17 @@ appraise "rails51" do
|
|
13
15
|
gem "mysql2", ">= 0.3.18", "< 0.6.0"
|
14
16
|
gem "pg", ">= 0.18", "< 2.0"
|
15
17
|
gem "sqlite3", "~> 1.3.6"
|
18
|
+
gem "psych", "~> 3.1"
|
19
|
+
gem "loofah", "2.20.0"
|
16
20
|
end
|
17
21
|
|
18
22
|
appraise "rails52" do
|
19
|
-
gem "rails", ">= 5.2.
|
23
|
+
gem "rails", ">= 5.2.8.1", "< 5.3"
|
20
24
|
gem "mysql2", ">= 0.4.4", "< 0.6.0"
|
21
25
|
gem "pg", ">= 0.18", "< 2.0"
|
22
26
|
gem "sqlite3", "~> 1.3.6"
|
27
|
+
gem "psych", "~> 3.1"
|
28
|
+
gem "loofah", "2.20.0"
|
23
29
|
end
|
24
30
|
|
25
31
|
appraise "rails60" do
|
@@ -37,7 +43,14 @@ appraise "rails61" do
|
|
37
43
|
end
|
38
44
|
|
39
45
|
appraise "rails70" do
|
40
|
-
gem "rails", ">= 7.0.0
|
46
|
+
gem "rails", ">= 7.0.0", "< 7.1"
|
47
|
+
gem "mysql2", ">= 0.4.4"
|
48
|
+
gem "pg", ">= 1.1"
|
49
|
+
gem "sqlite3", ">= 1.4"
|
50
|
+
end
|
51
|
+
|
52
|
+
appraise "rails71" do
|
53
|
+
gem "rails", ">= 7.1.0.beta1", "< 7.2"
|
41
54
|
gem "mysql2", ">= 0.4.4"
|
42
55
|
gem "pg", ">= 1.1"
|
43
56
|
gem "sqlite3", ">= 1.4"
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,109 @@
|
|
1
1
|
# Audited ChangeLog
|
2
2
|
|
3
|
+
### 5.6.0 (2024-04-05)
|
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.5.0 (2024-04-02)
|
10
|
+
|
11
|
+
- Bad release. Same code as 5.4.1. Use 5.6.0 for updated features.
|
12
|
+
|
13
|
+
### 5.4.3 (2024-01-11)
|
14
|
+
|
15
|
+
- Ignore readonly columns in audit - @sriddbs
|
16
|
+
[#692](https://github.com/collectiveidea/audited/pull/692)
|
17
|
+
- Robustify Rails version checks - @blaet
|
18
|
+
[#689](https://github.com/collectiveidea/audited/pull/689)
|
19
|
+
- Ignore callbacks if not specifed on the model
|
20
|
+
[#679](https://github.com/collectiveidea/audited/pull/679)
|
21
|
+
|
22
|
+
## 5.4.2 (2023-11-30)
|
23
|
+
|
24
|
+
- Revert replacing RequetStore with ActiveSupport::CurrentAttributes until it is fully tested.
|
25
|
+
|
26
|
+
## 5.4.1 (2023-11-30)
|
27
|
+
|
28
|
+
- Replace RequestStore with ActiveSupport::CurrentAttributes - @the-spectator
|
29
|
+
[#673](https://github.com/collectiveidea/audited/pull/673/)
|
30
|
+
- Don't require railtie when used outside of Rails - @nicduke38degrees
|
31
|
+
[#665](https://github.com/collectiveidea/audited/pull/665)
|
32
|
+
|
33
|
+
## 5.4.0 (2023-09-30)
|
34
|
+
|
35
|
+
- Add Rails 7.1 support - @yuki24
|
36
|
+
[#686](https://github.com/collectiveidea/audited/pull/686)
|
37
|
+
|
38
|
+
## 5.3.3 (2023-03-24)
|
39
|
+
|
40
|
+
- Use RequestStore instead of Thread.current for thread-safe requests - @tiagocassio
|
41
|
+
[#669](https://github.com/collectiveidea/audited/pull/669)
|
42
|
+
- Clean up Touch audits - @mcyoung, @akostadinov
|
43
|
+
[#668](https://github.com/collectiveidea/audited/pull/668)
|
44
|
+
|
45
|
+
## 5.3.2 (2023-02-22)
|
46
|
+
|
47
|
+
- Touch audit bug fixes - @mcyoung
|
48
|
+
[#662](https://github.com/collectiveidea/audited/pull/662)
|
49
|
+
|
50
|
+
## 5.3.1 (2023-02-21)
|
51
|
+
|
52
|
+
- Ensure touch support doesn't cause double audits - @mcyoung
|
53
|
+
[#660](https://github.com/collectiveidea/audited/pull/660)
|
54
|
+
- Testing Improvements - @vlad-psh
|
55
|
+
[#628](https://github.com/collectiveidea/audited/pull/628)
|
56
|
+
- Testing Improvements - @mcyoung
|
57
|
+
[#658](https://github.com/collectiveidea/audited/pull/658)
|
58
|
+
|
59
|
+
## 5.3.0 (2023-02-14)
|
60
|
+
|
61
|
+
- Audit touch calls - @mcyoung
|
62
|
+
[#657](https://github.com/collectiveidea/audited/pull/657)
|
63
|
+
- Allow using with Padrino and other non-Rails projects - @nicduke38degrees
|
64
|
+
[#655](https://github.com/collectiveidea/audited/pull/655)
|
65
|
+
- Testing updates - @jdufresne
|
66
|
+
[#652](https://github.com/collectiveidea/audited/pull/652)
|
67
|
+
[#653](https://github.com/collectiveidea/audited/pull/653)
|
68
|
+
|
69
|
+
## 5.2.0 (2023-01-23)
|
70
|
+
|
71
|
+
Improved
|
72
|
+
|
73
|
+
- config.audit_class can take a string or constant - @rocket-turtle
|
74
|
+
Fixes overzealous change in 5.1.0 where it only took a string.
|
75
|
+
[#648](https://github.com/collectiveidea/audited/pull/648)
|
76
|
+
- README link fix - @jeremiahlukus
|
77
|
+
[#646](https://github.com/collectiveidea/audited/pull/646)
|
78
|
+
- Typo fix in GitHub Actions - @jdufresne
|
79
|
+
[#644](https://github.com/collectiveidea/audited/pull/644)
|
80
|
+
|
81
|
+
## 5.1.0 (2022-12-23)
|
82
|
+
|
83
|
+
Changed
|
84
|
+
|
85
|
+
- config.audit_class takes a string - @simmerz
|
86
|
+
[#609](https://github.com/collectiveidea/audited/pull/609)
|
87
|
+
- Filter encrypted attributes automatically - @vlad-psh
|
88
|
+
[#630](https://github.com/collectiveidea/audited/pull/630)
|
89
|
+
|
90
|
+
Improved
|
91
|
+
|
92
|
+
- README improvements - @jess, @mstroming
|
93
|
+
[#605](https://github.com/collectiveidea/audited/pull/605)
|
94
|
+
[#640](https://github.com/collectiveidea/audited/issues/640)
|
95
|
+
- Ignore deadlocks in concurrent audit combinations - @Crammaman
|
96
|
+
[#621](https://github.com/collectiveidea/audited/pull/621)
|
97
|
+
- Fix timestamped_migrations deprecation warning - @shouichi
|
98
|
+
[#624](https://github.com/collectiveidea/audited/pull/624)
|
99
|
+
- Ensure audits are re-enabled after blocks - @dcorlett
|
100
|
+
[#632](https://github.com/collectiveidea/audited/pull/632)
|
101
|
+
- Replace raw string where clause with query methods - @macowie
|
102
|
+
[#642](https://github.com/collectiveidea/audited/pull/642)
|
103
|
+
- Test against more Ruby/Rails Versions - @enomotodev, @danielmorrison
|
104
|
+
[#610](https://github.com/collectiveidea/audited/pull/610)
|
105
|
+
[#643](https://github.com/collectiveidea/audited/pull/643)
|
106
|
+
|
3
107
|
## 5.0.2 (2021-09-16)
|
4
108
|
|
5
109
|
Added
|
@@ -11,7 +115,7 @@ Improved
|
|
11
115
|
|
12
116
|
- Improve loading - @mvastola
|
13
117
|
[#592](https://github.com/collectiveidea/audited/pull/592)
|
14
|
-
- Update README - @danirod, clement1234
|
118
|
+
- Update README - @danirod, @clement1234
|
15
119
|
[#596](https://github.com/collectiveidea/audited/pull/596)
|
16
120
|
[#594](https://github.com/collectiveidea/audited/pull/594)
|
17
121
|
|
data/README.md
CHANGED
@@ -2,15 +2,15 @@ Audited
|
|
2
2
|
[![Gem Version](https://img.shields.io/gem/v/audited.svg)](http://rubygems.org/gems/audited)
|
3
3
|
![Build Status](https://github.com/collectiveidea/audited/actions/workflows/ci.yml/badge.svg)
|
4
4
|
[![Code Climate](https://codeclimate.com/github/collectiveidea/audited.svg)](https://codeclimate.com/github/collectiveidea/audited)
|
5
|
-
[![Security](https://hakiri.io/github/collectiveidea/audited/master.svg)](https://hakiri.io/github/collectiveidea/audited/master)
|
6
5
|
[![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)
|
7
6
|
=======
|
8
7
|
|
9
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.
|
10
9
|
|
11
10
|
|
12
|
-
Audited currently (5.
|
11
|
+
Audited currently (5.6) works with Rails 7.1, 7.0, 6.1, 6.0, 5.2.
|
13
12
|
|
13
|
+
For Rails 5.0 & 5.1, use gem version 5.4.3
|
14
14
|
For Rails 4, use gem version 4.x
|
15
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).
|
16
16
|
|
@@ -18,12 +18,14 @@ For Rails 3, use gem version 3.0 or see the [3.0-stable branch](https://github.c
|
|
18
18
|
|
19
19
|
Audited supports and is [tested against](https://github.com/collectiveidea/audited/actions/workflows/ci.yml) the following Ruby versions:
|
20
20
|
|
21
|
-
* 2.3
|
21
|
+
* 2.3 (only tested on Sqlite due to testing issues with other DBs)
|
22
22
|
* 2.4
|
23
23
|
* 2.5
|
24
24
|
* 2.6
|
25
25
|
* 2.7
|
26
26
|
* 3.0
|
27
|
+
* 3.1
|
28
|
+
* 3.2
|
27
29
|
|
28
30
|
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
31
|
|
@@ -36,7 +38,7 @@ Audited is currently ActiveRecord-only. In a previous life, Audited worked with
|
|
36
38
|
Add the gem to your Gemfile:
|
37
39
|
|
38
40
|
```ruby
|
39
|
-
gem "audited"
|
41
|
+
gem "audited"
|
40
42
|
```
|
41
43
|
|
42
44
|
And if you're using ```require: false``` you must add initializers like this:
|
@@ -132,18 +134,24 @@ end
|
|
132
134
|
|
133
135
|
### Specifying callbacks
|
134
136
|
|
135
|
-
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.
|
136
138
|
|
137
139
|
```ruby
|
138
140
|
class User < ActiveRecord::Base
|
139
141
|
# All fields and actions
|
140
142
|
# audited
|
141
143
|
|
142
|
-
# Single field, only audit Update and Destroy (not Create)
|
144
|
+
# Single field, only audit Update and Destroy (not Create or Touch)
|
143
145
|
# audited only: :name, on: [:update, :destroy]
|
144
146
|
end
|
145
147
|
```
|
146
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
|
+
|
147
155
|
### Comments
|
148
156
|
|
149
157
|
You can attach comments to each audit using an `audit_comment` attribute on your model.
|
@@ -237,7 +245,7 @@ class ApplicationController < ActionController::Base
|
|
237
245
|
if current_user
|
238
246
|
current_user
|
239
247
|
else
|
240
|
-
'
|
248
|
+
'Alexander Fleming'
|
241
249
|
end
|
242
250
|
end
|
243
251
|
end
|
@@ -286,6 +294,7 @@ class User < ActiveRecord::Base
|
|
286
294
|
end
|
287
295
|
|
288
296
|
class Company < ActiveRecord::Base
|
297
|
+
audited
|
289
298
|
has_many :users
|
290
299
|
has_associated_audits
|
291
300
|
end
|
@@ -314,8 +323,6 @@ If you want to audit only under specific conditions, you can provide conditional
|
|
314
323
|
class User < ActiveRecord::Base
|
315
324
|
audited if: :active?
|
316
325
|
|
317
|
-
private
|
318
|
-
|
319
326
|
def active?
|
320
327
|
last_login > 6.months.ago
|
321
328
|
end
|
@@ -386,6 +393,17 @@ User.auditing_enabled = false
|
|
386
393
|
end
|
387
394
|
```
|
388
395
|
|
396
|
+
### Encrypted attributes
|
397
|
+
|
398
|
+
If you're using ActiveRecord's encryption (available from Rails 7) to encrypt some attributes, Audited will automatically filter values of these attributes. No additional configuration is required. Changes to encrypted attributes will be logged as `[FILTERED]`.
|
399
|
+
|
400
|
+
```ruby
|
401
|
+
class User < ActiveRecord::Base
|
402
|
+
audited
|
403
|
+
encrypts :password
|
404
|
+
end
|
405
|
+
```
|
406
|
+
|
389
407
|
### Custom `Audit` model
|
390
408
|
|
391
409
|
If you want to extend or modify the audit model, create a new class that
|
@@ -402,7 +420,7 @@ Then set it in an initializer:
|
|
402
420
|
# config/initializers/audited.rb
|
403
421
|
|
404
422
|
Audited.config do |config|
|
405
|
-
config.audit_class = CustomAudit
|
423
|
+
config.audit_class = "CustomAudit"
|
406
424
|
end
|
407
425
|
```
|
408
426
|
|
@@ -418,7 +436,7 @@ Audited.store_synthesized_enums = true
|
|
418
436
|
|
419
437
|
## Support
|
420
438
|
|
421
|
-
You can find documentation at:
|
439
|
+
You can find documentation at: https://www.rubydoc.info/gems/audited
|
422
440
|
|
423
441
|
Or join the [mailing list](http://groups.google.com/group/audited) to get help or offer suggestions.
|
424
442
|
|
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/audited.gemspec
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
require "audited/version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = "audited"
|
6
|
+
gem.version = Audited::VERSION
|
7
|
+
|
8
|
+
gem.authors = ["Brandon Keepers", "Kenneth Kalmer", "Daniel Morrison", "Brian Ryckbost", "Steve Richert", "Ryan Glover"]
|
9
|
+
gem.email = "info@collectiveidea.com"
|
10
|
+
gem.description = "Log all changes to your models"
|
11
|
+
gem.summary = gem.description
|
12
|
+
gem.homepage = "https://github.com/collectiveidea/audited"
|
13
|
+
gem.license = "MIT"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($\).reject { |f| f =~ /^(\.gemspec|\.git|\.standard|\.yard|gemfiles|test|spec)/ }
|
16
|
+
|
17
|
+
gem.required_ruby_version = ">= 2.3.0"
|
18
|
+
|
19
|
+
gem.add_dependency "activerecord", ">= 5.2", "< 7.2"
|
20
|
+
gem.add_dependency "activesupport", ">= 5.2", "< 7.2"
|
21
|
+
|
22
|
+
gem.add_development_dependency "appraisal"
|
23
|
+
gem.add_development_dependency "rails", ">= 5.2", "< 7.2"
|
24
|
+
gem.add_development_dependency "rspec-rails"
|
25
|
+
gem.add_development_dependency "standard"
|
26
|
+
gem.add_development_dependency "single_cov"
|
27
|
+
|
28
|
+
# JRuby support for the test ENV
|
29
|
+
if defined?(JRUBY_VERSION)
|
30
|
+
gem.add_development_dependency "activerecord-jdbcsqlite3-adapter", "~> 1.3"
|
31
|
+
gem.add_development_dependency "activerecord-jdbcpostgresql-adapter", "~> 1.3"
|
32
|
+
gem.add_development_dependency "activerecord-jdbcmysql-adapter", "~> 1.3"
|
33
|
+
else
|
34
|
+
gem.add_development_dependency "sqlite3", ">= 1.3.6"
|
35
|
+
gem.add_development_dependency "mysql2", ">= 0.3.20"
|
36
|
+
gem.add_development_dependency "pg", ">= 0.18", "< 2.0"
|
37
|
+
end
|
38
|
+
end
|
data/lib/audited/audit.rb
CHANGED
@@ -49,7 +49,11 @@ module Audited
|
|
49
49
|
cattr_accessor :audited_class_names
|
50
50
|
self.audited_class_names = Set.new
|
51
51
|
|
52
|
-
|
52
|
+
if Rails.gem_version >= Gem::Version.new("7.1")
|
53
|
+
serialize :audited_changes, coder: YAMLIfTextColumnType
|
54
|
+
else
|
55
|
+
serialize :audited_changes, YAMLIfTextColumnType
|
56
|
+
end
|
53
57
|
|
54
58
|
scope :ascending, -> { reorder(version: :asc) }
|
55
59
|
scope :descending, -> { reorder(version: :desc) }
|
@@ -78,14 +82,14 @@ module Audited
|
|
78
82
|
# Returns a hash of the changed attributes with the new values
|
79
83
|
def new_attributes
|
80
84
|
(audited_changes || {}).each_with_object({}.with_indifferent_access) do |(attr, values), attrs|
|
81
|
-
attrs[attr] = (action == "update" ? values.last : values
|
85
|
+
attrs[attr] = (action == "update") ? values.last : values
|
82
86
|
end
|
83
87
|
end
|
84
88
|
|
85
89
|
# Returns a hash of the changed attributes with the old values
|
86
90
|
def old_attributes
|
87
91
|
(audited_changes || {}).each_with_object({}.with_indifferent_access) do |(attr, values), attrs|
|
88
|
-
attrs[attr] = (action == "update" ? values.first : values
|
92
|
+
attrs[attr] = (action == "update") ? values.first : values
|
89
93
|
end
|
90
94
|
end
|
91
95
|
|
@@ -174,7 +178,7 @@ module Audited
|
|
174
178
|
if action == "create"
|
175
179
|
self.version = 1
|
176
180
|
else
|
177
|
-
collection =
|
181
|
+
collection = (ActiveRecord::VERSION::MAJOR >= 6) ? self.class.unscoped : self.class
|
178
182
|
max = collection.auditable_finder(auditable_id, auditable_type).maximum(:version) || 0
|
179
183
|
self.version = max + 1
|
180
184
|
end
|
data/lib/audited/auditor.rb
CHANGED
@@ -13,7 +13,7 @@ module Audited
|
|
13
13
|
#
|
14
14
|
# See <tt>Audited::Auditor::ClassMethods#audited</tt>
|
15
15
|
# for configuration options
|
16
|
-
module Auditor
|
16
|
+
module Auditor # :nodoc:
|
17
17
|
extend ActiveSupport::Concern
|
18
18
|
|
19
19
|
CALLBACKS = [:audit_create, :audit_update, :audit_destroy]
|
@@ -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
|
@@ -172,14 +173,15 @@ module Audited
|
|
172
173
|
# List of attributes that are audited.
|
173
174
|
def audited_attributes
|
174
175
|
audited_attributes = attributes.except(*self.class.non_audited_columns)
|
176
|
+
audited_attributes = redact_values(audited_attributes)
|
177
|
+
audited_attributes = filter_encrypted_attrs(audited_attributes)
|
175
178
|
normalize_enum_changes(audited_attributes)
|
176
179
|
end
|
177
180
|
|
178
181
|
# Returns a list combined of record audits and associated audits.
|
179
182
|
def own_and_associated_audits
|
180
|
-
Audited.audit_class.unscoped
|
181
|
-
.where(
|
182
|
-
type: self.class.base_class.name, id: id)
|
183
|
+
Audited.audit_class.unscoped.where(auditable: self)
|
184
|
+
.or(Audited.audit_class.unscoped.where(associated: self))
|
183
185
|
.order(created_at: :desc)
|
184
186
|
end
|
185
187
|
|
@@ -190,8 +192,13 @@ module Audited
|
|
190
192
|
combine_target.comment = "#{combine_target.comment}\nThis audit is the result of multiple audits being combined."
|
191
193
|
|
192
194
|
transaction do
|
193
|
-
|
194
|
-
|
195
|
+
begin
|
196
|
+
combine_target.save!
|
197
|
+
audits_to_combine.unscope(:limit).where("version < ?", combine_target.version).delete_all
|
198
|
+
rescue ActiveRecord::Deadlocked
|
199
|
+
# Ignore Deadlocks, if the same record is getting its old audits combined more than once at the same time then
|
200
|
+
# both combining operations will be the same. Ignoring this error allows one of the combines to go through successfully.
|
201
|
+
end
|
195
202
|
end
|
196
203
|
end
|
197
204
|
|
@@ -224,8 +231,17 @@ module Audited
|
|
224
231
|
|
225
232
|
private
|
226
233
|
|
227
|
-
def audited_changes
|
228
|
-
all_changes =
|
234
|
+
def audited_changes(for_touch: false, exclude_readonly_attrs: 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
|
+
|
243
|
+
all_changes = all_changes.except(*self.class.readonly_attributes.to_a) if exclude_readonly_attrs
|
244
|
+
|
229
245
|
filtered_changes = \
|
230
246
|
if audited_options[:only].present?
|
231
247
|
all_changes.slice(*self.class.audited_columns)
|
@@ -233,8 +249,17 @@ module Audited
|
|
233
249
|
all_changes.except(*self.class.non_audited_columns)
|
234
250
|
end
|
235
251
|
|
236
|
-
filtered_changes = redact_values(filtered_changes)
|
237
252
|
filtered_changes = normalize_enum_changes(filtered_changes)
|
253
|
+
|
254
|
+
if for_touch && (last_audit = audits.last&.audited_changes)
|
255
|
+
filtered_changes.reject! do |k, v|
|
256
|
+
last_audit[k].to_json == v.to_json ||
|
257
|
+
last_audit[k].to_json == v[1].to_json
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
filtered_changes = redact_values(filtered_changes)
|
262
|
+
filtered_changes = filter_encrypted_attrs(filtered_changes)
|
238
263
|
filtered_changes.to_hash
|
239
264
|
end
|
240
265
|
|
@@ -257,19 +282,36 @@ module Audited
|
|
257
282
|
end
|
258
283
|
|
259
284
|
def redact_values(filtered_changes)
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
filtered_changes
|
285
|
+
filter_attr_values(
|
286
|
+
audited_changes: filtered_changes,
|
287
|
+
attrs: Array(audited_options[:redacted]).map(&:to_s),
|
288
|
+
placeholder: audited_options[:redaction_value] || REDACTED
|
289
|
+
)
|
290
|
+
end
|
291
|
+
|
292
|
+
def filter_encrypted_attrs(filtered_changes)
|
293
|
+
filter_attr_values(
|
294
|
+
audited_changes: filtered_changes,
|
295
|
+
attrs: respond_to?(:encrypted_attributes) ? Array(encrypted_attributes).map(&:to_s) : []
|
296
|
+
)
|
297
|
+
end
|
298
|
+
|
299
|
+
# Replace values for given attrs to a placeholder and return modified hash
|
300
|
+
#
|
301
|
+
# @param audited_changes [Hash] Hash of changes to be saved to audited version record
|
302
|
+
# @param attrs [Array<String>] Array of attrs, values of which will be replaced to placeholder value
|
303
|
+
# @param placeholder [String] Placeholder to replace original attr values
|
304
|
+
def filter_attr_values(audited_changes: {}, attrs: [], placeholder: "[FILTERED]")
|
305
|
+
attrs.each do |attr|
|
306
|
+
next unless audited_changes.key?(attr)
|
307
|
+
|
308
|
+
changes = audited_changes[attr]
|
309
|
+
values = changes.is_a?(Array) ? changes.map { placeholder } : placeholder
|
310
|
+
|
311
|
+
audited_changes[attr] = values
|
270
312
|
end
|
271
313
|
|
272
|
-
|
314
|
+
audited_changes
|
273
315
|
end
|
274
316
|
|
275
317
|
def rails_below?(rails_version)
|
@@ -290,20 +332,27 @@ module Audited
|
|
290
332
|
|
291
333
|
def audit_create
|
292
334
|
write_audit(action: "create", audited_changes: audited_attributes,
|
293
|
-
|
335
|
+
comment: audit_comment)
|
294
336
|
end
|
295
337
|
|
296
338
|
def audit_update
|
297
|
-
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)
|
298
340
|
write_audit(action: "update", audited_changes: changes,
|
299
|
-
|
341
|
+
comment: audit_comment)
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
def audit_touch
|
346
|
+
unless (changes = audited_changes(for_touch: true, exclude_readonly_attrs: true)).empty?
|
347
|
+
write_audit(action: "update", audited_changes: changes,
|
348
|
+
comment: audit_comment)
|
300
349
|
end
|
301
350
|
end
|
302
351
|
|
303
352
|
def audit_destroy
|
304
353
|
unless new_record?
|
305
354
|
write_audit(action: "destroy", audited_changes: audited_attributes,
|
306
|
-
|
355
|
+
comment: audit_comment)
|
307
356
|
end
|
308
357
|
end
|
309
358
|
|
@@ -397,7 +446,7 @@ module Audited
|
|
397
446
|
# end
|
398
447
|
#
|
399
448
|
def without_auditing
|
400
|
-
auditing_was_enabled =
|
449
|
+
auditing_was_enabled = class_auditing_enabled
|
401
450
|
disable_auditing
|
402
451
|
yield
|
403
452
|
ensure
|
@@ -411,7 +460,7 @@ module Audited
|
|
411
460
|
# end
|
412
461
|
#
|
413
462
|
def with_auditing
|
414
|
-
auditing_was_enabled =
|
463
|
+
auditing_was_enabled = class_auditing_enabled
|
415
464
|
enable_auditing
|
416
465
|
yield
|
417
466
|
ensure
|
@@ -435,7 +484,7 @@ module Audited
|
|
435
484
|
end
|
436
485
|
|
437
486
|
def auditing_enabled
|
438
|
-
|
487
|
+
class_auditing_enabled && Audited.auditing_enabled
|
439
488
|
end
|
440
489
|
|
441
490
|
def auditing_enabled=(val)
|
@@ -450,7 +499,7 @@ module Audited
|
|
450
499
|
|
451
500
|
def normalize_audited_options
|
452
501
|
audited_options[:on] = Array.wrap(audited_options[:on])
|
453
|
-
audited_options[:on] = [:create, :update, :destroy] if audited_options[:on].empty?
|
502
|
+
audited_options[:on] = ([:create, :update, :touch, :destroy] - Audited.ignored_default_callbacks) if audited_options[:on].empty?
|
454
503
|
audited_options[:only] = Array.wrap(audited_options[:only]).map(&:to_s)
|
455
504
|
audited_options[:except] = Array.wrap(audited_options[:except]).map(&:to_s)
|
456
505
|
max_audits = audited_options[:max_audits] || Audited.max_audits
|
@@ -466,6 +515,10 @@ module Audited
|
|
466
515
|
default_ignored_attributes
|
467
516
|
end
|
468
517
|
end
|
518
|
+
|
519
|
+
def class_auditing_enabled
|
520
|
+
Audited.store.fetch("#{table_name}_auditing_enabled", true)
|
521
|
+
end
|
469
522
|
end
|
470
523
|
end
|
471
524
|
end
|
data/lib/audited/version.rb
CHANGED
data/lib/audited.rb
CHANGED
@@ -3,27 +3,35 @@
|
|
3
3
|
require "active_record"
|
4
4
|
|
5
5
|
module Audited
|
6
|
+
# Wrapper around ActiveSupport::CurrentAttributes
|
7
|
+
class RequestStore < ActiveSupport::CurrentAttributes
|
8
|
+
attribute :audited_store
|
9
|
+
end
|
10
|
+
|
6
11
|
class << self
|
7
12
|
attr_accessor \
|
8
13
|
:auditing_enabled,
|
9
14
|
:current_user_method,
|
10
15
|
:ignored_attributes,
|
16
|
+
:ignored_default_callbacks,
|
11
17
|
:max_audits,
|
12
18
|
:store_synthesized_enums
|
13
19
|
attr_writer :audit_class
|
14
20
|
|
15
21
|
def audit_class
|
16
|
-
|
22
|
+
# The audit_class is set as String in the initializer. It can not be constantized during initialization and must
|
23
|
+
# be constantized at runtime. See https://github.com/collectiveidea/audited/issues/608
|
24
|
+
@audit_class = @audit_class.safe_constantize if @audit_class.is_a?(String)
|
25
|
+
@audit_class ||= Audited::Audit
|
17
26
|
end
|
18
27
|
|
19
|
-
|
20
|
-
|
28
|
+
# remove audit_model in next major version it was only shortly present in 5.1.0
|
29
|
+
alias_method :audit_model, :audit_class
|
30
|
+
deprecate audit_model: "use Audited.audit_class instead of Audited.audit_model. This method will be removed.",
|
31
|
+
deprecator: ActiveSupport::Deprecation.new('6.0.0', 'Audited')
|
21
32
|
|
22
|
-
|
23
|
-
|
24
|
-
else
|
25
|
-
current_store_value
|
26
|
-
end
|
33
|
+
def store
|
34
|
+
RequestStore.audited_store ||= {}
|
27
35
|
end
|
28
36
|
|
29
37
|
def config
|
@@ -32,6 +40,7 @@ module Audited
|
|
32
40
|
end
|
33
41
|
|
34
42
|
@ignored_attributes = %w[lock_version created_at updated_at created_on updated_on]
|
43
|
+
@ignored_default_callbacks = []
|
35
44
|
|
36
45
|
@current_user_method = :current_user
|
37
46
|
@auditing_enabled = true
|
@@ -46,4 +55,4 @@ ActiveSupport.on_load :active_record do
|
|
46
55
|
end
|
47
56
|
|
48
57
|
require "audited/sweeper"
|
49
|
-
require "audited/railtie"
|
58
|
+
require "audited/railtie" if Audited.const_defined?(:Rails)
|