audited 4.2.0 → 4.3.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 +4 -4
- data/.travis.yml +11 -9
- data/Appraisals +10 -3
- data/Gemfile +1 -1
- data/README.md +57 -44
- data/Rakefile +3 -18
- data/gemfiles/rails40.gemfile +1 -1
- data/gemfiles/rails41.gemfile +1 -1
- data/gemfiles/rails42.gemfile +1 -1
- data/gemfiles/rails50.gemfile +8 -0
- data/lib/audited/audit.rb +97 -57
- data/lib/audited/auditor.rb +86 -43
- data/lib/audited/rspec_matchers.rb +6 -2
- data/lib/audited/sweeper.rb +10 -19
- data/lib/audited/version.rb +1 -1
- data/lib/audited-rspec.rb +4 -0
- data/lib/audited.rb +15 -2
- data/lib/generators/audited/install_generator.rb +20 -0
- data/lib/generators/audited/migration.rb +15 -0
- data/lib/generators/audited/templates/add_association_to_audits.rb +11 -0
- data/lib/generators/audited/templates/add_comment_to_audits.rb +9 -0
- data/lib/generators/audited/templates/add_remote_address_to_audits.rb +10 -0
- data/lib/generators/audited/templates/add_request_uuid_to_audits.rb +10 -0
- data/lib/generators/audited/templates/install.rb +30 -0
- data/lib/generators/audited/templates/rename_association_to_associated.rb +23 -0
- data/lib/generators/audited/templates/rename_changes_to_audited_changes.rb +9 -0
- data/lib/generators/audited/templates/rename_parent_to_association.rb +11 -0
- data/lib/generators/audited/upgrade_generator.rb +57 -0
- data/spec/audited/audit_spec.rb +199 -0
- data/spec/audited/auditor_spec.rb +607 -0
- data/spec/audited/sweeper_spec.rb +106 -0
- data/spec/audited_spec_helpers.rb +6 -22
- data/spec/rails_app/config/environments/test.rb +7 -4
- data/spec/rails_app/config/initializers/secret_token.rb +1 -1
- data/spec/rails_app/config/routes.rb +1 -4
- data/spec/spec_helper.rb +7 -9
- data/spec/support/active_record/models.rb +23 -13
- data/spec/support/active_record/schema.rb +37 -12
- data/test/db/version_1.rb +4 -4
- data/test/db/version_2.rb +4 -4
- data/test/db/version_3.rb +4 -4
- data/test/db/version_4.rb +4 -4
- data/test/db/version_5.rb +2 -2
- data/test/db/version_6.rb +2 -2
- data/test/install_generator_test.rb +1 -1
- data/test/upgrade_generator_test.rb +10 -10
- metadata +56 -76
- data/lib/audited/active_record/version.rb +0 -5
- data/lib/audited/mongo_mapper/version.rb +0 -5
- data/spec/support/mongo_mapper/connection.rb +0 -4
- data/spec/support/mongo_mapper/models.rb +0 -214
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Audited::Audit do
|
|
4
|
+
let(:user) { Models::ActiveRecord::User.new name: "Testing" }
|
|
5
|
+
|
|
6
|
+
describe "user=" do
|
|
7
|
+
|
|
8
|
+
it "should be able to set the user to a model object" do
|
|
9
|
+
subject.user = user
|
|
10
|
+
expect(subject.user).to eq(user)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should be able to set the user to nil" do
|
|
14
|
+
subject.user_id = 1
|
|
15
|
+
subject.user_type = 'Models::ActiveRecord::User'
|
|
16
|
+
subject.username = 'joe'
|
|
17
|
+
|
|
18
|
+
subject.user = nil
|
|
19
|
+
|
|
20
|
+
expect(subject.user).to be_nil
|
|
21
|
+
expect(subject.user_id).to be_nil
|
|
22
|
+
expect(subject.user_type).to be_nil
|
|
23
|
+
expect(subject.username).to be_nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "should be able to set the user to a string" do
|
|
27
|
+
subject.user = 'test'
|
|
28
|
+
expect(subject.user).to eq('test')
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "should clear model when setting to a string" do
|
|
32
|
+
subject.user = user
|
|
33
|
+
subject.user = 'testing'
|
|
34
|
+
expect(subject.user_id).to be_nil
|
|
35
|
+
expect(subject.user_type).to be_nil
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "should clear the username when setting to a model" do
|
|
39
|
+
subject.username = 'test'
|
|
40
|
+
subject.user = user
|
|
41
|
+
expect(subject.username).to be_nil
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe "revision" do
|
|
47
|
+
|
|
48
|
+
it "should recreate attributes" do
|
|
49
|
+
user = Models::ActiveRecord::User.create name: "1"
|
|
50
|
+
5.times {|i| user.update_attribute :name, (i + 2).to_s }
|
|
51
|
+
|
|
52
|
+
user.audits.each do |audit|
|
|
53
|
+
expect(audit.revision.name).to eq(audit.version.to_s)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "should set protected attributes" do
|
|
58
|
+
u = Models::ActiveRecord::User.create(name: "Brandon")
|
|
59
|
+
u.update_attribute :logins, 1
|
|
60
|
+
u.update_attribute :logins, 2
|
|
61
|
+
|
|
62
|
+
expect(u.audits[2].revision.logins).to eq(2)
|
|
63
|
+
expect(u.audits[1].revision.logins).to eq(1)
|
|
64
|
+
expect(u.audits[0].revision.logins).to eq(0)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "should bypass attribute assignment wrappers" do
|
|
68
|
+
u = Models::ActiveRecord::User.create(name: "<Joe>")
|
|
69
|
+
expect(u.audits.first.revision.name).to eq("<Joe>")
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "should work for deleted records" do
|
|
73
|
+
user = Models::ActiveRecord::User.create name: "1"
|
|
74
|
+
user.destroy
|
|
75
|
+
revision = user.audits.last.revision
|
|
76
|
+
expect(revision.name).to eq(user.name)
|
|
77
|
+
expect(revision).to be_a_new_record
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it "should set the version number on create" do
|
|
82
|
+
user = Models::ActiveRecord::User.create! name: "Set Version Number"
|
|
83
|
+
expect(user.audits.first.version).to eq(1)
|
|
84
|
+
user.update_attribute :name, "Set to 2"
|
|
85
|
+
expect(user.audits.reload.first.version).to eq(1)
|
|
86
|
+
expect(user.audits.reload.last.version).to eq(2)
|
|
87
|
+
user.destroy
|
|
88
|
+
expect(Audited::Audit.where(auditable_type: "Models::ActiveRecord::User", auditable_id: user.id).last.version).to eq(3)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it "should set the request uuid on create" do
|
|
92
|
+
user = Models::ActiveRecord::User.create! name: "Set Request UUID"
|
|
93
|
+
expect(user.audits.reload.first.request_uuid).not_to be_blank
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
describe "reconstruct_attributes" do
|
|
97
|
+
it "should work with the old way of storing just the new value" do
|
|
98
|
+
audits = Audited::Audit.reconstruct_attributes([Audited::Audit.new(audited_changes: {"attribute" => "value"})])
|
|
99
|
+
expect(audits["attribute"]).to eq("value")
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
describe "audited_classes" do
|
|
104
|
+
class Models::ActiveRecord::CustomUser < ::ActiveRecord::Base
|
|
105
|
+
end
|
|
106
|
+
class Models::ActiveRecord::CustomUserSubclass < Models::ActiveRecord::CustomUser
|
|
107
|
+
audited
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it "should include audited classes" do
|
|
111
|
+
expect(Audited::Audit.audited_classes).to include(Models::ActiveRecord::User)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "should include subclasses" do
|
|
115
|
+
expect(Audited::Audit.audited_classes).to include(Models::ActiveRecord::CustomUserSubclass)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
describe "new_attributes" do
|
|
120
|
+
it "should return a hash of the new values" do
|
|
121
|
+
new_attributes = Audited::Audit.new(audited_changes: {a: [1, 2], b: [3, 4]}).new_attributes
|
|
122
|
+
expect(new_attributes).to eq({"a" => 2, "b" => 4})
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
describe "old_attributes" do
|
|
127
|
+
it "should return a hash of the old values" do
|
|
128
|
+
old_attributes = Audited::Audit.new(audited_changes: {a: [1, 2], b: [3, 4]}).old_attributes
|
|
129
|
+
expect(old_attributes).to eq({"a" => 1, "b" => 3})
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
describe "as_user" do
|
|
134
|
+
it "should record user objects" do
|
|
135
|
+
Audited::Audit.as_user(user) do
|
|
136
|
+
company = Models::ActiveRecord::Company.create name: "The auditors"
|
|
137
|
+
company.name = "The Auditors, Inc"
|
|
138
|
+
company.save
|
|
139
|
+
|
|
140
|
+
company.audits.each do |audit|
|
|
141
|
+
expect(audit.user).to eq(user)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it "should record usernames" do
|
|
147
|
+
Audited::Audit.as_user(user.name) do
|
|
148
|
+
company = Models::ActiveRecord::Company.create name: "The auditors"
|
|
149
|
+
company.name = "The Auditors, Inc"
|
|
150
|
+
company.save
|
|
151
|
+
|
|
152
|
+
company.audits.each do |audit|
|
|
153
|
+
expect(audit.username).to eq(user.name)
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
it "should be thread safe" do
|
|
159
|
+
begin
|
|
160
|
+
expect(user.save).to eq(true)
|
|
161
|
+
|
|
162
|
+
t1 = Thread.new do
|
|
163
|
+
Audited::Audit.as_user(user) do
|
|
164
|
+
sleep 1
|
|
165
|
+
expect(Models::ActiveRecord::Company.create(name: "The Auditors, Inc").audits.first.user).to eq(user)
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
t2 = Thread.new do
|
|
170
|
+
Audited::Audit.as_user(user.name) do
|
|
171
|
+
expect(Models::ActiveRecord::Company.create(name: "The Competing Auditors, LLC").audits.first.username).to eq(user.name)
|
|
172
|
+
sleep 0.5
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
t1.join
|
|
177
|
+
t2.join
|
|
178
|
+
end
|
|
179
|
+
end if ActiveRecord::Base.connection.adapter_name != 'SQLite'
|
|
180
|
+
|
|
181
|
+
it "should return the value from the yield block" do
|
|
182
|
+
result = Audited::Audit.as_user('foo') do
|
|
183
|
+
42
|
|
184
|
+
end
|
|
185
|
+
expect(result).to eq(42)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
it "should reset audited_user when the yield block raises an exception" do
|
|
189
|
+
expect {
|
|
190
|
+
Audited::Audit.as_user('foo') do
|
|
191
|
+
raise StandardError.new('expected')
|
|
192
|
+
end
|
|
193
|
+
}.to raise_exception('expected')
|
|
194
|
+
expect(Thread.current[:audited_user]).to be_nil
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
end
|