velocity_audited 5.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yml +115 -0
  3. data/.gitignore +17 -0
  4. data/.standard.yml +5 -0
  5. data/.yardopts +3 -0
  6. data/Appraisals +44 -0
  7. data/CHANGELOG.md +419 -0
  8. data/Gemfile +3 -0
  9. data/LICENSE +19 -0
  10. data/README.md +433 -0
  11. data/Rakefile +18 -0
  12. data/gemfiles/rails50.gemfile +10 -0
  13. data/gemfiles/rails51.gemfile +10 -0
  14. data/gemfiles/rails52.gemfile +10 -0
  15. data/gemfiles/rails60.gemfile +10 -0
  16. data/gemfiles/rails61.gemfile +10 -0
  17. data/gemfiles/rails70.gemfile +10 -0
  18. data/lib/audited/audit.rb +198 -0
  19. data/lib/audited/auditor.rb +476 -0
  20. data/lib/audited/railtie.rb +16 -0
  21. data/lib/audited/rspec_matchers.rb +228 -0
  22. data/lib/audited/sweeper.rb +67 -0
  23. data/lib/audited/version.rb +5 -0
  24. data/lib/audited-rspec.rb +6 -0
  25. data/lib/audited.rb +49 -0
  26. data/lib/generators/audited/install_generator.rb +27 -0
  27. data/lib/generators/audited/migration.rb +17 -0
  28. data/lib/generators/audited/migration_helper.rb +11 -0
  29. data/lib/generators/audited/templates/add_association_to_audits.rb +13 -0
  30. data/lib/generators/audited/templates/add_comment_to_audits.rb +11 -0
  31. data/lib/generators/audited/templates/add_remote_address_to_audits.rb +12 -0
  32. data/lib/generators/audited/templates/add_request_uuid_to_audits.rb +12 -0
  33. data/lib/generators/audited/templates/add_version_to_auditable_index.rb +23 -0
  34. data/lib/generators/audited/templates/install.rb +32 -0
  35. data/lib/generators/audited/templates/rename_association_to_associated.rb +25 -0
  36. data/lib/generators/audited/templates/rename_changes_to_audited_changes.rb +11 -0
  37. data/lib/generators/audited/templates/rename_parent_to_association.rb +13 -0
  38. data/lib/generators/audited/templates/revert_polymorphic_indexes_order.rb +22 -0
  39. data/lib/generators/audited/upgrade_generator.rb +70 -0
  40. data/lib/velocity_audited.rb +5 -0
  41. data/spec/audited/audit_spec.rb +357 -0
  42. data/spec/audited/auditor_spec.rb +1097 -0
  43. data/spec/audited/rspec_matchers_spec.rb +69 -0
  44. data/spec/audited/sweeper_spec.rb +133 -0
  45. data/spec/audited_spec.rb +18 -0
  46. data/spec/audited_spec_helpers.rb +32 -0
  47. data/spec/rails_app/app/assets/config/manifest.js +2 -0
  48. data/spec/rails_app/config/application.rb +13 -0
  49. data/spec/rails_app/config/database.yml +26 -0
  50. data/spec/rails_app/config/environment.rb +5 -0
  51. data/spec/rails_app/config/environments/test.rb +47 -0
  52. data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  53. data/spec/rails_app/config/initializers/inflections.rb +2 -0
  54. data/spec/rails_app/config/initializers/secret_token.rb +3 -0
  55. data/spec/rails_app/config/routes.rb +3 -0
  56. data/spec/spec_helper.rb +24 -0
  57. data/spec/support/active_record/models.rb +151 -0
  58. data/spec/support/active_record/postgres/1_change_audited_changes_type_to_json.rb +11 -0
  59. data/spec/support/active_record/postgres/2_change_audited_changes_type_to_jsonb.rb +11 -0
  60. data/spec/support/active_record/schema.rb +90 -0
  61. data/test/db/version_1.rb +17 -0
  62. data/test/db/version_2.rb +18 -0
  63. data/test/db/version_3.rb +18 -0
  64. data/test/db/version_4.rb +19 -0
  65. data/test/db/version_5.rb +17 -0
  66. data/test/db/version_6.rb +19 -0
  67. data/test/install_generator_test.rb +62 -0
  68. data/test/test_helper.rb +18 -0
  69. data/test/upgrade_generator_test.rb +97 -0
  70. metadata +260 -0
data/README.md ADDED
@@ -0,0 +1,433 @@
1
+ Audited
2
+ [![Gem Version](https://img.shields.io/gem/v/audited.svg)](http://rubygems.org/gems/audited)
3
+ ![Build Status](https://github.com/collectiveidea/audited/actions/workflows/ci.yml/badge.svg)
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
+ [![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)
7
+ =======
8
+
9
+ **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
+
11
+
12
+ Audited currently (5.x) works with Rails 7.0, 6.1, 6.0, 5.2, 5.1, and 5.0.
13
+
14
+ For Rails 4, use gem version 4.x
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
+
17
+ ## Supported Rubies
18
+
19
+ Audited supports and is [tested against](https://github.com/collectiveidea/audited/actions/workflows/ci.yml) the following Ruby versions:
20
+
21
+ * 2.3
22
+ * 2.4
23
+ * 2.5
24
+ * 2.6
25
+ * 2.7
26
+ * 3.0
27
+
28
+ 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
+ ## Supported ORMs
31
+
32
+ Audited is currently ActiveRecord-only. In a previous life, Audited worked with MongoMapper. Use the [4.2-stable branch](https://github.com/collectiveidea/audited/tree/4.2-stable) if you need MongoMapper.
33
+
34
+ ## Installation
35
+
36
+ Add the gem to your Gemfile:
37
+
38
+ ```ruby
39
+ gem "audited", "~> 5.0"
40
+ ```
41
+
42
+ And if you're using ```require: false``` you must add initializers like this:
43
+
44
+ ```ruby
45
+ #./config/initializers/audited.rb
46
+ require "audited"
47
+
48
+ Audited::Railtie.initializers.each(&:run)
49
+ ```
50
+
51
+ Then, from your Rails app directory, create the `audits` table:
52
+
53
+ ```bash
54
+ $ rails generate audited:install
55
+ $ rake db:migrate
56
+ ```
57
+
58
+ By default changes are stored in YAML format. If you're using PostgreSQL, then you can use `rails generate audited:install --audited-changes-column-type jsonb` (or `json` for MySQL 5.7+ and Rails 5+) to store audit changes natively with database JSON column types.
59
+
60
+ If you're using something other than integer primary keys (e.g. UUID) for your User model, then you can use `rails generate audited:install --audited-user-id-column-type uuid` to customize the `audits` table `user_id` column type.
61
+
62
+ #### Upgrading
63
+
64
+ If you're already using Audited (or acts_as_audited), your `audits` table may require additional columns. After every upgrade, please run:
65
+
66
+ ```bash
67
+ $ rails generate audited:upgrade
68
+ $ rake db:migrate
69
+ ```
70
+
71
+ Upgrading will only make changes if changes are needed.
72
+
73
+
74
+ ## Usage
75
+
76
+ Simply call `audited` on your models:
77
+
78
+ ```ruby
79
+ class User < ActiveRecord::Base
80
+ audited
81
+ end
82
+ ```
83
+
84
+ By default, whenever a user is created, updated or destroyed, a new audit is created.
85
+
86
+ ```ruby
87
+ user = User.create!(name: "Steve")
88
+ user.audits.count # => 1
89
+ user.update!(name: "Ryan")
90
+ user.audits.count # => 2
91
+ user.destroy
92
+ user.audits.count # => 3
93
+ ```
94
+
95
+ Audits contain information regarding what action was taken on the model and what changes were made.
96
+
97
+ ```ruby
98
+ user.update!(name: "Ryan")
99
+ audit = user.audits.last
100
+ audit.action # => "update"
101
+ audit.audited_changes # => {"name"=>["Steve", "Ryan"]}
102
+ ```
103
+
104
+ You can get previous versions of a record by index or date, or list all
105
+ revisions.
106
+
107
+ ```ruby
108
+ user.revisions
109
+ user.revision(1)
110
+ user.revision_at(Date.parse("2016-01-01"))
111
+ ```
112
+
113
+ ### Specifying columns
114
+
115
+ By default, a new audit is created for any attribute changes. You can, however, limit the columns to be considered.
116
+
117
+ ```ruby
118
+ class User < ActiveRecord::Base
119
+ # All fields
120
+ # audited
121
+
122
+ # Single field
123
+ # audited only: :name
124
+
125
+ # Multiple fields
126
+ # audited only: [:name, :address]
127
+
128
+ # All except certain fields
129
+ # audited except: :password
130
+ end
131
+ ```
132
+
133
+ ### Specifying callbacks
134
+
135
+ By default, a new audit is created for any Create, Update or Destroy action. You can, however, limit the actions audited.
136
+
137
+ ```ruby
138
+ class User < ActiveRecord::Base
139
+ # All fields and actions
140
+ # audited
141
+
142
+ # Single field, only audit Update and Destroy (not Create)
143
+ # audited only: :name, on: [:update, :destroy]
144
+ end
145
+ ```
146
+
147
+ ### Comments
148
+
149
+ You can attach comments to each audit using an `audit_comment` attribute on your model.
150
+
151
+ ```ruby
152
+ user.update!(name: "Ryan", audit_comment: "Changing name, just because")
153
+ user.audits.last.comment # => "Changing name, just because"
154
+ ```
155
+
156
+ You can optionally add the `:comment_required` option to your `audited` call to require comments for all audits.
157
+
158
+ ```ruby
159
+ class User < ActiveRecord::Base
160
+ audited :comment_required => true
161
+ end
162
+ ```
163
+
164
+ You can update an audit only if audit_comment is present. You can optionally add the `:update_with_comment_only` option set to `false` to your `audited` call to turn this behavior off for all audits.
165
+
166
+ ```ruby
167
+ class User < ActiveRecord::Base
168
+ audited :update_with_comment_only => false
169
+ end
170
+ ```
171
+
172
+ ### Limiting stored audits
173
+
174
+ You can limit the number of audits stored for your model. To configure limiting for all audited models, put the following in an initializer file (`config/initializers/audited.rb`):
175
+
176
+ ```ruby
177
+ Audited.max_audits = 10 # keep only 10 latest audits
178
+ ```
179
+
180
+ or customize per model:
181
+
182
+ ```ruby
183
+ class User < ActiveRecord::Base
184
+ audited max_audits: 2
185
+ end
186
+ ```
187
+
188
+ Whenever an object is updated or destroyed, extra audits are combined with newer ones and the old ones are destroyed.
189
+
190
+ ```ruby
191
+ user = User.create!(name: "Steve")
192
+ user.audits.count # => 1
193
+ user.update!(name: "Ryan")
194
+ user.audits.count # => 2
195
+ user.destroy
196
+ user.audits.count # => 2
197
+ ```
198
+
199
+ ### Current User Tracking
200
+
201
+ If you're using Audited in a Rails application, all audited changes made within a request will automatically be attributed to the current user. By default, Audited uses the `current_user` method in your controller.
202
+
203
+ ```ruby
204
+ class PostsController < ApplicationController
205
+ def create
206
+ current_user # => #<User name: "Steve">
207
+ @post = Post.create(params[:post])
208
+ @post.audits.last.user # => #<User name: "Steve">
209
+ end
210
+ end
211
+ ```
212
+
213
+ To use a method other than `current_user`, put the following in an initializer file (`config/initializers/audited.rb`):
214
+
215
+ ```ruby
216
+ Audited.current_user_method = :authenticated_user
217
+ ```
218
+
219
+ Outside of a request, Audited can still record the user with the `as_user` method:
220
+
221
+ ```ruby
222
+ Audited.audit_class.as_user(User.find(1)) do
223
+ post.update!(title: "Hello, world!")
224
+ end
225
+ post.audits.last.user # => #<User id: 1>
226
+ ```
227
+
228
+ The standard Audited install assumes your User model has an integer primary key type. If this isn't true (e.g. you're using UUID primary keys), you'll need to create a migration to update the `audits` table `user_id` column type. (See Installation above for generator flags if you'd like to regenerate the install migration.)
229
+
230
+ #### Custom Audit User
231
+
232
+ You might need to use a custom auditor from time to time. This can be done by simply passing in a string:
233
+
234
+ ```ruby
235
+ class ApplicationController < ActionController::Base
236
+ def authenticated_user
237
+ if current_user
238
+ current_user
239
+ else
240
+ 'Elon Musk'
241
+ end
242
+ end
243
+ end
244
+ ```
245
+
246
+ `as_user` also accepts a string, which can be useful for auditing updates made in a CLI environment:
247
+
248
+ ```rb
249
+ Audited.audit_class.as_user("console-user-#{ENV['SSH_USER']}") do
250
+ post.update_attributes!(title: "Hello, world!")
251
+ end
252
+ post.audits.last.user # => 'console-user-username'
253
+ ```
254
+
255
+ If you want to set a specific user as the auditor of the commands in a CLI environment, whether that is a string or an ActiveRecord object, you can use the following command:
256
+
257
+ ```rb
258
+ Audited.store[:audited_user] = "username"
259
+
260
+ # or
261
+
262
+ Audited.store[:audited_user] = User.find(1)
263
+ ```
264
+
265
+ ### Associated Audits
266
+
267
+ Sometimes it's useful to associate an audit with a model other than the one being changed. For instance, given the following models:
268
+
269
+ ```ruby
270
+ class User < ActiveRecord::Base
271
+ belongs_to :company
272
+ audited
273
+ end
274
+
275
+ class Company < ActiveRecord::Base
276
+ has_many :users
277
+ end
278
+ ```
279
+
280
+ Every change to a user is audited, but what if you want to grab all of the audits of users belonging to a particular company? You can add the `:associated_with` option to your `audited` call:
281
+
282
+ ```ruby
283
+ class User < ActiveRecord::Base
284
+ belongs_to :company
285
+ audited associated_with: :company
286
+ end
287
+
288
+ class Company < ActiveRecord::Base
289
+ has_many :users
290
+ has_associated_audits
291
+ end
292
+ ```
293
+
294
+ Now, when an audit is created for a user, that user's company is also saved alongside the audit. This makes it much easier (and faster) to access audits indirectly related to a company.
295
+
296
+ ```ruby
297
+ company = Company.create!(name: "Collective Idea")
298
+ user = company.users.create!(name: "Steve")
299
+ user.update!(name: "Steve Richert")
300
+ user.audits.last.associated # => #<Company name: "Collective Idea">
301
+ company.associated_audits.last.auditable # => #<User name: "Steve Richert">
302
+ ```
303
+
304
+ You can access records' own audits and associated audits in one go:
305
+ ```ruby
306
+ company.own_and_associated_audits
307
+ ```
308
+
309
+ ### Conditional auditing
310
+
311
+ If you want to audit only under specific conditions, you can provide conditional options (similar to ActiveModel callbacks) that will ensure your model is only audited for these conditions.
312
+
313
+ ```ruby
314
+ class User < ActiveRecord::Base
315
+ audited if: :active?
316
+
317
+ private
318
+
319
+ def active?
320
+ last_login > 6.months.ago
321
+ end
322
+ end
323
+ ```
324
+
325
+ Just like in ActiveModel, you can use an inline Proc in your conditions:
326
+
327
+ ```ruby
328
+ class User < ActiveRecord::Base
329
+ audited unless: Proc.new { |u| u.ninja? }
330
+ end
331
+ ```
332
+
333
+ In the above case, the user will only be audited when `User#ninja` is `false`.
334
+
335
+ ### Disabling auditing
336
+
337
+ If you want to disable auditing temporarily doing certain tasks, there are a few
338
+ methods available.
339
+
340
+ To disable auditing on a save:
341
+
342
+ ```ruby
343
+ @user.save_without_auditing
344
+ ```
345
+
346
+ or:
347
+
348
+ ```ruby
349
+ @user.without_auditing do
350
+ @user.save
351
+ end
352
+ ```
353
+
354
+ To disable auditing on a column:
355
+
356
+ ```ruby
357
+ User.non_audited_columns = [:first_name, :last_name]
358
+ ```
359
+
360
+ To disable auditing on an entire model:
361
+
362
+ ```ruby
363
+ User.auditing_enabled = false
364
+ ```
365
+
366
+ To disable auditing on all models:
367
+
368
+ ```ruby
369
+ Audited.auditing_enabled = false
370
+ ```
371
+
372
+ If you have auditing disabled by default on your model you can enable auditing
373
+ temporarily.
374
+
375
+ ```ruby
376
+ User.auditing_enabled = false
377
+ @user.save_with_auditing
378
+ ```
379
+
380
+ or:
381
+
382
+ ```ruby
383
+ User.auditing_enabled = false
384
+ @user.with_auditing do
385
+ @user.save
386
+ end
387
+ ```
388
+
389
+ ### Custom `Audit` model
390
+
391
+ If you want to extend or modify the audit model, create a new class that
392
+ inherits from `Audited::Audit`:
393
+ ```ruby
394
+ class CustomAudit < Audited::Audit
395
+ def some_custom_behavior
396
+ "Hiya!"
397
+ end
398
+ end
399
+ ```
400
+ Then set it in an initializer:
401
+ ```ruby
402
+ # config/initializers/audited.rb
403
+
404
+ Audited.config do |config|
405
+ config.audit_class = CustomAudit
406
+ end
407
+ ```
408
+
409
+ ### Enum Storage
410
+
411
+ In 4.10, the default behavior for enums changed from storing the value synthesized by Rails to the value stored in the DB. You can restore the previous behavior by setting the store_synthesized_enums configuration value:
412
+
413
+ ```ruby
414
+ # config/initializers/audited.rb
415
+
416
+ Audited.store_synthesized_enums = true
417
+ ```
418
+
419
+ ## Support
420
+
421
+ You can find documentation at: http://rdoc.info/github/collectiveidea/audited
422
+
423
+ Or join the [mailing list](http://groups.google.com/group/audited) to get help or offer suggestions.
424
+
425
+ ## Contributing
426
+
427
+ In the spirit of [free software](http://www.fsf.org/licensing/essays/free-sw.html), **everyone** is encouraged to help improve this project. Here are a few ways _you_ can pitch in:
428
+
429
+ * Use prerelease versions of Audited.
430
+ * [Report bugs](https://github.com/collectiveidea/audited/issues).
431
+ * Fix bugs and submit [pull requests](http://github.com/collectiveidea/audited/pulls).
432
+ * Write, clarify or fix documentation.
433
+ * Refactor code.
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env rake
2
+
3
+ require "bundler/gem_helper"
4
+ require "rspec/core/rake_task"
5
+ require "rake/testtask"
6
+ require "appraisal"
7
+
8
+ Bundler::GemHelper.install_tasks(name: "velocity_audited")
9
+
10
+ RSpec::Core::RakeTask.new(:spec)
11
+
12
+ Rake::TestTask.new do |t|
13
+ t.libs << "test"
14
+ t.test_files = FileList["test/**/*_test.rb"]
15
+ t.verbose = true
16
+ end
17
+
18
+ task default: [:spec, :test]
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 5.0.0"
6
+ gem "mysql2", ">= 0.3.18", "< 0.6.0"
7
+ gem "pg", ">= 0.18", "< 2.0"
8
+ gem "sqlite3", "~> 1.3.6"
9
+
10
+ gemspec name: "velocity_audited", path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 5.1.4"
6
+ gem "mysql2", ">= 0.3.18", "< 0.6.0"
7
+ gem "pg", ">= 0.18", "< 2.0"
8
+ gem "sqlite3", "~> 1.3.6"
9
+
10
+ gemspec name: "velocity_audited", path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", ">= 5.2.0", "< 5.3"
6
+ gem "mysql2", ">= 0.4.4", "< 0.6.0"
7
+ gem "pg", ">= 0.18", "< 2.0"
8
+ gem "sqlite3", "~> 1.3.6"
9
+
10
+ gemspec name: "velocity_audited", path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", ">= 6.0.0", "< 6.1"
6
+ gem "mysql2", ">= 0.4.4"
7
+ gem "pg", ">= 0.18", "< 2.0"
8
+ gem "sqlite3", "~> 1.4"
9
+
10
+ gemspec name: "velocity_audited", path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", ">= 6.1.0", "< 6.2"
6
+ gem "mysql2", ">= 0.4.4"
7
+ gem "pg", ">= 1.1", "< 2.0"
8
+ gem "sqlite3", "~> 1.4"
9
+
10
+ gemspec name: "velocity_audited", path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", ">= 7.0.0.alpha2", "< 7.1"
6
+ gem "mysql2", ">= 0.4.4"
7
+ gem "pg", ">= 1.1"
8
+ gem "sqlite3", ">= 1.4"
9
+
10
+ gemspec name: "velocity_audited", path: "../"