audited 4.2.2 → 4.3.0

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.

Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +10 -9
  3. data/Appraisals +10 -6
  4. data/Gemfile +1 -13
  5. data/README.md +46 -33
  6. data/Rakefile +3 -18
  7. data/gemfiles/rails40.gemfile +1 -5
  8. data/gemfiles/rails41.gemfile +1 -5
  9. data/gemfiles/rails42.gemfile +1 -5
  10. data/gemfiles/rails50.gemfile +8 -0
  11. data/lib/audited-rspec.rb +4 -0
  12. data/lib/audited.rb +15 -2
  13. data/lib/audited/audit.rb +97 -57
  14. data/lib/audited/auditor.rb +73 -45
  15. data/lib/audited/rspec_matchers.rb +6 -2
  16. data/lib/audited/sweeper.rb +12 -23
  17. data/lib/audited/version.rb +1 -1
  18. data/lib/generators/audited/install_generator.rb +20 -0
  19. data/lib/generators/audited/migration.rb +15 -0
  20. data/lib/generators/audited/templates/add_association_to_audits.rb +11 -0
  21. data/lib/generators/audited/templates/add_comment_to_audits.rb +9 -0
  22. data/lib/generators/audited/templates/add_remote_address_to_audits.rb +10 -0
  23. data/lib/generators/audited/templates/add_request_uuid_to_audits.rb +10 -0
  24. data/lib/generators/audited/templates/install.rb +30 -0
  25. data/lib/generators/audited/templates/rename_association_to_associated.rb +23 -0
  26. data/lib/generators/audited/templates/rename_changes_to_audited_changes.rb +9 -0
  27. data/lib/generators/audited/templates/rename_parent_to_association.rb +11 -0
  28. data/lib/generators/audited/upgrade_generator.rb +57 -0
  29. data/spec/audited/audit_spec.rb +199 -0
  30. data/spec/audited/auditor_spec.rb +607 -0
  31. data/spec/audited/sweeper_spec.rb +106 -0
  32. data/spec/audited_spec_helpers.rb +6 -22
  33. data/spec/rails_app/config/environments/test.rb +7 -4
  34. data/spec/rails_app/config/initializers/secret_token.rb +1 -1
  35. data/spec/rails_app/config/routes.rb +1 -4
  36. data/spec/spec_helper.rb +7 -9
  37. data/spec/support/active_record/models.rb +20 -13
  38. data/spec/support/active_record/schema.rb +36 -12
  39. data/test/db/version_1.rb +4 -4
  40. data/test/db/version_2.rb +4 -4
  41. data/test/db/version_3.rb +4 -4
  42. data/test/db/version_4.rb +4 -4
  43. data/test/db/version_5.rb +2 -2
  44. data/test/db/version_6.rb +2 -2
  45. data/test/install_generator_test.rb +1 -1
  46. data/test/upgrade_generator_test.rb +10 -10
  47. metadata +73 -37
  48. data/lib/audited/active_record/version.rb +0 -5
  49. data/lib/audited/mongo_mapper/version.rb +0 -5
  50. data/spec/support/mongo_mapper/connection.rb +0 -4
  51. data/spec/support/mongo_mapper/models.rb +0 -214
@@ -0,0 +1,106 @@
1
+ require "spec_helper"
2
+
3
+ class AuditsController < ActionController::Base
4
+ attr_reader :company
5
+
6
+ def create
7
+ @company = Models::ActiveRecord::Company.create
8
+ head :ok
9
+ end
10
+
11
+ def update
12
+ current_user.update_attributes(password: 'foo')
13
+ head :ok
14
+ end
15
+
16
+ private
17
+
18
+ attr_accessor :current_user
19
+ attr_accessor :custom_user
20
+ end
21
+
22
+ describe AuditsController do
23
+ include RSpec::Rails::ControllerExampleGroup
24
+ render_views
25
+
26
+ before(:each) do
27
+ Audited.current_user_method = :current_user
28
+ end
29
+
30
+ let(:user) { create_user }
31
+
32
+ describe "POST audit" do
33
+
34
+ it "should audit user" do
35
+ controller.send(:current_user=, user)
36
+ expect {
37
+ post :create
38
+ }.to change( Audited::Audit, :count )
39
+
40
+ expect(controller.company.audits.last.user).to eq(user)
41
+ end
42
+
43
+ it "should support custom users for sweepers" do
44
+ controller.send(:custom_user=, user)
45
+ Audited.current_user_method = :custom_user
46
+
47
+ expect {
48
+ post :create
49
+ }.to change( Audited::Audit, :count )
50
+
51
+ expect(controller.company.audits.last.user).to eq(user)
52
+ end
53
+
54
+ it "should record the remote address responsible for the change" do
55
+ request.env['REMOTE_ADDR'] = "1.2.3.4"
56
+ controller.send(:current_user=, user)
57
+
58
+ post :create
59
+
60
+ expect(controller.company.audits.last.remote_address).to eq('1.2.3.4')
61
+ end
62
+
63
+ it "should record a UUID for the web request responsible for the change" do
64
+ allow_any_instance_of(ActionDispatch::Request).to receive(:uuid).and_return("abc123")
65
+ controller.send(:current_user=, user)
66
+
67
+ post :create
68
+
69
+ expect(controller.company.audits.last.request_uuid).to eq("abc123")
70
+ end
71
+
72
+ end
73
+
74
+ describe "PUT update" do
75
+ it "should not save blank audits" do
76
+ controller.send(:current_user=, user)
77
+
78
+ expect {
79
+ put :update, id: 123
80
+ }.to_not change( Audited::Audit, :count )
81
+ end
82
+ end
83
+ end
84
+
85
+
86
+ describe Audited::Sweeper do
87
+
88
+ it "should be thread-safe" do
89
+ t1 = Thread.new do
90
+ sleep 0.5
91
+ Audited::Sweeper.instance.controller = 'thread1 controller instance'
92
+ expect(Audited::Sweeper.instance.controller).to eq('thread1 controller instance')
93
+ end
94
+
95
+ t2 = Thread.new do
96
+ Audited::Sweeper.instance.controller = 'thread2 controller instance'
97
+ sleep 1
98
+ expect(Audited::Sweeper.instance.controller).to eq('thread2 controller instance')
99
+ end
100
+
101
+ t1.join; t2.join
102
+
103
+ expect(Audited::Sweeper.instance.controller).to be_nil
104
+ end
105
+
106
+ end
@@ -1,19 +1,15 @@
1
1
  module AuditedSpecHelpers
2
2
 
3
- def create_user(use_mongo = false, attrs = {})
4
- klass = use_mongo ? Models::MongoMapper::User : Models::ActiveRecord::User
5
- klass.create({:name => 'Brandon', :username => 'brandon', :password => 'password'}.merge(attrs))
3
+ def create_user(attrs = {})
4
+ Models::ActiveRecord::User.create({name: 'Brandon', username: 'brandon', password: 'password'}.merge(attrs))
6
5
  end
7
6
 
8
- def build_user(use_mongo = false, attrs = {})
9
- klass = use_mongo ? Models::MongoMapper::User : Models::ActiveRecord::User
10
- klass.new({:name => 'darth', :username => 'darth', :password => 'noooooooo'}.merge(attrs))
7
+ def build_user(attrs = {})
8
+ Models::ActiveRecord::User.new({name: 'darth', username: 'darth', password: 'noooooooo'}.merge(attrs))
11
9
  end
12
10
 
13
- def create_versions(n = 2, use_mongo = false)
14
- klass = use_mongo ? Models::MongoMapper::User : Models::ActiveRecord::User
15
-
16
- klass.create(:name => 'Foobar 1').tap do |u|
11
+ def create_versions(n = 2)
12
+ Models::ActiveRecord::User.create(name: 'Foobar 1').tap do |u|
17
13
  (n - 1).times do |i|
18
14
  u.update_attribute :name, "Foobar #{i + 2}"
19
15
  end
@@ -21,16 +17,4 @@ module AuditedSpecHelpers
21
17
  end
22
18
  end
23
19
 
24
- def create_active_record_user(attrs = {})
25
- create_user(false, attrs)
26
- end
27
-
28
- def create_mongo_user(attrs = {})
29
- create_user(true, attrs)
30
- end
31
-
32
- def create_mongo_versions(n = 2)
33
- create_versions(n, true)
34
- end
35
-
36
20
  end
@@ -12,11 +12,14 @@ RailsApp::Application.configure do
12
12
  # preloads Rails for running tests, you may have to set it to true.
13
13
  config.eager_load = false
14
14
 
15
- # Configure static asset server for tests with Cache-Control for performance.
16
- config.serve_static_assets = true
17
15
  # Configure static file server for tests with Cache-Control for performance.
18
- config.serve_static_files = true
19
- config.static_cache_control = 'public, max-age=3600'
16
+ if config.respond_to?(:public_file_server)
17
+ config.public_file_server.enabled = true
18
+ config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=3600' }
19
+ else
20
+ config.static_cache_control = 'public, max-age=3600'
21
+ config.serve_static_files = true
22
+ end
20
23
 
21
24
  # Show full error reports and disable caching.
22
25
  config.consider_all_requests_local = true
@@ -1,3 +1,3 @@
1
1
  Rails.application.config.secret_token = 'ea942c41850d502f2c8283e26bdc57829f471bb18224ddff0a192c4f32cdf6cb5aa0d82b3a7a7adbeb640c4b06f3aa1cd5f098162d8240f669b39d6b49680571'
2
- Rails.application.config.session_store :cookie_store, :key => "_my_app"
2
+ Rails.application.config.session_store :cookie_store, key: "_my_app"
3
3
  Rails.application.config.secret_key_base = 'secret value'
@@ -1,6 +1,3 @@
1
1
  Rails.application.routes.draw do
2
-
3
- # This is a legacy wild controller route that's not recommended for RESTful applications.
4
- # Note: This route will make all actions in every controller accessible via GET requests.
5
- match ':controller(/:action(/:id(.:format)))', via: [:get, :post, :put, :delete]
2
+ resources :audits
6
3
  end
@@ -1,10 +1,14 @@
1
1
  ENV['RAILS_ENV'] = 'test'
2
2
 
3
- require 'protected_attributes'
3
+ if Bundler.definition.dependencies.map(&:name).include?('protected_attributes')
4
+ require 'protected_attributes'
5
+ end
4
6
  require 'rails_app/config/environment'
5
7
  require 'rspec/rails'
6
8
  require 'audited'
7
9
  require 'audited_spec_helpers'
10
+ require 'support/active_record/models'
11
+ load "audited/sweeper.rb" # force to reload sweeper
8
12
 
9
13
  SPEC_ROOT = Pathname.new(File.expand_path('../', __FILE__))
10
14
 
@@ -12,12 +16,6 @@ Dir[SPEC_ROOT.join('support/*.rb')].each{|f| require f }
12
16
 
13
17
  RSpec.configure do |config|
14
18
  config.include AuditedSpecHelpers
15
-
16
- config.before(:each, :adapter => :active_record) do
17
- Audited.audit_class = Audited::Adapters::ActiveRecord::Audit
18
- end
19
-
20
- config.before(:each, :adapter => :mongo_mapper) do
21
- Audited.audit_class = Audited::Adapters::MongoMapper::Audit
22
- end
19
+ config.use_transactional_fixtures = false if Rails.version.start_with?('4.')
20
+ config.use_transactional_tests = false if config.respond_to?(:use_transactional_tests=)
23
21
  end
@@ -4,35 +4,40 @@ require File.expand_path('../schema', __FILE__)
4
4
  module Models
5
5
  module ActiveRecord
6
6
  class User < ::ActiveRecord::Base
7
- audited :allow_mass_assignment => true, :except => :password
7
+ audited allow_mass_assignment: true, except: :password
8
8
 
9
- attr_protected :logins
9
+ attr_protected :logins if respond_to?(:attr_protected)
10
10
 
11
11
  def name=(val)
12
12
  write_attribute(:name, CGI.escapeHTML(val))
13
13
  end
14
14
  end
15
15
 
16
+ class UserOnlyPassword < ::ActiveRecord::Base
17
+ self.table_name = :users
18
+ audited allow_mass_assignment: true, only: :password
19
+ end
20
+
16
21
  class CommentRequiredUser < ::ActiveRecord::Base
17
22
  self.table_name = :users
18
- audited :comment_required => true
23
+ audited comment_required: true
19
24
  end
20
25
 
21
26
  class AccessibleAfterDeclarationUser < ::ActiveRecord::Base
22
27
  self.table_name = :users
23
28
  audited
24
- attr_accessible :name, :username, :password
29
+ attr_accessible :name, :username, :password if respond_to?(:attr_accessible)
25
30
  end
26
31
 
27
32
  class AccessibleBeforeDeclarationUser < ::ActiveRecord::Base
28
33
  self.table_name = :users
29
- attr_accessible :name, :username, :password # declare attr_accessible before calling aaa
34
+ attr_accessible :name, :username, :password if respond_to?(:attr_accessible) # declare attr_accessible before calling aaa
30
35
  audited
31
36
  end
32
37
 
33
38
  class NoAttributeProtectionUser < ::ActiveRecord::Base
34
39
  self.table_name = :users
35
- audited :allow_mass_assignment => true
40
+ audited allow_mass_assignment: true
36
41
  end
37
42
 
38
43
  class UserWithAfterAudit < ::ActiveRecord::Base
@@ -40,6 +45,8 @@ module Models
40
45
  audited
41
46
  attr_accessor :bogus_attr, :around_attr
42
47
 
48
+ private
49
+
43
50
  def after_audit
44
51
  self.bogus_attr = "do something"
45
52
  end
@@ -64,29 +71,29 @@ module Models
64
71
 
65
72
  class OwnedCompany < ::ActiveRecord::Base
66
73
  self.table_name = 'companies'
67
- belongs_to :owner, :class_name => "Owner"
68
- attr_accessible :name, :owner # declare attr_accessible before calling aaa
69
- audited :associated_with => :owner
74
+ belongs_to :owner, class_name: "Owner"
75
+ attr_accessible :name, :owner if respond_to?(:attr_accessible) # declare attr_accessible before calling aaa
76
+ audited associated_with: :owner
70
77
  end
71
78
 
72
79
  class OnUpdateDestroy < ::ActiveRecord::Base
73
80
  self.table_name = 'companies'
74
- audited :on => [:update, :destroy]
81
+ audited on: [:update, :destroy]
75
82
  end
76
83
 
77
84
  class OnCreateDestroy < ::ActiveRecord::Base
78
85
  self.table_name = 'companies'
79
- audited :on => [:create, :destroy]
86
+ audited on: [:create, :destroy]
80
87
  end
81
88
 
82
89
  class OnCreateDestroyExceptName < ::ActiveRecord::Base
83
90
  self.table_name = 'companies'
84
- audited :except => :name, :on => [:create, :destroy]
91
+ audited except: :name, on: [:create, :destroy]
85
92
  end
86
93
 
87
94
  class OnCreateUpdate < ::ActiveRecord::Base
88
95
  self.table_name = 'companies'
89
- audited :on => [:create, :update]
96
+ audited on: [:create, :update]
90
97
  end
91
98
  end
92
99
  end
@@ -1,38 +1,62 @@
1
1
  require 'active_record'
2
2
  require 'logger'
3
3
 
4
- ActiveRecord::Base.establish_connection
5
- ActiveRecord::Base.logger = Logger.new(SPEC_ROOT.join('debug.log'))
4
+ begin
5
+ db_config = ActiveRecord::Base.configurations[Rails.env].clone
6
+ db_type = db_config['adapter']
7
+ db_name = db_config.delete('database')
8
+ raise Exception.new('No database name specified.') if db_name.blank?
9
+ if db_type == 'sqlite3'
10
+ db_file = Pathname.new(__FILE__).dirname.join(db_name)
11
+ db_file.unlink if db_file.file?
12
+ else
13
+ if defined?(JRUBY_VERSION)
14
+ db_config.symbolize_keys!
15
+ db_config[:configure_connection] = false
16
+ end
17
+ adapter = ActiveRecord::Base.send("#{db_type}_connection", db_config)
18
+ adapter.recreate_database db_name
19
+ adapter.disconnect!
20
+ end
21
+ rescue Exception => e
22
+ Kernel.warn e
23
+ end
24
+
25
+ logfile = Pathname.new(__FILE__).dirname.join('debug.log')
26
+ logfile.unlink if logfile.file?
27
+ ActiveRecord::Base.logger = Logger.new(logfile)
28
+
6
29
  ActiveRecord::Migration.verbose = false
30
+ ActiveRecord::Base.establish_connection
7
31
 
8
32
  ActiveRecord::Schema.define do
9
- create_table :users, :force => true do |t|
33
+ create_table :users do |t|
10
34
  t.column :name, :string
11
35
  t.column :username, :string
12
36
  t.column :password, :string
13
37
  t.column :activated, :boolean
14
38
  t.column :suspended_at, :datetime
15
- t.column :logins, :integer, :default => 0
39
+ t.column :logins, :integer, default: 0
16
40
  t.column :created_at, :datetime
17
41
  t.column :updated_at, :datetime
18
42
  end
19
43
 
20
- create_table :companies, :force => true do |t|
44
+ create_table :companies do |t|
21
45
  t.column :name, :string
22
46
  t.column :owner_id, :integer
23
47
  t.column :type, :string
24
48
  end
25
49
 
26
- create_table :authors, :force => true do |t|
50
+ create_table :authors do |t|
27
51
  t.column :name, :string
28
52
  end
29
53
 
30
- create_table :books, :force => true do |t|
54
+ create_table :books do |t|
31
55
  t.column :authord_id, :integer
32
56
  t.column :title, :string
33
57
  end
34
58
 
35
- create_table :audits, :force => true do |t|
59
+ create_table :audits do |t|
36
60
  t.column :auditable_id, :integer
37
61
  t.column :auditable_type, :string
38
62
  t.column :associated_id, :integer
@@ -42,16 +66,16 @@ ActiveRecord::Schema.define do
42
66
  t.column :username, :string
43
67
  t.column :action, :string
44
68
  t.column :audited_changes, :text
45
- t.column :version, :integer, :default => 0
69
+ t.column :version, :integer, default: 0
46
70
  t.column :comment, :string
47
71
  t.column :remote_address, :string
48
72
  t.column :request_uuid, :string
49
73
  t.column :created_at, :datetime
50
74
  end
51
75
 
52
- add_index :audits, [:auditable_id, :auditable_type], :name => 'auditable_index'
53
- add_index :audits, [:associated_id, :associated_type], :name => 'associated_index'
54
- add_index :audits, [:user_id, :user_type], :name => 'user_index'
76
+ add_index :audits, [:auditable_id, :auditable_type], name: 'auditable_index'
77
+ add_index :audits, [:associated_id, :associated_type], name: 'associated_index'
78
+ add_index :audits, [:user_id, :user_type], name: 'user_index'
55
79
  add_index :audits, :request_uuid
56
80
  add_index :audits, :created_at
57
81
  end
@@ -1,5 +1,5 @@
1
1
  ActiveRecord::Schema.define do
2
- create_table :audits, :force => true do |t|
2
+ create_table :audits, force: true do |t|
3
3
  t.column :auditable_id, :integer
4
4
  t.column :auditable_type, :string
5
5
  t.column :user_id, :integer
@@ -7,11 +7,11 @@ ActiveRecord::Schema.define do
7
7
  t.column :username, :string
8
8
  t.column :action, :string
9
9
  t.column :changes, :text
10
- t.column :version, :integer, :default => 0
10
+ t.column :version, :integer, default: 0
11
11
  t.column :created_at, :datetime
12
12
  end
13
13
 
14
- add_index :audits, [:auditable_id, :auditable_type], :name => 'auditable_index'
15
- add_index :audits, [:user_id, :user_type], :name => 'user_index'
14
+ add_index :audits, [:auditable_id, :auditable_type], name: 'auditable_index'
15
+ add_index :audits, [:user_id, :user_type], name: 'user_index'
16
16
  add_index :audits, :created_at
17
17
  end
@@ -1,5 +1,5 @@
1
1
  ActiveRecord::Schema.define do
2
- create_table :audits, :force => true do |t|
2
+ create_table :audits, force: true do |t|
3
3
  t.column :auditable_id, :integer
4
4
  t.column :auditable_type, :string
5
5
  t.column :user_id, :integer
@@ -7,12 +7,12 @@ ActiveRecord::Schema.define do
7
7
  t.column :username, :string
8
8
  t.column :action, :string
9
9
  t.column :changes, :text
10
- t.column :version, :integer, :default => 0
10
+ t.column :version, :integer, default: 0
11
11
  t.column :comment, :string
12
12
  t.column :created_at, :datetime
13
13
  end
14
14
 
15
- add_index :audits, [:auditable_id, :auditable_type], :name => 'auditable_index'
16
- add_index :audits, [:user_id, :user_type], :name => 'user_index'
15
+ add_index :audits, [:auditable_id, :auditable_type], name: 'auditable_index'
16
+ add_index :audits, [:user_id, :user_type], name: 'user_index'
17
17
  add_index :audits, :created_at
18
18
  end
@@ -1,5 +1,5 @@
1
1
  ActiveRecord::Schema.define do
2
- create_table :audits, :force => true do |t|
2
+ create_table :audits, force: true do |t|
3
3
  t.column :auditable_id, :integer
4
4
  t.column :auditable_type, :string
5
5
  t.column :user_id, :integer
@@ -7,13 +7,13 @@ ActiveRecord::Schema.define do
7
7
  t.column :username, :string
8
8
  t.column :action, :string
9
9
  t.column :audited_changes, :text
10
- t.column :version, :integer, :default => 0
10
+ t.column :version, :integer, default: 0
11
11
  t.column :comment, :string
12
12
  t.column :created_at, :datetime
13
13
  end
14
14
 
15
- add_index :audits, [:auditable_id, :auditable_type], :name => 'auditable_index'
16
- add_index :audits, [:user_id, :user_type], :name => 'user_index'
15
+ add_index :audits, [:auditable_id, :auditable_type], name: 'auditable_index'
16
+ add_index :audits, [:user_id, :user_type], name: 'user_index'
17
17
  add_index :audits, :created_at
18
18
  end
19
19