devise-security 0.13.0 → 0.14.0.rc1
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/.codeclimate.yml +1 -1
- data/.gitignore +1 -0
- data/.ruby-version +1 -1
- data/.travis.yml +30 -12
- data/Appraisals +21 -5
- data/Gemfile +8 -1
- data/README.md +47 -7
- data/app/views/devise/paranoid_verification_code/show.html.erb +1 -1
- data/app/views/devise/password_expired/show.html.erb +1 -1
- data/config/locales/de.yml +11 -11
- data/config/locales/fr.yml +13 -13
- data/config/locales/ja.yml +29 -0
- data/devise-security.gemspec +12 -6
- data/gemfiles/rails_4.2_stable.gemfile +9 -1
- data/gemfiles/rails_5.0_stable.gemfile +8 -1
- data/gemfiles/rails_5.1_stable.gemfile +8 -1
- data/gemfiles/{rails_5.2.0.gemfile → rails_5.2_stable.gemfile} +8 -1
- data/gemfiles/rails_6.0_beta.gemfile +15 -0
- data/lib/devise-security.rb +2 -4
- data/lib/devise-security/models/{old_password.rb → active_record/old_password.rb} +1 -2
- data/lib/devise-security/models/compatibility.rb +6 -15
- data/lib/devise-security/models/compatibility/active_record.rb +29 -0
- data/lib/devise-security/models/compatibility/mongoid.rb +21 -0
- data/lib/devise-security/models/database_authenticatable_patch.rb +1 -1
- data/lib/devise-security/models/expirable.rb +6 -2
- data/lib/devise-security/models/mongoid/old_password.rb +21 -0
- data/lib/devise-security/models/password_archivable.rb +16 -7
- data/lib/devise-security/models/password_expirable.rb +5 -0
- data/lib/devise-security/models/secure_validatable.rb +2 -2
- data/lib/devise-security/orm/mongoid.rb +7 -0
- data/lib/devise-security/patches/controller_security_question.rb +1 -1
- data/lib/devise-security/version.rb +1 -1
- data/lib/generators/devise_security/install_generator.rb +1 -1
- data/test/dummy/app/models/application_record.rb +8 -2
- data/test/dummy/app/models/application_user_record.rb +11 -0
- data/test/dummy/app/models/captcha_user.rb +5 -2
- data/test/dummy/app/models/mongoid/confirmable_fields.rb +13 -0
- data/test/dummy/app/models/mongoid/database_authenticable_fields.rb +17 -0
- data/test/dummy/app/models/mongoid/expirable_fields.rb +11 -0
- data/test/dummy/app/models/mongoid/lockable_fields.rb +13 -0
- data/test/dummy/app/models/mongoid/mappings.rb +13 -0
- data/test/dummy/app/models/mongoid/omniauthable_fields.rb +11 -0
- data/test/dummy/app/models/mongoid/paranoid_verification_fields.rb +10 -0
- data/test/dummy/app/models/mongoid/password_archivable_fields.rb +9 -0
- data/test/dummy/app/models/mongoid/password_expirable_fields.rb +10 -0
- data/test/dummy/app/models/mongoid/recoverable_fields.rb +11 -0
- data/test/dummy/app/models/mongoid/registerable_fields.rb +19 -0
- data/test/dummy/app/models/mongoid/rememberable_fields.rb +10 -0
- data/test/dummy/app/models/mongoid/secure_validatable_fields.rb +11 -0
- data/test/dummy/app/models/mongoid/security_questionable_fields.rb +13 -0
- data/test/dummy/app/models/mongoid/session_limitable_fields.rb +10 -0
- data/test/dummy/app/models/mongoid/timeoutable_fields.rb +9 -0
- data/test/dummy/app/models/mongoid/trackable_fields.rb +14 -0
- data/test/dummy/app/models/mongoid/validatable_fields.rb +7 -0
- data/test/dummy/app/models/secure_user.rb +5 -1
- data/test/dummy/app/models/security_question_user.rb +7 -4
- data/test/dummy/app/models/user.rb +5 -0
- data/test/dummy/app/models/widget.rb +4 -0
- data/test/dummy/app/mongoid/admin.rb +31 -0
- data/test/dummy/app/mongoid/one_user.rb +58 -0
- data/test/dummy/app/mongoid/shim.rb +25 -0
- data/test/dummy/app/mongoid/user_on_engine.rb +41 -0
- data/test/dummy/app/mongoid/user_on_main_app.rb +41 -0
- data/test/dummy/app/mongoid/user_with_validations.rb +37 -0
- data/test/dummy/app/mongoid/user_without_email.rb +35 -0
- data/test/dummy/config/application.rb +10 -7
- data/test/dummy/config/environments/test.rb +2 -2
- data/test/dummy/config/initializers/devise.rb +3 -4
- data/test/dummy/config/initializers/migration_class.rb +8 -6
- data/test/dummy/config/mongoid.yml +6 -0
- data/test/dummy/lib/shared_expirable_columns.rb +14 -0
- data/test/dummy/lib/shared_security_questions_fields.rb +16 -0
- data/test/dummy/lib/shared_user.rb +32 -0
- data/test/dummy/lib/shared_user_with_password_verification.rb +13 -0
- data/test/dummy/lib/shared_user_without_email.rb +28 -0
- data/test/dummy/lib/shared_user_without_omniauth.rb +15 -0
- data/test/dummy/lib/shared_verification_fields.rb +15 -0
- data/test/orm/active_record.rb +12 -0
- data/test/orm/mongoid.rb +12 -0
- data/test/support/mongoid.yml +6 -0
- data/test/test_helper.rb +16 -9
- data/test/test_install_generator.rb +1 -0
- data/test/test_password_archivable.rb +6 -7
- data/test/test_password_expirable.rb +3 -1
- data/test/test_secure_validatable.rb +11 -10
- data/test/test_security_question_controller.rb +9 -11
- metadata +125 -16
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "shared_user_without_email"
|
|
4
|
+
|
|
5
|
+
class UserWithoutEmail
|
|
6
|
+
include Mongoid::Document
|
|
7
|
+
include Shim
|
|
8
|
+
include SharedUserWithoutEmail
|
|
9
|
+
|
|
10
|
+
field :username, type: String
|
|
11
|
+
field :facebook_token, type: String
|
|
12
|
+
|
|
13
|
+
## Database authenticatable
|
|
14
|
+
field :email, type: String, default: ""
|
|
15
|
+
field :encrypted_password, type: String, default: ""
|
|
16
|
+
|
|
17
|
+
## Recoverable
|
|
18
|
+
field :reset_password_token, type: String
|
|
19
|
+
field :reset_password_sent_at, type: Time
|
|
20
|
+
|
|
21
|
+
## Rememberable
|
|
22
|
+
field :remember_created_at, type: Time
|
|
23
|
+
|
|
24
|
+
## Trackable
|
|
25
|
+
field :sign_in_count, type: Integer, default: 0
|
|
26
|
+
field :current_sign_in_at, type: Time
|
|
27
|
+
field :last_sign_in_at, type: Time
|
|
28
|
+
field :current_sign_in_ip, type: String
|
|
29
|
+
field :last_sign_in_ip, type: String
|
|
30
|
+
|
|
31
|
+
## Lockable
|
|
32
|
+
field :failed_attempts, type: Integer, default: 0 # Only if lock strategy is :failed_attempts
|
|
33
|
+
field :unlock_token, type: String # Only if unlock strategy is :email or :both
|
|
34
|
+
field :locked_at, type: Time
|
|
35
|
+
end
|
|
@@ -2,22 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
require File.expand_path('../boot', __FILE__)
|
|
4
4
|
|
|
5
|
+
require 'action_mailer/railtie'
|
|
6
|
+
require "action_mailer/railtie"
|
|
7
|
+
require "rails/test_unit/railtie"
|
|
8
|
+
|
|
9
|
+
Bundler.require :default, DEVISE_ORM
|
|
10
|
+
require "#{DEVISE_ORM}/railtie"
|
|
11
|
+
|
|
5
12
|
require 'rails/all'
|
|
6
13
|
require 'devise-security'
|
|
7
14
|
|
|
8
|
-
if defined?(Bundler)
|
|
9
|
-
# If you precompile assets before deploying to production, use this line
|
|
10
|
-
Bundler.require(*Rails.groups(assets: %w[development test]))
|
|
11
|
-
# If you want your assets lazily compiled in production, use this line
|
|
12
|
-
# Bundler.require(:default, :assets, Rails.env)
|
|
13
|
-
end
|
|
14
|
-
|
|
15
15
|
module RailsApp
|
|
16
16
|
class Application < Rails::Application
|
|
17
17
|
config.encoding = 'utf-8'
|
|
18
18
|
|
|
19
19
|
config.filter_parameters += [:password]
|
|
20
20
|
|
|
21
|
+
config.autoload_paths += ["#{config.root}/app/#{DEVISE_ORM}"]
|
|
22
|
+
config.autoload_paths += ["#{config.root}/lib"]
|
|
23
|
+
|
|
21
24
|
config.assets.enabled = true
|
|
22
25
|
|
|
23
26
|
config.assets.version = '1.0'
|
|
@@ -27,10 +27,10 @@ RailsApp::Application.configure do
|
|
|
27
27
|
|
|
28
28
|
config.active_support.test_order = :sorted
|
|
29
29
|
config.log_level = :debug
|
|
30
|
-
if Rails.gem_version >= Gem::Version.new('4.2') && Rails.gem_version < Gem::Version.new('5.0')
|
|
30
|
+
if Rails.gem_version >= Gem::Version.new('4.2') && Rails.gem_version.release < Gem::Version.new('5.0')
|
|
31
31
|
config.active_record.raise_in_transactional_callbacks = true
|
|
32
32
|
end
|
|
33
|
-
if Rails.gem_version.release >= Gem::Version.new('5.2')
|
|
33
|
+
if Rails.gem_version.release >= Gem::Version.new('5.2') && Rails.gem_version.release < Gem::Version.new('6.0')
|
|
34
34
|
config.active_record.sqlite3.represent_boolean_as_integer = true
|
|
35
35
|
end
|
|
36
36
|
end
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'rails_email_validator'
|
|
4
|
+
require "devise/orm/#{DEVISE_ORM}"
|
|
5
|
+
|
|
4
6
|
Devise.setup do |config|
|
|
5
7
|
config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com'
|
|
6
|
-
|
|
7
|
-
require 'devise/orm/active_record'
|
|
8
8
|
config.secret_key = 'f08cf11a38906f531d2dfc9a2c2d671aa0021be806c21255d4'
|
|
9
9
|
config.case_insensitive_keys = [:email]
|
|
10
|
-
|
|
11
10
|
config.strip_whitespace_keys = [:email]
|
|
12
|
-
|
|
13
11
|
config.password_complexity = {
|
|
14
12
|
digit: 1,
|
|
15
13
|
lower: 1,
|
|
16
14
|
upper: 1,
|
|
17
15
|
}
|
|
16
|
+
config.password_length = 7..128
|
|
18
17
|
end
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
if DEVISE_ORM == :active_record
|
|
4
|
+
MIGRATION_CLASS =
|
|
5
|
+
if Rails.gem_version >= Gem::Version.new('5.0')
|
|
6
|
+
ActiveRecord::Migration[Rails.version.to_f]
|
|
7
|
+
else
|
|
8
|
+
ActiveRecord::Migration
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'shared_user'
|
|
3
|
+
|
|
4
|
+
module SharedVerificationColumns
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
include SharedUser
|
|
9
|
+
devise :expirable
|
|
10
|
+
|
|
11
|
+
field :expired_at, type: Time
|
|
12
|
+
field :last_activity_at, type: Time
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'shared_user'
|
|
3
|
+
|
|
4
|
+
module SharedSecurityQuestionsFields
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
include SharedUser
|
|
9
|
+
devise :lockable, :security_questionable
|
|
10
|
+
|
|
11
|
+
field :locked_at, type: Time
|
|
12
|
+
field :unlock_token, type: String
|
|
13
|
+
field :security_question_id, type: Integer
|
|
14
|
+
field :security_question_answer, type: String
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SharedUser
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
included do
|
|
7
|
+
devise :database_authenticatable, :confirmable, :lockable, :recoverable,
|
|
8
|
+
:registerable, :rememberable, :timeoutable,
|
|
9
|
+
:trackable, :secure_validatable, :omniauthable, :validatable, password_length: 7..72,
|
|
10
|
+
reconfirmable: false
|
|
11
|
+
|
|
12
|
+
attr_accessor :other_key
|
|
13
|
+
|
|
14
|
+
# They need to be included after Devise is called.
|
|
15
|
+
extend ExtendMethods
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def raw_confirmation_token
|
|
19
|
+
@raw_confirmation_token
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
module ExtendMethods
|
|
23
|
+
def new_with_session(params, session)
|
|
24
|
+
super.tap do |user|
|
|
25
|
+
if data = session["devise.facebook_data"]
|
|
26
|
+
user.email = data["email"]
|
|
27
|
+
user.confirmed_at = Time.zone.now
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SharedUserWithoutEmail
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
included do
|
|
7
|
+
# NOTE: This is missing :validatable and :confirmable, as they both require
|
|
8
|
+
# an email field at the moment. It is also missing :omniauthable because that
|
|
9
|
+
# adds unnecessary complexity to the setup
|
|
10
|
+
devise :database_authenticatable, :lockable, :recoverable,
|
|
11
|
+
:registerable, :rememberable, :timeoutable,
|
|
12
|
+
:trackable
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# This test stub is a bit rubbish because it's tied very closely to the
|
|
16
|
+
# implementation where we care about this one case. However, completely
|
|
17
|
+
# removing the email field breaks "recoverable" tests completely, so we are
|
|
18
|
+
# just taking the approach here that "email" is something that is a not an
|
|
19
|
+
# ActiveRecord field.
|
|
20
|
+
def email_changed?
|
|
21
|
+
raise NoMethodError
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def respond_to?(method_name, include_all=false)
|
|
25
|
+
return false if method_name.to_sym == :email_changed?
|
|
26
|
+
super(method_name, include_all)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SharedUserWithoutOmniauth
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
included do
|
|
7
|
+
devise :database_authenticatable, :confirmable, :lockable, :recoverable,
|
|
8
|
+
:registerable, :rememberable, :timeoutable,
|
|
9
|
+
:trackable, :validatable, reconfirmable: false
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def raw_confirmation_token
|
|
13
|
+
@raw_confirmation_token
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'shared_user'
|
|
3
|
+
|
|
4
|
+
module SharedVerificationFields
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
include SharedUser
|
|
9
|
+
devise :paranoid_verification
|
|
10
|
+
|
|
11
|
+
field :paranoid_verified_at, type: Time
|
|
12
|
+
field :paranoid_verification_attempt, type: Integer, default: 0
|
|
13
|
+
field :paranoid_verification_code, type: String
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require 'active_record'
|
|
2
|
+
|
|
3
|
+
ActiveRecord::Migration.verbose = false
|
|
4
|
+
ActiveRecord::Base.logger = Logger.new(nil)
|
|
5
|
+
if Rails.gem_version >= Gem::Version.new('5.2.0')
|
|
6
|
+
ActiveRecord::MigrationContext.new(File.expand_path('../../dummy/db/migrate', __FILE__)).migrate
|
|
7
|
+
else
|
|
8
|
+
ActiveRecord::Migrator.migrate(File.expand_path('../../dummy/db/migrate', __FILE__))
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
DatabaseCleaner[:active_record].strategy = :transaction
|
|
12
|
+
ORMInvalidRecordException = ActiveRecord::RecordInvalid
|
data/test/orm/mongoid.rb
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'mongoid/version'
|
|
4
|
+
|
|
5
|
+
Mongoid.configure do |config|
|
|
6
|
+
config.load!('test/support/mongoid.yml', Rails.env)
|
|
7
|
+
config.use_utc = true
|
|
8
|
+
config.include_root_in_json = true
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
DatabaseCleaner[:mongoid].strategy = :truncation
|
|
12
|
+
ORMInvalidRecordException = Mongoid::Errors::Validations
|
data/test/test_helper.rb
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
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
|
|
4
5
|
|
|
5
6
|
require 'simplecov'
|
|
6
7
|
SimpleCov.start do
|
|
7
8
|
add_filter 'gemfiles'
|
|
8
9
|
add_group 'Tests', 'test'
|
|
9
|
-
add_group 'Password
|
|
10
|
+
add_group 'Password Archivable', 'password_archivable'
|
|
11
|
+
add_group 'Password Expirable', 'password_expirable'
|
|
10
12
|
end
|
|
11
13
|
|
|
12
14
|
if ENV['CI']
|
|
@@ -15,17 +17,22 @@ if ENV['CI']
|
|
|
15
17
|
Coveralls.wear!
|
|
16
18
|
end
|
|
17
19
|
|
|
20
|
+
require 'pry'
|
|
18
21
|
require 'dummy/config/environment'
|
|
19
22
|
require 'minitest/autorun'
|
|
20
23
|
require 'rails/test_help'
|
|
21
|
-
|
|
22
24
|
require 'devise-security'
|
|
23
|
-
require '
|
|
25
|
+
require 'database_cleaner'
|
|
26
|
+
require "orm/#{DEVISE_ORM}"
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
class Minitest::Test
|
|
29
|
+
def before_setup
|
|
30
|
+
DatabaseCleaner.start
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def after_teardown
|
|
34
|
+
DatabaseCleaner.clean
|
|
35
|
+
end
|
|
31
36
|
end
|
|
37
|
+
|
|
38
|
+
DatabaseCleaner.clean
|
|
@@ -17,6 +17,7 @@ class TestInstallGenerator < Rails::Generators::TestCase
|
|
|
17
17
|
assert_file 'config/locales/devise.security_extension.es.yml'
|
|
18
18
|
assert_file 'config/locales/devise.security_extension.fr.yml'
|
|
19
19
|
assert_file 'config/locales/devise.security_extension.it.yml'
|
|
20
|
+
assert_file 'config/locales/devise.security_extension.ja.yml'
|
|
20
21
|
assert_file 'config/locales/devise.security_extension.tr.yml'
|
|
21
22
|
end
|
|
22
23
|
end
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require 'test_helper'
|
|
4
4
|
|
|
5
5
|
class TestPasswordArchivable < ActiveSupport::TestCase
|
|
6
|
+
|
|
6
7
|
setup do
|
|
7
8
|
Devise.password_archiving_count = 2
|
|
8
9
|
end
|
|
@@ -19,7 +20,7 @@ class TestPasswordArchivable < ActiveSupport::TestCase
|
|
|
19
20
|
|
|
20
21
|
test 'cannot use same password' do
|
|
21
22
|
user = User.create email: 'bob@microsoft.com', password: 'Password1', password_confirmation: 'Password1'
|
|
22
|
-
assert_raises(
|
|
23
|
+
assert_raises(ORMInvalidRecordException) { set_password(user, 'Password1') }
|
|
23
24
|
end
|
|
24
25
|
|
|
25
26
|
test 'indirectly saving associated user does not cause deprecation warning' do
|
|
@@ -37,17 +38,15 @@ class TestPasswordArchivable < ActiveSupport::TestCase
|
|
|
37
38
|
assert_equal 0, OldPassword.count
|
|
38
39
|
end
|
|
39
40
|
|
|
40
|
-
test 'cannot
|
|
41
|
+
test 'cannot reuse archived passwords' do
|
|
41
42
|
assert_equal 2, Devise.password_archiving_count
|
|
42
43
|
|
|
43
44
|
user = User.create! email: 'bob@microsoft.com', password: 'Password1', password_confirmation: 'Password1'
|
|
44
45
|
assert_equal 0, OldPassword.count
|
|
45
|
-
|
|
46
46
|
set_password(user, 'Password2')
|
|
47
47
|
assert_equal 1, OldPassword.count
|
|
48
48
|
|
|
49
|
-
assert_raises(
|
|
50
|
-
|
|
49
|
+
assert_raises(ORMInvalidRecordException) { set_password(user, 'Password1') }
|
|
51
50
|
set_password(user, 'Password3')
|
|
52
51
|
assert_equal 2, OldPassword.count
|
|
53
52
|
|
|
@@ -70,8 +69,8 @@ class TestPasswordArchivable < ActiveSupport::TestCase
|
|
|
70
69
|
|
|
71
70
|
assert set_password(user, 'Password2')
|
|
72
71
|
|
|
73
|
-
assert_raises(
|
|
72
|
+
assert_raises(ORMInvalidRecordException) { set_password(user, 'Password2') }
|
|
74
73
|
|
|
75
|
-
assert_raises(
|
|
74
|
+
assert_raises(ORMInvalidRecordException) { set_password(user, 'Password1') }
|
|
76
75
|
end
|
|
77
76
|
end
|
|
@@ -58,12 +58,14 @@ class TestPasswordArchivable < ActiveSupport::TestCase
|
|
|
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))
|
|
62
|
+
original_password_changed_at = user.password_changed_at
|
|
61
63
|
user.expire_password!
|
|
62
64
|
assert user.password_change_requested?
|
|
63
65
|
user.password = "NewPassword1"
|
|
64
66
|
user.password_confirmation = "NewPassword1"
|
|
65
67
|
user.save
|
|
66
|
-
assert user.
|
|
68
|
+
assert user.password_changed_at > original_password_changed_at
|
|
67
69
|
refute user.password_change_requested?
|
|
68
70
|
end
|
|
69
71
|
|
|
@@ -4,9 +4,10 @@ require 'test_helper'
|
|
|
4
4
|
require 'rails_email_validator'
|
|
5
5
|
|
|
6
6
|
class TestSecureValidatable < ActiveSupport::TestCase
|
|
7
|
-
class User <
|
|
7
|
+
class User < ApplicationRecord
|
|
8
8
|
devise :database_authenticatable, :password_archivable,
|
|
9
9
|
:paranoid_verification, :password_expirable, :secure_validatable
|
|
10
|
+
include ::Mongoid::Mappings if DEVISE_ORM == :mongoid
|
|
10
11
|
end
|
|
11
12
|
|
|
12
13
|
test 'email cannot be blank' do
|
|
@@ -15,7 +16,7 @@ class TestSecureValidatable < ActiveSupport::TestCase
|
|
|
15
16
|
|
|
16
17
|
assert_equal(false, user.valid?)
|
|
17
18
|
assert_equal([msg], user.errors.full_messages)
|
|
18
|
-
assert_raises(
|
|
19
|
+
assert_raises(ORMInvalidRecordException) do
|
|
19
20
|
user.save!
|
|
20
21
|
end
|
|
21
22
|
end
|
|
@@ -25,7 +26,7 @@ class TestSecureValidatable < ActiveSupport::TestCase
|
|
|
25
26
|
user = User.create email: 'bob', password: 'passWord1', password_confirmation: 'passWord1'
|
|
26
27
|
assert_equal(false, user.valid?)
|
|
27
28
|
assert_equal([msg], user.errors.full_messages)
|
|
28
|
-
assert_raises(
|
|
29
|
+
assert_raises(ORMInvalidRecordException) do
|
|
29
30
|
user.save!
|
|
30
31
|
end
|
|
31
32
|
end
|
|
@@ -35,7 +36,7 @@ class TestSecureValidatable < ActiveSupport::TestCase
|
|
|
35
36
|
user = User.create email: 'bob@@foo.tv', password: 'password1', password_confirmation: 'password1'
|
|
36
37
|
assert_equal(false, user.valid?)
|
|
37
38
|
assert_equal(msgs, user.errors.full_messages)
|
|
38
|
-
assert_raises(
|
|
39
|
+
assert_raises(ORMInvalidRecordException) { user.save! }
|
|
39
40
|
end
|
|
40
41
|
|
|
41
42
|
test 'password must have capital letter' do
|
|
@@ -43,7 +44,7 @@ class TestSecureValidatable < ActiveSupport::TestCase
|
|
|
43
44
|
user = User.create email: 'bob@microsoft.com', password: 'password1', password_confirmation: 'password1'
|
|
44
45
|
assert_equal(false, user.valid?)
|
|
45
46
|
assert_equal(msgs, user.errors.full_messages)
|
|
46
|
-
assert_raises(
|
|
47
|
+
assert_raises(ORMInvalidRecordException) { user.save! }
|
|
47
48
|
end
|
|
48
49
|
|
|
49
50
|
test 'password must have lowercase letter' do
|
|
@@ -51,7 +52,7 @@ class TestSecureValidatable < ActiveSupport::TestCase
|
|
|
51
52
|
user = User.create email: 'bob@microsoft.com', password: 'PASSWORD1', password_confirmation: 'PASSWORD1'
|
|
52
53
|
assert_equal(false, user.valid?)
|
|
53
54
|
assert_equal([msg], user.errors.full_messages)
|
|
54
|
-
assert_raises(
|
|
55
|
+
assert_raises(ORMInvalidRecordException) { user.save! }
|
|
55
56
|
end
|
|
56
57
|
|
|
57
58
|
test 'password must have number' do
|
|
@@ -59,15 +60,15 @@ class TestSecureValidatable < ActiveSupport::TestCase
|
|
|
59
60
|
user = User.create email: 'bob@microsoft.com', password: 'PASSword', password_confirmation: 'PASSword'
|
|
60
61
|
assert_equal(false, user.valid?)
|
|
61
62
|
assert_equal([msg], user.errors.full_messages)
|
|
62
|
-
assert_raises(
|
|
63
|
+
assert_raises(ORMInvalidRecordException) { user.save! }
|
|
63
64
|
end
|
|
64
65
|
|
|
65
66
|
test 'password must have minimum length' do
|
|
66
|
-
msg = 'Password is too short (minimum is
|
|
67
|
+
msg = 'Password is too short (minimum is 7 characters)'
|
|
67
68
|
user = User.create email: 'bob@microsoft.com', password: 'Pa3zZ', password_confirmation: 'Pa3zZ'
|
|
68
69
|
assert_equal(false, user.valid?)
|
|
69
70
|
assert_equal([msg], user.errors.full_messages)
|
|
70
|
-
assert_raises(
|
|
71
|
+
assert_raises(ORMInvalidRecordException) { user.save! }
|
|
71
72
|
end
|
|
72
73
|
|
|
73
74
|
test 'duplicate email validation message is added only once' do
|
|
@@ -79,6 +80,6 @@ class TestSecureValidatable < ActiveSupport::TestCase
|
|
|
79
80
|
SecureUser.create!(options)
|
|
80
81
|
user = SecureUser.new(options)
|
|
81
82
|
refute user.valid?
|
|
82
|
-
assert_equal ['Email has already been taken'], user.errors.full_messages
|
|
83
|
+
assert_equal DEVISE_ORM == :active_record ? ['Email has already been taken'] : ['Email is already taken'], user.errors.full_messages
|
|
83
84
|
end
|
|
84
85
|
end
|