devise-security 0.11.1 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +41 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +22 -2
  5. data/.ruby-version +1 -1
  6. data/.travis.yml +15 -3
  7. data/Appraisals +19 -0
  8. data/Gemfile +1 -0
  9. data/README.md +15 -10
  10. data/Rakefile +3 -1
  11. data/app/controllers/devise/paranoid_verification_code_controller.rb +1 -1
  12. data/app/controllers/devise/password_expired_controller.rb +1 -1
  13. data/app/views/devise/paranoid_verification_code/show.html.erb +2 -2
  14. data/app/views/devise/password_expired/show.html.erb +5 -5
  15. data/config/locales/de.yml +7 -7
  16. data/config/locales/en.yml +8 -8
  17. data/config/locales/es.yml +8 -8
  18. data/devise-security.gemspec +12 -6
  19. data/gemfiles/rails_4.1_stable.gemfile +8 -0
  20. data/gemfiles/rails_4.2_stable.gemfile +8 -0
  21. data/gemfiles/rails_5.0_stable.gemfile +8 -0
  22. data/gemfiles/rails_5.1_stable.gemfile +8 -0
  23. data/gemfiles/rails_5.2_rc1.gemfile +8 -0
  24. data/lib/devise-security/controllers/helpers.rb +2 -2
  25. data/lib/devise-security/hooks/session_limitable.rb +3 -3
  26. data/lib/devise-security/models/compatibility.rb +22 -0
  27. data/lib/devise-security/models/expirable.rb +13 -13
  28. data/lib/devise-security/models/old_password.rb +1 -1
  29. data/lib/devise-security/models/paranoid_verification.rb +5 -2
  30. data/lib/devise-security/models/password_archivable.rb +34 -38
  31. data/lib/devise-security/models/password_expirable.rb +1 -1
  32. data/lib/devise-security/models/secure_validatable.rb +16 -14
  33. data/lib/devise-security/models/security_questionable.rb +1 -2
  34. data/lib/devise-security/models/session_limitable.rb +3 -3
  35. data/lib/devise-security/orm/active_record.rb +1 -3
  36. data/lib/devise-security/patches/confirmations_controller_captcha.rb +2 -2
  37. data/lib/devise-security/patches/confirmations_controller_security_question.rb +2 -2
  38. data/lib/devise-security/patches/passwords_controller_captcha.rb +2 -2
  39. data/lib/devise-security/patches/passwords_controller_security_question.rb +2 -2
  40. data/lib/devise-security/patches/registrations_controller_captcha.rb +2 -2
  41. data/lib/devise-security/patches/sessions_controller_captcha.rb +3 -3
  42. data/lib/devise-security/patches/unlocks_controller_captcha.rb +2 -2
  43. data/lib/devise-security/patches/unlocks_controller_security_question.rb +2 -2
  44. data/lib/devise-security/rails.rb +2 -2
  45. data/lib/devise-security/routes.rb +2 -3
  46. data/lib/devise-security/schema.rb +11 -6
  47. data/lib/devise-security/version.rb +1 -1
  48. data/test/dummy/app/models/application_record.rb +3 -0
  49. data/test/dummy/app/models/captcha_user.rb +1 -1
  50. data/test/dummy/app/models/security_question_user.rb +2 -3
  51. data/test/dummy/app/models/user.rb +21 -4
  52. data/test/dummy/app/models/widget.rb +4 -0
  53. data/test/dummy/config/environments/test.rb +10 -2
  54. data/test/dummy/config/initializers/devise.rb +1 -0
  55. data/test/dummy/config/secrets.yml +1 -2
  56. data/test/dummy/db/migrate/20120508165529_create_tables.rb +9 -3
  57. data/test/dummy/db/migrate/20180318103603_add_expireable_columns.rb +6 -0
  58. data/test/dummy/db/migrate/20180318105329_add_confirmable_columns.rb +8 -0
  59. data/test/dummy/db/migrate/20180318105732_add_rememberable_columns.rb +5 -0
  60. data/test/dummy/db/migrate/20180318111336_add_recoverable_columns.rb +6 -0
  61. data/test/dummy/db/migrate/20180319114023_add_widget.rb +8 -0
  62. data/test/test_captcha_controller.rb +13 -13
  63. data/test/test_helper.rb +7 -0
  64. data/test/test_paranoid_verification.rb +2 -2
  65. data/test/test_password_archivable.rb +27 -13
  66. data/test/test_password_expirable.rb +2 -2
  67. data/test/test_password_expired_controller.rb +25 -10
  68. data/test/test_security_question_controller.rb +45 -21
  69. metadata +90 -13
@@ -22,7 +22,7 @@ class TestParanoidVerification < ActiveSupport::TestCase
22
22
  assert_equal(0, user.paranoid_verification_attempt)
23
23
  end
24
24
 
25
- test "generate code must reset attempt counter" do
25
+ test 'generate code must reset attempt counter' do
26
26
  user = User.new
27
27
  user.generate_paranoid_code
28
28
  # default generator generates 5 char string
@@ -30,7 +30,7 @@ class TestParanoidVerification < ActiveSupport::TestCase
30
30
  assert_equal(user.paranoid_verification_code.length, 5)
31
31
  end
32
32
 
33
- test "when code match upon verify code, should mark record that it's no loger needed to verify" do
33
+ test 'when code match upon verify code, should mark record that it\'s no loger needed to verify' do
34
34
  user = User.new(paranoid_verification_code: 'abcde')
35
35
 
36
36
  assert_equal(true, user.need_paranoid_verification?)
@@ -16,31 +16,45 @@ class TestPasswordArchivable < ActiveSupport::TestCase
16
16
  end
17
17
 
18
18
  test 'cannot use same password' do
19
- user = User.create password: 'password1', password_confirmation: 'password1'
19
+ user = User.create email: 'bob@microsoft.com', password: 'Password1', password_confirmation: 'Password1'
20
+ assert_raises(ActiveRecord::RecordInvalid) { set_password(user, 'Password1') }
21
+ end
22
+
23
+ test 'indirectly saving associated user does not cause deprecation warning' do
24
+ old_behavior = ActiveSupport::Deprecation.behavior
25
+ ActiveSupport::Deprecation.behavior = :raise
26
+ user = User.new email: 'bob@microsoft.com', password: 'Password1', password_confirmation: 'Password1'
27
+ widget = Widget.new(user: user)
28
+ widget.save
29
+ ActiveSupport::Deprecation.behavior = old_behavior
30
+ end
20
31
 
21
- assert_raises(ActiveRecord::RecordInvalid) { set_password(user, 'password1') }
32
+ test 'does not save an OldPassword if user password was originally nil' do
33
+ user = User.new(email: 'bob@microsoft.com', password: nil, password_confirmation: nil)
34
+ set_password(user, 'Password1')
35
+ assert_equal 0, OldPassword.count
22
36
  end
23
37
 
24
38
  test 'cannot use archived passwords' do
25
39
  assert_equal 2, Devise.password_archiving_count
26
40
 
27
- user = User.create password: 'password1', password_confirmation: 'password1'
41
+ user = User.create! email: 'bob@microsoft.com', password: 'Password1', password_confirmation: 'Password1'
28
42
  assert_equal 0, OldPassword.count
29
43
 
30
- set_password(user, 'password2')
44
+ set_password(user, 'Password2')
31
45
  assert_equal 1, OldPassword.count
32
46
 
33
- assert_raises(ActiveRecord::RecordInvalid) { set_password(user, 'password1') }
47
+ assert_raises(ActiveRecord::RecordInvalid) { set_password(user, 'Password1') }
34
48
 
35
- set_password(user, 'password3')
49
+ set_password(user, 'Password3')
36
50
  assert_equal 2, OldPassword.count
37
51
 
38
52
  # rotate first password out of archive
39
- assert set_password(user, 'password4')
53
+ assert set_password(user, 'Password4')
40
54
 
41
55
  # archive count was 2, so first password should work again
42
- assert set_password(user, 'password1')
43
- assert set_password(user, 'password2')
56
+ assert set_password(user, 'Password1')
57
+ assert set_password(user, 'Password2')
44
58
  end
45
59
 
46
60
  test 'the option should be dynamic during runtime' do
@@ -50,12 +64,12 @@ class TestPasswordArchivable < ActiveSupport::TestCase
50
64
  end
51
65
  end
52
66
 
53
- user = User.create password: 'password1', password_confirmation: 'password1'
67
+ user = User.create email: 'bob@microsoft.com', password: 'Password1', password_confirmation: 'Password1'
54
68
 
55
- assert set_password(user, 'password2')
69
+ assert set_password(user, 'Password2')
56
70
 
57
- assert_raises(ActiveRecord::RecordInvalid) { set_password(user, 'password2') }
71
+ assert_raises(ActiveRecord::RecordInvalid) { set_password(user, 'Password2') }
58
72
 
59
- assert_raises(ActiveRecord::RecordInvalid) { set_password(user, 'password1') }
73
+ assert_raises(ActiveRecord::RecordInvalid) { set_password(user, 'Password1') }
60
74
  end
61
75
  end
@@ -10,7 +10,7 @@ class TestPasswordArchivable < ActiveSupport::TestCase
10
10
  end
11
11
 
12
12
  test 'password expires' do
13
- user = User.create password: 'password1', password_confirmation: 'password1'
13
+ user = User.create email: 'bob@microsoft.com', password: 'Password1', password_confirmation: 'Password1'
14
14
  refute user.need_change_password?
15
15
 
16
16
  user.update(password_changed_at: Time.now.ago(3.month))
@@ -18,7 +18,7 @@ class TestPasswordArchivable < ActiveSupport::TestCase
18
18
  end
19
19
 
20
20
  test 'override expire after at runtime' do
21
- user = User.new password: 'password1', password_confirmation: 'password1'
21
+ user = User.new email: 'bob@microsoft.com', password: 'Password1', password_confirmation: 'Password1'
22
22
  user.instance_eval do
23
23
  def expire_password_after
24
24
  4.month
@@ -5,9 +5,14 @@ class Devise::PasswordExpiredControllerTest < ActionController::TestCase
5
5
 
6
6
  setup do
7
7
  @request.env["devise.mapping"] = Devise.mappings[:user]
8
- @user = User.create(username: 'hello', email: 'hello@path.travel',
9
- password: '1234', password_changed_at: 4.months.ago)
10
-
8
+ @user = User.create!(
9
+ username: 'hello',
10
+ email: 'hello@path.travel',
11
+ password: 'Password4',
12
+ password_changed_at: 4.months.ago,
13
+ confirmed_at: 5.months.ago
14
+ )
15
+ assert @user.valid?
11
16
  sign_in(@user)
12
17
  end
13
18
 
@@ -16,14 +21,24 @@ class Devise::PasswordExpiredControllerTest < ActionController::TestCase
16
21
  assert_includes @response.body, 'Renew your password'
17
22
  end
18
23
 
19
- test 'shold update password' do
20
- put :update, params: {
21
- user: {
22
- current_password: '1234',
23
- password: '12345',
24
- password_confirmation: '12345'
24
+ test 'should update password' do
25
+ if Rails.version < "5"
26
+ put :update, {
27
+ user: {
28
+ current_password: 'Password4',
29
+ password: 'Password5',
30
+ password_confirmation: 'Password5'
31
+ }
32
+ }
33
+ else
34
+ put :update, params: {
35
+ user: {
36
+ current_password: 'Password4',
37
+ password: 'Password5',
38
+ password_confirmation: 'Password5'
39
+ }
25
40
  }
26
- }
41
+ end
27
42
  assert_redirected_to root_path
28
43
  end
29
44
  end
@@ -6,31 +6,47 @@ class TestWithSecurityQuestion < ActionController::TestCase
6
6
 
7
7
  setup do
8
8
  @user = User.create(username: 'hello', email: 'hello@path.travel',
9
- password: '1234', security_question_answer: "Right Answer")
9
+ password: '1234', security_question_answer: 'Right Answer')
10
10
  @user.lock_access!
11
11
 
12
- @request.env["devise.mapping"] = Devise.mappings[:security_question_user]
12
+ @request.env['devise.mapping'] = Devise.mappings[:security_question_user]
13
13
  end
14
14
 
15
15
  test 'When security question is enabled, it is inserted correctly' do
16
- post :create, params: {
17
- security_question_user: {
18
- email: @user.email
19
- }, security_question_answer: "wrong answer"
20
- }
16
+ if Rails.version < "5"
17
+ post :create, {
18
+ security_question_user: {
19
+ email: @user.email
20
+ }, security_question_answer: "wrong answer"
21
+ }
22
+ else
23
+ post :create, params: {
24
+ security_question_user: {
25
+ email: @user.email
26
+ }, security_question_answer: "wrong answer"
27
+ }
28
+ end
21
29
 
22
- assert_equal "The security question answer was invalid.", flash[:alert]
30
+ assert_equal 'The security question answer was invalid.', flash[:alert]
23
31
  assert_redirected_to new_security_question_user_unlock_path
24
32
  end
25
33
 
26
34
  test 'When security_question is valid, it runs as normal' do
27
- post :create, params: {
28
- security_question_user: {
29
- email: @user.email
30
- }, security_question_answer: @user.security_question_answer
31
- }
35
+ if Rails.version < "5"
36
+ post :create, {
37
+ security_question_user: {
38
+ email: @user.email
39
+ }, security_question_answer: @user.security_question_answer
40
+ }
41
+ else
42
+ post :create, params: {
43
+ security_question_user: {
44
+ email: @user.email
45
+ }, security_question_answer: @user.security_question_answer
46
+ }
47
+ end
32
48
 
33
- assert_equal "You will receive an email with instructions for how to unlock your account in a few minutes.", flash[:notice]
49
+ assert_equal 'You will receive an email with instructions for how to unlock your account in a few minutes.', flash[:notice]
34
50
  assert_redirected_to new_security_question_user_session_path
35
51
  end
36
52
  end
@@ -41,20 +57,28 @@ class TestWithoutSecurityQuestion < ActionController::TestCase
41
57
 
42
58
  setup do
43
59
  @user = User.create(username: 'hello', email: 'hello@path.travel',
44
- password: '1234', security_question_answer: "Right Answer")
60
+ password: '1234', security_question_answer: 'Right Answer')
45
61
  @user.lock_access!
46
62
 
47
- @request.env["devise.mapping"] = Devise.mappings[:user]
63
+ @request.env['devise.mapping'] = Devise.mappings[:user]
48
64
  end
49
65
 
50
66
  test 'When security question is not enabled it is not inserted' do
51
- post :create, params: {
52
- user: {
53
- email: @user.email
67
+ if Rails.version < "5"
68
+ post :create, {
69
+ user: {
70
+ email: @user.email
71
+ }
72
+ }
73
+ else
74
+ post :create, params: {
75
+ user: {
76
+ email: @user.email
77
+ }
54
78
  }
55
- }
79
+ end
56
80
 
57
- assert_equal "You will receive an email with instructions for how to unlock your account in a few minutes.", flash[:notice]
81
+ assert_equal 'You will receive an email with instructions for how to unlock your account in a few minutes.', flash[:notice]
58
82
  assert_redirected_to new_user_session_path
59
83
  end
60
84
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devise-security
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.1
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marco Scholl
@@ -11,15 +11,15 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2018-01-30 00:00:00.000000000 Z
14
+ date: 2018-04-16 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
- name: railties
17
+ name: rails
18
18
  requirement: !ruby/object:Gem::Requirement
19
19
  requirements:
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 3.2.6
22
+ version: 4.1.0
23
23
  - - "<"
24
24
  - !ruby/object:Gem::Version
25
25
  version: '6.0'
@@ -29,7 +29,7 @@ dependencies:
29
29
  requirements:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 3.2.6
32
+ version: 4.1.0
33
33
  - - "<"
34
34
  - !ruby/object:Gem::Version
35
35
  version: '6.0'
@@ -53,6 +53,20 @@ dependencies:
53
53
  - - "<"
54
54
  - !ruby/object:Gem::Version
55
55
  version: '5.0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: appraisal
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
56
70
  - !ruby/object:Gem::Dependency
57
71
  name: bundler
58
72
  requirement: !ruby/object:Gem::Requirement
@@ -119,16 +133,58 @@ dependencies:
119
133
  name: minitest
120
134
  requirement: !ruby/object:Gem::Requirement
121
135
  requirements:
122
- - - "~>"
136
+ - - '='
123
137
  - !ruby/object:Gem::Version
124
- version: '5.0'
138
+ version: 5.10.3
125
139
  type: :development
126
140
  prerelease: false
127
141
  version_requirements: !ruby/object:Gem::Requirement
128
142
  requirements:
129
- - - "~>"
143
+ - - '='
130
144
  - !ruby/object:Gem::Version
131
- version: '5.0'
145
+ version: 5.10.3
146
+ - !ruby/object:Gem::Dependency
147
+ name: pry-byebug
148
+ requirement: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ type: :development
154
+ prerelease: false
155
+ version_requirements: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ - !ruby/object:Gem::Dependency
161
+ name: pry-rescue
162
+ requirement: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ type: :development
168
+ prerelease: false
169
+ version_requirements: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ - !ruby/object:Gem::Dependency
175
+ name: pry
176
+ requirement: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ type: :development
182
+ prerelease: false
183
+ version_requirements: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
132
188
  - !ruby/object:Gem::Dependency
133
189
  name: rails_email_validator
134
190
  requirement: !ruby/object:Gem::Requirement
@@ -177,18 +233,19 @@ dependencies:
177
233
  - - ">="
178
234
  - !ruby/object:Gem::Version
179
235
  version: 1.3.10
180
- description: An enterprise security extension for devise, trying to meet industrial
181
- standard security demands for web applications.
236
+ description: An enterprise security extension for devise.
182
237
  email: natebird@gmail.com
183
238
  executables: []
184
239
  extensions: []
185
240
  extra_rdoc_files: []
186
241
  files:
242
+ - ".circleci/config.yml"
187
243
  - ".document"
188
244
  - ".gitignore"
189
245
  - ".rubocop.yml"
190
246
  - ".ruby-version"
191
247
  - ".travis.yml"
248
+ - Appraisals
192
249
  - Gemfile
193
250
  - LICENSE.txt
194
251
  - README.md
@@ -202,12 +259,18 @@ files:
202
259
  - config/locales/es.yml
203
260
  - config/locales/it.yml
204
261
  - devise-security.gemspec
262
+ - gemfiles/rails_4.1_stable.gemfile
263
+ - gemfiles/rails_4.2_stable.gemfile
264
+ - gemfiles/rails_5.0_stable.gemfile
265
+ - gemfiles/rails_5.1_stable.gemfile
266
+ - gemfiles/rails_5.2_rc1.gemfile
205
267
  - lib/devise-security.rb
206
268
  - lib/devise-security/controllers/helpers.rb
207
269
  - lib/devise-security/hooks/expirable.rb
208
270
  - lib/devise-security/hooks/paranoid_verification.rb
209
271
  - lib/devise-security/hooks/password_expirable.rb
210
272
  - lib/devise-security/hooks/session_limitable.rb
273
+ - lib/devise-security/models/compatibility.rb
211
274
  - lib/devise-security/models/database_authenticatable_patch.rb
212
275
  - lib/devise-security/models/expirable.rb
213
276
  - lib/devise-security/models/old_password.rb
@@ -241,10 +304,12 @@ files:
241
304
  - test/dummy/app/controllers/foos_controller.rb
242
305
  - test/dummy/app/controllers/security_question/unlocks_controller.rb
243
306
  - test/dummy/app/models/.gitkeep
307
+ - test/dummy/app/models/application_record.rb
244
308
  - test/dummy/app/models/captcha_user.rb
245
309
  - test/dummy/app/models/secure_user.rb
246
310
  - test/dummy/app/models/security_question_user.rb
247
311
  - test/dummy/app/models/user.rb
312
+ - test/dummy/app/models/widget.rb
248
313
  - test/dummy/app/views/foos/index.html.erb
249
314
  - test/dummy/config.ru
250
315
  - test/dummy/config/application.rb
@@ -260,6 +325,11 @@ files:
260
325
  - test/dummy/db/migrate/20150402165590_add_verification_columns.rb
261
326
  - test/dummy/db/migrate/20150407162345_add_verification_attempt_column.rb
262
327
  - test/dummy/db/migrate/20160320162345_add_security_questions_fields.rb
328
+ - test/dummy/db/migrate/20180318103603_add_expireable_columns.rb
329
+ - test/dummy/db/migrate/20180318105329_add_confirmable_columns.rb
330
+ - test/dummy/db/migrate/20180318105732_add_rememberable_columns.rb
331
+ - test/dummy/db/migrate/20180318111336_add_recoverable_columns.rb
332
+ - test/dummy/db/migrate/20180319114023_add_widget.rb
263
333
  - test/test_captcha_controller.rb
264
334
  - test/test_helper.rb
265
335
  - test/test_install_generator.rb
@@ -281,7 +351,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
281
351
  requirements:
282
352
  - - ">="
283
353
  - !ruby/object:Gem::Version
284
- version: 2.2.2
354
+ version: 2.2.9
285
355
  required_rubygems_version: !ruby/object:Gem::Requirement
286
356
  requirements:
287
357
  - - ">="
@@ -289,7 +359,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
289
359
  version: '0'
290
360
  requirements: []
291
361
  rubyforge_project:
292
- rubygems_version: 2.6.13
362
+ rubygems_version: 2.7.6
293
363
  signing_key:
294
364
  specification_version: 4
295
365
  summary: Security extension for devise
@@ -300,10 +370,12 @@ test_files:
300
370
  - test/dummy/app/controllers/foos_controller.rb
301
371
  - test/dummy/app/controllers/security_question/unlocks_controller.rb
302
372
  - test/dummy/app/models/.gitkeep
373
+ - test/dummy/app/models/application_record.rb
303
374
  - test/dummy/app/models/captcha_user.rb
304
375
  - test/dummy/app/models/secure_user.rb
305
376
  - test/dummy/app/models/security_question_user.rb
306
377
  - test/dummy/app/models/user.rb
378
+ - test/dummy/app/models/widget.rb
307
379
  - test/dummy/app/views/foos/index.html.erb
308
380
  - test/dummy/config.ru
309
381
  - test/dummy/config/application.rb
@@ -319,6 +391,11 @@ test_files:
319
391
  - test/dummy/db/migrate/20150402165590_add_verification_columns.rb
320
392
  - test/dummy/db/migrate/20150407162345_add_verification_attempt_column.rb
321
393
  - test/dummy/db/migrate/20160320162345_add_security_questions_fields.rb
394
+ - test/dummy/db/migrate/20180318103603_add_expireable_columns.rb
395
+ - test/dummy/db/migrate/20180318105329_add_confirmable_columns.rb
396
+ - test/dummy/db/migrate/20180318105732_add_rememberable_columns.rb
397
+ - test/dummy/db/migrate/20180318111336_add_recoverable_columns.rb
398
+ - test/dummy/db/migrate/20180319114023_add_widget.rb
322
399
  - test/test_captcha_controller.rb
323
400
  - test/test_helper.rb
324
401
  - test/test_install_generator.rb