devise-security 0.14.0 → 0.16.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/README.md +124 -60
- data/app/controllers/devise/password_expired_controller.rb +11 -6
- 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/by.yml +49 -0
- data/config/locales/cs.yml +41 -0
- data/config/locales/de.yml +13 -2
- data/config/locales/en.yml +13 -1
- data/config/locales/es.yml +10 -9
- data/config/locales/fa.yml +41 -0
- data/config/locales/fr.yml +1 -0
- data/config/locales/hi.yml +42 -0
- data/config/locales/it.yml +35 -4
- data/config/locales/ja.yml +2 -1
- data/config/locales/nl.yml +41 -0
- data/config/locales/pt.yml +41 -0
- data/config/locales/ru.yml +49 -0
- data/config/locales/tr.yml +1 -0
- data/config/locales/uk.yml +49 -0
- data/config/locales/zh_CN.yml +41 -0
- data/config/locales/zh_TW.yml +41 -0
- data/lib/devise-security.rb +7 -3
- data/lib/devise-security/controllers/helpers.rb +59 -50
- data/lib/devise-security/hooks/password_expirable.rb +2 -0
- data/lib/devise-security/hooks/session_limitable.rb +29 -14
- data/lib/devise-security/models/compatibility.rb +2 -2
- data/lib/devise-security/models/compatibility/{active_record.rb → active_record_patch.rb} +12 -1
- data/lib/devise-security/models/compatibility/{mongoid.rb → mongoid_patch.rb} +11 -1
- data/lib/devise-security/models/password_expirable.rb +5 -1
- data/lib/devise-security/models/secure_validatable.rb +15 -1
- data/lib/devise-security/models/session_limitable.rb +17 -2
- data/lib/devise-security/validators/password_complexity_validator.rb +4 -2
- data/lib/devise-security/version.rb +1 -1
- data/lib/generators/devise_security/install_generator.rb +3 -3
- data/lib/generators/templates/devise_security.rb +47 -0
- data/test/{test_captcha_controller.rb → controllers/test_captcha_controller.rb} +0 -0
- data/test/controllers/test_password_expired_controller.rb +110 -0
- data/test/{test_security_question_controller.rb → controllers/test_security_question_controller.rb} +16 -40
- data/test/dummy/app/assets/config/manifest.js +3 -0
- data/test/dummy/app/controllers/widgets_controller.rb +6 -0
- data/test/dummy/app/models/user.rb +8 -0
- data/test/dummy/config/application.rb +1 -0
- data/test/dummy/config/environments/test.rb +3 -13
- data/test/dummy/config/initializers/migration_class.rb +1 -8
- data/test/dummy/config/mongoid.yml +1 -1
- data/test/dummy/config/routes.rb +4 -3
- data/test/dummy/db/migrate/20120508165529_create_tables.rb +10 -1
- data/test/dummy/log/development.log +883 -0
- data/test/dummy/log/test.log +21689 -0
- data/test/integration/test_password_expirable_workflow.rb +53 -0
- data/test/integration/test_session_limitable_workflow.rb +67 -0
- data/test/orm/active_record.rb +4 -1
- data/test/orm/mongoid.rb +2 -1
- data/test/support/integration_helpers.rb +29 -0
- data/test/support/mongoid.yml +1 -1
- data/test/test_compatibility.rb +13 -0
- data/test/test_complexity_validator.rb +12 -0
- data/test/test_helper.rb +21 -6
- data/test/test_install_generator.rb +11 -1
- data/test/test_secure_validatable.rb +76 -0
- data/test/test_session_limitable.rb +57 -0
- data/{lib/generators/templates → test/tmp/config/initializers}/devise-security.rb +3 -0
- data/test/tmp/config/locales/devise.security_extension.by.yml +49 -0
- data/test/tmp/config/locales/devise.security_extension.cs.yml +41 -0
- data/test/tmp/config/locales/devise.security_extension.de.yml +39 -0
- data/test/tmp/config/locales/devise.security_extension.en.yml +41 -0
- data/test/tmp/config/locales/devise.security_extension.es.yml +30 -0
- data/test/tmp/config/locales/devise.security_extension.fa.yml +41 -0
- data/test/tmp/config/locales/devise.security_extension.fr.yml +30 -0
- data/test/tmp/config/locales/devise.security_extension.hi.yml +42 -0
- data/test/tmp/config/locales/devise.security_extension.it.yml +41 -0
- data/test/tmp/config/locales/devise.security_extension.ja.yml +30 -0
- data/test/tmp/config/locales/devise.security_extension.nl.yml +41 -0
- data/test/tmp/config/locales/devise.security_extension.pt.yml +41 -0
- data/test/tmp/config/locales/devise.security_extension.ru.yml +49 -0
- data/test/tmp/config/locales/devise.security_extension.tr.yml +18 -0
- data/test/tmp/config/locales/devise.security_extension.uk.yml +49 -0
- data/test/tmp/config/locales/devise.security_extension.zh_CN.yml +41 -0
- data/test/tmp/config/locales/devise.security_extension.zh_TW.yml +41 -0
- metadata +156 -133
- 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 -41
- 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/schema.rb +0 -66
- data/test/dummy/app/models/.gitkeep +0 -0
- data/test/test_password_expired_controller.rb +0 -46
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
|
|
5
|
+
class TestPasswordExpirableWorkflow < ActionDispatch::IntegrationTest
|
|
6
|
+
include IntegrationHelpers
|
|
7
|
+
|
|
8
|
+
setup do
|
|
9
|
+
@user = User.create!(password: 'passWord1',
|
|
10
|
+
password_confirmation: 'passWord1',
|
|
11
|
+
email: 'bob@microsoft.com',
|
|
12
|
+
password_changed_at: 4.months.ago) # the default expiration time is 3.months.ago
|
|
13
|
+
@user.confirm
|
|
14
|
+
|
|
15
|
+
assert @user.valid?
|
|
16
|
+
assert @user.need_change_password?
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
test 'sign in and change expired password' do
|
|
20
|
+
sign_in(@user)
|
|
21
|
+
assert_redirected_to(root_path)
|
|
22
|
+
follow_redirect!
|
|
23
|
+
assert_redirected_to(user_password_expired_path)
|
|
24
|
+
# @note This is not the same controller used by Devise for password changes
|
|
25
|
+
put '/users/password_expired', params: {
|
|
26
|
+
user: {
|
|
27
|
+
current_password: 'passWord1',
|
|
28
|
+
password: 'Password12345!',
|
|
29
|
+
password_confirmation: 'Password12345!',
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
assert_redirected_to(root_path)
|
|
33
|
+
@user.reload
|
|
34
|
+
assert_not @user.need_change_password?
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
test 'sign in and password is updated before redirect completes' do
|
|
38
|
+
sign_in(@user)
|
|
39
|
+
assert_redirected_to(root_path)
|
|
40
|
+
|
|
41
|
+
# simulates an external process updating the password
|
|
42
|
+
@user.update(password_changed_at: Time.zone.now)
|
|
43
|
+
assert_not @user.need_change_password?
|
|
44
|
+
|
|
45
|
+
follow_redirect!
|
|
46
|
+
assert_response :success
|
|
47
|
+
|
|
48
|
+
# if the password is expired at this point they will be redirected to the
|
|
49
|
+
# password change controller.
|
|
50
|
+
get root_path
|
|
51
|
+
assert_response :success
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class TestSessionLimitableWorkflow < ActionDispatch::IntegrationTest
|
|
4
|
+
include IntegrationHelpers
|
|
5
|
+
|
|
6
|
+
setup do
|
|
7
|
+
@user = User.create!(password: 'passWord1',
|
|
8
|
+
password_confirmation: 'passWord1',
|
|
9
|
+
email: 'bob@microsoft.com')
|
|
10
|
+
@user.confirm
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
test 'failed login' do
|
|
14
|
+
assert_nil @user.unique_session_id
|
|
15
|
+
|
|
16
|
+
open_session do |session|
|
|
17
|
+
failed_sign_in(@user, session)
|
|
18
|
+
session.assert_response(:success)
|
|
19
|
+
assert_equal session.flash[:alert], I18n.t('devise.failure.invalid', authentication_keys: 'Email')
|
|
20
|
+
assert_nil @user.reload.unique_session_id
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
test 'successful login' do
|
|
25
|
+
assert_nil @user.unique_session_id
|
|
26
|
+
|
|
27
|
+
open_session do |session|
|
|
28
|
+
sign_in(@user, session)
|
|
29
|
+
session.assert_redirected_to '/'
|
|
30
|
+
session.get widgets_path
|
|
31
|
+
session.assert_response(:success)
|
|
32
|
+
assert_equal session.response.body, 'success'
|
|
33
|
+
assert_not_nil @user.reload.unique_session_id
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
test 'session is logged out when another session is created' do
|
|
38
|
+
first_session = open_session
|
|
39
|
+
second_session = open_session
|
|
40
|
+
unique_session_id = nil
|
|
41
|
+
|
|
42
|
+
first_session.tap do |session|
|
|
43
|
+
sign_in(@user, session)
|
|
44
|
+
session.assert_redirected_to '/'
|
|
45
|
+
session.get widgets_path
|
|
46
|
+
session.assert_response(:success)
|
|
47
|
+
assert_equal session.response.body, 'success'
|
|
48
|
+
unique_session_id = @user.reload.unique_session_id
|
|
49
|
+
assert_not_nil unique_session_id
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
second_session.tap do |session|
|
|
53
|
+
sign_in(@user, session)
|
|
54
|
+
session.assert_redirected_to '/'
|
|
55
|
+
session.get widgets_path
|
|
56
|
+
session.assert_response(:success)
|
|
57
|
+
assert_equal session.response.body, 'success'
|
|
58
|
+
assert_not_equal unique_session_id, @user.reload.unique_session_id
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
first_session.tap do |session|
|
|
62
|
+
session.get widgets_path
|
|
63
|
+
session.assert_redirected_to new_user_session_path
|
|
64
|
+
assert_equal session.flash[:alert], I18n.t('devise.failure.session_limited')
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
data/test/orm/active_record.rb
CHANGED
|
@@ -2,7 +2,10 @@ require 'active_record'
|
|
|
2
2
|
|
|
3
3
|
ActiveRecord::Migration.verbose = false
|
|
4
4
|
ActiveRecord::Base.logger = Logger.new(nil)
|
|
5
|
-
|
|
5
|
+
case
|
|
6
|
+
when Rails.gem_version >= Gem::Version.new('6.0.0')
|
|
7
|
+
ActiveRecord::MigrationContext.new(File.expand_path('../../dummy/db/migrate', __FILE__), ActiveRecord::SchemaMigration).migrate
|
|
8
|
+
when Rails.gem_version >= Gem::Version.new('5.2.0')
|
|
6
9
|
ActiveRecord::MigrationContext.new(File.expand_path('../../dummy/db/migrate', __FILE__)).migrate
|
|
7
10
|
else
|
|
8
11
|
ActiveRecord::Migrator.migrate(File.expand_path('../../dummy/db/migrate', __FILE__))
|
data/test/orm/mongoid.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'mongoid/version'
|
|
4
|
+
require 'database_cleaner-mongoid'
|
|
4
5
|
|
|
5
6
|
Mongoid.configure do |config|
|
|
6
7
|
config.load!('test/support/mongoid.yml', Rails.env)
|
|
@@ -8,5 +9,5 @@ Mongoid.configure do |config|
|
|
|
8
9
|
config.include_root_in_json = true
|
|
9
10
|
end
|
|
10
11
|
|
|
11
|
-
DatabaseCleaner[:mongoid].strategy = :
|
|
12
|
+
DatabaseCleaner[:mongoid].strategy = :deletion
|
|
12
13
|
ORMInvalidRecordException = Mongoid::Errors::Validations
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module IntegrationHelpers
|
|
4
|
+
# login the user. This will exercise all the Warden Hooks
|
|
5
|
+
# @param user [User]
|
|
6
|
+
# @param session [ActionDispatch::Integration::Session]
|
|
7
|
+
# @return [void]
|
|
8
|
+
def sign_in(user, session = integration_session)
|
|
9
|
+
session.post new_user_session_path, params: {
|
|
10
|
+
user: {
|
|
11
|
+
email: user.email,
|
|
12
|
+
password: user.password,
|
|
13
|
+
},
|
|
14
|
+
}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# attempt to login the user with a bad password. This will exercise all the Warden Hooks
|
|
18
|
+
# @param user [User]
|
|
19
|
+
# @param session [ActionDispatch::Integration::Session]
|
|
20
|
+
# @return [void]
|
|
21
|
+
def failed_sign_in(user, session)
|
|
22
|
+
session.post new_user_session_path, params: {
|
|
23
|
+
user: {
|
|
24
|
+
email: user.email,
|
|
25
|
+
password: 'bad-password',
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
end
|
|
29
|
+
end
|
data/test/support/mongoid.yml
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class TestCompatibility < ActiveSupport::TestCase
|
|
4
|
+
test 'can access ActiveRecord namespace' do
|
|
5
|
+
skip unless DEVISE_ORM == :active_record
|
|
6
|
+
assert_nothing_raised { User.new.some_method_calling_active_record }
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
test 'can access Mongoid namespace' do
|
|
10
|
+
skip unless DEVISE_ORM == :mongoid
|
|
11
|
+
assert_nothing_raised { User.new.some_method_calling_mongoid }
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -37,6 +37,12 @@ class PasswordComplexityValidatorTest < Minitest::Test
|
|
|
37
37
|
assert(ModelWithPassword.new('aaa1').valid?)
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
+
def test_enforces_digits
|
|
41
|
+
ModelWithPassword.validates :password, 'devise_security/password_complexity': { digits: 2 }
|
|
42
|
+
refute(ModelWithPassword.new('aaa1').valid?)
|
|
43
|
+
assert(ModelWithPassword.new('aa12').valid?)
|
|
44
|
+
end
|
|
45
|
+
|
|
40
46
|
def test_enforces_lower
|
|
41
47
|
ModelWithPassword.validates :password, 'devise_security/password_complexity': { lower: 1 }
|
|
42
48
|
refute(ModelWithPassword.new('AAAA').valid?)
|
|
@@ -49,6 +55,12 @@ class PasswordComplexityValidatorTest < Minitest::Test
|
|
|
49
55
|
assert(ModelWithPassword.new('aaa!').valid?)
|
|
50
56
|
end
|
|
51
57
|
|
|
58
|
+
def test_enforces_symbols
|
|
59
|
+
ModelWithPassword.validates :password, 'devise_security/password_complexity': { symbols: 2 }
|
|
60
|
+
refute(ModelWithPassword.new('aaa!').valid?)
|
|
61
|
+
assert(ModelWithPassword.new('aa!?').valid?)
|
|
62
|
+
end
|
|
63
|
+
|
|
52
64
|
def test_enforces_combination
|
|
53
65
|
ModelWithPassword.validates :password, 'devise_security/password_complexity': { lower: 1, upper: 1, digit: 1, symbol: 1 }
|
|
54
66
|
refute(ModelWithPassword.new('abcd').valid?)
|
data/test/test_helper.rb
CHANGED
|
@@ -1,20 +1,29 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
ENV['RAILS_ENV'] ||= 'test'
|
|
4
|
-
DEVISE_ORM = ENV.fetch('DEVISE_ORM', 'active_record').to_sym
|
|
5
4
|
|
|
6
5
|
require 'simplecov'
|
|
7
6
|
SimpleCov.start do
|
|
8
7
|
add_filter 'gemfiles'
|
|
8
|
+
add_filter 'test/dummy/db'
|
|
9
|
+
add_group 'ActiveRecord', 'active_record'
|
|
10
|
+
add_group 'Expirable', /(?<!password_)expirable/
|
|
11
|
+
add_group 'Mongoid', 'mongoid'
|
|
12
|
+
add_group 'Paranoid Verifiable', 'paranoid_verification'
|
|
13
|
+
add_group 'Password Archivable', /password_archivable|old_password/
|
|
14
|
+
add_group 'Password Expirable', /password_expirable|password_expired/
|
|
15
|
+
add_group 'Secure Validateable', 'secure_validatable'
|
|
16
|
+
add_group 'Security Questionable', 'security_question'
|
|
17
|
+
add_group 'Session Limitable', 'session_limitable'
|
|
9
18
|
add_group 'Tests', 'test'
|
|
10
|
-
add_group 'Password Archivable', 'password_archivable'
|
|
11
|
-
add_group 'Password Expirable', 'password_expirable'
|
|
12
19
|
end
|
|
13
20
|
|
|
14
21
|
if ENV['CI']
|
|
15
|
-
require '
|
|
16
|
-
|
|
17
|
-
|
|
22
|
+
require 'simplecov'
|
|
23
|
+
require 'simplecov-lcov'
|
|
24
|
+
SimpleCov.formatter = SimpleCov::Formatter::LcovFormatter
|
|
25
|
+
SimpleCov::Formatter::LcovFormatter.config.report_with_single_file = true
|
|
26
|
+
SimpleCov.start
|
|
18
27
|
end
|
|
19
28
|
|
|
20
29
|
require 'pry'
|
|
@@ -25,6 +34,12 @@ require 'devise-security'
|
|
|
25
34
|
require 'database_cleaner'
|
|
26
35
|
require "orm/#{DEVISE_ORM}"
|
|
27
36
|
|
|
37
|
+
# Controller testing is the way that Devise itself tests the functionality of
|
|
38
|
+
# controller, even though it has been deprecated in favor of request tests.
|
|
39
|
+
require 'rails-controller-testing'
|
|
40
|
+
Rails::Controller::Testing.install
|
|
41
|
+
require 'support/integration_helpers'
|
|
42
|
+
|
|
28
43
|
class Minitest::Test
|
|
29
44
|
def before_setup
|
|
30
45
|
DatabaseCleaner.start
|
|
@@ -11,13 +11,23 @@ class TestInstallGenerator < Rails::Generators::TestCase
|
|
|
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
|
|
@@ -82,4 +82,80 @@ class TestSecureValidatable < ActiveSupport::TestCase
|
|
|
82
82
|
refute user.valid?
|
|
83
83
|
assert_equal DEVISE_ORM == :active_record ? ['Email has already been taken'] : ['Email is already taken'], user.errors.full_messages
|
|
84
84
|
end
|
|
85
|
+
|
|
86
|
+
test 'password can not equal email for new user' do
|
|
87
|
+
msg = 'Password must be different than the email.'
|
|
88
|
+
user = User.create email: 'bob@microsoft.com', password: 'bob@microsoft.com', password_confirmation: 'bob@microsoft.com'
|
|
89
|
+
refute user.valid?
|
|
90
|
+
assert_includes(user.errors.full_messages, msg)
|
|
91
|
+
assert_raises(ORMInvalidRecordException) { user.save! }
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
test 'password can not equal case sensitive version of email for new user' do
|
|
95
|
+
msg = 'Password must be different than the email.'
|
|
96
|
+
user = User.create email: 'bob@microsoft.com', password: 'BoB@microsoft.com', password_confirmation: 'BoB@microsoft.com'
|
|
97
|
+
refute user.valid?
|
|
98
|
+
assert_includes(user.errors.full_messages, msg)
|
|
99
|
+
assert_raises(ORMInvalidRecordException) { user.save! }
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
test 'password can not equal email with spaces for new user' do
|
|
103
|
+
msg = 'Password must be different than the email.'
|
|
104
|
+
user = User.create email: 'bob@microsoft.com', password: 'bob@microsoft.com ', password_confirmation: 'bob@microsoft.com '
|
|
105
|
+
refute user.valid?
|
|
106
|
+
assert_includes(user.errors.full_messages, msg)
|
|
107
|
+
assert_raises(ORMInvalidRecordException) { user.save! }
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
test 'password can not equal case sensitive version of email with spaces for new user' do
|
|
111
|
+
msg = 'Password must be different than the email.'
|
|
112
|
+
user = User.create email: 'bob@microsoft.com', password: ' BoB@microsoft.com ', password_confirmation: ' BoB@microsoft.com '
|
|
113
|
+
refute user.valid?
|
|
114
|
+
assert_includes(user.errors.full_messages, msg)
|
|
115
|
+
assert_raises(ORMInvalidRecordException) { user.save! }
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
test 'password can not equal email for existing user' do
|
|
119
|
+
user = User.create email: 'bob@microsoft.com', password: 'pAs5W0rd!Is5e6Ure', password_confirmation: 'pAs5W0rd!Is5e6Ure'
|
|
120
|
+
|
|
121
|
+
msg = 'Password must be different than the email.'
|
|
122
|
+
user.password = 'bob@microsoft.com'
|
|
123
|
+
user.password_confirmation = 'bob@microsoft.com'
|
|
124
|
+
refute user.valid?
|
|
125
|
+
assert_includes(user.errors.full_messages, msg)
|
|
126
|
+
assert_raises(ORMInvalidRecordException) { user.save! }
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
test 'password can not equal case sensitive version of email for existing user' do
|
|
130
|
+
user = User.create email: 'bob@microsoft.com', password: 'pAs5W0rd!Is5e6Ure', password_confirmation: 'pAs5W0rd!Is5e6Ure'
|
|
131
|
+
|
|
132
|
+
msg = 'Password must be different than the email.'
|
|
133
|
+
user.password = 'BoB@microsoft.com'
|
|
134
|
+
user.password_confirmation = 'BoB@microsoft.com'
|
|
135
|
+
refute user.valid?
|
|
136
|
+
assert_includes(user.errors.full_messages, msg)
|
|
137
|
+
assert_raises(ORMInvalidRecordException) { user.save! }
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
test 'password can not equal email with spaces for existing user' do
|
|
141
|
+
user = User.create email: 'bob@microsoft.com', password: 'pAs5W0rd!Is5e6Ure', password_confirmation: 'pAs5W0rd!Is5e6Ure'
|
|
142
|
+
|
|
143
|
+
msg = 'Password must be different than the email.'
|
|
144
|
+
user.password = 'bob@microsoft.com '
|
|
145
|
+
user.password_confirmation = 'bob@microsoft.com '
|
|
146
|
+
refute user.valid?
|
|
147
|
+
assert_includes(user.errors.full_messages, msg)
|
|
148
|
+
assert_raises(ORMInvalidRecordException) { user.save! }
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
test 'password can not equal case sensitive version of email with spaces for existing user' do
|
|
152
|
+
user = User.create email: 'bob@microsoft.com', password: 'pAs5W0rd!Is5e6Ure', password_confirmation: 'pAs5W0rd!Is5e6Ure'
|
|
153
|
+
|
|
154
|
+
msg = 'Password must be different than the email.'
|
|
155
|
+
user.password = ' BoB@microsoft.com '
|
|
156
|
+
user.password_confirmation = ' BoB@microsoft.com '
|
|
157
|
+
refute user.valid?
|
|
158
|
+
assert_includes(user.errors.full_messages, msg)
|
|
159
|
+
assert_raises(ORMInvalidRecordException) { user.save! }
|
|
160
|
+
end
|
|
85
161
|
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
|
|
5
|
+
class TestSessionLimitable < ActiveSupport::TestCase
|
|
6
|
+
class ModifiedUser < User
|
|
7
|
+
def skip_session_limitable?
|
|
8
|
+
true
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
test 'check is not skipped by default' do
|
|
13
|
+
user = User.create email: 'bob@microsoft.com', password: 'password1', password_confirmation: 'password1'
|
|
14
|
+
assert_equal(false, user.skip_session_limitable?)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
test 'default check can be overridden by record instance' do
|
|
18
|
+
modified_user = ModifiedUser.create email: 'bob2@microsoft.com', password: 'password1', password_confirmation: 'password1'
|
|
19
|
+
assert_equal(true, modified_user.skip_session_limitable?)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class SessionLimitableUser < User
|
|
23
|
+
devise :session_limitable
|
|
24
|
+
include ::Mongoid::Mappings if DEVISE_ORM == :mongoid
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
test 'includes Devise::Models::Compatibility' do
|
|
28
|
+
assert_kind_of(Devise::Models::Compatibility, SessionLimitableUser.new)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
test '#update_unique_session_id!(value) updates valid record' do
|
|
32
|
+
user = User.create! password: 'passWord1', password_confirmation: 'passWord1', email: 'bob@microsoft.com'
|
|
33
|
+
assert user.persisted?
|
|
34
|
+
assert_nil user.unique_session_id
|
|
35
|
+
user.update_unique_session_id!('unique_value')
|
|
36
|
+
user.reload
|
|
37
|
+
assert_equal user.unique_session_id, 'unique_value'
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
test '#update_unique_session_id!(value) updates invalid record atomically' do
|
|
41
|
+
user = User.create! password: 'passWord1', password_confirmation: 'passWord1', email: 'bob@microsoft.com'
|
|
42
|
+
assert user.persisted?
|
|
43
|
+
user.email = ''
|
|
44
|
+
assert user.invalid?
|
|
45
|
+
assert_nil user.unique_session_id
|
|
46
|
+
user.update_unique_session_id!('unique_value')
|
|
47
|
+
user.reload
|
|
48
|
+
assert_equal user.email, 'bob@microsoft.com'
|
|
49
|
+
assert_equal user.unique_session_id, 'unique_value'
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
test '#update_unique_session_id!(value) raises an exception on an unpersisted record' do
|
|
53
|
+
user = User.create
|
|
54
|
+
assert !user.persisted?
|
|
55
|
+
assert_raises(Devise::Models::Compatibility::NotPersistedError) { user.update_unique_session_id!('unique_value') }
|
|
56
|
+
end
|
|
57
|
+
end
|