devise-security 0.14.3 → 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 +123 -59
- 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 +6 -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 +21 -11
- 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 +8 -1
- 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/controllers/test_password_expired_controller.rb +83 -19
- data/test/controllers/test_security_question_controller.rb +16 -40
- data/test/dummy/app/assets/config/manifest.js +3 -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 +3 -3
- 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/orm/active_record.rb +4 -1
- data/test/orm/mongoid.rb +2 -1
- data/test/support/integration_helpers.rb +15 -33
- data/test/support/mongoid.yml +1 -1
- data/test/test_complexity_validator.rb +12 -0
- data/test/test_helper.rb +10 -3
- data/test/test_install_generator.rb +11 -1
- data/test/test_secure_validatable.rb +76 -0
- data/test/test_session_limitable.rb +17 -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 +145 -132
- 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/schema.rb +0 -66
- data/test/dummy/app/models/.gitkeep +0 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
zh_CN:
|
2
|
+
errors:
|
3
|
+
messages:
|
4
|
+
taken_in_past: '曾被使用过。'
|
5
|
+
equal_to_current_password: '必须与当前密码不同。'
|
6
|
+
equal_to_email: '必须与电子邮件地址不同。'
|
7
|
+
password_complexity:
|
8
|
+
digit:
|
9
|
+
one: 必须包含至少1个数字
|
10
|
+
other: 必须包含至少%{count}个数字
|
11
|
+
lower:
|
12
|
+
one: 必须包含至少1个小写字母
|
13
|
+
other: 必须包含至少%{count}个小写字母
|
14
|
+
symbol:
|
15
|
+
one: 必须包含至少1个特殊符号(!"#$%&'()*+,-./:;<=>?@[\]^_‘{|}~)
|
16
|
+
other: 必须包含至少%{count}个特殊符号(!"#$%&'()*+,-./:;<=>?@[\]^_‘{|}~)
|
17
|
+
upper:
|
18
|
+
one: 必须包含至少1个大写字母
|
19
|
+
other: 必须包含至少%{count}个大写字母
|
20
|
+
devise:
|
21
|
+
invalid_captcha: '验证码无效。'
|
22
|
+
invalid_security_question: '安全问题答案无效。'
|
23
|
+
paranoid_verify:
|
24
|
+
code_required: '请输入我们支持团队提供的代码'
|
25
|
+
paranoid_verification_code:
|
26
|
+
show:
|
27
|
+
submit_verification_code: 提交验证码
|
28
|
+
verification_code: 验证码
|
29
|
+
submit: 提交
|
30
|
+
password_expired:
|
31
|
+
updated: '你的新密码已保存。'
|
32
|
+
change_required: '你的密码已过期,请更新密码。'
|
33
|
+
show:
|
34
|
+
renew_your_password: 更新你的密码
|
35
|
+
current_password: 当前密码
|
36
|
+
new_password: 新密码
|
37
|
+
new_password_confirmation: 确认新密码
|
38
|
+
change_my_password: 更改密码
|
39
|
+
failure:
|
40
|
+
session_limited: '你的登录凭据已在另一个浏览器上被使用。请重新登录以在此浏览器继续。'
|
41
|
+
expired: '由于不活跃,你的账户已过期。请联系站点管理员。'
|
@@ -0,0 +1,41 @@
|
|
1
|
+
zh_TW:
|
2
|
+
errors:
|
3
|
+
messages:
|
4
|
+
taken_in_past: '曾被使用過。'
|
5
|
+
equal_to_current_password: '必須與目前密碼不同。'
|
6
|
+
equal_to_email: '必須與電子郵件地址不同。'
|
7
|
+
password_complexity:
|
8
|
+
digit:
|
9
|
+
one: 必須包含至少一個數字
|
10
|
+
other: 必須包含至少 %{count} 個數字
|
11
|
+
lower:
|
12
|
+
one: 必須包含至少一個小寫字母
|
13
|
+
other: 必須包含至少 %{count} 個小寫字母
|
14
|
+
symbol:
|
15
|
+
one: 必須包含至少一個特殊符號
|
16
|
+
other: 必須包含至少 %{count} 個特殊符號
|
17
|
+
upper:
|
18
|
+
one: 必須包含至少一個大寫字母
|
19
|
+
other: 必須包含至少 %{count} 個大寫字母
|
20
|
+
devise:
|
21
|
+
invalid_captcha: '輸入的驗證碼無效。'
|
22
|
+
invalid_security_question: '安全問題答案無效。'
|
23
|
+
paranoid_verify:
|
24
|
+
code_required: '請輸入由我們客服團隊提供的代碼'
|
25
|
+
paranoid_verification_code:
|
26
|
+
show:
|
27
|
+
submit_verification_code: 送出驗證碼
|
28
|
+
verification_code: 驗證碼
|
29
|
+
submit: 送出
|
30
|
+
password_expired:
|
31
|
+
updated: '你的新密碼已儲存'
|
32
|
+
change_required: '你的密碼已經過期,請更新密碼。'
|
33
|
+
show:
|
34
|
+
renew_your_password: 更新你的密碼
|
35
|
+
current_password: 目前密碼
|
36
|
+
new_password: 新密碼
|
37
|
+
new_password_confirmation: 確認新密碼
|
38
|
+
change_my_password: 更改我的密碼
|
39
|
+
failure:
|
40
|
+
session_limited: '你的登入憑證已在另一個瀏覽器上被使用,請重新登入以在此瀏覽器繼續使用。'
|
41
|
+
expired: '你的帳號因過久沒使用而已經過期,請洽網站管理員。'
|
data/lib/devise-security.rb
CHANGED
@@ -79,11 +79,14 @@ module Devise
|
|
79
79
|
# paranoid_verification will regenerate verifacation code after faild attempt
|
80
80
|
mattr_accessor :paranoid_code_regenerate_after_attempt
|
81
81
|
@@paranoid_code_regenerate_after_attempt = 10
|
82
|
+
|
83
|
+
# Whether to allow passwords that are equal (case insensitive) to the email
|
84
|
+
mattr_accessor :allow_passwords_equal_to_email
|
85
|
+
@@allow_passwords_equal_to_email = false
|
82
86
|
end
|
83
87
|
|
84
|
-
#
|
88
|
+
# a security extension for devise
|
85
89
|
module DeviseSecurity
|
86
|
-
autoload :Schema, 'devise-security/schema'
|
87
90
|
autoload :Patches, 'devise-security/patches'
|
88
91
|
|
89
92
|
module Controllers
|
@@ -104,6 +107,6 @@ Devise.add_module :paranoid_verification, controller: :paranoid_verification_cod
|
|
104
107
|
# requires
|
105
108
|
require 'devise-security/routes'
|
106
109
|
require 'devise-security/rails'
|
107
|
-
require "devise-security/orm/#{DEVISE_ORM}"
|
110
|
+
require "devise-security/orm/#{DEVISE_ORM}" if DEVISE_ORM == :mongoid
|
108
111
|
require 'devise-security/models/database_authenticatable_patch'
|
109
112
|
require 'devise-security/models/paranoid_verification'
|
@@ -40,71 +40,80 @@ module DeviseSecurity
|
|
40
40
|
|
41
41
|
# controller instance methods
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
43
|
+
private
|
44
|
+
|
45
|
+
# Called as a `before_action` on all actions on any controller that uses
|
46
|
+
# this helper. If the user's session is marked as having an expired
|
47
|
+
# password we double check in case it has been changed by another process,
|
48
|
+
# then redirect to the password change url.
|
49
|
+
#
|
50
|
+
# @note `Warden::Manager.after_authentication` is run AFTER this method
|
51
|
+
#
|
52
|
+
# @note Once the warden session has `'password_expired'` set to `false`,
|
53
|
+
# it will **never** be checked again until the user re-logs in.
|
54
|
+
def handle_password_change
|
55
|
+
return if warden.nil?
|
56
|
+
|
57
|
+
if !devise_controller? &&
|
58
|
+
!ignore_password_expire? &&
|
59
|
+
!request.format.nil? &&
|
60
|
+
request.format.html?
|
61
|
+
Devise.mappings.keys.flatten.any? do |scope|
|
62
|
+
if signed_in?(scope) && warden.session(scope)['password_expired'] == true
|
63
|
+
if send(:"current_#{scope}").try(:need_change_password?)
|
64
|
+
store_location_for(scope, request.original_fullpath) if request.get?
|
65
|
+
redirect_for_password_change(scope)
|
66
|
+
else
|
67
|
+
warden.session(scope)['password_expired'] = false
|
60
68
|
end
|
61
69
|
end
|
62
70
|
end
|
63
71
|
end
|
72
|
+
end
|
64
73
|
|
65
|
-
|
66
|
-
|
67
|
-
|
74
|
+
# lookup if extra (paranoid) code verification is needed
|
75
|
+
def handle_paranoid_verification
|
76
|
+
return if warden.nil?
|
68
77
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
end
|
78
|
+
if !devise_controller? && !request.format.nil? && request.format.html?
|
79
|
+
Devise.mappings.keys.flatten.any? do |scope|
|
80
|
+
if signed_in?(scope) && warden.session(scope)['paranoid_verify']
|
81
|
+
store_location_for(scope, request.original_fullpath) if request.get?
|
82
|
+
redirect_for_paranoid_verification scope
|
83
|
+
return
|
76
84
|
end
|
77
85
|
end
|
78
86
|
end
|
87
|
+
end
|
79
88
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
89
|
+
# redirect for password update with alert message
|
90
|
+
def redirect_for_password_change(scope)
|
91
|
+
redirect_to change_password_required_path_for(scope), alert: I18n.t('change_required', scope: 'devise.password_expired')
|
92
|
+
end
|
84
93
|
|
85
|
-
|
86
|
-
|
87
|
-
|
94
|
+
def redirect_for_paranoid_verification(scope)
|
95
|
+
redirect_to paranoid_verification_code_path_for(scope), alert: I18n.t('code_required', scope: 'devise.paranoid_verify')
|
96
|
+
end
|
88
97
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
98
|
+
# path for change password
|
99
|
+
def change_password_required_path_for(resource_or_scope = nil)
|
100
|
+
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
101
|
+
change_path = "#{scope}_password_expired_path"
|
102
|
+
send(change_path)
|
103
|
+
end
|
95
104
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
105
|
+
def paranoid_verification_code_path_for(resource_or_scope = nil)
|
106
|
+
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
107
|
+
change_path = "#{scope}_paranoid_verification_code_path"
|
108
|
+
send(change_path)
|
109
|
+
end
|
101
110
|
|
102
|
-
|
111
|
+
protected
|
103
112
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
113
|
+
# allow to overwrite for some special handlings
|
114
|
+
def ignore_password_expire?
|
115
|
+
false
|
116
|
+
end
|
108
117
|
end
|
109
118
|
end
|
110
119
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# @note This happens after
|
4
|
+
# {DeviseSecurity::Controller::Helpers#handle_password_change}
|
3
5
|
Warden::Manager.after_authentication do |record, warden, options|
|
4
6
|
if record.respond_to?(:need_change_password?)
|
5
7
|
warden.session(options[:scope])['password_expired'] = record.need_change_password?
|
@@ -4,10 +4,17 @@
|
|
4
4
|
# user is explicitly set (with set_user) and on authentication. Retrieving the
|
5
5
|
# user from session (:fetch) does not trigger it.
|
6
6
|
Warden::Manager.after_set_user except: :fetch do |record, warden, options|
|
7
|
-
if record.
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
if record.devise_modules.include?(:session_limitable) &&
|
8
|
+
warden.authenticated?(options[:scope]) &&
|
9
|
+
!record.skip_session_limitable?
|
10
|
+
|
11
|
+
if !options[:skip_session_limitable]
|
12
|
+
unique_session_id = Devise.friendly_token
|
13
|
+
warden.session(options[:scope])['unique_session_id'] = unique_session_id
|
14
|
+
record.update_unique_session_id!(unique_session_id)
|
15
|
+
else
|
16
|
+
warden.session(options[:scope])['devise.skip_session_limitable'] = true
|
17
|
+
end
|
11
18
|
end
|
12
19
|
end
|
13
20
|
|
@@ -17,15 +24,18 @@ end
|
|
17
24
|
# page on the next request.
|
18
25
|
Warden::Manager.after_set_user only: :fetch do |record, warden, options|
|
19
26
|
scope = options[:scope]
|
20
|
-
env = warden.request.env
|
21
27
|
|
22
|
-
if record.
|
23
|
-
|
24
|
-
|
25
|
-
|
28
|
+
if record.devise_modules.include?(:session_limitable) &&
|
29
|
+
warden.authenticated?(scope) &&
|
30
|
+
options[:store] != false
|
31
|
+
if record.unique_session_id != warden.session(scope)['unique_session_id'] &&
|
32
|
+
!record.skip_session_limitable? &&
|
33
|
+
!warden.session(scope)['devise.skip_session_limitable']
|
34
|
+
Rails.logger.warn do
|
35
|
+
'[devise-security][session_limitable] session id mismatch: '\
|
26
36
|
"expected=#{record.unique_session_id.inspect} "\
|
27
|
-
"actual=#{warden.session(scope)['unique_session_id'].inspect}"
|
28
|
-
|
37
|
+
"actual=#{warden.session(scope)['unique_session_id'].inspect}"
|
38
|
+
end
|
29
39
|
warden.raw_session.clear
|
30
40
|
warden.logout(scope)
|
31
41
|
throw :warden, scope: scope, message: :session_limited
|
@@ -92,7 +92,11 @@ module Devise::Models
|
|
92
92
|
# Update +password_changed_at+ for new records and changed passwords.
|
93
93
|
# @note called as a +before_save+ hook
|
94
94
|
def update_password_changed
|
95
|
-
|
95
|
+
if defined?(will_save_change_to_attribute?)
|
96
|
+
return unless (new_record? || will_save_change_to_encrypted_password?) && !will_save_change_to_password_changed_at?
|
97
|
+
else
|
98
|
+
return unless (new_record? || encrypted_password_changed?) && !password_changed_at_changed?
|
99
|
+
end
|
96
100
|
|
97
101
|
self.password_changed_at = Time.zone.now
|
98
102
|
end
|
@@ -55,6 +55,9 @@ module Devise
|
|
55
55
|
|
56
56
|
# don't allow use same password
|
57
57
|
validate :current_equal_password_validation
|
58
|
+
|
59
|
+
# don't allow email to equal password
|
60
|
+
validate :email_not_equal_password_validation unless allow_passwords_equal_to_email
|
58
61
|
end
|
59
62
|
end
|
60
63
|
|
@@ -70,6 +73,17 @@ module Devise
|
|
70
73
|
self.errors.add(:password, :equal_to_current_password) if dummy.valid_password?(password)
|
71
74
|
end
|
72
75
|
|
76
|
+
def email_not_equal_password_validation
|
77
|
+
return if password.blank? || (!new_record? && !will_save_change_to_encrypted_password?)
|
78
|
+
dummy = self.class.new.tap do |user|
|
79
|
+
user.password_salt = password_salt if respond_to?(:password_salt)
|
80
|
+
# whether case_insensitive_keys or strip_whitespace_keys include email or not, any
|
81
|
+
# variation of the email should not be a supported password
|
82
|
+
user.password = email.downcase.strip
|
83
|
+
end
|
84
|
+
self.errors.add(:password, :equal_to_email) if dummy.valid_password?(password.downcase.strip)
|
85
|
+
end
|
86
|
+
|
73
87
|
protected
|
74
88
|
|
75
89
|
# Checks whether a password is needed or not. For validations only.
|
@@ -84,7 +98,7 @@ module Devise
|
|
84
98
|
end
|
85
99
|
|
86
100
|
module ClassMethods
|
87
|
-
Devise::Models.config(self, :password_complexity, :password_length, :email_validation)
|
101
|
+
Devise::Models.config(self, :password_complexity, :password_length, :email_validation, :allow_passwords_equal_to_email)
|
88
102
|
|
89
103
|
private
|
90
104
|
|
@@ -21,11 +21,18 @@ module Devise
|
|
21
21
|
# @raise [Devise::Models::Compatibility::NotPersistedError] if record is unsaved
|
22
22
|
def update_unique_session_id!(unique_session_id)
|
23
23
|
raise Devise::Models::Compatibility::NotPersistedError, 'cannot update a new record' unless persisted?
|
24
|
+
|
24
25
|
update_attribute_without_validatons_or_callbacks(:unique_session_id, unique_session_id).tap do
|
25
|
-
Rails.logger.debug { "[devise-security][session_limitable] unique_session_id=#{unique_session_id}"}
|
26
|
+
Rails.logger.debug { "[devise-security][session_limitable] unique_session_id=#{unique_session_id}" }
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
30
|
+
# Should session_limitable be skipped for this instance?
|
31
|
+
# @return [Boolean]
|
32
|
+
# @return [false] by default. This can be overridden by application logic as necessary.
|
33
|
+
def skip_session_limitable?
|
34
|
+
false
|
35
|
+
end
|
29
36
|
end
|
30
37
|
end
|
31
38
|
end
|
@@ -3,17 +3,19 @@
|
|
3
3
|
# Password complexity validator
|
4
4
|
# Options:
|
5
5
|
# - digit: minimum number of digits in the validated string
|
6
|
+
# - digits: minimum number of digits in the validated string
|
6
7
|
# - lower: minimum number of lower-case letters in the validated string
|
7
8
|
# - symbol: minimum number of punctuation characters or symbols in the validated string
|
9
|
+
# - symbols: minimum number of punctuation characters or symbols in the validated string
|
8
10
|
# - upper: minimum number of upper-case letters in the validated string
|
9
11
|
class DeviseSecurity::PasswordComplexityValidator < ActiveModel::EachValidator
|
10
12
|
PATTERNS = {
|
11
13
|
digit: /\p{Digit}/,
|
12
14
|
digits: /\p{Digit}/,
|
13
15
|
lower: /\p{Lower}/,
|
14
|
-
upper: /\p{Upper}/,
|
15
16
|
symbol: /\p{Punct}|\p{S}/,
|
16
|
-
symbols: /\p{Punct}|\p{S}
|
17
|
+
symbols: /\p{Punct}|\p{S}/,
|
18
|
+
upper: /\p{Upper}/
|
17
19
|
}.freeze
|
18
20
|
|
19
21
|
def validate_each(record, attribute, value)
|
@@ -4,14 +4,14 @@ module DeviseSecurity
|
|
4
4
|
module Generators
|
5
5
|
# Generator for Rails to create or append to a Devise initializer.
|
6
6
|
class InstallGenerator < Rails::Generators::Base
|
7
|
-
LOCALES = %w[en es
|
7
|
+
LOCALES = %w[by cs de en es fa fr hi it ja nl pt ru tr uk zh_CN zh_TW].freeze
|
8
8
|
|
9
9
|
source_root File.expand_path('../../templates', __FILE__)
|
10
10
|
desc 'Install the devise security extension'
|
11
11
|
|
12
12
|
def copy_initializer
|
13
|
-
template('
|
14
|
-
'config/initializers/
|
13
|
+
template('devise_security.rb',
|
14
|
+
'config/initializers/devise_security.rb',
|
15
15
|
)
|
16
16
|
end
|
17
17
|
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Devise.setup do |config|
|
4
|
+
# ==> Security Extension
|
5
|
+
# Configure security extension for devise
|
6
|
+
|
7
|
+
# Should the password expire (e.g 3.months)
|
8
|
+
# config.expire_password_after = false
|
9
|
+
|
10
|
+
# Need 1 char of A-Z, a-z and 0-9
|
11
|
+
# config.password_complexity = { digit: 1, lower: 1, symbol: 1, upper: 1 }
|
12
|
+
|
13
|
+
# How many passwords to keep in archive
|
14
|
+
# config.password_archiving_count = 5
|
15
|
+
|
16
|
+
# Deny old passwords (true, false, number_of_old_passwords_to_check)
|
17
|
+
# Examples:
|
18
|
+
# config.deny_old_passwords = false # allow old passwords
|
19
|
+
# config.deny_old_passwords = true # will deny all the old passwords
|
20
|
+
# config.deny_old_passwords = 3 # will deny new passwords that matches with the last 3 passwords
|
21
|
+
# config.deny_old_passwords = true
|
22
|
+
|
23
|
+
# enable email validation for :secure_validatable. (true, false, validation_options)
|
24
|
+
# dependency: see https://github.com/devise-security/devise-security/blob/master/README.md#e-mail-validation
|
25
|
+
# config.email_validation = true
|
26
|
+
|
27
|
+
# captcha integration for recover form
|
28
|
+
# config.captcha_for_recover = true
|
29
|
+
|
30
|
+
# captcha integration for sign up form
|
31
|
+
# config.captcha_for_sign_up = true
|
32
|
+
|
33
|
+
# captcha integration for sign in form
|
34
|
+
# config.captcha_for_sign_in = true
|
35
|
+
|
36
|
+
# captcha integration for unlock form
|
37
|
+
# config.captcha_for_unlock = true
|
38
|
+
|
39
|
+
# captcha integration for confirmation form
|
40
|
+
# config.captcha_for_confirmation = true
|
41
|
+
|
42
|
+
# Time period for account expiry from last_activity_at
|
43
|
+
# config.expire_after = 90.days
|
44
|
+
|
45
|
+
# Allow password to equal the email
|
46
|
+
# config.allow_passwords_equal_to_email = false
|
47
|
+
end
|