sorcery 0.7.0 → 0.8.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.
- data/.travis.yml +3 -0
- data/Gemfile +9 -6
- data/Gemfile.lock +106 -75
- data/README.rdoc +42 -55
- data/Rakefile +32 -7
- data/VERSION +1 -1
- data/lib/generators/sorcery/USAGE +22 -0
- data/lib/generators/sorcery/install_generator.rb +77 -0
- data/lib/generators/sorcery/templates/initializer.rb +417 -0
- data/lib/generators/sorcery/templates/migration/activity_logging.rb +17 -0
- data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +13 -0
- data/lib/generators/{sorcery_migration/templates → sorcery/templates/migration}/core.rb +2 -2
- data/lib/generators/{sorcery_migration/templates → sorcery/templates/migration}/external.rb +1 -1
- data/lib/generators/sorcery/templates/migration/remember_me.rb +15 -0
- data/lib/generators/sorcery/templates/migration/reset_password.rb +17 -0
- data/lib/generators/sorcery/templates/migration/user_activation.rb +17 -0
- data/lib/sorcery/controller/submodules/activity_logging.rb +8 -11
- data/lib/sorcery/controller/submodules/brute_force_protection.rb +2 -3
- data/lib/sorcery/controller/submodules/external/protocols/oauth2.rb +25 -10
- data/lib/sorcery/controller/submodules/external/providers/facebook.rb +20 -5
- data/lib/sorcery/controller/submodules/external/providers/github.rb +15 -4
- data/lib/sorcery/controller/submodules/external/providers/google.rb +90 -0
- data/lib/sorcery/controller/submodules/external/providers/linkedin.rb +101 -0
- data/lib/sorcery/controller/submodules/external/providers/liveid.rb +91 -0
- data/lib/sorcery/controller/submodules/external/providers/twitter.rb +3 -2
- data/lib/sorcery/controller/submodules/external/providers/vkontakte.rb +94 -0
- data/lib/sorcery/controller/submodules/external.rb +89 -15
- data/lib/sorcery/controller/submodules/http_basic_auth.rb +1 -1
- data/lib/sorcery/controller/submodules/remember_me.rb +26 -15
- data/lib/sorcery/controller/submodules/session_timeout.rb +3 -3
- data/lib/sorcery/controller.rb +55 -46
- data/lib/sorcery/crypto_providers/bcrypt.rb +1 -0
- data/lib/sorcery/model/adapters/active_record.rb +21 -1
- data/lib/sorcery/model/adapters/mongo_mapper.rb +56 -0
- data/lib/sorcery/model/adapters/mongoid.rb +23 -4
- data/lib/sorcery/model/submodules/activity_logging.rb +4 -4
- data/lib/sorcery/model/submodules/brute_force_protection.rb +54 -15
- data/lib/sorcery/model/submodules/remember_me.rb +12 -7
- data/lib/sorcery/model/submodules/reset_password.rb +27 -11
- data/lib/sorcery/model/submodules/user_activation.rb +27 -8
- data/lib/sorcery/model/temporary_token.rb +4 -2
- data/lib/sorcery/model.rb +78 -47
- data/lib/sorcery/railties/tasks.rake +2 -0
- data/lib/sorcery.rb +10 -8
- data/sorcery.gemspec +107 -228
- data/spec/Gemfile +1 -1
- data/spec/Gemfile.lock +27 -23
- data/spec/README.md +12 -7
- data/spec/rails3/Gemfile +3 -3
- data/spec/rails3/Gemfile.lock +62 -55
- data/spec/rails3/app/controllers/application_controller.rb +85 -2
- data/spec/rails3/app/mailers/sorcery_mailer.rb +7 -0
- data/spec/rails3/app/views/sorcery_mailer/send_unlock_token_email.text.erb +1 -0
- data/spec/rails3/config/environments/in_memory.rb +35 -0
- data/spec/rails3/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +2 -0
- data/spec/rails3/spec/controller_activity_logging_spec.rb +16 -6
- data/spec/rails3/spec/controller_brute_force_protection_spec.rb +25 -3
- data/spec/rails3/spec/controller_oauth2_spec.rb +260 -20
- data/spec/rails3/spec/controller_oauth_spec.rb +111 -6
- data/spec/rails3/spec/controller_session_timeout_spec.rb +4 -4
- data/spec/rails3/spec/controller_spec.rb +37 -2
- data/spec/rails3/spec/integration_spec.rb +15 -15
- data/spec/rails3/spec/spec_helper.rb +0 -2
- data/spec/rails3_mongo_mapper/.gitignore +4 -0
- data/spec/rails3_mongo_mapper/.rspec +1 -0
- data/spec/{sinatra_modular → rails3_mongo_mapper}/Gemfile +6 -5
- data/spec/rails3_mongo_mapper/Gemfile.lock +156 -0
- data/spec/{sinatra → rails3_mongo_mapper}/Rakefile +3 -3
- data/spec/rails3_mongo_mapper/app/controllers/application_controller.rb +122 -0
- data/spec/rails3_mongo_mapper/app/helpers/application_helper.rb +2 -0
- data/spec/rails3_mongo_mapper/app/models/authentication.rb +6 -0
- data/spec/rails3_mongo_mapper/app/models/user.rb +5 -0
- data/spec/rails3_mongo_mapper/app/views/layouts/application.html.erb +14 -0
- data/spec/rails3_mongo_mapper/app/views/sorcery_mailer/activation_email.html.erb +17 -0
- data/spec/rails3_mongo_mapper/app/views/sorcery_mailer/activation_email.text.erb +9 -0
- data/spec/rails3_mongo_mapper/app/views/sorcery_mailer/activation_success_email.html.erb +17 -0
- data/spec/rails3_mongo_mapper/app/views/sorcery_mailer/activation_success_email.text.erb +9 -0
- data/spec/rails3_mongo_mapper/app/views/sorcery_mailer/reset_password_email.html.erb +16 -0
- data/spec/rails3_mongo_mapper/app/views/sorcery_mailer/reset_password_email.text.erb +8 -0
- data/spec/rails3_mongo_mapper/config/application.rb +51 -0
- data/spec/rails3_mongo_mapper/config/boot.rb +13 -0
- data/spec/rails3_mongo_mapper/config/environment.rb +5 -0
- data/spec/rails3_mongo_mapper/config/environments/development.rb +30 -0
- data/spec/rails3_mongo_mapper/config/environments/in_memory.rb +0 -0
- data/spec/rails3_mongo_mapper/config/environments/production.rb +49 -0
- data/spec/rails3_mongo_mapper/config/environments/test.rb +35 -0
- data/spec/rails3_mongo_mapper/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/rails3_mongo_mapper/config/initializers/inflections.rb +10 -0
- data/spec/rails3_mongo_mapper/config/initializers/mime_types.rb +5 -0
- data/spec/rails3_mongo_mapper/config/initializers/mongo.rb +2 -0
- data/spec/rails3_mongo_mapper/config/initializers/secret_token.rb +7 -0
- data/spec/rails3_mongo_mapper/config/initializers/session_store.rb +8 -0
- data/spec/rails3_mongo_mapper/config/locales/en.yml +5 -0
- data/spec/rails3_mongo_mapper/config/routes.rb +59 -0
- data/spec/rails3_mongo_mapper/config.ru +4 -0
- data/spec/rails3_mongo_mapper/db/schema.rb +23 -0
- data/spec/rails3_mongo_mapper/db/seeds.rb +7 -0
- data/spec/rails3_mongo_mapper/lib/tasks/.gitkeep +0 -0
- data/spec/rails3_mongo_mapper/public/404.html +26 -0
- data/spec/rails3_mongo_mapper/public/422.html +26 -0
- data/spec/rails3_mongo_mapper/public/500.html +26 -0
- data/spec/rails3_mongo_mapper/public/favicon.ico +0 -0
- data/spec/rails3_mongo_mapper/public/images/rails.png +0 -0
- data/spec/rails3_mongo_mapper/public/javascripts/application.js +2 -0
- data/spec/rails3_mongo_mapper/public/javascripts/controls.js +965 -0
- data/spec/rails3_mongo_mapper/public/javascripts/dragdrop.js +974 -0
- data/spec/rails3_mongo_mapper/public/javascripts/effects.js +1123 -0
- data/spec/rails3_mongo_mapper/public/javascripts/prototype.js +6001 -0
- data/spec/rails3_mongo_mapper/public/javascripts/rails.js +175 -0
- data/spec/rails3_mongo_mapper/public/robots.txt +5 -0
- data/spec/rails3_mongo_mapper/public/stylesheets/.gitkeep +0 -0
- data/spec/rails3_mongo_mapper/script/rails +6 -0
- data/spec/rails3_mongo_mapper/spec/controller_spec.rb +170 -0
- data/spec/rails3_mongo_mapper/spec/spec_helper.orig.rb +27 -0
- data/spec/rails3_mongo_mapper/spec/spec_helper.rb +55 -0
- data/spec/rails3_mongo_mapper/spec/user_activation_spec.rb +9 -0
- data/spec/rails3_mongo_mapper/spec/user_activity_logging_spec.rb +8 -0
- data/spec/rails3_mongo_mapper/spec/user_brute_force_protection_spec.rb +8 -0
- data/spec/rails3_mongo_mapper/spec/user_oauth_spec.rb +8 -0
- data/spec/rails3_mongo_mapper/spec/user_remember_me_spec.rb +8 -0
- data/spec/rails3_mongo_mapper/spec/user_reset_password_spec.rb +8 -0
- data/spec/rails3_mongo_mapper/spec/user_spec.rb +37 -0
- data/spec/rails3_mongo_mapper/vendor/plugins/.gitkeep +0 -0
- data/spec/rails3_mongoid/Gemfile +2 -1
- data/spec/rails3_mongoid/Gemfile.lock +47 -42
- data/spec/rails3_mongoid/app/controllers/application_controller.rb +19 -0
- data/spec/rails3_mongoid/config/mongoid.yml +1 -1
- data/spec/rails3_mongoid/script/rails +0 -0
- data/spec/rails3_mongoid/spec/controller_activity_logging_spec.rb +105 -0
- data/spec/rails3_mongoid/spec/controller_spec.rb +52 -1
- data/spec/rails3_mongoid/spec/user_spec.rb +1 -0
- data/spec/shared_examples/controller_oauth2_shared_examples.rb +20 -1
- data/spec/shared_examples/controller_oauth_shared_examples.rb +18 -0
- data/spec/shared_examples/user_activation_shared_examples.rb +72 -42
- data/spec/shared_examples/user_remember_me_shared_examples.rb +1 -1
- data/spec/shared_examples/user_reset_password_shared_examples.rb +81 -28
- data/spec/shared_examples/user_shared_examples.rb +29 -1
- data/spec/sorcery_crypto_providers_spec.rb +14 -1
- metadata +111 -229
- data/lib/generators/sorcery_migration/sorcery_migration_generator.rb +0 -24
- data/lib/generators/sorcery_migration/templates/activity_logging.rb +0 -17
- data/lib/generators/sorcery_migration/templates/brute_force_protection.rb +0 -11
- data/lib/generators/sorcery_migration/templates/remember_me.rb +0 -15
- data/lib/generators/sorcery_migration/templates/reset_password.rb +0 -17
- data/lib/generators/sorcery_migration/templates/user_activation.rb +0 -17
- data/lib/sorcery/controller/adapters/sinatra.rb +0 -115
- data/lib/sorcery/initializers/initializer.rb +0 -199
- data/lib/sorcery/sinatra.rb +0 -4
- data/lib/sorcery/test_helpers/internal/sinatra.rb +0 -74
- data/lib/sorcery/test_helpers/internal/sinatra_modular.rb +0 -74
- data/lib/sorcery/test_helpers/sinatra.rb +0 -88
- data/spec/rails3/Rakefile.unused +0 -7
- data/spec/sinatra/Gemfile +0 -15
- data/spec/sinatra/Gemfile.lock +0 -115
- data/spec/sinatra/authentication.rb +0 -3
- data/spec/sinatra/db/migrate/activation/20101224223622_add_activation_to_users.rb +0 -17
- data/spec/sinatra/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +0 -17
- data/spec/sinatra/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +0 -11
- data/spec/sinatra/db/migrate/core/20101224223620_create_users.rb +0 -16
- data/spec/sinatra/db/migrate/external/20101224223628_create_authentications.rb +0 -14
- data/spec/sinatra/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb +0 -15
- data/spec/sinatra/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +0 -13
- data/spec/sinatra/filters.rb +0 -27
- data/spec/sinatra/modular.rb +0 -157
- data/spec/sinatra/myapp.rb +0 -133
- data/spec/sinatra/spec/controller_activity_logging_spec.rb +0 -85
- data/spec/sinatra/spec/controller_brute_force_protection_spec.rb +0 -70
- data/spec/sinatra/spec/controller_http_basic_auth_spec.rb +0 -53
- data/spec/sinatra/spec/controller_oauth2_spec.rb +0 -96
- data/spec/sinatra/spec/controller_oauth_spec.rb +0 -100
- data/spec/sinatra/spec/controller_remember_me_spec.rb +0 -64
- data/spec/sinatra/spec/controller_session_timeout_spec.rb +0 -57
- data/spec/sinatra/spec/controller_spec.rb +0 -127
- data/spec/sinatra/spec/spec_helper.rb +0 -45
- data/spec/sinatra/user.rb +0 -6
- data/spec/sinatra/views/test_login.erb +0 -4
- data/spec/sinatra_modular/Gemfile.lock +0 -115
- data/spec/sinatra_modular/Rakefile +0 -11
- data/spec/sinatra_modular/authentication.rb +0 -3
- data/spec/sinatra_modular/db/migrate/activation/20101224223622_add_activation_to_users.rb +0 -17
- data/spec/sinatra_modular/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +0 -17
- data/spec/sinatra_modular/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +0 -11
- data/spec/sinatra_modular/db/migrate/core/20101224223620_create_users.rb +0 -16
- data/spec/sinatra_modular/db/migrate/external/20101224223628_create_authentications.rb +0 -14
- data/spec/sinatra_modular/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb +0 -15
- data/spec/sinatra_modular/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +0 -13
- data/spec/sinatra_modular/filters.rb +0 -27
- data/spec/sinatra_modular/modular.rb +0 -157
- data/spec/sinatra_modular/myapp.rb +0 -133
- data/spec/sinatra_modular/sorcery_mailer.rb +0 -25
- data/spec/sinatra_modular/spec_modular/controller_activity_logging_spec.rb +0 -85
- data/spec/sinatra_modular/spec_modular/controller_brute_force_protection_spec.rb +0 -70
- data/spec/sinatra_modular/spec_modular/controller_http_basic_auth_spec.rb +0 -53
- data/spec/sinatra_modular/spec_modular/controller_oauth2_spec.rb +0 -96
- data/spec/sinatra_modular/spec_modular/controller_oauth_spec.rb +0 -100
- data/spec/sinatra_modular/spec_modular/controller_remember_me_spec.rb +0 -64
- data/spec/sinatra_modular/spec_modular/controller_session_timeout_spec.rb +0 -57
- data/spec/sinatra_modular/spec_modular/controller_spec.rb +0 -116
- data/spec/sinatra_modular/spec_modular/spec.opts +0 -2
- data/spec/sinatra_modular/spec_modular/spec_helper.rb +0 -51
- data/spec/sinatra_modular/user.rb +0 -6
- data/spec/sinatra_modular/views/test_login.erb +0 -4
- /data/spec/{sinatra → rails3_mongo_mapper/app/mailers}/sorcery_mailer.rb +0 -0
- /data/spec/{sinatra → rails3_mongo_mapper}/spec/spec.opts +0 -0
|
@@ -1,31 +1,40 @@
|
|
|
1
1
|
module Sorcery
|
|
2
2
|
module Controller
|
|
3
3
|
module Submodules
|
|
4
|
-
# The Remember Me submodule takes care of setting the user's cookie so that he will
|
|
4
|
+
# The Remember Me submodule takes care of setting the user's cookie so that he will
|
|
5
5
|
# be automatically logged in to the site on every visit,
|
|
6
6
|
# until the cookie expires.
|
|
7
7
|
# See Sorcery::Model::Submodules::RememberMe for configuration options.
|
|
8
8
|
module RememberMe
|
|
9
9
|
def self.included(base)
|
|
10
10
|
base.send(:include, InstanceMethods)
|
|
11
|
+
Config.module_eval do
|
|
12
|
+
class << self
|
|
13
|
+
attr_accessor :remember_me_httponly
|
|
14
|
+
def merge_remember_me_defaults!
|
|
15
|
+
@defaults.merge!(:@remember_me_httponly => true)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
merge_remember_me_defaults!
|
|
19
|
+
end
|
|
11
20
|
Config.login_sources << :login_from_cookie
|
|
12
21
|
Config.after_login << :remember_me_if_asked_to
|
|
13
22
|
Config.after_logout << :forget_me!
|
|
14
23
|
end
|
|
15
|
-
|
|
24
|
+
|
|
16
25
|
module InstanceMethods
|
|
17
26
|
# This method sets the cookie and calls the user to save the token and the expiration to db.
|
|
18
27
|
def remember_me!
|
|
19
28
|
current_user.remember_me!
|
|
20
|
-
set_remember_me_cookie!(current_user)
|
|
29
|
+
set_remember_me_cookie!(current_user)
|
|
21
30
|
end
|
|
22
31
|
|
|
23
32
|
# Clears the cookie and clears the token from the db.
|
|
24
33
|
def forget_me!
|
|
25
|
-
current_user.forget_me!
|
|
26
|
-
cookies
|
|
34
|
+
@current_user.forget_me!
|
|
35
|
+
cookies.delete(:remember_me_token, :domain => Config.cookie_domain)
|
|
27
36
|
end
|
|
28
|
-
|
|
37
|
+
|
|
29
38
|
# Override.
|
|
30
39
|
# logins a user instance, and optionally remembers him.
|
|
31
40
|
def auto_login(user, should_remember = false)
|
|
@@ -33,33 +42,35 @@ module Sorcery
|
|
|
33
42
|
@current_user = user
|
|
34
43
|
remember_me! if should_remember
|
|
35
44
|
end
|
|
36
|
-
|
|
45
|
+
|
|
37
46
|
protected
|
|
38
|
-
|
|
47
|
+
|
|
39
48
|
# calls remember_me! if a third credential was passed to the login method.
|
|
40
49
|
# Runs as a hook after login.
|
|
41
50
|
def remember_me_if_asked_to(user, credentials)
|
|
42
51
|
remember_me! if ( credentials.size == 3 && credentials[2] && credentials[2] != "0" )
|
|
43
52
|
end
|
|
44
|
-
|
|
45
|
-
# Checks the cookie for a remember me token, tried to find a user with that token
|
|
53
|
+
|
|
54
|
+
# Checks the cookie for a remember me token, tried to find a user with that token
|
|
46
55
|
# and logs the user in if found.
|
|
47
56
|
# Runs as a login source. See 'current_user' method for how it is used.
|
|
48
57
|
def login_from_cookie
|
|
49
58
|
user = cookies.signed[:remember_me_token] && user_class.find_by_remember_me_token(cookies.signed[:remember_me_token])
|
|
50
59
|
if user && user.remember_me_token?
|
|
51
60
|
set_remember_me_cookie!(user)
|
|
61
|
+
session[:user_id] = user.id
|
|
52
62
|
@current_user = user
|
|
53
63
|
else
|
|
54
64
|
@current_user = false
|
|
55
65
|
end
|
|
56
66
|
end
|
|
57
|
-
|
|
67
|
+
|
|
58
68
|
def set_remember_me_cookie!(user)
|
|
59
|
-
cookies.signed[:remember_me_token] = {
|
|
60
|
-
:value => user.send(user.sorcery_config.remember_me_token_attribute_name),
|
|
69
|
+
cookies.signed[:remember_me_token] = {
|
|
70
|
+
:value => user.send(user.sorcery_config.remember_me_token_attribute_name),
|
|
61
71
|
:expires => user.send(user.sorcery_config.remember_me_token_expires_at_attribute_name),
|
|
62
|
-
:httponly =>
|
|
72
|
+
:httponly => Config.remember_me_httponly,
|
|
73
|
+
:domain => Config.cookie_domain
|
|
63
74
|
}
|
|
64
75
|
end
|
|
65
76
|
end
|
|
@@ -67,4 +78,4 @@ module Sorcery
|
|
|
67
78
|
end
|
|
68
79
|
end
|
|
69
80
|
end
|
|
70
|
-
end
|
|
81
|
+
end
|
|
@@ -30,18 +30,18 @@ module Sorcery
|
|
|
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
|
-
session[:login_time] = session[:last_action_time] = Time.now.
|
|
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 && (Time.now.
|
|
40
|
+
if session_to_use && (Time.now.in_time_zone - session_to_use > Config.session_timeout)
|
|
41
41
|
reset_session
|
|
42
42
|
@current_user = nil
|
|
43
43
|
else
|
|
44
|
-
session[:last_action_time] = Time.now.
|
|
44
|
+
session[:last_action_time] = Time.now.in_time_zone
|
|
45
45
|
end
|
|
46
46
|
end
|
|
47
47
|
|
data/lib/sorcery/controller.rb
CHANGED
|
@@ -5,7 +5,7 @@ module Sorcery
|
|
|
5
5
|
include InstanceMethods
|
|
6
6
|
Config.submodules.each do |mod|
|
|
7
7
|
begin
|
|
8
|
-
include Submodules.const_get(mod.to_s.split("_").map {|p| p.capitalize}.join(""))
|
|
8
|
+
include Submodules.const_get(mod.to_s.split("_").map {|p| p.capitalize}.join(""))
|
|
9
9
|
rescue NameError
|
|
10
10
|
# don't stop on a missing submodule.
|
|
11
11
|
end
|
|
@@ -14,26 +14,29 @@ module Sorcery
|
|
|
14
14
|
Config.update!
|
|
15
15
|
Config.configure!
|
|
16
16
|
end
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
module InstanceMethods
|
|
19
19
|
# To be used as before_filter.
|
|
20
20
|
# Will trigger auto-login attempts via the call to logged_in?
|
|
21
21
|
# If all attempts to auto-login fail, the failure callback will be called.
|
|
22
22
|
def require_login
|
|
23
23
|
if !logged_in?
|
|
24
|
-
session[:return_to_url] = request.url if Config.save_return_to_url
|
|
25
|
-
self.send(Config.not_authenticated_action)
|
|
24
|
+
session[:return_to_url] = request.url if Config.save_return_to_url && request.get?
|
|
25
|
+
self.send(Config.not_authenticated_action)
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
# Takes credentials and returns a user on successful authentication.
|
|
30
30
|
# Runs hooks after login or failed login.
|
|
31
|
-
|
|
31
|
+
def login(*credentials)
|
|
32
|
+
@current_user = nil
|
|
32
33
|
user = user_class.authenticate(*credentials)
|
|
33
34
|
if user
|
|
34
|
-
|
|
35
|
+
old_session = session.dup
|
|
35
36
|
reset_session # protect from session fixation attacks
|
|
36
|
-
|
|
37
|
+
old_session.to_hash.each_pair do |k,v|
|
|
38
|
+
session[k.to_sym] = v
|
|
39
|
+
end
|
|
37
40
|
auto_login(user)
|
|
38
41
|
after_login!(user, credentials)
|
|
39
42
|
current_user
|
|
@@ -42,43 +45,45 @@ module Sorcery
|
|
|
42
45
|
nil
|
|
43
46
|
end
|
|
44
47
|
end
|
|
45
|
-
|
|
48
|
+
|
|
46
49
|
# Resets the session and runs hooks before and after.
|
|
47
50
|
def logout
|
|
48
51
|
if logged_in?
|
|
49
52
|
before_logout!(current_user)
|
|
50
53
|
reset_session
|
|
51
54
|
after_logout!
|
|
55
|
+
@current_user = nil
|
|
52
56
|
end
|
|
53
57
|
end
|
|
54
|
-
|
|
58
|
+
|
|
55
59
|
def logged_in?
|
|
56
60
|
!!current_user
|
|
57
61
|
end
|
|
58
|
-
|
|
62
|
+
|
|
59
63
|
# attempts to auto-login from the sources defined (session, basic_auth, cookie, etc.)
|
|
60
64
|
# returns the logged in user if found, false if not (using old restful-authentication trick, nil != false).
|
|
61
65
|
def current_user
|
|
62
66
|
@current_user ||= login_from_session || login_from_other_sources unless @current_user == false
|
|
63
67
|
end
|
|
64
|
-
|
|
68
|
+
|
|
65
69
|
def current_user=(user)
|
|
66
70
|
@current_user = user
|
|
67
71
|
end
|
|
68
|
-
|
|
69
|
-
# used when a user tries to access a page while logged out, is asked to login,
|
|
72
|
+
|
|
73
|
+
# used when a user tries to access a page while logged out, is asked to login,
|
|
70
74
|
# and we want to return him back to the page he originally wanted.
|
|
71
75
|
def redirect_back_or_to(url, flash_hash = {})
|
|
72
76
|
redirect_to(session[:return_to_url] || url, :flash => flash_hash)
|
|
77
|
+
session[:return_to_url] = nil
|
|
73
78
|
end
|
|
74
|
-
|
|
79
|
+
|
|
75
80
|
# The default action for denying non-authenticated users.
|
|
76
81
|
# You can override this method in your controllers,
|
|
77
82
|
# or provide a different method in the configuration.
|
|
78
83
|
def not_authenticated
|
|
79
84
|
redirect_to root_path
|
|
80
85
|
end
|
|
81
|
-
|
|
86
|
+
|
|
82
87
|
# login a user instance
|
|
83
88
|
#
|
|
84
89
|
# @param [<User-Model>] user the user instance.
|
|
@@ -87,16 +92,16 @@ module Sorcery
|
|
|
87
92
|
session[:user_id] = user.id
|
|
88
93
|
@current_user = user
|
|
89
94
|
end
|
|
90
|
-
|
|
95
|
+
|
|
91
96
|
# Overwrite Rails' handle unverified request
|
|
92
97
|
def handle_unverified_request
|
|
93
98
|
cookies[:remember_me_token] = nil
|
|
94
99
|
@current_user = nil
|
|
95
100
|
super # call the default behaviour which resets the session
|
|
96
101
|
end
|
|
97
|
-
|
|
102
|
+
|
|
98
103
|
protected
|
|
99
|
-
|
|
104
|
+
|
|
100
105
|
# Tries all available sources (methods) until one doesn't return false.
|
|
101
106
|
def login_from_other_sources
|
|
102
107
|
result = nil
|
|
@@ -105,51 +110,55 @@ module Sorcery
|
|
|
105
110
|
end
|
|
106
111
|
result || false
|
|
107
112
|
end
|
|
108
|
-
|
|
113
|
+
|
|
109
114
|
def login_from_session
|
|
110
|
-
@current_user = (user_class.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
115
|
+
@current_user = (user_class.find(session[:user_id]) if session[:user_id]) || false
|
|
116
|
+
rescue => exception
|
|
117
|
+
return false if defined?(Mongoid) and exception.is_a?(Mongoid::Errors::DocumentNotFound)
|
|
118
|
+
return false if defined?(ActiveRecord) and exception.is_a?(ActiveRecord::RecordNotFound)
|
|
119
|
+
raise exception
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def after_login!(user, credentials = [])
|
|
114
123
|
Config.after_login.each {|c| self.send(c, user, credentials)}
|
|
115
124
|
end
|
|
116
|
-
|
|
125
|
+
|
|
117
126
|
def after_failed_login!(credentials)
|
|
118
127
|
Config.after_failed_login.each {|c| self.send(c, credentials)}
|
|
119
128
|
end
|
|
120
|
-
|
|
129
|
+
|
|
121
130
|
def before_logout!(user)
|
|
122
131
|
Config.before_logout.each {|c| self.send(c, user)}
|
|
123
132
|
end
|
|
124
|
-
|
|
133
|
+
|
|
125
134
|
def after_logout!
|
|
126
135
|
Config.after_logout.each {|c| self.send(c)}
|
|
127
136
|
end
|
|
128
|
-
|
|
137
|
+
|
|
129
138
|
def user_class
|
|
130
139
|
@user_class ||= Config.user_class.to_s.constantize
|
|
131
140
|
end
|
|
132
|
-
|
|
141
|
+
|
|
133
142
|
end
|
|
134
|
-
|
|
143
|
+
|
|
135
144
|
module Config
|
|
136
145
|
class << self
|
|
137
146
|
attr_accessor :submodules,
|
|
138
|
-
:user_class, # what class to use as the user class.
|
|
147
|
+
:user_class, # what class to use as the user class.
|
|
139
148
|
:not_authenticated_action, # what controller action to call for non-authenticated users.
|
|
140
|
-
|
|
149
|
+
|
|
141
150
|
:save_return_to_url, # when a non logged in user tries to enter a page that requires
|
|
142
|
-
# login, save the URL he wanted to reach,
|
|
151
|
+
# login, save the URL he wanted to reach,
|
|
143
152
|
# and send him there after login.
|
|
144
|
-
|
|
145
|
-
:
|
|
146
|
-
|
|
153
|
+
|
|
154
|
+
:cookie_domain, # set domain option for cookies
|
|
155
|
+
|
|
147
156
|
:login_sources,
|
|
148
157
|
:after_login,
|
|
149
158
|
:after_failed_login,
|
|
150
159
|
:before_logout,
|
|
151
|
-
:after_logout
|
|
152
|
-
|
|
160
|
+
:after_logout
|
|
161
|
+
|
|
153
162
|
def init!
|
|
154
163
|
@defaults = {
|
|
155
164
|
:@user_class => nil,
|
|
@@ -161,31 +170,31 @@ module Sorcery
|
|
|
161
170
|
:@before_logout => [],
|
|
162
171
|
:@after_logout => [],
|
|
163
172
|
:@save_return_to_url => true,
|
|
164
|
-
:@
|
|
173
|
+
:@cookie_domain => nil
|
|
165
174
|
}
|
|
166
175
|
end
|
|
167
|
-
|
|
176
|
+
|
|
168
177
|
# Resets all configuration options to their default values.
|
|
169
178
|
def reset!
|
|
170
179
|
@defaults.each do |k,v|
|
|
171
180
|
instance_variable_set(k,v)
|
|
172
|
-
end
|
|
181
|
+
end
|
|
173
182
|
end
|
|
174
|
-
|
|
183
|
+
|
|
175
184
|
def update!
|
|
176
185
|
@defaults.each do |k,v|
|
|
177
186
|
instance_variable_set(k,v) if !instance_variable_defined?(k)
|
|
178
187
|
end
|
|
179
188
|
end
|
|
180
|
-
|
|
189
|
+
|
|
181
190
|
def user_config(&blk)
|
|
182
191
|
block_given? ? @user_config = blk : @user_config
|
|
183
192
|
end
|
|
184
|
-
|
|
193
|
+
|
|
185
194
|
def configure(&blk)
|
|
186
195
|
@configure_blk = blk
|
|
187
196
|
end
|
|
188
|
-
|
|
197
|
+
|
|
189
198
|
def configure!
|
|
190
199
|
@configure_blk.call(self) if @configure_blk
|
|
191
200
|
end
|
|
@@ -194,4 +203,4 @@ module Sorcery
|
|
|
194
203
|
reset!
|
|
195
204
|
end
|
|
196
205
|
end
|
|
197
|
-
end
|
|
206
|
+
end
|
|
@@ -4,11 +4,31 @@ module Sorcery
|
|
|
4
4
|
module ActiveRecord
|
|
5
5
|
def self.included(klass)
|
|
6
6
|
klass.extend ClassMethods
|
|
7
|
+
klass.send(:include, InstanceMethods)
|
|
7
8
|
end
|
|
8
9
|
|
|
10
|
+
module InstanceMethods
|
|
11
|
+
def update_many_attributes(attrs)
|
|
12
|
+
attrs.each do |name, value|
|
|
13
|
+
self.send(:"#{name}=", value)
|
|
14
|
+
end
|
|
15
|
+
primary_key = self.class.primary_key
|
|
16
|
+
self.class.where(:"#{primary_key}" => self.send(:"#{primary_key}")).update_all(attrs)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def update_single_attribute(name, value)
|
|
20
|
+
update_many_attributes(name => value)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
9
24
|
module ClassMethods
|
|
25
|
+
def column_name(attribute)
|
|
26
|
+
return "LOWER(#{attribute})" if (@sorcery_config.downcase_username_before_authenticating)
|
|
27
|
+
return "#{attribute}"
|
|
28
|
+
end
|
|
29
|
+
|
|
10
30
|
def find_by_credentials(credentials)
|
|
11
|
-
sql = @sorcery_config.username_attribute_names.map{|attribute|
|
|
31
|
+
sql = @sorcery_config.username_attribute_names.map{|attribute| column_name(attribute) + " = :login"}
|
|
12
32
|
where(sql.join(' OR '), :login => credentials[0]).first
|
|
13
33
|
end
|
|
14
34
|
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
module Sorcery
|
|
2
|
+
module Model
|
|
3
|
+
module Adapters
|
|
4
|
+
module MongoMapper
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
include Sorcery::Model
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def increment(attr)
|
|
12
|
+
self.class.increment(id, attr => 1)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def save!(options = {})
|
|
16
|
+
save(options)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def update_many_attributes(attrs)
|
|
20
|
+
update_attributes(attrs)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module ClassMethods
|
|
24
|
+
def credential_regex(credential)
|
|
25
|
+
return { :$regex => /^#{credential}$/i } if (@sorcery_config.downcase_username_before_authenticating)
|
|
26
|
+
return credential
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def find_by_credentials(credentials)
|
|
30
|
+
@sorcery_config.username_attribute_names.each do |attribute|
|
|
31
|
+
@user = where(attribute => credential_regex(credentials[0])).first
|
|
32
|
+
break if @user
|
|
33
|
+
end
|
|
34
|
+
@user
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def find_by_id(id)
|
|
38
|
+
find(id)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def find_by_activation_token(token)
|
|
42
|
+
where(sorcery_config.activation_token_attribute_name => token).first
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def transaction(&blk)
|
|
46
|
+
tap(&blk)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def find_by_sorcery_token(token_attr_name, token)
|
|
50
|
+
where(token_attr_name => token).first
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -11,12 +11,29 @@ module Sorcery
|
|
|
11
11
|
def increment(attr)
|
|
12
12
|
self.inc(attr,1)
|
|
13
13
|
end
|
|
14
|
+
|
|
15
|
+
def update_many_attributes(attrs)
|
|
16
|
+
attrs.each do |name, value|
|
|
17
|
+
attrs[name] = value.utc if value.is_a?(ActiveSupport::TimeWithZone)
|
|
18
|
+
self.send(:"#{name}=", value)
|
|
19
|
+
end
|
|
20
|
+
self.class.where(:_id => self.id).update_all(attrs)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def update_single_attribute(name, value)
|
|
24
|
+
update_many_attributes(name => value)
|
|
25
|
+
end
|
|
14
26
|
end
|
|
15
27
|
|
|
16
28
|
module ClassMethods
|
|
29
|
+
def credential_regex(credential)
|
|
30
|
+
return { :$regex => /^#{credential}$/i } if (@sorcery_config.downcase_username_before_authenticating)
|
|
31
|
+
return credential
|
|
32
|
+
end
|
|
33
|
+
|
|
17
34
|
def find_by_credentials(credentials)
|
|
18
35
|
@sorcery_config.username_attribute_names.each do |attribute|
|
|
19
|
-
@user = where(attribute => credentials[0]).first
|
|
36
|
+
@user = where(attribute => credential_regex(credentials[0])).first
|
|
20
37
|
break if @user
|
|
21
38
|
end
|
|
22
39
|
@user
|
|
@@ -29,6 +46,8 @@ module Sorcery
|
|
|
29
46
|
|
|
30
47
|
def find_by_id(id)
|
|
31
48
|
find(id)
|
|
49
|
+
rescue ::Mongoid::Errors::DocumentNotFound
|
|
50
|
+
nil
|
|
32
51
|
end
|
|
33
52
|
|
|
34
53
|
def find_by_activation_token(token)
|
|
@@ -41,7 +60,7 @@ module Sorcery
|
|
|
41
60
|
|
|
42
61
|
def find_by_username(username)
|
|
43
62
|
query = sorcery_config.username_attribute_names.map {|name| {name => username}}
|
|
44
|
-
|
|
63
|
+
any_of(*query).first
|
|
45
64
|
end
|
|
46
65
|
|
|
47
66
|
def transaction(&blk)
|
|
@@ -59,8 +78,8 @@ module Sorcery
|
|
|
59
78
|
def get_current_users
|
|
60
79
|
config = sorcery_config
|
|
61
80
|
where(config.last_activity_at_attribute_name.ne => nil) \
|
|
62
|
-
.
|
|
63
|
-
.
|
|
81
|
+
.where("this.#{config.last_logout_at_attribute_name} == null || this.#{config.last_activity_at_attribute_name} > this.#{config.last_logout_at_attribute_name}") \
|
|
82
|
+
.where(config.last_activity_at_attribute_name.gt => config.activity_timeout.seconds.ago.utc).order_by([:_id,:asc])
|
|
64
83
|
end
|
|
65
84
|
end
|
|
66
85
|
end
|
|
@@ -39,12 +39,12 @@ module Sorcery
|
|
|
39
39
|
protected
|
|
40
40
|
|
|
41
41
|
def define_activity_logging_mongoid_fields
|
|
42
|
-
field sorcery_config.last_login_at_attribute_name, :type =>
|
|
43
|
-
field sorcery_config.last_logout_at_attribute_name, :type =>
|
|
44
|
-
field sorcery_config.last_activity_at_attribute_name, :type =>
|
|
42
|
+
field sorcery_config.last_login_at_attribute_name, :type => Time
|
|
43
|
+
field sorcery_config.last_logout_at_attribute_name, :type => Time
|
|
44
|
+
field sorcery_config.last_activity_at_attribute_name, :type => Time
|
|
45
45
|
end
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
end
|
|
50
|
-
end
|
|
50
|
+
end
|
|
@@ -12,30 +12,56 @@ module Sorcery
|
|
|
12
12
|
:lock_expires_at_attribute_name, # this field indicates whether user
|
|
13
13
|
# is banned and when it will be active again.
|
|
14
14
|
:consecutive_login_retries_amount_limit, # how many failed logins allowed.
|
|
15
|
-
:login_lock_time_period
|
|
15
|
+
:login_lock_time_period, # how long the user should be banned.
|
|
16
16
|
# in seconds. 0 for permanent.
|
|
17
|
+
|
|
18
|
+
:unlock_token_attribute_name, # Unlock token attribute name
|
|
19
|
+
:unlock_token_email_method_name, # Mailer method name
|
|
20
|
+
:unlock_token_mailer_disabled, # When true, dont send unlock token via email
|
|
21
|
+
:unlock_token_mailer # Mailer class
|
|
17
22
|
end
|
|
18
23
|
|
|
19
24
|
base.sorcery_config.instance_eval do
|
|
20
25
|
@defaults.merge!(:@failed_logins_count_attribute_name => :failed_logins_count,
|
|
21
26
|
:@lock_expires_at_attribute_name => :lock_expires_at,
|
|
22
27
|
:@consecutive_login_retries_amount_limit => 50,
|
|
23
|
-
:@login_lock_time_period => 60 * 60
|
|
28
|
+
:@login_lock_time_period => 60 * 60,
|
|
29
|
+
|
|
30
|
+
:@unlock_token_attribute_name => :unlock_token,
|
|
31
|
+
:@unlock_token_email_method_name => :send_unlock_token_email,
|
|
32
|
+
:@unlock_token_mailer_disabled => false,
|
|
33
|
+
:@unlock_token_mailer => nil)
|
|
24
34
|
reset!
|
|
25
35
|
end
|
|
26
36
|
|
|
27
37
|
base.sorcery_config.before_authenticate << :prevent_locked_user_login
|
|
28
38
|
base.sorcery_config.after_config << :define_brute_force_protection_mongoid_fields if defined?(Mongoid) and base.ancestors.include?(Mongoid::Document)
|
|
39
|
+
if defined?(MongoMapper) and base.ancestors.include?(MongoMapper::Document)
|
|
40
|
+
base.sorcery_config.after_config << :define_brute_force_protection_mongo_mapper_fields
|
|
41
|
+
end
|
|
29
42
|
base.extend(ClassMethods)
|
|
30
43
|
base.send(:include, InstanceMethods)
|
|
31
44
|
end
|
|
32
45
|
|
|
33
46
|
module ClassMethods
|
|
47
|
+
def load_from_unlock_token(token)
|
|
48
|
+
return nil if token.blank?
|
|
49
|
+
user = find_by_sorcery_token(sorcery_config.unlock_token_attribute_name,token)
|
|
50
|
+
user
|
|
51
|
+
end
|
|
52
|
+
|
|
34
53
|
protected
|
|
35
54
|
|
|
36
55
|
def define_brute_force_protection_mongoid_fields
|
|
37
|
-
field sorcery_config.failed_logins_count_attribute_name, :type => Integer
|
|
38
|
-
field sorcery_config.lock_expires_at_attribute_name, :type =>
|
|
56
|
+
field sorcery_config.failed_logins_count_attribute_name, :type => Integer, :default => 0
|
|
57
|
+
field sorcery_config.lock_expires_at_attribute_name, :type => Time
|
|
58
|
+
field sorcery_config.unlock_token_attribute_name, :type => String
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def define_brute_force_protection_mongo_mapper_fields
|
|
62
|
+
key sorcery_config.failed_logins_count_attribute_name, Integer, :default => 0
|
|
63
|
+
key sorcery_config.lock_expires_at_attribute_name, Time
|
|
64
|
+
key sorcery_config.unlock_token_attribute_name, String
|
|
39
65
|
end
|
|
40
66
|
end
|
|
41
67
|
|
|
@@ -46,36 +72,49 @@ module Sorcery
|
|
|
46
72
|
config = sorcery_config
|
|
47
73
|
return if !unlocked?
|
|
48
74
|
self.increment(config.failed_logins_count_attribute_name)
|
|
49
|
-
|
|
75
|
+
self.update_many_attributes(config.failed_logins_count_attribute_name => self.send(config.failed_logins_count_attribute_name))
|
|
50
76
|
self.lock! if self.send(config.failed_logins_count_attribute_name) >= config.consecutive_login_retries_amount_limit
|
|
51
77
|
end
|
|
52
78
|
|
|
79
|
+
# /!\
|
|
80
|
+
# Moved out of protected for use like activate! in controller
|
|
81
|
+
# /!\
|
|
82
|
+
def unlock!
|
|
83
|
+
config = sorcery_config
|
|
84
|
+
attributes = {config.lock_expires_at_attribute_name => nil,
|
|
85
|
+
config.failed_logins_count_attribute_name => 0}
|
|
86
|
+
attributes[config.unlock_token_attribute_name] = nil unless config.unlock_token_mailer_disabled or config.unlock_token_mailer.nil?
|
|
87
|
+
self.update_many_attributes(attributes)
|
|
88
|
+
end
|
|
89
|
+
|
|
53
90
|
protected
|
|
54
91
|
|
|
55
92
|
def lock!
|
|
56
93
|
config = sorcery_config
|
|
57
|
-
|
|
58
|
-
self.save!
|
|
59
|
-
end
|
|
94
|
+
attributes = {config.lock_expires_at_attribute_name => Time.now.in_time_zone + config.login_lock_time_period}
|
|
60
95
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
self.
|
|
96
|
+
unless config.unlock_token_mailer_disabled || config.unlock_token_mailer.nil?
|
|
97
|
+
attributes[config.unlock_token_attribute_name] = TemporaryToken.generate_random_token
|
|
98
|
+
send_unlock_token_email!
|
|
99
|
+
end
|
|
100
|
+
self.update_many_attributes(attributes)
|
|
66
101
|
end
|
|
67
102
|
|
|
68
103
|
def unlocked?
|
|
69
104
|
config = sorcery_config
|
|
70
105
|
self.send(config.lock_expires_at_attribute_name).nil?
|
|
71
106
|
end
|
|
107
|
+
|
|
108
|
+
def send_unlock_token_email!
|
|
109
|
+
generic_send_email(:unlock_token_email_method_name, :unlock_token_mailer) unless sorcery_config.unlock_token_email_method_name.nil? or sorcery_config.unlock_token_mailer_disabled == true
|
|
110
|
+
end
|
|
72
111
|
|
|
73
112
|
# Prevents a locked user from logging in, and unlocks users that expired their lock time.
|
|
74
113
|
# Runs as a hook before authenticate.
|
|
75
114
|
def prevent_locked_user_login
|
|
76
115
|
config = sorcery_config
|
|
77
116
|
if !self.unlocked? && config.login_lock_time_period != 0
|
|
78
|
-
self.unlock! if self.send(config.lock_expires_at_attribute_name) <= Time.now.
|
|
117
|
+
self.unlock! if self.send(config.lock_expires_at_attribute_name) <= Time.now.in_time_zone
|
|
79
118
|
end
|
|
80
119
|
unlocked?
|
|
81
120
|
end
|
|
@@ -83,4 +122,4 @@ module Sorcery
|
|
|
83
122
|
end
|
|
84
123
|
end
|
|
85
124
|
end
|
|
86
|
-
end
|
|
125
|
+
end
|