devise-security 0.14.1 → 0.18.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/LICENSE.txt +3 -1
- data/README.md +136 -61
- data/app/controllers/devise/paranoid_verification_code_controller.rb +26 -12
- data/app/controllers/devise/password_expired_controller.rb +32 -10
- data/app/views/devise/paranoid_verification_code/show.html.erb +3 -3
- data/app/views/devise/password_expired/show.html.erb +5 -5
- data/config/locales/bg.yml +42 -0
- data/config/locales/by.yml +50 -0
- data/config/locales/cs.yml +46 -0
- data/config/locales/de.yml +16 -2
- data/config/locales/en.yml +15 -2
- data/config/locales/es.yml +22 -9
- data/config/locales/fa.yml +42 -0
- data/config/locales/fr.yml +15 -2
- data/config/locales/hi.yml +43 -0
- data/config/locales/it.yml +36 -4
- data/config/locales/ja.yml +14 -1
- data/config/locales/nl.yml +42 -0
- data/config/locales/pt.yml +42 -0
- data/config/locales/ru.yml +50 -0
- data/config/locales/tr.yml +26 -1
- data/config/locales/uk.yml +50 -0
- data/config/locales/zh_CN.yml +42 -0
- data/config/locales/zh_TW.yml +42 -0
- data/lib/devise-security/controllers/helpers.rb +72 -51
- data/lib/devise-security/hooks/expirable.rb +3 -3
- data/lib/devise-security/hooks/paranoid_verification.rb +1 -3
- data/lib/devise-security/hooks/password_expirable.rb +3 -3
- data/lib/devise-security/hooks/session_limitable.rb +29 -14
- data/lib/devise-security/models/compatibility/{active_record.rb → active_record_patch.rb} +14 -2
- data/lib/devise-security/models/compatibility/{mongoid.rb → mongoid_patch.rb} +12 -1
- data/lib/devise-security/models/compatibility.rb +2 -2
- data/lib/devise-security/models/database_authenticatable_patch.rb +18 -10
- data/lib/devise-security/models/expirable.rb +6 -5
- data/lib/devise-security/models/paranoid_verification.rb +2 -2
- data/lib/devise-security/models/password_archivable.rb +3 -3
- data/lib/devise-security/models/password_expirable.rb +5 -1
- data/lib/devise-security/models/secure_validatable.rb +62 -11
- data/lib/devise-security/models/session_limitable.rb +17 -2
- data/lib/devise-security/orm/mongoid.rb +1 -1
- data/lib/devise-security/patches.rb +14 -8
- data/lib/devise-security/routes.rb +2 -3
- data/lib/devise-security/validators/password_complexity_validator.rb +53 -24
- data/lib/devise-security/version.rb +1 -1
- data/lib/devise-security.rb +15 -6
- data/lib/generators/devise_security/install_generator.rb +4 -6
- data/lib/generators/templates/{devise-security.rb → devise_security.rb} +9 -1
- data/test/controllers/test_paranoid_verification_code_controller.rb +133 -0
- data/test/controllers/test_password_expired_controller.rb +164 -0
- data/test/{test_security_question_controller.rb → controllers/test_security_question_controller.rb} +19 -37
- data/test/dummy/app/assets/config/manifest.js +3 -0
- data/test/dummy/app/controllers/overrides/paranoid_verification_code_controller.rb +7 -0
- data/test/dummy/app/controllers/overrides/password_expired_controller.rb +17 -0
- data/test/dummy/app/controllers/widgets_controller.rb +9 -0
- data/test/dummy/app/models/application_user_record.rb +2 -1
- data/test/dummy/app/models/mongoid/confirmable_fields.rb +2 -0
- data/test/dummy/app/models/mongoid/database_authenticable_fields.rb +4 -3
- data/test/dummy/app/models/mongoid/expirable_fields.rb +2 -0
- data/test/dummy/app/models/mongoid/lockable_fields.rb +2 -0
- data/test/dummy/app/models/mongoid/mappings.rb +4 -2
- data/test/dummy/app/models/mongoid/omniauthable_fields.rb +2 -0
- data/test/dummy/app/models/mongoid/paranoid_verification_fields.rb +2 -0
- data/test/dummy/app/models/mongoid/password_archivable_fields.rb +2 -0
- data/test/dummy/app/models/mongoid/password_expirable_fields.rb +2 -0
- data/test/dummy/app/models/mongoid/recoverable_fields.rb +2 -0
- data/test/dummy/app/models/mongoid/registerable_fields.rb +4 -2
- data/test/dummy/app/models/mongoid/rememberable_fields.rb +2 -0
- data/test/dummy/app/models/mongoid/secure_validatable_fields.rb +2 -0
- data/test/dummy/app/models/mongoid/security_questionable_fields.rb +2 -0
- data/test/dummy/app/models/mongoid/session_limitable_fields.rb +2 -0
- data/test/dummy/app/models/mongoid/timeoutable_fields.rb +2 -0
- data/test/dummy/app/models/mongoid/trackable_fields.rb +2 -0
- data/test/dummy/app/models/mongoid/validatable_fields.rb +2 -0
- data/test/dummy/app/models/paranoid_verification_user.rb +26 -0
- data/test/dummy/app/models/password_expired_user.rb +26 -0
- data/test/dummy/app/models/user.rb +10 -2
- data/test/dummy/app/models/widget.rb +1 -3
- data/test/dummy/app/mongoid/one_user.rb +5 -5
- data/test/dummy/app/mongoid/user_on_engine.rb +2 -2
- data/test/dummy/app/mongoid/user_on_main_app.rb +2 -2
- data/test/dummy/app/mongoid/user_with_validations.rb +3 -3
- data/test/dummy/app/mongoid/user_without_email.rb +7 -4
- data/test/dummy/config/application.rb +3 -7
- data/test/dummy/config/boot.rb +1 -1
- data/test/dummy/config/environment.rb +1 -1
- data/test/dummy/config/environments/test.rb +4 -13
- data/test/dummy/config/initializers/devise.rb +1 -5
- data/test/dummy/config/initializers/migration_class.rb +1 -8
- data/test/dummy/config/locales/en.yml +10 -0
- data/test/dummy/config/mongoid.yml +1 -1
- data/test/dummy/config/routes.rb +6 -3
- data/test/dummy/config.ru +1 -1
- data/test/dummy/db/migrate/20120508165529_create_tables.rb +15 -6
- data/test/dummy/lib/shared_expirable_columns.rb +1 -0
- data/test/dummy/lib/shared_security_questions_fields.rb +1 -0
- data/test/dummy/lib/shared_user.rb +17 -6
- data/test/dummy/lib/shared_user_without_omniauth.rb +12 -3
- data/test/dummy/lib/shared_verification_fields.rb +1 -0
- data/test/dummy/log/test.log +45240 -0
- data/test/i18n_test.rb +22 -0
- data/test/integration/test_paranoid_verification_code_workflow.rb +53 -0
- data/test/integration/test_password_expirable_workflow.rb +53 -0
- data/test/integration/test_session_limitable_workflow.rb +69 -0
- data/test/orm/active_record.rb +7 -4
- data/test/orm/mongoid.rb +2 -1
- data/test/support/integration_helpers.rb +35 -0
- data/test/support/mongoid.yml +1 -1
- data/test/test_compatibility.rb +15 -0
- data/test/test_complexity_validator.rb +251 -29
- data/test/test_database_authenticatable_patch.rb +146 -0
- data/test/test_helper.rb +23 -8
- data/test/test_install_generator.rb +12 -2
- data/test/test_paranoid_verification.rb +8 -9
- data/test/test_password_archivable.rb +34 -11
- data/test/test_password_expirable.rb +27 -27
- data/test/test_secure_validatable.rb +284 -50
- data/test/test_secure_validatable_overrides.rb +185 -0
- data/test/test_session_limitable.rb +57 -0
- data/test/tmp/config/initializers/devise_security.rb +52 -0
- data/test/tmp/config/locales/devise.security_extension.by.yml +50 -0
- data/test/tmp/config/locales/devise.security_extension.cs.yml +46 -0
- data/test/tmp/config/locales/devise.security_extension.de.yml +42 -0
- data/test/tmp/config/locales/devise.security_extension.en.yml +42 -0
- data/test/tmp/config/locales/devise.security_extension.es.yml +42 -0
- data/test/tmp/config/locales/devise.security_extension.fa.yml +42 -0
- data/test/tmp/config/locales/devise.security_extension.fr.yml +42 -0
- data/test/tmp/config/locales/devise.security_extension.hi.yml +43 -0
- data/test/tmp/config/locales/devise.security_extension.it.yml +42 -0
- data/test/tmp/config/locales/devise.security_extension.ja.yml +42 -0
- data/test/tmp/config/locales/devise.security_extension.nl.yml +42 -0
- data/test/tmp/config/locales/devise.security_extension.pt.yml +42 -0
- data/test/tmp/config/locales/devise.security_extension.ru.yml +50 -0
- data/test/tmp/config/locales/devise.security_extension.tr.yml +42 -0
- data/test/tmp/config/locales/devise.security_extension.uk.yml +50 -0
- data/test/tmp/config/locales/devise.security_extension.zh_CN.yml +42 -0
- data/test/tmp/config/locales/devise.security_extension.zh_TW.yml +42 -0
- metadata +202 -138
- data/.codeclimate.yml +0 -63
- data/.document +0 -5
- data/.gitignore +0 -43
- data/.mdlrc +0 -1
- data/.rubocop.yml +0 -64
- data/.ruby-version +0 -1
- data/.travis.yml +0 -39
- data/Appraisals +0 -35
- data/Gemfile +0 -10
- data/Rakefile +0 -27
- data/devise-security.gemspec +0 -50
- data/gemfiles/rails_4.2_stable.gemfile +0 -16
- data/gemfiles/rails_5.0_stable.gemfile +0 -15
- data/gemfiles/rails_5.1_stable.gemfile +0 -15
- data/gemfiles/rails_5.2_stable.gemfile +0 -15
- data/gemfiles/rails_6.0_beta.gemfile +0 -15
- data/lib/devise-security/orm/active_record.rb +0 -20
- data/lib/devise-security/patches/confirmations_controller_captcha.rb +0 -23
- data/lib/devise-security/patches/confirmations_controller_security_question.rb +0 -26
- data/lib/devise-security/patches/passwords_controller_captcha.rb +0 -22
- data/lib/devise-security/patches/passwords_controller_security_question.rb +0 -25
- data/lib/devise-security/patches/registrations_controller_captcha.rb +0 -35
- data/lib/devise-security/patches/sessions_controller_captcha.rb +0 -26
- data/lib/devise-security/patches/unlocks_controller_captcha.rb +0 -22
- data/lib/devise-security/patches/unlocks_controller_security_question.rb +0 -25
- data/lib/devise-security/schema.rb +0 -66
- data/test/dummy/app/controllers/foos_controller.rb +0 -0
- data/test/dummy/app/models/.gitkeep +0 -0
- data/test/dummy/app/models/secure_user.rb +0 -9
- data/test/dummy/lib/shared_user_without_email.rb +0 -28
- data/test/test_password_expired_controller.rb +0 -46
- /data/test/{test_captcha_controller.rb → controllers/test_captcha_controller.rb} +0 -0
@@ -0,0 +1,146 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
class TestDatabaseAuthenticatablePatch < ActiveSupport::TestCase
|
6
|
+
def create_user
|
7
|
+
User.create(
|
8
|
+
email: 'bob@microsoft.com',
|
9
|
+
password: 'Password1!',
|
10
|
+
password_confirmation: 'Password1!'
|
11
|
+
) do |user|
|
12
|
+
user.extend(Devise::Models::DatabaseAuthenticatablePatch)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
test 'updates if all params are present and valid' do
|
17
|
+
user = create_user
|
18
|
+
|
19
|
+
assert(
|
20
|
+
user.update_with_password(
|
21
|
+
{
|
22
|
+
current_password: 'Password1!',
|
23
|
+
password: 'Password2!',
|
24
|
+
password_confirmation: 'Password2!'
|
25
|
+
}
|
26
|
+
)
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
test 'does not update if current_password is missing' do
|
31
|
+
user = create_user
|
32
|
+
|
33
|
+
user.update_with_password(
|
34
|
+
{
|
35
|
+
password: 'Password2!',
|
36
|
+
password_confirmation: 'Password2!'
|
37
|
+
}
|
38
|
+
)
|
39
|
+
|
40
|
+
assert_equal(["Current password can't be blank"], user.errors.full_messages)
|
41
|
+
end
|
42
|
+
|
43
|
+
test 'does not update if current_password is incorrect' do
|
44
|
+
user = create_user
|
45
|
+
|
46
|
+
user.update_with_password(
|
47
|
+
{
|
48
|
+
current_password: 'Password2!',
|
49
|
+
password: 'Password2!',
|
50
|
+
password_confirmation: 'Password2!'
|
51
|
+
}
|
52
|
+
)
|
53
|
+
|
54
|
+
assert_equal(['Current password is invalid'], user.errors.full_messages)
|
55
|
+
end
|
56
|
+
|
57
|
+
test 'does not update if password is missing' do
|
58
|
+
user = create_user
|
59
|
+
|
60
|
+
user.update_with_password(
|
61
|
+
{
|
62
|
+
current_password: 'Password1!',
|
63
|
+
password: '',
|
64
|
+
password_confirmation: 'Password2!'
|
65
|
+
}
|
66
|
+
)
|
67
|
+
|
68
|
+
assert_equal(["Password can't be blank"], user.errors.full_messages)
|
69
|
+
end
|
70
|
+
|
71
|
+
test 'does not update if password is invalid and mismatches confirmation' do
|
72
|
+
user = create_user
|
73
|
+
|
74
|
+
user.update_with_password(
|
75
|
+
{
|
76
|
+
current_password: 'Password1!',
|
77
|
+
password: 'f',
|
78
|
+
password_confirmation: 'Password2!'
|
79
|
+
}
|
80
|
+
)
|
81
|
+
|
82
|
+
assert_equal(
|
83
|
+
[
|
84
|
+
"Password confirmation doesn't match Password",
|
85
|
+
'Password is too short (minimum is 7 characters)',
|
86
|
+
'Password must contain at least one digit',
|
87
|
+
'Password must contain at least one upper-case letter'
|
88
|
+
],
|
89
|
+
user.errors.full_messages
|
90
|
+
)
|
91
|
+
end
|
92
|
+
|
93
|
+
test 'does not update if password is invalid and matches confirmation' do
|
94
|
+
user = create_user
|
95
|
+
|
96
|
+
user.update_with_password(
|
97
|
+
{
|
98
|
+
current_password: 'Password1!',
|
99
|
+
password: 'f',
|
100
|
+
password_confirmation: 'f'
|
101
|
+
}
|
102
|
+
)
|
103
|
+
|
104
|
+
assert_equal(
|
105
|
+
[
|
106
|
+
'Password is too short (minimum is 7 characters)',
|
107
|
+
'Password must contain at least one digit',
|
108
|
+
'Password must contain at least one upper-case letter'
|
109
|
+
],
|
110
|
+
user.errors.full_messages
|
111
|
+
)
|
112
|
+
end
|
113
|
+
|
114
|
+
test 'does not update if password_confirmation is missing' do
|
115
|
+
user = create_user
|
116
|
+
|
117
|
+
user.update_with_password(
|
118
|
+
{
|
119
|
+
current_password: 'Password1!',
|
120
|
+
password: 'Password2!',
|
121
|
+
password_confirmation: ''
|
122
|
+
}
|
123
|
+
)
|
124
|
+
|
125
|
+
assert_equal(
|
126
|
+
["Password confirmation can't be blank"], user.errors.full_messages
|
127
|
+
)
|
128
|
+
end
|
129
|
+
|
130
|
+
test 'does not update if password_confirmation is mismatched' do
|
131
|
+
user = create_user
|
132
|
+
|
133
|
+
user.update_with_password(
|
134
|
+
{
|
135
|
+
current_password: 'Password1!',
|
136
|
+
password: 'Password2!',
|
137
|
+
password_confirmation: 'Password3!'
|
138
|
+
}
|
139
|
+
)
|
140
|
+
|
141
|
+
assert_equal(
|
142
|
+
["Password confirmation doesn't match Password"],
|
143
|
+
user.errors.full_messages
|
144
|
+
)
|
145
|
+
end
|
146
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -3,17 +3,26 @@
|
|
3
3
|
ENV['RAILS_ENV'] ||= 'test'
|
4
4
|
|
5
5
|
require 'simplecov'
|
6
|
+
|
7
|
+
if ENV['CI']
|
8
|
+
require 'simplecov-lcov'
|
9
|
+
SimpleCov.formatter = SimpleCov::Formatter::LcovFormatter
|
10
|
+
SimpleCov::Formatter::LcovFormatter.config.report_with_single_file = true
|
11
|
+
end
|
12
|
+
|
6
13
|
SimpleCov.start do
|
7
14
|
add_filter 'gemfiles'
|
15
|
+
add_filter 'test/dummy/db'
|
16
|
+
add_group 'ActiveRecord', 'active_record'
|
17
|
+
add_group 'Expirable', /(?<!password_)expirable/
|
18
|
+
add_group 'Mongoid', 'mongoid'
|
19
|
+
add_group 'Paranoid Verifiable', 'paranoid_verification'
|
20
|
+
add_group 'Password Archivable', /password_archivable|old_password/
|
21
|
+
add_group 'Password Expirable', /password_expirable|password_expired/
|
22
|
+
add_group 'Secure Validateable', 'secure_validatable'
|
23
|
+
add_group 'Security Questionable', 'security_question'
|
24
|
+
add_group 'Session Limitable', 'session_limitable'
|
8
25
|
add_group 'Tests', 'test'
|
9
|
-
add_group 'Password Archivable', 'password_archivable'
|
10
|
-
add_group 'Password Expirable', 'password_expirable'
|
11
|
-
end
|
12
|
-
|
13
|
-
if ENV['CI']
|
14
|
-
require 'coveralls'
|
15
|
-
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
|
16
|
-
Coveralls.wear!
|
17
26
|
end
|
18
27
|
|
19
28
|
require 'pry'
|
@@ -24,6 +33,12 @@ require 'devise-security'
|
|
24
33
|
require 'database_cleaner'
|
25
34
|
require "orm/#{DEVISE_ORM}"
|
26
35
|
|
36
|
+
# Controller testing is the way that Devise itself tests the functionality of
|
37
|
+
# controller, even though it has been deprecated in favor of request tests.
|
38
|
+
require 'rails-controller-testing'
|
39
|
+
Rails::Controller::Testing.install
|
40
|
+
require 'support/integration_helpers'
|
41
|
+
|
27
42
|
class Minitest::Test
|
28
43
|
def before_setup
|
29
44
|
DatabaseCleaner.start
|
@@ -6,18 +6,28 @@ require 'generators/devise_security/install_generator'
|
|
6
6
|
|
7
7
|
class TestInstallGenerator < Rails::Generators::TestCase
|
8
8
|
tests DeviseSecurity::Generators::InstallGenerator
|
9
|
-
destination File.expand_path('
|
9
|
+
destination File.expand_path('tmp', __dir__)
|
10
10
|
setup :prepare_destination
|
11
11
|
|
12
12
|
test 'Assert all files are properly created' do
|
13
13
|
run_generator
|
14
|
-
assert_file 'config/initializers/
|
14
|
+
assert_file 'config/initializers/devise_security.rb'
|
15
|
+
assert_file 'config/locales/devise.security_extension.by.yml'
|
16
|
+
assert_file 'config/locales/devise.security_extension.cs.yml'
|
15
17
|
assert_file 'config/locales/devise.security_extension.de.yml'
|
16
18
|
assert_file 'config/locales/devise.security_extension.en.yml'
|
17
19
|
assert_file 'config/locales/devise.security_extension.es.yml'
|
20
|
+
assert_file 'config/locales/devise.security_extension.fa.yml'
|
18
21
|
assert_file 'config/locales/devise.security_extension.fr.yml'
|
22
|
+
assert_file 'config/locales/devise.security_extension.hi.yml'
|
19
23
|
assert_file 'config/locales/devise.security_extension.it.yml'
|
20
24
|
assert_file 'config/locales/devise.security_extension.ja.yml'
|
25
|
+
assert_file 'config/locales/devise.security_extension.nl.yml'
|
26
|
+
assert_file 'config/locales/devise.security_extension.pt.yml'
|
27
|
+
assert_file 'config/locales/devise.security_extension.ru.yml'
|
21
28
|
assert_file 'config/locales/devise.security_extension.tr.yml'
|
29
|
+
assert_file 'config/locales/devise.security_extension.uk.yml'
|
30
|
+
assert_file 'config/locales/devise.security_extension.zh_CN.yml'
|
31
|
+
assert_file 'config/locales/devise.security_extension.zh_TW.yml'
|
22
32
|
end
|
23
33
|
end
|
@@ -6,12 +6,12 @@ class TestParanoidVerification < ActiveSupport::TestCase
|
|
6
6
|
test 'need to paranoid verify if code present' do
|
7
7
|
user = User.new
|
8
8
|
user.generate_paranoid_code
|
9
|
-
|
9
|
+
assert(user.need_paranoid_verification?)
|
10
10
|
end
|
11
11
|
|
12
12
|
test 'no need to paranoid verify if no code' do
|
13
13
|
user = User.new
|
14
|
-
|
14
|
+
assert_not(user.need_paranoid_verification?)
|
15
15
|
end
|
16
16
|
|
17
17
|
test 'generate code' do
|
@@ -29,23 +29,23 @@ class TestParanoidVerification < ActiveSupport::TestCase
|
|
29
29
|
user.generate_paranoid_code
|
30
30
|
# default generator generates 5 char string
|
31
31
|
assert_equal(user.paranoid_verification_code.class, String)
|
32
|
-
assert_equal(user.paranoid_verification_code.length
|
32
|
+
assert_equal(5, user.paranoid_verification_code.length)
|
33
33
|
end
|
34
34
|
|
35
35
|
test 'when code match upon verify code, should mark record that it\'s no loger needed to verify' do
|
36
36
|
user = User.new(paranoid_verification_code: 'abcde')
|
37
37
|
|
38
|
-
|
38
|
+
assert(user.need_paranoid_verification?)
|
39
39
|
user.verify_code('abcde')
|
40
|
-
|
40
|
+
assert_not(user.need_paranoid_verification?)
|
41
41
|
end
|
42
42
|
|
43
43
|
test 'when code match upon verify code, should no longer need verification' do
|
44
44
|
user = User.new(paranoid_verification_code: 'abcde')
|
45
45
|
|
46
|
-
|
46
|
+
assert(user.need_paranoid_verification?)
|
47
47
|
user.verify_code('abcde')
|
48
|
-
|
48
|
+
assert_not(user.need_paranoid_verification?)
|
49
49
|
end
|
50
50
|
|
51
51
|
test 'when code match upon verification code, should set when verification was accepted' do
|
@@ -57,7 +57,7 @@ class TestParanoidVerification < ActiveSupport::TestCase
|
|
57
57
|
test 'when code not match upon verify code, should still need verification' do
|
58
58
|
user = User.new(paranoid_verification_code: 'abcde')
|
59
59
|
user.verify_code('wrong')
|
60
|
-
|
60
|
+
assert(user.need_paranoid_verification?)
|
61
61
|
end
|
62
62
|
|
63
63
|
test 'when code not match upon verification code, should not set paranoid_verified_at' do
|
@@ -94,7 +94,6 @@ class TestParanoidVerification < ActiveSupport::TestCase
|
|
94
94
|
Devise.paranoid_code_regenerate_after_attempt = original_regenerate
|
95
95
|
end
|
96
96
|
|
97
|
-
|
98
97
|
test 'by default paranoid code regenerate should have 10 attempts' do
|
99
98
|
user = User.new(paranoid_verification_code: 'abcde')
|
100
99
|
assert_equal 10, user.paranoid_attempts_remaining
|
@@ -3,7 +3,6 @@
|
|
3
3
|
require 'test_helper'
|
4
4
|
|
5
5
|
class TestPasswordArchivable < ActiveSupport::TestCase
|
6
|
-
|
7
6
|
setup do
|
8
7
|
Devise.password_archiving_count = 2
|
9
8
|
end
|
@@ -20,7 +19,7 @@ class TestPasswordArchivable < ActiveSupport::TestCase
|
|
20
19
|
|
21
20
|
test 'cannot use same password' do
|
22
21
|
user = User.create email: 'bob@microsoft.com', password: 'Password1', password_confirmation: 'Password1'
|
23
|
-
assert_raises(ORMInvalidRecordException) { set_password(user,
|
22
|
+
assert_raises(ORMInvalidRecordException) { set_password(user, 'Password1') }
|
24
23
|
end
|
25
24
|
|
26
25
|
test 'indirectly saving associated user does not cause deprecation warning' do
|
@@ -43,19 +42,19 @@ class TestPasswordArchivable < ActiveSupport::TestCase
|
|
43
42
|
|
44
43
|
user = User.create! email: 'bob@microsoft.com', password: 'Password1', password_confirmation: 'Password1'
|
45
44
|
assert_equal 0, OldPassword.count
|
46
|
-
set_password(user,
|
45
|
+
set_password(user, 'Password2')
|
47
46
|
assert_equal 1, OldPassword.count
|
48
47
|
|
49
|
-
assert_raises(ORMInvalidRecordException) { set_password(user,
|
50
|
-
set_password(user,
|
48
|
+
assert_raises(ORMInvalidRecordException) { set_password(user, 'Password1') }
|
49
|
+
set_password(user, 'Password3')
|
51
50
|
assert_equal 2, OldPassword.count
|
52
51
|
|
53
52
|
# rotate first password out of archive
|
54
|
-
assert set_password(user,
|
53
|
+
assert set_password(user, 'Password4')
|
55
54
|
|
56
55
|
# archive count was 2, so first password should work again
|
57
|
-
assert set_password(user,
|
58
|
-
assert set_password(user,
|
56
|
+
assert set_password(user, 'Password1')
|
57
|
+
assert set_password(user, 'Password2')
|
59
58
|
end
|
60
59
|
|
61
60
|
test 'the option should be dynamic during runtime' do
|
@@ -67,10 +66,34 @@ class TestPasswordArchivable < ActiveSupport::TestCase
|
|
67
66
|
|
68
67
|
user = User.create email: 'bob@microsoft.com', password: 'Password1', password_confirmation: 'Password1'
|
69
68
|
|
70
|
-
assert set_password(user,
|
69
|
+
assert set_password(user, 'Password2')
|
70
|
+
|
71
|
+
assert_raises(ORMInvalidRecordException) { set_password(user, 'Password2') }
|
72
|
+
|
73
|
+
assert_raises(ORMInvalidRecordException) { set_password(user, 'Password1') }
|
74
|
+
end
|
75
|
+
|
76
|
+
test 'default sort orders do not affect archiving' do
|
77
|
+
class ::OldPassword
|
78
|
+
default_scope { order(created_at: :asc) }
|
79
|
+
end
|
80
|
+
|
81
|
+
assert_equal 2, Devise.password_archiving_count
|
82
|
+
|
83
|
+
user = User.create! email: 'bob@microsoft.com', password: 'Password1', password_confirmation: 'Password1'
|
84
|
+
assert_equal 0, OldPassword.count
|
85
|
+
set_password(user, 'Password2')
|
86
|
+
assert_equal 1, OldPassword.count
|
87
|
+
|
88
|
+
assert_raises(ORMInvalidRecordException) { set_password(user, 'Password1') }
|
89
|
+
set_password(user, 'Password3')
|
90
|
+
assert_equal 2, OldPassword.count
|
71
91
|
|
72
|
-
|
92
|
+
# rotate first password out of archive
|
93
|
+
assert set_password(user, 'Password4')
|
73
94
|
|
74
|
-
|
95
|
+
# archive count was 2, so first password should work again
|
96
|
+
assert set_password(user, 'Password1')
|
97
|
+
assert set_password(user, 'Password2')
|
75
98
|
end
|
76
99
|
end
|
@@ -14,59 +14,59 @@ class TestPasswordArchivable < ActiveSupport::TestCase
|
|
14
14
|
test 'does nothing if disabled' do
|
15
15
|
Devise.expire_password_after = false
|
16
16
|
user = User.create email: 'bob@microsoft.com', password: 'Password1', password_confirmation: 'Password1'
|
17
|
-
|
18
|
-
|
17
|
+
assert_not user.need_change_password?
|
18
|
+
assert_not user.password_expired?
|
19
19
|
user.need_change_password!
|
20
|
-
|
21
|
-
|
20
|
+
assert_not user.need_change_password?
|
21
|
+
assert_not user.password_expired?
|
22
22
|
end
|
23
23
|
|
24
24
|
test 'password change can be requested' do
|
25
25
|
Devise.expire_password_after = true
|
26
26
|
user = User.create email: 'bob@microsoft.com', password: 'Password1', password_confirmation: 'Password1'
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
assert_not user.need_change_password?
|
28
|
+
assert_not user.password_expired?
|
29
|
+
assert_not user.password_change_requested?
|
30
30
|
user.need_change_password!
|
31
31
|
assert user.need_change_password?
|
32
|
-
|
32
|
+
assert_not user.password_expired? # it's not too old because it's not set at all
|
33
33
|
assert user.password_change_requested?
|
34
34
|
end
|
35
35
|
|
36
36
|
test 'password expires' do
|
37
37
|
user = User.create email: 'bob@microsoft.com', password: 'Password1', password_confirmation: 'Password1'
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
user.update(password_changed_at: Time.now.ago(3.months))
|
38
|
+
assert_not user.need_change_password?
|
39
|
+
assert_not user.password_expired?
|
40
|
+
assert_not user.password_too_old?
|
41
|
+
user.update(password_changed_at: Time.zone.now.ago(3.months))
|
42
42
|
assert user.password_too_old?
|
43
43
|
assert user.need_change_password?
|
44
44
|
assert user.password_expired?
|
45
|
-
|
45
|
+
assert_not user.password_change_requested?
|
46
46
|
end
|
47
47
|
|
48
48
|
test 'saving a record records the time the password was changed' do
|
49
49
|
user = User.new email: 'bob@microsoft.com', password: 'Password1', password_confirmation: 'Password1'
|
50
|
-
|
51
|
-
|
52
|
-
|
50
|
+
assert_nil user.password_changed_at
|
51
|
+
assert_not user.password_change_requested?
|
52
|
+
assert_not user.password_expired?
|
53
53
|
user.save
|
54
54
|
assert user.password_changed_at.present?
|
55
|
-
|
56
|
-
|
55
|
+
assert_not user.password_change_requested?
|
56
|
+
assert_not user.password_expired?
|
57
57
|
end
|
58
58
|
|
59
59
|
test 'updating a record updates the time the password was changed if the password is changed' do
|
60
60
|
user = User.create email: 'bob@microsoft.com', password: 'Password1', password_confirmation: 'Password1'
|
61
|
-
user.update(password_changed_at: Time.now.ago(3.months))
|
61
|
+
user.update(password_changed_at: Time.zone.now.ago(3.months))
|
62
62
|
original_password_changed_at = user.password_changed_at
|
63
63
|
user.expire_password!
|
64
64
|
assert user.password_change_requested?
|
65
|
-
user.password =
|
66
|
-
user.password_confirmation =
|
65
|
+
user.password = 'NewPassword1'
|
66
|
+
user.password_confirmation = 'NewPassword1'
|
67
67
|
user.save
|
68
68
|
assert user.password_changed_at > original_password_changed_at
|
69
|
-
|
69
|
+
assert_not user.password_change_requested?
|
70
70
|
end
|
71
71
|
|
72
72
|
test 'updating a record does not updates the time the password was changed if the password was not changed' do
|
@@ -74,7 +74,7 @@ class TestPasswordArchivable < ActiveSupport::TestCase
|
|
74
74
|
user.expire_password!
|
75
75
|
assert user.password_change_requested?
|
76
76
|
user.save
|
77
|
-
|
77
|
+
assert_not user.previous_changes.key?(:password_changed_at)
|
78
78
|
assert user.password_change_requested?
|
79
79
|
end
|
80
80
|
|
@@ -85,10 +85,10 @@ class TestPasswordArchivable < ActiveSupport::TestCase
|
|
85
85
|
4.months
|
86
86
|
end
|
87
87
|
end
|
88
|
-
user.password_changed_at = Time.now.ago(3.months)
|
89
|
-
|
90
|
-
|
91
|
-
user.password_changed_at = Time.now.ago(5.months)
|
88
|
+
user.password_changed_at = Time.zone.now.ago(3.months)
|
89
|
+
assert_not user.need_change_password?
|
90
|
+
assert_not user.password_expired?
|
91
|
+
user.password_changed_at = Time.zone.now.ago(5.months)
|
92
92
|
assert user.need_change_password?
|
93
93
|
assert user.password_expired?
|
94
94
|
end
|