sorcery 0.8.6 → 0.9.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 +4 -4
- data/.gitignore +2 -1
- data/.travis.yml +75 -14
- data/CHANGELOG.md +23 -1
- data/Gemfile +1 -0
- data/README.md +137 -86
- data/gemfiles/active_record-rails40.gemfile +7 -0
- data/gemfiles/active_record-rails41.gemfile +3 -2
- data/gemfiles/mongo_mapper-rails40.gemfile +9 -0
- data/gemfiles/mongo_mapper-rails41.gemfile +2 -1
- data/gemfiles/mongoid-rails40.gemfile +9 -0
- data/gemfiles/mongoid-rails41.gemfile +3 -5
- data/gemfiles/mongoid3-rails32.gemfile +9 -0
- data/lib/generators/sorcery/USAGE +1 -1
- data/lib/generators/sorcery/install_generator.rb +19 -5
- data/lib/generators/sorcery/templates/initializer.rb +34 -9
- data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +3 -1
- data/lib/generators/sorcery/templates/migration/core.rb +2 -2
- data/lib/generators/sorcery/templates/migration/external.rb +3 -1
- data/lib/sorcery.rb +75 -43
- data/lib/sorcery/adapters/active_record_adapter.rb +120 -0
- data/lib/sorcery/adapters/base_adapter.rb +30 -0
- data/lib/sorcery/adapters/data_mapper_adapter.rb +176 -0
- data/lib/sorcery/adapters/mongo_mapper_adapter.rb +110 -0
- data/lib/sorcery/adapters/mongoid_adapter.rb +97 -0
- data/lib/sorcery/controller.rb +5 -64
- data/lib/sorcery/controller/config.rb +65 -0
- data/lib/sorcery/controller/submodules/activity_logging.rb +16 -21
- data/lib/sorcery/controller/submodules/brute_force_protection.rb +6 -6
- data/lib/sorcery/controller/submodules/external.rb +8 -28
- data/lib/sorcery/controller/submodules/remember_me.rb +4 -4
- data/lib/sorcery/controller/submodules/session_timeout.rb +10 -6
- data/lib/sorcery/model.rb +43 -175
- data/lib/sorcery/model/config.rb +96 -0
- data/lib/sorcery/model/submodules/activity_logging.rb +29 -36
- data/lib/sorcery/model/submodules/brute_force_protection.rb +21 -37
- data/lib/sorcery/model/submodules/external.rb +53 -9
- data/lib/sorcery/model/submodules/remember_me.rb +12 -31
- data/lib/sorcery/model/submodules/reset_password.rb +21 -39
- data/lib/sorcery/model/submodules/user_activation.rb +21 -63
- data/lib/sorcery/model/temporary_token.rb +4 -4
- data/lib/sorcery/providers/base.rb +11 -0
- data/lib/sorcery/providers/facebook.rb +1 -1
- data/lib/sorcery/providers/github.rb +1 -1
- data/lib/sorcery/providers/google.rb +1 -1
- data/lib/sorcery/providers/heroku.rb +57 -0
- data/lib/sorcery/providers/jira.rb +77 -0
- data/lib/sorcery/providers/linkedin.rb +1 -1
- data/lib/sorcery/providers/liveid.rb +1 -1
- data/lib/sorcery/providers/salesforce.rb +50 -0
- data/lib/sorcery/providers/twitter.rb +1 -1
- data/lib/sorcery/providers/vk.rb +6 -4
- data/lib/sorcery/providers/xing.rb +1 -1
- data/lib/sorcery/test_helpers/internal.rb +7 -3
- data/lib/sorcery/test_helpers/rails/controller.rb +5 -1
- data/lib/sorcery/version.rb +3 -0
- data/sorcery.gemspec +6 -2
- data/spec/active_record/user_activity_logging_spec.rb +9 -0
- data/spec/controllers/controller_activity_logging_spec.rb +124 -0
- data/spec/controllers/controller_brute_force_protection_spec.rb +43 -0
- data/spec/{active_record → controllers}/controller_http_basic_auth_spec.rb +14 -11
- data/spec/{active_record → controllers}/controller_oauth2_spec.rb +128 -56
- data/spec/{active_record → controllers}/controller_oauth_spec.rb +94 -70
- data/spec/{active_record → controllers}/controller_remember_me_spec.rb +32 -12
- data/spec/{active_record → controllers}/controller_session_timeout_spec.rb +15 -5
- data/spec/{shared_examples/controller_shared_examples.rb → controllers/controller_spec.rb} +34 -19
- data/spec/{datamapper → data_mapper}/user_activation_spec.rb +1 -1
- data/spec/data_mapper/user_activity_logging_spec.rb +14 -0
- data/spec/{datamapper → data_mapper}/user_brute_force_protection_spec.rb +1 -1
- data/spec/{datamapper → data_mapper}/user_oauth_spec.rb +1 -1
- data/spec/{datamapper → data_mapper}/user_remember_me_spec.rb +1 -1
- data/spec/{datamapper → data_mapper}/user_reset_password_spec.rb +1 -1
- data/spec/{datamapper → data_mapper}/user_spec.rb +1 -1
- data/spec/mongoid/user_spec.rb +13 -0
- data/spec/orm/active_record.rb +12 -0
- data/spec/orm/{datamapper.rb → data_mapper.rb} +16 -2
- data/spec/orm/mongo_mapper.rb +0 -1
- data/spec/orm/mongoid.rb +4 -0
- data/spec/rails_app/app/controllers/sorcery_controller.rb +62 -1
- data/spec/rails_app/app/{datamapper → data_mapper}/authentication.rb +0 -0
- data/spec/rails_app/app/{datamapper → data_mapper}/user.rb +0 -0
- data/spec/rails_app/app/mongo_mapper/user.rb +2 -0
- data/spec/rails_app/config/routes.rb +9 -0
- data/spec/rails_app/db/migrate/core/20101224223620_create_users.rb +2 -2
- data/spec/shared_examples/user_activation_shared_examples.rb +7 -7
- data/spec/shared_examples/user_activity_logging_shared_examples.rb +73 -5
- data/spec/shared_examples/user_brute_force_protection_shared_examples.rb +127 -9
- data/spec/shared_examples/user_oauth_shared_examples.rb +3 -6
- data/spec/shared_examples/user_remember_me_shared_examples.rb +6 -3
- data/spec/shared_examples/user_reset_password_shared_examples.rb +10 -10
- data/spec/shared_examples/user_shared_examples.rb +117 -30
- data/spec/spec_helper.rb +7 -22
- metadata +36 -58
- data/Gemfile.rails4 +0 -22
- data/VERSION +0 -1
- data/lib/sorcery/model/adapters/active_record.rb +0 -54
- data/lib/sorcery/model/adapters/datamapper.rb +0 -123
- data/lib/sorcery/model/adapters/mongo_mapper.rb +0 -60
- data/lib/sorcery/model/adapters/mongoid.rb +0 -88
- data/lib/sorcery/test_helpers/rails.rb +0 -7
- data/spec/active_record/controller_activity_logging_spec.rb +0 -29
- data/spec/active_record/controller_brute_force_protection_spec.rb +0 -158
- data/spec/active_record/controller_spec.rb +0 -8
- data/spec/active_record/integration_spec.rb +0 -23
- data/spec/datamapper/controller_activity_logging_spec.rb +0 -17
- data/spec/datamapper/controller_spec.rb +0 -8
- data/spec/datamapper/user_activity_logging_spec.rb +0 -9
- data/spec/mongo_mapper/controller_spec.rb +0 -8
- data/spec/mongoid/controller_activity_logging_spec.rb +0 -16
- data/spec/mongoid/controller_spec.rb +0 -8
- data/spec/rails_app/public/404.html +0 -26
- data/spec/rails_app/public/422.html +0 -26
- data/spec/rails_app/public/500.html +0 -26
- data/spec/rails_app/public/favicon.ico +0 -0
- data/spec/rails_app/public/images/rails.png +0 -0
- data/spec/rails_app/public/javascripts/application.js +0 -2
- data/spec/rails_app/public/javascripts/controls.js +0 -965
- data/spec/rails_app/public/javascripts/dragdrop.js +0 -974
- data/spec/rails_app/public/javascripts/effects.js +0 -1123
- data/spec/rails_app/public/javascripts/prototype.js +0 -6001
- data/spec/rails_app/public/javascripts/rails.js +0 -175
- data/spec/rails_app/public/robots.txt +0 -5
- data/spec/rails_app/public/stylesheets/.gitkeep +0 -0
- data/spec/shared_examples/controller_activity_logging_shared_examples.rb +0 -125
- data/spec/shared_examples/controller_oauth2_shared_examples.rb +0 -52
- data/spec/shared_examples/controller_oauth_shared_examples.rb +0 -62
@@ -0,0 +1,65 @@
|
|
1
|
+
module Sorcery
|
2
|
+
module Controller
|
3
|
+
module Config
|
4
|
+
class << self
|
5
|
+
attr_accessor :submodules,
|
6
|
+
:user_class, # what class to use as the user class.
|
7
|
+
:not_authenticated_action, # what controller action to call for non-authenticated users.
|
8
|
+
|
9
|
+
:save_return_to_url, # when a non logged in user tries to enter a page that requires
|
10
|
+
# login, save the URL he wanted to reach,
|
11
|
+
# and send him there after login.
|
12
|
+
|
13
|
+
:cookie_domain, # set domain option for cookies
|
14
|
+
|
15
|
+
:login_sources,
|
16
|
+
:after_login,
|
17
|
+
:after_failed_login,
|
18
|
+
:before_logout,
|
19
|
+
:after_logout
|
20
|
+
|
21
|
+
def init!
|
22
|
+
@defaults = {
|
23
|
+
:@user_class => nil,
|
24
|
+
:@submodules => [],
|
25
|
+
:@not_authenticated_action => :not_authenticated,
|
26
|
+
:@login_sources => [],
|
27
|
+
:@after_login => [],
|
28
|
+
:@after_failed_login => [],
|
29
|
+
:@before_logout => [],
|
30
|
+
:@after_logout => [],
|
31
|
+
:@save_return_to_url => true,
|
32
|
+
:@cookie_domain => nil
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
# Resets all configuration options to their default values.
|
37
|
+
def reset!
|
38
|
+
@defaults.each do |k,v|
|
39
|
+
instance_variable_set(k,v)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def update!
|
44
|
+
@defaults.each do |k,v|
|
45
|
+
instance_variable_set(k,v) if !instance_variable_defined?(k)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def user_config(&blk)
|
50
|
+
block_given? ? @user_config = blk : @user_config
|
51
|
+
end
|
52
|
+
|
53
|
+
def configure(&blk)
|
54
|
+
@configure_blk = blk
|
55
|
+
end
|
56
|
+
|
57
|
+
def configure!
|
58
|
+
@configure_blk.call(self) if @configure_blk
|
59
|
+
end
|
60
|
+
end
|
61
|
+
init!
|
62
|
+
reset!
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
module Sorcery
|
2
2
|
module Controller
|
3
3
|
module Submodules
|
4
|
-
# This submodule keeps track of events such as login, logout,
|
4
|
+
# This submodule keeps track of events such as login, logout,
|
5
5
|
# and last activity time, per user.
|
6
6
|
# It helps in estimating which users are active now in the site.
|
7
|
-
# This cannot be determined absolutely because a user might be
|
7
|
+
# This cannot be determined absolutely because a user might be
|
8
8
|
# reading a page without clicking anything for a while.
|
9
|
-
# This is the controller part of the submodule, which adds hooks
|
10
|
-
# to register user events,
|
9
|
+
# This is the controller part of the submodule, which adds hooks
|
10
|
+
# to register user events,
|
11
11
|
# and methods to collect active users data for use in the app.
|
12
12
|
# see Socery::Model::Submodules::ActivityLogging for configuration
|
13
13
|
# options.
|
@@ -20,7 +20,7 @@ module Sorcery
|
|
20
20
|
attr_accessor :register_logout_time
|
21
21
|
attr_accessor :register_last_activity_time
|
22
22
|
attr_accessor :register_last_ip_address
|
23
|
-
|
23
|
+
|
24
24
|
def merge_activity_logging_defaults!
|
25
25
|
@defaults.merge!(:@register_login_time => true,
|
26
26
|
:@register_logout_time => true,
|
@@ -36,49 +36,44 @@ module Sorcery
|
|
36
36
|
Config.before_logout << :register_logout_time_to_db
|
37
37
|
base.after_filter :register_last_activity_time_to_db
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
module InstanceMethods
|
41
41
|
# Returns an array of the active users.
|
42
42
|
def current_users
|
43
|
+
ActiveSupport::Deprecation.warn("Sorcery: `current_users` method is deprecated. Read more on Github: https://github.com/NoamB/sorcery/issues/602")
|
44
|
+
|
43
45
|
user_class.current_users
|
44
|
-
# A possible patch here:
|
45
|
-
# we'll add the current_user to the users list if he's not in it
|
46
|
-
# (can happen when he was inactive for more than activity timeout):
|
47
|
-
#
|
48
|
-
# users.unshift!(current_user) if logged_in? && users.find {|u| u.id == current_user.id}.nil?
|
49
|
-
#
|
50
|
-
# disadvantages: can hurt performance.
|
51
46
|
end
|
52
|
-
|
47
|
+
|
53
48
|
protected
|
54
|
-
|
49
|
+
|
55
50
|
# registers last login time on every login.
|
56
51
|
# This runs as a hook just after a successful login.
|
57
52
|
def register_login_time_to_db(user, credentials)
|
58
53
|
return unless Config.register_login_time
|
59
|
-
user.
|
54
|
+
user.set_last_login_at(Time.now.in_time_zone)
|
60
55
|
end
|
61
|
-
|
56
|
+
|
62
57
|
# registers last logout time on every logout.
|
63
58
|
# This runs as a hook just before a logout.
|
64
59
|
def register_logout_time_to_db(user)
|
65
60
|
return unless Config.register_logout_time
|
66
|
-
user.
|
61
|
+
user.set_last_logout_at(Time.now.in_time_zone)
|
67
62
|
end
|
68
|
-
|
63
|
+
|
69
64
|
# Updates last activity time on every request.
|
70
65
|
# The only exception is logout - we do not update activity on logout
|
71
66
|
def register_last_activity_time_to_db
|
72
67
|
return unless Config.register_last_activity_time
|
73
68
|
return unless logged_in?
|
74
|
-
current_user.
|
69
|
+
current_user.set_last_activity_at(Time.now.in_time_zone)
|
75
70
|
end
|
76
71
|
|
77
72
|
# Updates IP address on every login.
|
78
73
|
# This runs as a hook just after a successful login.
|
79
74
|
def register_last_ip_address(user, credentials)
|
80
75
|
return unless Config.register_last_ip_address
|
81
|
-
current_user.
|
76
|
+
current_user.set_last_ip_addess(request.remote_ip)
|
82
77
|
end
|
83
78
|
end
|
84
79
|
end
|
@@ -14,22 +14,22 @@ module Sorcery
|
|
14
14
|
Config.after_login << :reset_failed_logins_count!
|
15
15
|
Config.after_failed_login << :update_failed_logins_count!
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
module InstanceMethods
|
19
|
-
|
19
|
+
|
20
20
|
protected
|
21
|
-
|
21
|
+
|
22
22
|
# Increments the failed logins counter on every failed login.
|
23
23
|
# Runs as a hook after a failed login.
|
24
24
|
def update_failed_logins_count!(credentials)
|
25
|
-
user = user_class.find_by_credentials(credentials)
|
25
|
+
user = user_class.sorcery_adapter.find_by_credentials(credentials)
|
26
26
|
user.register_failed_login! if user
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
# Resets the failed logins counter.
|
30
30
|
# Runs as a hook after a successful login.
|
31
31
|
def reset_failed_logins_count!(user, credentials)
|
32
|
-
user.
|
32
|
+
user.sorcery_adapter.update_attribute(user_class.sorcery_config.failed_logins_count_attribute_name, 0)
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
@@ -15,7 +15,10 @@ module Sorcery
|
|
15
15
|
require 'sorcery/providers/liveid'
|
16
16
|
require 'sorcery/providers/xing'
|
17
17
|
require 'sorcery/providers/github'
|
18
|
+
require 'sorcery/providers/heroku'
|
18
19
|
require 'sorcery/providers/google'
|
20
|
+
require 'sorcery/providers/jira'
|
21
|
+
require 'sorcery/providers/salesforce'
|
19
22
|
|
20
23
|
Config.module_eval do
|
21
24
|
class << self
|
@@ -133,15 +136,7 @@ module Sorcery
|
|
133
136
|
sorcery_fetch_user_hash provider_name
|
134
137
|
config = user_class.sorcery_config
|
135
138
|
|
136
|
-
|
137
|
-
unless (current_user.send(config.authentications_class.name.underscore.pluralize).send("find_by_#{config.provider_attribute_name}_and_#{config.provider_uid_attribute_name}", provider_name, @user_hash[:uid].to_s))
|
138
|
-
user = current_user.send(config.authentications_class.name.underscore.pluralize).build(config.provider_uid_attribute_name => @user_hash[:uid], config.provider_attribute_name => provider_name.to_s)
|
139
|
-
user.sorcery_save(:validate => false)
|
140
|
-
else
|
141
|
-
user = false
|
142
|
-
end
|
143
|
-
|
144
|
-
return user
|
139
|
+
current_user.add_provider_to_user(provider_name.to_s, @user_hash[:uid].to_s)
|
145
140
|
end
|
146
141
|
|
147
142
|
# Initialize new user from provider informations.
|
@@ -153,13 +148,12 @@ module Sorcery
|
|
153
148
|
|
154
149
|
attrs = user_attrs(@provider.user_info_mapping, @user_hash)
|
155
150
|
|
156
|
-
user = user_class.
|
157
|
-
user.send(config.authentications_class.to_s.downcase.pluralize).build(config.provider_uid_attribute_name => @user_hash[:uid], config.provider_attribute_name => provider_name)
|
151
|
+
user, saved = user_class.create_and_validate_from_provider(provider_name, @user_hash[:uid], attrs)
|
158
152
|
|
159
153
|
session[:incomplete_user] = {
|
160
154
|
:provider => {config.provider_uid_attribute_name => @user_hash[:uid], config.provider_attribute_name => provider_name},
|
161
155
|
:user_hash => attrs
|
162
|
-
} unless
|
156
|
+
} unless saved
|
163
157
|
|
164
158
|
return user
|
165
159
|
end
|
@@ -180,26 +174,12 @@ module Sorcery
|
|
180
174
|
#
|
181
175
|
# create_from(provider) {|user| user.some_check }
|
182
176
|
#
|
183
|
-
def create_from(provider_name)
|
177
|
+
def create_from(provider_name, &block)
|
184
178
|
sorcery_fetch_user_hash provider_name
|
185
179
|
config = user_class.sorcery_config
|
186
180
|
|
187
181
|
attrs = user_attrs(@provider.user_info_mapping, @user_hash)
|
188
|
-
|
189
|
-
user_class.transaction do
|
190
|
-
@user = user_class.new()
|
191
|
-
attrs.each do |k,v|
|
192
|
-
@user.send(:"#{k}=", v)
|
193
|
-
end
|
194
|
-
|
195
|
-
if block_given?
|
196
|
-
return false unless yield @user
|
197
|
-
end
|
198
|
-
|
199
|
-
@user.sorcery_save(:validate => false)
|
200
|
-
user_class.sorcery_config.authentications_class.create!({config.authentications_user_id_attribute_name => @user.id, config.provider_attribute_name => provider_name, config.provider_uid_attribute_name => @user_hash[:uid]})
|
201
|
-
end
|
202
|
-
@user
|
182
|
+
@user = user_class.create_from_provider(provider_name, @user_hash[:uid], attrs, &block)
|
203
183
|
end
|
204
184
|
|
205
185
|
def user_attrs(user_info_mapping, user_hash)
|
@@ -38,7 +38,7 @@ module Sorcery
|
|
38
38
|
# Override.
|
39
39
|
# logins a user instance, and optionally remembers him.
|
40
40
|
def auto_login(user, should_remember = false)
|
41
|
-
session[:user_id] = user.id
|
41
|
+
session[:user_id] = user.id.to_s
|
42
42
|
@current_user = user
|
43
43
|
remember_me! if should_remember
|
44
44
|
end
|
@@ -55,10 +55,10 @@ module Sorcery
|
|
55
55
|
# and logs the user in if found.
|
56
56
|
# Runs as a login source. See 'current_user' method for how it is used.
|
57
57
|
def login_from_cookie
|
58
|
-
user = cookies.signed[:remember_me_token] && user_class.find_by_remember_me_token(cookies.signed[:remember_me_token])
|
59
|
-
if user && user.
|
58
|
+
user = cookies.signed[:remember_me_token] && user_class.sorcery_adapter.find_by_remember_me_token(cookies.signed[:remember_me_token])
|
59
|
+
if user && user.has_remember_me_token?
|
60
60
|
set_remember_me_cookie!(user)
|
61
|
-
session[:user_id] = user.id
|
61
|
+
session[:user_id] = user.id.to_s
|
62
62
|
@current_user = user
|
63
63
|
else
|
64
64
|
@current_user = false
|
@@ -9,10 +9,10 @@ module Sorcery
|
|
9
9
|
Config.module_eval do
|
10
10
|
class << self
|
11
11
|
attr_accessor :session_timeout, # how long in seconds to keep the session alive.
|
12
|
-
|
12
|
+
|
13
13
|
:session_timeout_from_last_action # use the last action as the beginning of session
|
14
14
|
# timeout.
|
15
|
-
|
15
|
+
|
16
16
|
def merge_session_timeout_defaults!
|
17
17
|
@defaults.merge!(:@session_timeout => 3600, # 1.hour
|
18
18
|
:@session_timeout_from_last_action => false)
|
@@ -23,21 +23,21 @@ module Sorcery
|
|
23
23
|
Config.after_login << :register_login_time
|
24
24
|
base.prepend_before_filter :validate_session
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
module InstanceMethods
|
28
28
|
protected
|
29
|
-
|
29
|
+
|
30
30
|
# Registers last login to be used as the timeout starting point.
|
31
31
|
# Runs as a hook after a successful login.
|
32
32
|
def register_login_time(user, credentials)
|
33
33
|
session[:login_time] = session[:last_action_time] = Time.now.in_time_zone
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
# Checks if session timeout was reached and expires the current session if so.
|
37
37
|
# To be used as a before_filter, before require_login
|
38
38
|
def validate_session
|
39
39
|
session_to_use = Config.session_timeout_from_last_action ? session[:last_action_time] : session[:login_time]
|
40
|
-
if session_to_use && (
|
40
|
+
if session_to_use && sorcery_session_expired?(session_to_use.to_time)
|
41
41
|
reset_sorcery_session
|
42
42
|
@current_user = nil
|
43
43
|
else
|
@@ -45,6 +45,10 @@ module Sorcery
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
+
def sorcery_session_expired?(time)
|
49
|
+
Time.now.in_time_zone - time > Config.session_timeout
|
50
|
+
end
|
51
|
+
|
48
52
|
end
|
49
53
|
end
|
50
54
|
end
|
data/lib/sorcery/model.rb
CHANGED
@@ -19,17 +19,28 @@ module Sorcery
|
|
19
19
|
# This runs the options block set in the initializer on the model class.
|
20
20
|
::Sorcery::Controller::Config.user_config.tap{|blk| blk.call(@sorcery_config) if blk}
|
21
21
|
|
22
|
-
|
23
|
-
init_mongo_mapper_support! if defined?(MongoMapper) and self.ancestors.include?(MongoMapper::Document)
|
24
|
-
init_datamapper_support! if defined?(DataMapper) and self.ancestors.include?(DataMapper::Resource)
|
25
|
-
|
22
|
+
define_base_fields
|
26
23
|
init_orm_hooks!
|
27
24
|
|
28
25
|
@sorcery_config.after_config << :add_config_inheritance if @sorcery_config.subclasses_inherit_config
|
29
26
|
@sorcery_config.after_config.each { |c| send(c) }
|
30
27
|
end
|
31
28
|
|
32
|
-
|
29
|
+
private
|
30
|
+
|
31
|
+
def define_base_fields
|
32
|
+
self.class_eval do
|
33
|
+
sorcery_config.username_attribute_names.each do |username|
|
34
|
+
sorcery_adapter.define_field username, String, length: 255
|
35
|
+
end
|
36
|
+
unless sorcery_config.username_attribute_names.include?(sorcery_config.email_attribute_name)
|
37
|
+
sorcery_adapter.define_field sorcery_config.email_attribute_name, String, length: 255
|
38
|
+
end
|
39
|
+
sorcery_adapter.define_field sorcery_config.crypted_password_attribute_name, String, length: 255
|
40
|
+
sorcery_adapter.define_field sorcery_config.salt_attribute_name, String, length: 255
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
33
44
|
|
34
45
|
# includes required submodules into the model class,
|
35
46
|
# which usually is called User.
|
@@ -47,77 +58,17 @@ module Sorcery
|
|
47
58
|
end
|
48
59
|
end
|
49
60
|
|
50
|
-
# defines mongoid fields on the model class,
|
51
|
-
# using 1.8.x hash syntax to perserve compatibility.
|
52
|
-
def init_mongoid_support!
|
53
|
-
self.class_eval do
|
54
|
-
sorcery_config.username_attribute_names.each do |username|
|
55
|
-
field username, :type => String
|
56
|
-
end
|
57
|
-
field sorcery_config.email_attribute_name, :type => String unless sorcery_config.username_attribute_names.include?(sorcery_config.email_attribute_name)
|
58
|
-
field sorcery_config.crypted_password_attribute_name, :type => String
|
59
|
-
field sorcery_config.salt_attribute_name, :type => String
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
# defines mongo_mapper fields on the model class,
|
64
|
-
def init_mongo_mapper_support!
|
65
|
-
self.class_eval do
|
66
|
-
sorcery_config.username_attribute_names.each do |username|
|
67
|
-
key username, String
|
68
|
-
end
|
69
|
-
key sorcery_config.email_attribute_name, String unless sorcery_config.username_attribute_names.include?(sorcery_config.email_attribute_name)
|
70
|
-
key sorcery_config.crypted_password_attribute_name, String
|
71
|
-
key sorcery_config.salt_attribute_name, String
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
# defines datamapper fields on the model class
|
76
|
-
def init_datamapper_support!
|
77
|
-
self.class_eval do
|
78
|
-
sorcery_config.username_attribute_names.each do |username|
|
79
|
-
property username, String, :length => 255
|
80
|
-
end
|
81
|
-
unless sorcery_config.username_attribute_names.include?(sorcery_config.email_attribute_name)
|
82
|
-
property sorcery_config.email_attribute_name, String, :length => 255
|
83
|
-
end
|
84
|
-
property sorcery_config.crypted_password_attribute_name, String, :length => 255
|
85
|
-
property sorcery_config.salt_attribute_name, String, :length => 255
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
61
|
# add virtual password accessor and ORM callbacks.
|
90
62
|
def init_orm_hooks!
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
end
|
95
|
-
self.class_eval do
|
96
|
-
attr_accessor @sorcery_config.password_attribute_name
|
97
|
-
#attr_protected @sorcery_config.crypted_password_attribute_name, @sorcery_config.salt_attribute_name
|
98
|
-
before_save :encrypt_password, :if => Proc.new { |record|
|
99
|
-
record.send(sorcery_config.password_attribute_name).present?
|
100
|
-
}
|
101
|
-
after_save :clear_virtual_password, :if => Proc.new { |record|
|
102
|
-
record.send(sorcery_config.password_attribute_name).present?
|
103
|
-
}
|
104
|
-
end
|
105
|
-
end
|
63
|
+
sorcery_adapter.define_callback :before, :validation, :encrypt_password, if: Proc.new {|record|
|
64
|
+
record.send(sorcery_config.password_attribute_name).present?
|
65
|
+
}
|
106
66
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
encrypt_password
|
113
|
-
end
|
114
|
-
end
|
115
|
-
after :save do
|
116
|
-
if self.send(sorcery_config.password_attribute_name).present?
|
117
|
-
clear_virtual_password
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
67
|
+
sorcery_adapter.define_callback :after, :save, :clear_virtual_password, if: Proc.new {|record|
|
68
|
+
record.send(sorcery_config.password_attribute_name).present?
|
69
|
+
}
|
70
|
+
|
71
|
+
attr_accessor sorcery_config.password_attribute_name
|
121
72
|
end
|
122
73
|
|
123
74
|
module ClassMethods
|
@@ -139,12 +90,11 @@ module Sorcery
|
|
139
90
|
credentials[0].downcase!
|
140
91
|
end
|
141
92
|
|
142
|
-
user = find_by_credentials(credentials)
|
93
|
+
user = sorcery_adapter.find_by_credentials(credentials)
|
143
94
|
|
144
95
|
set_encryption_attributes
|
145
96
|
|
146
|
-
|
147
|
-
user if user && @sorcery_config.before_authenticate.all? {|c| user.send(c)} && credentials_match?(user.send(@sorcery_config.crypted_password_attribute_name),credentials[1],_salt)
|
97
|
+
user if user && @sorcery_config.before_authenticate.all? {|c| user.send(c)} && user.valid_password?(credentials[1])
|
148
98
|
end
|
149
99
|
|
150
100
|
# encrypt tokens using current encryption_provider.
|
@@ -163,13 +113,7 @@ module Sorcery
|
|
163
113
|
@sorcery_config.encryption_provider.stretches = @sorcery_config.stretches if @sorcery_config.encryption_provider.respond_to?(:stretches) && @sorcery_config.stretches
|
164
114
|
@sorcery_config.encryption_provider.join_token = @sorcery_config.salt_join_token if @sorcery_config.encryption_provider.respond_to?(:join_token) && @sorcery_config.salt_join_token
|
165
115
|
end
|
166
|
-
|
167
|
-
# Calls the configured encryption provider to compare the supplied password with the encrypted one.
|
168
|
-
def credentials_match?(crypted, *tokens)
|
169
|
-
return crypted == tokens.join if @sorcery_config.encryption_provider.nil?
|
170
|
-
@sorcery_config.encryption_provider.matches?(crypted, *tokens)
|
171
|
-
end
|
172
|
-
|
116
|
+
|
173
117
|
def add_config_inheritance
|
174
118
|
self.class_eval do
|
175
119
|
def self.inherited(subclass)
|
@@ -198,6 +142,16 @@ module Sorcery
|
|
198
142
|
send(sorcery_config.crypted_password_attribute_name).nil?
|
199
143
|
end
|
200
144
|
|
145
|
+
# Calls the configured encryption provider to compare the supplied password with the encrypted one.
|
146
|
+
def valid_password?(pass)
|
147
|
+
_crypted = self.send(sorcery_config.crypted_password_attribute_name)
|
148
|
+
return _crypted == pass if sorcery_config.encryption_provider.nil?
|
149
|
+
|
150
|
+
_salt = self.send(sorcery_config.salt_attribute_name) unless sorcery_config.salt_attribute_name.nil?
|
151
|
+
|
152
|
+
sorcery_config.encryption_provider.matches?(_crypted, pass, _salt)
|
153
|
+
end
|
154
|
+
|
201
155
|
protected
|
202
156
|
|
203
157
|
# creates new salt and saves it.
|
@@ -223,100 +177,14 @@ module Sorcery
|
|
223
177
|
config = sorcery_config
|
224
178
|
mail = config.send(mailer).send(config.send(method),self)
|
225
179
|
if defined?(ActionMailer) and config.send(mailer).kind_of?(Class) and config.send(mailer) < ActionMailer::Base
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
# Every submodule which gets loaded may add accessors to this class so that all
|
233
|
-
# options will be configured from a single place.
|
234
|
-
class Config
|
235
|
-
|
236
|
-
attr_accessor :username_attribute_names, # change default username attribute, for example, to use :email
|
237
|
-
# as the login.
|
238
|
-
|
239
|
-
:password_attribute_name, # change *virtual* password attribute, the one which is used
|
240
|
-
# until an encrypted one is generated.
|
241
|
-
|
242
|
-
:email_attribute_name, # change default email attribute.
|
243
|
-
|
244
|
-
:downcase_username_before_authenticating, # downcase the username before trying to authenticate, default is false
|
245
|
-
|
246
|
-
:crypted_password_attribute_name, # change default crypted_password attribute.
|
247
|
-
:salt_join_token, # what pattern to use to join the password with the salt
|
248
|
-
:salt_attribute_name, # change default salt attribute.
|
249
|
-
:stretches, # how many times to apply encryption to the password.
|
250
|
-
:encryption_key, # encryption key used to encrypt reversible encryptions such as
|
251
|
-
# AES256.
|
252
|
-
|
253
|
-
:subclasses_inherit_config, # make this configuration inheritable for subclasses. Useful for
|
254
|
-
# ActiveRecord's STI.
|
255
|
-
|
256
|
-
:submodules, # configured in config/application.rb
|
257
|
-
:before_authenticate, # an array of method names to call before authentication
|
258
|
-
# completes. used internally.
|
259
|
-
|
260
|
-
:after_config # an array of method names to call after configuration by user.
|
261
|
-
# used internally.
|
262
|
-
|
263
|
-
attr_reader :encryption_provider, # change default encryption_provider.
|
264
|
-
:custom_encryption_provider, # use an external encryption class.
|
265
|
-
:encryption_algorithm # encryption algorithm name. See 'encryption_algorithm=' below
|
266
|
-
# for available options.
|
267
|
-
|
268
|
-
def initialize
|
269
|
-
@defaults = {
|
270
|
-
:@submodules => [],
|
271
|
-
:@username_attribute_names => [:email],
|
272
|
-
:@password_attribute_name => :password,
|
273
|
-
:@downcase_username_before_authenticating => false,
|
274
|
-
:@email_attribute_name => :email,
|
275
|
-
:@crypted_password_attribute_name => :crypted_password,
|
276
|
-
:@encryption_algorithm => :bcrypt,
|
277
|
-
:@encryption_provider => CryptoProviders::BCrypt,
|
278
|
-
:@custom_encryption_provider => nil,
|
279
|
-
:@encryption_key => nil,
|
280
|
-
:@salt_join_token => "",
|
281
|
-
:@salt_attribute_name => :salt,
|
282
|
-
:@stretches => nil,
|
283
|
-
:@subclasses_inherit_config => false,
|
284
|
-
:@before_authenticate => [],
|
285
|
-
:@after_config => []
|
286
|
-
}
|
287
|
-
reset!
|
288
|
-
end
|
289
|
-
|
290
|
-
# Resets all configuration options to their default values.
|
291
|
-
def reset!
|
292
|
-
@defaults.each do |k,v|
|
293
|
-
instance_variable_set(k,v)
|
294
|
-
end
|
295
|
-
end
|
296
|
-
|
297
|
-
def username_attribute_names=(fields)
|
298
|
-
@username_attribute_names = fields.kind_of?(Array) ? fields : [fields]
|
299
|
-
end
|
300
|
-
|
301
|
-
def custom_encryption_provider=(provider)
|
302
|
-
@custom_encryption_provider = @encryption_provider = provider
|
303
|
-
end
|
304
|
-
|
305
|
-
def encryption_algorithm=(algo)
|
306
|
-
@encryption_algorithm = algo
|
307
|
-
@encryption_provider = case @encryption_algorithm.to_sym
|
308
|
-
when :none then nil
|
309
|
-
when :md5 then CryptoProviders::MD5
|
310
|
-
when :sha1 then CryptoProviders::SHA1
|
311
|
-
when :sha256 then CryptoProviders::SHA256
|
312
|
-
when :sha512 then CryptoProviders::SHA512
|
313
|
-
when :aes256 then CryptoProviders::AES256
|
314
|
-
when :bcrypt then CryptoProviders::BCrypt
|
315
|
-
when :custom then @custom_encryption_provider
|
316
|
-
else raise ArgumentError.new("Encryption algorithm supplied, #{algo}, is invalid")
|
180
|
+
# Rails 4.2 deprecates #deliver
|
181
|
+
if mail.respond_to?(:deliver_now)
|
182
|
+
mail.deliver_now
|
183
|
+
else
|
184
|
+
mail.deliver
|
185
|
+
end
|
317
186
|
end
|
318
187
|
end
|
319
|
-
|
320
188
|
end
|
321
189
|
|
322
190
|
end
|