sorcery 0.12.0 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sorcery might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/.github/ISSUE_TEMPLATE.md +20 -0
- data/.rubocop.yml +52 -2
- data/.rubocop_todo.yml +1 -429
- data/.travis.yml +11 -21
- data/CHANGELOG.md +16 -0
- data/Gemfile +2 -2
- data/{LICENSE.txt → LICENSE.md} +1 -1
- data/README.md +7 -1
- data/gemfiles/{active_record-rails40.gemfile → active_record_rails_40.gemfile} +1 -2
- data/gemfiles/{active_record-rails41.gemfile → active_record_rails_41.gemfile} +1 -2
- data/gemfiles/{active_record-rails42.gemfile → active_record_rails_42.gemfile} +1 -2
- data/lib/generators/sorcery/USAGE +1 -1
- data/lib/generators/sorcery/install_generator.rb +21 -21
- data/lib/generators/sorcery/templates/initializer.rb +19 -1
- data/lib/sorcery/adapters/active_record_adapter.rb +1 -1
- data/lib/sorcery/adapters/mongoid_adapter.rb +23 -11
- data/lib/sorcery/controller.rb +22 -16
- data/lib/sorcery/controller/config.rb +2 -0
- data/lib/sorcery/controller/submodules/activity_logging.rb +4 -0
- data/lib/sorcery/controller/submodules/external.rb +37 -33
- data/lib/sorcery/controller/submodules/http_basic_auth.rb +1 -0
- data/lib/sorcery/controller/submodules/remember_me.rb +1 -7
- data/lib/sorcery/controller/submodules/session_timeout.rb +25 -4
- data/lib/sorcery/crypto_providers/aes256.rb +1 -0
- data/lib/sorcery/crypto_providers/bcrypt.rb +2 -1
- data/lib/sorcery/engine.rb +10 -3
- data/lib/sorcery/model.rb +9 -6
- data/lib/sorcery/model/config.rb +3 -3
- data/lib/sorcery/model/submodules/brute_force_protection.rb +6 -7
- data/lib/sorcery/model/submodules/external.rb +4 -3
- data/lib/sorcery/model/submodules/magic_login.rb +29 -36
- data/lib/sorcery/model/submodules/reset_password.rb +5 -4
- data/lib/sorcery/model/submodules/user_activation.rb +1 -1
- data/lib/sorcery/protocols/oauth.rb +1 -0
- data/lib/sorcery/providers/auth0.rb +46 -0
- data/lib/sorcery/providers/heroku.rb +1 -0
- data/lib/sorcery/providers/instagram.rb +73 -0
- data/lib/sorcery/providers/linkedin.rb +1 -1
- data/lib/sorcery/providers/vk.rb +1 -1
- data/lib/sorcery/providers/wechat.rb +8 -6
- data/lib/sorcery/test_helpers/internal.rb +5 -4
- data/lib/sorcery/test_helpers/internal/rails.rb +11 -11
- data/lib/sorcery/version.rb +1 -1
- data/sorcery.gemspec +25 -9
- data/spec/active_record/user_activation_spec.rb +2 -2
- data/spec/active_record/user_activity_logging_spec.rb +2 -2
- data/spec/active_record/user_brute_force_protection_spec.rb +2 -2
- data/spec/active_record/user_magic_login_spec.rb +4 -4
- data/spec/active_record/user_oauth_spec.rb +2 -2
- data/spec/active_record/user_remember_me_spec.rb +2 -2
- data/spec/active_record/user_reset_password_spec.rb +2 -2
- data/spec/active_record/user_spec.rb +0 -10
- data/spec/controllers/controller_http_basic_auth_spec.rb +1 -1
- data/spec/controllers/controller_oauth2_spec.rb +195 -123
- data/spec/controllers/controller_oauth_spec.rb +7 -7
- data/spec/controllers/controller_remember_me_spec.rb +11 -6
- data/spec/controllers/controller_session_timeout_spec.rb +90 -3
- data/spec/controllers/controller_spec.rb +2 -2
- data/spec/orm/active_record.rb +2 -2
- data/spec/providers/vk_spec.rb +13 -12
- data/spec/rails_app/app/controllers/sorcery_controller.rb +83 -32
- data/spec/rails_app/app/mailers/sorcery_mailer.rb +1 -1
- data/spec/rails_app/config/application.rb +8 -3
- data/spec/rails_app/config/boot.rb +1 -1
- data/spec/rails_app/config/environment.rb +1 -1
- data/spec/rails_app/config/routes.rb +7 -0
- data/spec/rails_app/config/secrets.yml +4 -0
- data/spec/rails_app/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +2 -2
- data/spec/rails_app/db/migrate/invalidate_active_sessions/20180221093235_add_invalidate_active_sessions_before_to_users.rb +9 -0
- data/spec/rails_app/db/migrate/magic_login/20170924151831_add_magic_login_to_users.rb +3 -3
- data/spec/rails_app/db/schema.rb +7 -9
- data/spec/shared_examples/user_magic_login_shared_examples.rb +50 -50
- data/spec/shared_examples/user_oauth_shared_examples.rb +1 -1
- data/spec/shared_examples/user_remember_me_shared_examples.rb +1 -1
- data/spec/shared_examples/user_reset_password_shared_examples.rb +3 -3
- data/spec/shared_examples/user_shared_examples.rb +41 -43
- data/spec/sorcery_crypto_providers_spec.rb +1 -1
- data/spec/spec.opts +1 -1
- data/spec/spec_helper.rb +2 -2
- data/spec/support/migration_helper.rb +19 -0
- metadata +60 -38
- data/spec/rails_app/config/initializers/secret_token.rb +0 -7
@@ -18,6 +18,7 @@ module Sorcery
|
|
18
18
|
attr_accessor :after_failed_login
|
19
19
|
attr_accessor :before_logout
|
20
20
|
attr_accessor :after_logout
|
21
|
+
attr_accessor :after_remember_me
|
21
22
|
|
22
23
|
def init!
|
23
24
|
@defaults = {
|
@@ -29,6 +30,7 @@ module Sorcery
|
|
29
30
|
:@after_failed_login => [],
|
30
31
|
:@before_logout => [],
|
31
32
|
:@after_logout => [],
|
33
|
+
:@after_remember_me => [],
|
32
34
|
:@save_return_to_url => true,
|
33
35
|
:@cookie_domain => nil
|
34
36
|
}
|
@@ -43,6 +43,7 @@ module Sorcery
|
|
43
43
|
# This runs as a hook just after a successful login.
|
44
44
|
def register_login_time_to_db(user, _credentials)
|
45
45
|
return unless Config.register_login_time
|
46
|
+
|
46
47
|
user.set_last_login_at(Time.now.in_time_zone)
|
47
48
|
end
|
48
49
|
|
@@ -50,6 +51,7 @@ module Sorcery
|
|
50
51
|
# This runs as a hook just before a logout.
|
51
52
|
def register_logout_time_to_db
|
52
53
|
return unless Config.register_logout_time
|
54
|
+
|
53
55
|
current_user.set_last_logout_at(Time.now.in_time_zone)
|
54
56
|
end
|
55
57
|
|
@@ -58,6 +60,7 @@ module Sorcery
|
|
58
60
|
def register_last_activity_time_to_db
|
59
61
|
return unless Config.register_last_activity_time
|
60
62
|
return unless logged_in?
|
63
|
+
|
61
64
|
current_user.set_last_activity_at(Time.now.in_time_zone)
|
62
65
|
end
|
63
66
|
|
@@ -65,6 +68,7 @@ module Sorcery
|
|
65
68
|
# This runs as a hook just after a successful login.
|
66
69
|
def register_last_ip_address(_user, _credentials)
|
67
70
|
return unless Config.register_last_ip_address
|
71
|
+
|
68
72
|
current_user.set_last_ip_address(request.remote_ip)
|
69
73
|
end
|
70
74
|
end
|
@@ -23,6 +23,8 @@ module Sorcery
|
|
23
23
|
require 'sorcery/providers/slack'
|
24
24
|
require 'sorcery/providers/wechat'
|
25
25
|
require 'sorcery/providers/microsoft'
|
26
|
+
require 'sorcery/providers/instagram'
|
27
|
+
require 'sorcery/providers/auth0'
|
26
28
|
|
27
29
|
Config.module_eval do
|
28
30
|
class << self
|
@@ -33,17 +35,17 @@ module Sorcery
|
|
33
35
|
@external_providers = providers
|
34
36
|
|
35
37
|
providers.each do |name|
|
36
|
-
class_eval <<-
|
38
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
37
39
|
def self.#{name}
|
38
40
|
@#{name} ||= Sorcery::Providers.const_get('#{name}'.to_s.capitalize).new
|
39
41
|
end
|
40
|
-
|
42
|
+
RUBY
|
41
43
|
end
|
42
44
|
end
|
43
45
|
|
44
46
|
def merge_external_defaults!
|
45
47
|
@defaults.merge!(:@external_providers => [],
|
46
|
-
:@ca_file => File.join(
|
48
|
+
:@ca_file => File.join(__dir__, '../../protocols/certs/ca-bundle.crt'))
|
47
49
|
end
|
48
50
|
end
|
49
51
|
merge_external_defaults!
|
@@ -56,6 +58,7 @@ module Sorcery
|
|
56
58
|
# save the singleton ProviderClient instance into @provider
|
57
59
|
def sorcery_get_provider(provider_name)
|
58
60
|
return unless Config.external_providers.include?(provider_name.to_sym)
|
61
|
+
|
59
62
|
Config.send(provider_name.to_sym)
|
60
63
|
end
|
61
64
|
|
@@ -64,12 +67,11 @@ module Sorcery
|
|
64
67
|
def sorcery_login_url(provider_name, args = {})
|
65
68
|
@provider = sorcery_get_provider provider_name
|
66
69
|
sorcery_fixup_callback_url @provider
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
end
|
70
|
+
|
71
|
+
return nil unless @provider.respond_to?(:login_url) && @provider.has_callback?
|
72
|
+
|
73
|
+
@provider.state = args[:state]
|
74
|
+
@provider.login_url(params, session)
|
73
75
|
end
|
74
76
|
|
75
77
|
# get the user hash from a provider using information from the params and session.
|
@@ -88,6 +90,7 @@ module Sorcery
|
|
88
90
|
# cache them in instance variables.
|
89
91
|
@access_token ||= @provider.process_callback(params, session) # sends request to oauth agent to get the token
|
90
92
|
@user_hash ||= @provider.get_user_hash(@access_token) # uses the token to send another request to the oauth agent requesting user info
|
93
|
+
nil
|
91
94
|
end
|
92
95
|
|
93
96
|
# for backwards compatibility
|
@@ -98,14 +101,15 @@ module Sorcery
|
|
98
101
|
# this method should be somewhere else. It only does something once per application per provider.
|
99
102
|
def sorcery_fixup_callback_url(provider)
|
100
103
|
provider.original_callback_url ||= provider.callback_url
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
104
|
+
|
105
|
+
return unless provider.original_callback_url.present? && provider.original_callback_url[0] == '/'
|
106
|
+
|
107
|
+
uri = URI.parse(request.url.gsub(/\?.*$/, ''))
|
108
|
+
uri.path = ''
|
109
|
+
uri.query = nil
|
110
|
+
uri.scheme = 'https' if request.env['HTTP_X_FORWARDED_PROTO'] == 'https'
|
111
|
+
host = uri.to_s
|
112
|
+
provider.callback_url = "#{host}#{@provider.original_callback_url}"
|
109
113
|
end
|
110
114
|
|
111
115
|
# sends user to authenticate at the provider's website.
|
@@ -118,26 +122,26 @@ module Sorcery
|
|
118
122
|
def login_from(provider_name, should_remember = false)
|
119
123
|
sorcery_fetch_user_hash provider_name
|
120
124
|
|
121
|
-
|
122
|
-
# we found the user.
|
123
|
-
# clear the session
|
124
|
-
return_to_url = session[:return_to_url]
|
125
|
-
reset_sorcery_session
|
126
|
-
session[:return_to_url] = return_to_url
|
125
|
+
return unless (user = user_class.load_from_provider(provider_name, @user_hash[:uid].to_s))
|
127
126
|
|
128
|
-
|
129
|
-
|
130
|
-
|
127
|
+
# we found the user.
|
128
|
+
# clear the session
|
129
|
+
return_to_url = session[:return_to_url]
|
130
|
+
reset_sorcery_session
|
131
|
+
session[:return_to_url] = return_to_url
|
131
132
|
|
132
|
-
|
133
|
-
|
134
|
-
|
133
|
+
# sign in the user
|
134
|
+
auto_login(user, should_remember)
|
135
|
+
after_login!(user)
|
136
|
+
|
137
|
+
# return the user
|
138
|
+
user
|
135
139
|
end
|
136
140
|
|
137
141
|
# If user is logged, he can add all available providers into his account
|
138
142
|
def add_provider_to_user(provider_name)
|
139
143
|
sorcery_fetch_user_hash provider_name
|
140
|
-
config = user_class.sorcery_config
|
144
|
+
# config = user_class.sorcery_config # TODO: Unused, remove?
|
141
145
|
|
142
146
|
current_user.add_provider_to_user(provider_name.to_s, @user_hash[:uid].to_s)
|
143
147
|
end
|
@@ -181,7 +185,7 @@ module Sorcery
|
|
181
185
|
#
|
182
186
|
def create_from(provider_name, &block)
|
183
187
|
sorcery_fetch_user_hash provider_name
|
184
|
-
config = user_class.sorcery_config
|
188
|
+
# config = user_class.sorcery_config # TODO: Unused, remove?
|
185
189
|
|
186
190
|
attrs = user_attrs(@provider.user_info_mapping, @user_hash)
|
187
191
|
@user = user_class.create_from_provider(provider_name, @user_hash[:uid], attrs, &block)
|
@@ -190,7 +194,7 @@ module Sorcery
|
|
190
194
|
# follows the same patterns as create_from, but builds the user instead of creating
|
191
195
|
def build_from(provider_name, &block)
|
192
196
|
sorcery_fetch_user_hash provider_name
|
193
|
-
config = user_class.sorcery_config
|
197
|
+
# config = user_class.sorcery_config # TODO: Unused, remove?
|
194
198
|
|
195
199
|
attrs = user_attrs(@provider.user_info_mapping, @user_hash)
|
196
200
|
@user = user_class.build_from_provider(attrs, &block)
|
@@ -202,7 +206,7 @@ module Sorcery
|
|
202
206
|
if (varr = v.split('/')).size > 1
|
203
207
|
attribute_value = begin
|
204
208
|
varr.inject(user_hash[:user_info]) { |hash, value| hash[value] }
|
205
|
-
rescue
|
209
|
+
rescue StandardError
|
206
210
|
nil
|
207
211
|
end
|
208
212
|
attribute_value.nil? ? attrs : attrs.merge!(k => attribute_value)
|
@@ -18,7 +18,6 @@ module Sorcery
|
|
18
18
|
merge_remember_me_defaults!
|
19
19
|
end
|
20
20
|
Config.login_sources << :login_from_cookie
|
21
|
-
Config.after_login << :remember_me_if_asked_to
|
22
21
|
Config.before_logout << :forget_me!
|
23
22
|
end
|
24
23
|
|
@@ -51,12 +50,6 @@ module Sorcery
|
|
51
50
|
|
52
51
|
protected
|
53
52
|
|
54
|
-
# calls remember_me! if a third credential was passed to the login method.
|
55
|
-
# Runs as a hook after login.
|
56
|
-
def remember_me_if_asked_to(_user, credentials)
|
57
|
-
remember_me! if credentials.size == 3 && credentials[2] && credentials[2] != '0'
|
58
|
-
end
|
59
|
-
|
60
53
|
# Checks the cookie for a remember me token, tried to find a user with that token
|
61
54
|
# and logs the user in if found.
|
62
55
|
# Runs as a login source. See 'current_user' method for how it is used.
|
@@ -65,6 +58,7 @@ module Sorcery
|
|
65
58
|
if user && user.has_remember_me_token?
|
66
59
|
set_remember_me_cookie!(user)
|
67
60
|
session[:user_id] = user.id.to_s
|
61
|
+
after_remember_me!(user)
|
68
62
|
@current_user = user
|
69
63
|
else
|
70
64
|
@current_user = false
|
@@ -12,24 +12,36 @@ module Sorcery
|
|
12
12
|
attr_accessor :session_timeout
|
13
13
|
# use the last action as the beginning of session timeout.
|
14
14
|
attr_accessor :session_timeout_from_last_action
|
15
|
+
# allow users to invalidate active sessions
|
16
|
+
attr_accessor :session_timeout_invalidate_active_sessions_enabled
|
15
17
|
|
16
18
|
def merge_session_timeout_defaults!
|
17
|
-
@defaults.merge!(:@session_timeout
|
18
|
-
:@session_timeout_from_last_action
|
19
|
+
@defaults.merge!(:@session_timeout => 3600, # 1.hour
|
20
|
+
:@session_timeout_from_last_action => false,
|
21
|
+
:@session_timeout_invalidate_active_sessions_enabled => false)
|
19
22
|
end
|
20
23
|
end
|
21
24
|
merge_session_timeout_defaults!
|
22
25
|
end
|
23
26
|
Config.after_login << :register_login_time
|
27
|
+
Config.after_remember_me << :register_login_time
|
24
28
|
base.prepend_before_action :validate_session
|
25
29
|
end
|
26
30
|
|
27
31
|
module InstanceMethods
|
32
|
+
def invalidate_active_sessions!
|
33
|
+
return unless Config.session_timeout_invalidate_active_sessions_enabled
|
34
|
+
return unless current_user.present?
|
35
|
+
|
36
|
+
current_user.send(:invalidate_sessions_before=, Time.now.in_time_zone)
|
37
|
+
current_user.save
|
38
|
+
end
|
39
|
+
|
28
40
|
protected
|
29
41
|
|
30
42
|
# Registers last login to be used as the timeout starting point.
|
31
43
|
# Runs as a hook after a successful login.
|
32
|
-
def register_login_time(_user, _credentials)
|
44
|
+
def register_login_time(_user, _credentials = nil)
|
33
45
|
session[:login_time] = session[:last_action_time] = Time.now.in_time_zone
|
34
46
|
end
|
35
47
|
|
@@ -37,7 +49,7 @@ module Sorcery
|
|
37
49
|
# To be used as a before_action, before require_login
|
38
50
|
def validate_session
|
39
51
|
session_to_use = Config.session_timeout_from_last_action ? session[:last_action_time] : session[:login_time]
|
40
|
-
if session_to_use && sorcery_session_expired?(session_to_use.to_time)
|
52
|
+
if (session_to_use && sorcery_session_expired?(session_to_use.to_time)) || sorcery_session_invalidated?
|
41
53
|
reset_sorcery_session
|
42
54
|
remove_instance_variable :@current_user if defined? @current_user
|
43
55
|
else
|
@@ -48,6 +60,15 @@ module Sorcery
|
|
48
60
|
def sorcery_session_expired?(time)
|
49
61
|
Time.now.in_time_zone - time > Config.session_timeout
|
50
62
|
end
|
63
|
+
|
64
|
+
# Use login time if present, otherwise use last action time.
|
65
|
+
def sorcery_session_invalidated?
|
66
|
+
return false unless Config.session_timeout_invalidate_active_sessions_enabled
|
67
|
+
return false unless current_user.present? && current_user.try(:invalidate_sessions_before).present?
|
68
|
+
|
69
|
+
time = session[:login_time] || session[:last_action_time] || Time.now.in_time_zone
|
70
|
+
time < current_user.invalidate_sessions_before
|
71
|
+
end
|
51
72
|
end
|
52
73
|
end
|
53
74
|
end
|
@@ -60,6 +60,7 @@ module Sorcery
|
|
60
60
|
def matches?(hash, *tokens)
|
61
61
|
hash = new_from_hash(hash)
|
62
62
|
return false if hash.nil? || hash == {}
|
63
|
+
|
63
64
|
hash == join_tokens(tokens)
|
64
65
|
end
|
65
66
|
|
@@ -87,7 +88,7 @@ module Sorcery
|
|
87
88
|
def new_from_hash(hash)
|
88
89
|
::BCrypt::Password.new(hash)
|
89
90
|
rescue ::BCrypt::Errors::InvalidHash
|
90
|
-
|
91
|
+
nil
|
91
92
|
end
|
92
93
|
end
|
93
94
|
end
|
data/lib/sorcery/engine.rb
CHANGED
@@ -8,9 +8,16 @@ module Sorcery
|
|
8
8
|
config.sorcery = ::Sorcery::Controller::Config
|
9
9
|
|
10
10
|
initializer 'extend Controller with sorcery' do
|
11
|
-
|
12
|
-
ActionController::
|
13
|
-
|
11
|
+
# TODO: Should this include a modified version of the helper methods?
|
12
|
+
if defined?(ActionController::API)
|
13
|
+
ActionController::API.send(:include, Sorcery::Controller)
|
14
|
+
end
|
15
|
+
|
16
|
+
if defined?(ActionController::Base)
|
17
|
+
ActionController::Base.send(:include, Sorcery::Controller)
|
18
|
+
ActionController::Base.helper_method :current_user
|
19
|
+
ActionController::Base.helper_method :logged_in?
|
20
|
+
end
|
14
21
|
end
|
15
22
|
end
|
16
23
|
end
|
data/lib/sorcery/model.rb
CHANGED
@@ -47,12 +47,15 @@ module Sorcery
|
|
47
47
|
class_eval do
|
48
48
|
@sorcery_config.submodules = ::Sorcery::Controller::Config.submodules
|
49
49
|
@sorcery_config.submodules.each do |mod|
|
50
|
+
# TODO: Is there a cleaner way to handle missing submodules?
|
51
|
+
# rubocop:disable Lint/HandleExceptions
|
50
52
|
begin
|
51
53
|
include Submodules.const_get(mod.to_s.split('_').map(&:capitalize).join)
|
52
54
|
rescue NameError
|
53
55
|
# don't stop on a missing submodule. Needed because some submodules are only defined
|
54
56
|
# in the controller side.
|
55
57
|
end
|
58
|
+
# rubocop:enable Lint/HandleExceptions
|
56
59
|
end
|
57
60
|
end
|
58
61
|
end
|
@@ -192,9 +195,9 @@ module Sorcery
|
|
192
195
|
config = sorcery_config
|
193
196
|
send(:"#{config.password_attribute_name}=", nil)
|
194
197
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
+
return unless respond_to?(:"#{config.password_attribute_name}_confirmation=")
|
199
|
+
|
200
|
+
send(:"#{config.password_attribute_name}_confirmation=", nil)
|
198
201
|
end
|
199
202
|
|
200
203
|
# calls the requested email method on the configured mailer
|
@@ -202,9 +205,9 @@ module Sorcery
|
|
202
205
|
def generic_send_email(method, mailer)
|
203
206
|
config = sorcery_config
|
204
207
|
mail = config.send(mailer).send(config.send(method), self)
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
+
return unless defined?(ActionMailer) && config.send(mailer).is_a?(Class) && config.send(mailer) < ActionMailer::Base
|
209
|
+
|
210
|
+
mail.send(config.email_delivery_method)
|
208
211
|
end
|
209
212
|
end
|
210
213
|
end
|
data/lib/sorcery/model/config.rb
CHANGED
@@ -4,8 +4,6 @@
|
|
4
4
|
module Sorcery
|
5
5
|
module Model
|
6
6
|
class Config
|
7
|
-
# change default username attribute, for example, to use :email as the login.
|
8
|
-
attr_accessor :username_attribute_names
|
9
7
|
# change *virtual* password attribute, the one which is used until an encrypted one is generated.
|
10
8
|
attr_accessor :password_attribute_name
|
11
9
|
# change default email attribute.
|
@@ -38,6 +36,8 @@ module Sorcery
|
|
38
36
|
# Set token randomness
|
39
37
|
attr_accessor :token_randomness
|
40
38
|
|
39
|
+
# change default username attribute, for example, to use :email as the login. See 'username_attribute_names=' below.
|
40
|
+
attr_reader :username_attribute_names
|
41
41
|
# change default encryption_provider.
|
42
42
|
attr_reader :encryption_provider
|
43
43
|
# use an external encryption class.
|
@@ -96,7 +96,7 @@ module Sorcery
|
|
96
96
|
when :bcrypt then CryptoProviders::BCrypt
|
97
97
|
when :custom then @custom_encryption_provider
|
98
98
|
else raise ArgumentError, "Encryption algorithm supplied, #{algo}, is invalid"
|
99
|
-
|
99
|
+
end
|
100
100
|
end
|
101
101
|
|
102
102
|
private
|
@@ -14,7 +14,6 @@ module Sorcery
|
|
14
14
|
:consecutive_login_retries_amount_limit, # how many failed logins allowed.
|
15
15
|
:login_lock_time_period, # how long the user should be banned.
|
16
16
|
# in seconds. 0 for permanent.
|
17
|
-
|
18
17
|
:unlock_token_attribute_name, # Unlock token attribute name
|
19
18
|
:unlock_token_email_method_name, # Mailer method name
|
20
19
|
:unlock_token_mailer_disabled, # When true, dont send unlock token via email
|
@@ -70,9 +69,9 @@ module Sorcery
|
|
70
69
|
|
71
70
|
sorcery_adapter.increment(config.failed_logins_count_attribute_name)
|
72
71
|
|
73
|
-
|
74
|
-
|
75
|
-
|
72
|
+
return unless send(config.failed_logins_count_attribute_name) >= config.consecutive_login_retries_amount_limit
|
73
|
+
|
74
|
+
login_lock!
|
76
75
|
end
|
77
76
|
|
78
77
|
# /!\
|
@@ -98,9 +97,9 @@ module Sorcery
|
|
98
97
|
config.unlock_token_attribute_name => TemporaryToken.generate_random_token }
|
99
98
|
sorcery_adapter.update_attributes(attributes)
|
100
99
|
|
101
|
-
|
102
|
-
|
103
|
-
|
100
|
+
return if config.unlock_token_mailer_disabled || config.unlock_token_mailer.nil?
|
101
|
+
|
102
|
+
send_unlock_token_email!
|
104
103
|
end
|
105
104
|
|
106
105
|
def login_unlocked?
|