sorcery 0.6.1 → 0.7.1
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/Gemfile +1 -0
- data/Gemfile.lock +52 -45
- data/README.rdoc +26 -54
- data/Rakefile +26 -0
- data/VERSION +1 -1
- data/lib/generators/sorcery/USAGE +22 -0
- data/lib/generators/sorcery/install_generator.rb +71 -0
- data/lib/{sorcery/initializers → generators/sorcery/templates}/initializer.rb +82 -61
- data/lib/generators/sorcery/templates/migration/activity_logging.rb +17 -0
- data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +11 -0
- data/lib/generators/{sorcery_migration/templates → sorcery/templates/migration}/core.rb +3 -3
- 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 +23 -9
- data/lib/sorcery/controller/submodules/brute_force_protection.rb +2 -1
- data/lib/sorcery/controller/submodules/external/protocols/certs/ca-bundle.crt +5182 -0
- data/lib/sorcery/controller/submodules/external/protocols/oauth2.rb +27 -8
- data/lib/sorcery/controller/submodules/external/providers/github.rb +80 -0
- data/lib/sorcery/controller/submodules/external/providers/twitter.rb +5 -0
- data/lib/sorcery/controller/submodules/external.rb +10 -3
- data/lib/sorcery/controller/submodules/http_basic_auth.rb +1 -1
- data/lib/sorcery/controller/submodules/remember_me.rb +15 -5
- data/lib/sorcery/controller/submodules/session_timeout.rb +1 -1
- data/lib/sorcery/controller.rb +59 -38
- data/lib/sorcery/crypto_providers/aes256.rb +7 -3
- data/lib/sorcery/engine.rb +1 -0
- data/lib/sorcery/model/adapters/active_record.rb +2 -1
- data/lib/sorcery/model/adapters/mongo_mapper.rb +49 -0
- data/lib/sorcery/model/adapters/mongoid.rb +7 -2
- data/lib/sorcery/model/submodules/brute_force_protection.rb +13 -3
- data/lib/sorcery/model/submodules/remember_me.rb +9 -2
- data/lib/sorcery/model/submodules/reset_password.rb +11 -2
- data/lib/sorcery/model/submodules/user_activation.rb +13 -2
- data/lib/sorcery/model/temporary_token.rb +5 -0
- data/lib/sorcery/model.rb +34 -15
- data/lib/sorcery/test_helpers/internal/rails.rb +1 -1
- data/lib/sorcery/test_helpers/rails.rb +2 -2
- data/lib/sorcery.rb +6 -7
- data/sorcery.gemspec +86 -203
- data/spec/Gemfile.lock +23 -12
- data/spec/README.md +31 -0
- data/spec/rails3/Gemfile +3 -1
- data/spec/rails3/Gemfile.lock +45 -28
- data/spec/rails3/app/controllers/application_controller.rb +40 -22
- data/spec/rails3/app/views/application/index.html.erb +17 -0
- data/spec/rails3/spec/controller_activity_logging_spec.rb +23 -0
- data/spec/rails3/spec/controller_oauth2_spec.rb +59 -16
- data/spec/rails3/spec/controller_remember_me_spec.rb +37 -6
- data/spec/rails3/spec/controller_spec.rb +30 -0
- data/spec/rails3/spec/integration_spec.rb +23 -0
- data/spec/rails3/spec/spec_helper.rb +6 -5
- data/spec/rails3_mongo_mapper/.gitignore +4 -0
- data/spec/rails3_mongo_mapper/.rspec +1 -0
- data/spec/{sinatra_modular → rails3_mongo_mapper}/Gemfile +5 -5
- data/spec/rails3_mongo_mapper/Gemfile.lock +159 -0
- data/spec/{sinatra → rails3_mongo_mapper}/Rakefile +3 -3
- data/spec/rails3_mongo_mapper/app/controllers/application_controller.rb +108 -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/{sinatra → rails3_mongo_mapper}/spec/controller_spec.rb +51 -41
- 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 +1 -1
- data/spec/rails3_mongoid/Gemfile.lock +41 -34
- data/spec/rails3_mongoid/spec/controller_activity_logging_spec.rb +98 -0
- data/spec/rails3_mongoid/spec/controller_spec.rb +130 -0
- data/spec/rails3_mongoid/spec/user_spec.rb +1 -0
- data/spec/shared_examples/user_remember_me_shared_examples.rb +1 -0
- data/spec/shared_examples/user_shared_examples.rb +36 -8
- metadata +128 -234
- 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 -13
- data/lib/generators/sorcery_migration/templates/user_activation.rb +0 -17
- data/lib/sorcery/controller/adapters/sinatra.rb +0 -104
- 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/rails3/public/index.html +0 -239
- data/spec/sinatra/Gemfile +0 -15
- data/spec/sinatra/Gemfile.lock +0 -117
- 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 -99
- 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/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 -117
- 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 -99
- 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
|
@@ -8,19 +8,38 @@ module Sorcery
|
|
|
8
8
|
def oauth_version
|
|
9
9
|
"2.0"
|
|
10
10
|
end
|
|
11
|
-
|
|
12
|
-
def authorize_url(
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
|
|
12
|
+
def authorize_url(options = {})
|
|
13
|
+
defaults = {
|
|
14
|
+
:site => @site,
|
|
15
|
+
:ssl => { :ca_file => Config.ca_file }
|
|
16
|
+
}
|
|
17
|
+
client = ::OAuth2::Client.new(
|
|
18
|
+
@key,
|
|
19
|
+
@secret,
|
|
20
|
+
defaults.merge!(options)
|
|
21
|
+
)
|
|
22
|
+
client.web_server.authorize_url(
|
|
23
|
+
:redirect_uri => @callback_url,
|
|
24
|
+
:scope => @scope
|
|
25
|
+
)
|
|
15
26
|
end
|
|
16
|
-
|
|
27
|
+
|
|
17
28
|
def get_access_token(args)
|
|
18
|
-
client = ::OAuth2::Client.new(
|
|
19
|
-
|
|
29
|
+
client = ::OAuth2::Client.new(
|
|
30
|
+
@key,
|
|
31
|
+
@secret,
|
|
32
|
+
:site => @site,
|
|
33
|
+
:ssl => { :ca_file => Config.ca_file }
|
|
34
|
+
)
|
|
35
|
+
client.web_server.get_access_token(
|
|
36
|
+
args[:code],
|
|
37
|
+
:redirect_uri => @callback_url
|
|
38
|
+
)
|
|
20
39
|
end
|
|
21
40
|
end
|
|
22
41
|
end
|
|
23
42
|
end
|
|
24
43
|
end
|
|
25
44
|
end
|
|
26
|
-
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
module Sorcery
|
|
2
|
+
module Controller
|
|
3
|
+
module Submodules
|
|
4
|
+
module External
|
|
5
|
+
module Providers
|
|
6
|
+
# This module adds support for OAuth with github.com.
|
|
7
|
+
# When included in the 'config.providers' option, it adds a new option, 'config.github'.
|
|
8
|
+
# Via this new option you can configure Github specific settings like your app's key and secret.
|
|
9
|
+
#
|
|
10
|
+
# config.github.key = <key>
|
|
11
|
+
# config.github.secret = <secret>
|
|
12
|
+
# ...
|
|
13
|
+
#
|
|
14
|
+
module Github
|
|
15
|
+
def self.included(base)
|
|
16
|
+
base.module_eval do
|
|
17
|
+
class << self
|
|
18
|
+
attr_reader :github # access to github_client.
|
|
19
|
+
|
|
20
|
+
def merge_github_defaults!
|
|
21
|
+
@defaults.merge!(:@github => GithubClient)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
merge_github_defaults!
|
|
25
|
+
update!
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
module GithubClient
|
|
30
|
+
class << self
|
|
31
|
+
attr_accessor :key,
|
|
32
|
+
:secret,
|
|
33
|
+
:callback_url,
|
|
34
|
+
:site,
|
|
35
|
+
:user_info_path,
|
|
36
|
+
:user_info_mapping
|
|
37
|
+
|
|
38
|
+
include Protocols::Oauth2
|
|
39
|
+
|
|
40
|
+
def init
|
|
41
|
+
@site = "https://github.com/"
|
|
42
|
+
@user_info_path = "/api/v2/json/user/show"
|
|
43
|
+
@user_info_mapping = {}
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def get_user_hash
|
|
47
|
+
user_hash = {}
|
|
48
|
+
response = @access_token.get(@user_info_path)
|
|
49
|
+
user_hash[:user_info] = JSON.parse(response)
|
|
50
|
+
user_hash[:uid] = user_hash[:user_info]['id']
|
|
51
|
+
user_hash
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def has_callback?
|
|
55
|
+
true
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# calculates and returns the url to which the user should be redirected,
|
|
59
|
+
# to get authenticated at the external provider's site.
|
|
60
|
+
def login_url(params,session)
|
|
61
|
+
self.authorize_url({:authorize_path => '/login/oauth/authorize'})
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# tries to login the user from access token
|
|
65
|
+
def process_callback(params,session)
|
|
66
|
+
args = {}
|
|
67
|
+
args.merge!({:code => params[:code]}) if params[:code]
|
|
68
|
+
@access_token = self.get_access_token(args)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|
|
72
|
+
init
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -39,6 +39,11 @@ module Sorcery
|
|
|
39
39
|
:user_info_mapping
|
|
40
40
|
|
|
41
41
|
include Protocols::Oauth1
|
|
42
|
+
|
|
43
|
+
# Override included get_consumer method to provide authorize_path
|
|
44
|
+
def get_consumer
|
|
45
|
+
::OAuth::Consumer.new(@key, @secret, :site => @site, :authorize_path => "/oauth/authenticate")
|
|
46
|
+
end
|
|
42
47
|
|
|
43
48
|
def init
|
|
44
49
|
@site = "https://api.twitter.com"
|
|
@@ -9,9 +9,11 @@ module Sorcery
|
|
|
9
9
|
Config.module_eval do
|
|
10
10
|
class << self
|
|
11
11
|
attr_reader :external_providers # external providers like twitter.
|
|
12
|
+
attr_accessor :ca_file # path to ca_file. By default use a internal ca-bundle.crt.
|
|
12
13
|
|
|
13
14
|
def merge_external_defaults!
|
|
14
|
-
@defaults.merge!(:@external_providers => []
|
|
15
|
+
@defaults.merge!(:@external_providers => [],
|
|
16
|
+
:@ca_file => File.join(File.expand_path(File.dirname(__FILE__)), 'external/protocols/certs/ca-bundle.crt'))
|
|
15
17
|
end
|
|
16
18
|
|
|
17
19
|
def external_providers=(providers)
|
|
@@ -45,7 +47,7 @@ module Sorcery
|
|
|
45
47
|
@user_hash = @provider.get_user_hash
|
|
46
48
|
if user = user_class.load_from_provider(provider,@user_hash[:uid])
|
|
47
49
|
reset_session
|
|
48
|
-
|
|
50
|
+
auto_login(user)
|
|
49
51
|
user
|
|
50
52
|
end
|
|
51
53
|
end
|
|
@@ -61,6 +63,7 @@ module Sorcery
|
|
|
61
63
|
# {:username => "user/name"}
|
|
62
64
|
#
|
|
63
65
|
# And this will cause 'moishe' to be set as the value of :username field.
|
|
66
|
+
# Note: Be careful. This method skips validations model.
|
|
64
67
|
def create_from(provider)
|
|
65
68
|
provider = provider.to_sym
|
|
66
69
|
@provider = Config.send(provider)
|
|
@@ -76,7 +79,11 @@ module Sorcery
|
|
|
76
79
|
end
|
|
77
80
|
end
|
|
78
81
|
user_class.transaction do
|
|
79
|
-
@user = user_class.
|
|
82
|
+
@user = user_class.new()
|
|
83
|
+
attrs.each do |k,v|
|
|
84
|
+
@user.send(:"#{k}=", v)
|
|
85
|
+
end
|
|
86
|
+
@user.save(:validate => false)
|
|
80
87
|
user_class.sorcery_config.authentications_class.create!({config.authentications_user_id_attribute_name => @user.id, config.provider_attribute_name => provider, config.provider_uid_attribute_name => @user_hash[:uid]})
|
|
81
88
|
end
|
|
82
89
|
@user
|
|
@@ -46,7 +46,7 @@ module Sorcery
|
|
|
46
46
|
def login_from_basic_auth
|
|
47
47
|
authenticate_with_http_basic do |username, password|
|
|
48
48
|
@current_user = (user_class.authenticate(username, password) if session[:http_authentication_used]) || false
|
|
49
|
-
|
|
49
|
+
auto_login(@current_user) if @current_user
|
|
50
50
|
@current_user
|
|
51
51
|
end
|
|
52
52
|
end
|
|
@@ -22,23 +22,31 @@ module Sorcery
|
|
|
22
22
|
|
|
23
23
|
# Clears the cookie and clears the token from the db.
|
|
24
24
|
def forget_me!
|
|
25
|
-
current_user.forget_me!
|
|
25
|
+
@current_user.forget_me!
|
|
26
26
|
cookies[:remember_me_token] = nil
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
+
# Override.
|
|
30
|
+
# logins a user instance, and optionally remembers him.
|
|
31
|
+
def auto_login(user, should_remember = false)
|
|
32
|
+
session[:user_id] = user.id
|
|
33
|
+
@current_user = user
|
|
34
|
+
remember_me! if should_remember
|
|
35
|
+
end
|
|
36
|
+
|
|
29
37
|
protected
|
|
30
38
|
|
|
31
39
|
# calls remember_me! if a third credential was passed to the login method.
|
|
32
40
|
# Runs as a hook after login.
|
|
33
41
|
def remember_me_if_asked_to(user, credentials)
|
|
34
|
-
remember_me! if credentials.size == 3 && credentials[2]
|
|
42
|
+
remember_me! if ( credentials.size == 3 && credentials[2] && credentials[2] != "0" )
|
|
35
43
|
end
|
|
36
44
|
|
|
37
45
|
# Checks the cookie for a remember me token, tried to find a user with that token
|
|
38
46
|
# and logs the user in if found.
|
|
39
47
|
# Runs as a login source. See 'current_user' method for how it is used.
|
|
40
48
|
def login_from_cookie
|
|
41
|
-
user = cookies[:remember_me_token] && user_class.find_by_remember_me_token(cookies[:remember_me_token])
|
|
49
|
+
user = cookies.signed[:remember_me_token] && user_class.find_by_remember_me_token(cookies.signed[:remember_me_token])
|
|
42
50
|
if user && user.remember_me_token?
|
|
43
51
|
set_remember_me_cookie!(user)
|
|
44
52
|
@current_user = user
|
|
@@ -48,9 +56,11 @@ module Sorcery
|
|
|
48
56
|
end
|
|
49
57
|
|
|
50
58
|
def set_remember_me_cookie!(user)
|
|
51
|
-
cookies[:remember_me_token] = {
|
|
59
|
+
cookies.signed[:remember_me_token] = {
|
|
52
60
|
:value => user.send(user.sorcery_config.remember_me_token_attribute_name),
|
|
53
|
-
:expires => user.send(user.sorcery_config.remember_me_token_expires_at_attribute_name)
|
|
61
|
+
:expires => user.send(user.sorcery_config.remember_me_token_expires_at_attribute_name),
|
|
62
|
+
:httponly => true,
|
|
63
|
+
:domain => Config.cookie_domain
|
|
54
64
|
}
|
|
55
65
|
end
|
|
56
66
|
end
|
|
@@ -39,7 +39,7 @@ module Sorcery
|
|
|
39
39
|
session_to_use = Config.session_timeout_from_last_action ? session[:last_action_time] : session[:login_time]
|
|
40
40
|
if session_to_use && (Time.now.utc - session_to_use > Config.session_timeout)
|
|
41
41
|
reset_session
|
|
42
|
-
@current_user =
|
|
42
|
+
@current_user = nil
|
|
43
43
|
else
|
|
44
44
|
session[:last_action_time] = Time.now.utc
|
|
45
45
|
end
|
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,7 +14,7 @@ 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?
|
|
@@ -22,10 +22,10 @@ module Sorcery
|
|
|
22
22
|
def require_login
|
|
23
23
|
if !logged_in?
|
|
24
24
|
session[:return_to_url] = request.url if Config.save_return_to_url
|
|
25
|
-
self.send(Config.not_authenticated_action)
|
|
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)
|
|
@@ -34,7 +34,7 @@ module Sorcery
|
|
|
34
34
|
return_to_url = session[:return_to_url]
|
|
35
35
|
reset_session # protect from session fixation attacks
|
|
36
36
|
session[:return_to_url] = return_to_url
|
|
37
|
-
|
|
37
|
+
auto_login(user)
|
|
38
38
|
after_login!(user, credentials)
|
|
39
39
|
current_user
|
|
40
40
|
else
|
|
@@ -42,41 +42,62 @@ module Sorcery
|
|
|
42
42
|
nil
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
# Resets the session and runs hooks before and after.
|
|
47
47
|
def logout
|
|
48
48
|
if logged_in?
|
|
49
49
|
before_logout!(current_user)
|
|
50
50
|
reset_session
|
|
51
51
|
after_logout!
|
|
52
|
+
@current_user = nil
|
|
52
53
|
end
|
|
53
54
|
end
|
|
54
|
-
|
|
55
|
+
|
|
55
56
|
def logged_in?
|
|
56
57
|
!!current_user
|
|
57
58
|
end
|
|
58
|
-
|
|
59
|
+
|
|
59
60
|
# attempts to auto-login from the sources defined (session, basic_auth, cookie, etc.)
|
|
60
61
|
# returns the logged in user if found, false if not (using old restful-authentication trick, nil != false).
|
|
61
62
|
def current_user
|
|
62
63
|
@current_user ||= login_from_session || login_from_other_sources unless @current_user == false
|
|
63
64
|
end
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
|
|
66
|
+
def current_user=(user)
|
|
67
|
+
@current_user = user
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# used when a user tries to access a page while logged out, is asked to login,
|
|
66
71
|
# and we want to return him back to the page he originally wanted.
|
|
67
72
|
def redirect_back_or_to(url, flash_hash = {})
|
|
68
73
|
redirect_to(session[:return_to_url] || url, :flash => flash_hash)
|
|
69
74
|
end
|
|
70
|
-
|
|
75
|
+
|
|
71
76
|
# The default action for denying non-authenticated users.
|
|
72
77
|
# You can override this method in your controllers,
|
|
73
78
|
# or provide a different method in the configuration.
|
|
74
79
|
def not_authenticated
|
|
75
80
|
redirect_to root_path
|
|
76
81
|
end
|
|
77
|
-
|
|
82
|
+
|
|
83
|
+
# login a user instance
|
|
84
|
+
#
|
|
85
|
+
# @param [<User-Model>] user the user instance.
|
|
86
|
+
# @return - do not depend on the return value.
|
|
87
|
+
def auto_login(user)
|
|
88
|
+
session[:user_id] = user.id
|
|
89
|
+
@current_user = user
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Overwrite Rails' handle unverified request
|
|
93
|
+
def handle_unverified_request
|
|
94
|
+
cookies[:remember_me_token] = nil
|
|
95
|
+
@current_user = nil
|
|
96
|
+
super # call the default behaviour which resets the session
|
|
97
|
+
end
|
|
98
|
+
|
|
78
99
|
protected
|
|
79
|
-
|
|
100
|
+
|
|
80
101
|
# Tries all available sources (methods) until one doesn't return false.
|
|
81
102
|
def login_from_other_sources
|
|
82
103
|
result = nil
|
|
@@ -85,52 +106,51 @@ module Sorcery
|
|
|
85
106
|
end
|
|
86
107
|
result || false
|
|
87
108
|
end
|
|
88
|
-
|
|
89
|
-
def login_user(user)
|
|
90
|
-
session[:user_id] = user.id
|
|
91
|
-
end
|
|
92
|
-
|
|
109
|
+
|
|
93
110
|
def login_from_session
|
|
94
111
|
@current_user = (user_class.find_by_id(session[:user_id]) if session[:user_id]) || false
|
|
95
112
|
end
|
|
96
|
-
|
|
113
|
+
|
|
97
114
|
def after_login!(user, credentials)
|
|
98
115
|
Config.after_login.each {|c| self.send(c, user, credentials)}
|
|
99
116
|
end
|
|
100
|
-
|
|
117
|
+
|
|
101
118
|
def after_failed_login!(credentials)
|
|
102
119
|
Config.after_failed_login.each {|c| self.send(c, credentials)}
|
|
103
120
|
end
|
|
104
|
-
|
|
121
|
+
|
|
105
122
|
def before_logout!(user)
|
|
106
123
|
Config.before_logout.each {|c| self.send(c, user)}
|
|
107
124
|
end
|
|
108
|
-
|
|
125
|
+
|
|
109
126
|
def after_logout!
|
|
110
127
|
Config.after_logout.each {|c| self.send(c)}
|
|
111
128
|
end
|
|
112
|
-
|
|
129
|
+
|
|
113
130
|
def user_class
|
|
114
131
|
@user_class ||= Config.user_class.to_s.constantize
|
|
115
132
|
end
|
|
133
|
+
|
|
116
134
|
end
|
|
117
|
-
|
|
135
|
+
|
|
118
136
|
module Config
|
|
119
137
|
class << self
|
|
120
138
|
attr_accessor :submodules,
|
|
121
|
-
:user_class, # what class to use as the user class.
|
|
139
|
+
:user_class, # what class to use as the user class.
|
|
122
140
|
:not_authenticated_action, # what controller action to call for non-authenticated users.
|
|
123
|
-
|
|
141
|
+
|
|
124
142
|
:save_return_to_url, # when a non logged in user tries to enter a page that requires
|
|
125
|
-
# login, save the URL he wanted to reach,
|
|
143
|
+
# login, save the URL he wanted to reach,
|
|
126
144
|
# and send him there after login.
|
|
127
|
-
|
|
145
|
+
|
|
146
|
+
:cookie_domain, # set domain option for cookies
|
|
147
|
+
|
|
128
148
|
:login_sources,
|
|
129
149
|
:after_login,
|
|
130
150
|
:after_failed_login,
|
|
131
151
|
:before_logout,
|
|
132
|
-
:after_logout
|
|
133
|
-
|
|
152
|
+
:after_logout
|
|
153
|
+
|
|
134
154
|
def init!
|
|
135
155
|
@defaults = {
|
|
136
156
|
:@user_class => nil,
|
|
@@ -141,31 +161,32 @@ module Sorcery
|
|
|
141
161
|
:@after_failed_login => [],
|
|
142
162
|
:@before_logout => [],
|
|
143
163
|
:@after_logout => [],
|
|
144
|
-
:@save_return_to_url => true
|
|
164
|
+
:@save_return_to_url => true,
|
|
165
|
+
:@cookie_domain => nil
|
|
145
166
|
}
|
|
146
167
|
end
|
|
147
|
-
|
|
168
|
+
|
|
148
169
|
# Resets all configuration options to their default values.
|
|
149
170
|
def reset!
|
|
150
171
|
@defaults.each do |k,v|
|
|
151
172
|
instance_variable_set(k,v)
|
|
152
|
-
end
|
|
173
|
+
end
|
|
153
174
|
end
|
|
154
|
-
|
|
175
|
+
|
|
155
176
|
def update!
|
|
156
177
|
@defaults.each do |k,v|
|
|
157
178
|
instance_variable_set(k,v) if !instance_variable_defined?(k)
|
|
158
179
|
end
|
|
159
180
|
end
|
|
160
|
-
|
|
181
|
+
|
|
161
182
|
def user_config(&blk)
|
|
162
183
|
block_given? ? @user_config = blk : @user_config
|
|
163
184
|
end
|
|
164
|
-
|
|
185
|
+
|
|
165
186
|
def configure(&blk)
|
|
166
187
|
@configure_blk = blk
|
|
167
188
|
end
|
|
168
|
-
|
|
189
|
+
|
|
169
190
|
def configure!
|
|
170
191
|
@configure_blk.call(self) if @configure_blk
|
|
171
192
|
end
|
|
@@ -174,4 +195,4 @@ module Sorcery
|
|
|
174
195
|
reset!
|
|
175
196
|
end
|
|
176
197
|
end
|
|
177
|
-
end
|
|
198
|
+
end
|
|
@@ -28,12 +28,16 @@ module Sorcery
|
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def matches?(crypted, *tokens)
|
|
31
|
-
|
|
32
|
-
aes.key = @key
|
|
33
|
-
(aes.update(crypted.unpack("m").first) + aes.final) == tokens.join
|
|
31
|
+
decrypt(crypted) == tokens.join
|
|
34
32
|
rescue OpenSSL::CipherError
|
|
35
33
|
false
|
|
36
34
|
end
|
|
35
|
+
|
|
36
|
+
def decrypt(crypted)
|
|
37
|
+
aes.decrypt
|
|
38
|
+
aes.key = @key
|
|
39
|
+
(aes.update(crypted.unpack("m").first) + aes.final)
|
|
40
|
+
end
|
|
37
41
|
|
|
38
42
|
private
|
|
39
43
|
|
data/lib/sorcery/engine.rb
CHANGED
|
@@ -10,6 +10,7 @@ module Sorcery
|
|
|
10
10
|
initializer "extend Controller with sorcery" do |app|
|
|
11
11
|
ActionController::Base.send(:include, Sorcery::Controller)
|
|
12
12
|
ActionController::Base.helper_method :current_user
|
|
13
|
+
ActionController::Base.helper_method :logged_in?
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
rake_tasks do
|
|
@@ -8,7 +8,8 @@ module Sorcery
|
|
|
8
8
|
|
|
9
9
|
module ClassMethods
|
|
10
10
|
def find_by_credentials(credentials)
|
|
11
|
-
|
|
11
|
+
sql = @sorcery_config.username_attribute_names.map{|attribute| "#{attribute} = :login"}
|
|
12
|
+
where(sql.join(' OR '), :login => credentials[0]).first
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
def find_by_sorcery_token(token_attr_name, token)
|
|
@@ -0,0 +1,49 @@
|
|
|
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
|
+
module InstanceMethods
|
|
12
|
+
def increment(attr)
|
|
13
|
+
self.inc(attr,1)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def save!(options = {})
|
|
17
|
+
save(options)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
module ClassMethods
|
|
22
|
+
def find_by_credentials(credentials)
|
|
23
|
+
@sorcery_config.username_attribute_names.each do |attribute|
|
|
24
|
+
@user = where(attribute => credentials[0]).first
|
|
25
|
+
break if @user
|
|
26
|
+
end
|
|
27
|
+
@user
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def find_by_id(id)
|
|
31
|
+
find(id)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def find_by_activation_token(token)
|
|
35
|
+
where(sorcery_config.activation_token_attribute_name => token).first
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def transaction(&blk)
|
|
39
|
+
tap(&blk)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def find_by_sorcery_token(token_attr_name, token)
|
|
43
|
+
where(token_attr_name => token).first
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -15,7 +15,11 @@ module Sorcery
|
|
|
15
15
|
|
|
16
16
|
module ClassMethods
|
|
17
17
|
def find_by_credentials(credentials)
|
|
18
|
-
|
|
18
|
+
@sorcery_config.username_attribute_names.each do |attribute|
|
|
19
|
+
@user = where(attribute => credentials[0]).first
|
|
20
|
+
break if @user
|
|
21
|
+
end
|
|
22
|
+
@user
|
|
19
23
|
end
|
|
20
24
|
|
|
21
25
|
def find_by_provider_and_uid(provider, uid)
|
|
@@ -36,7 +40,8 @@ module Sorcery
|
|
|
36
40
|
end
|
|
37
41
|
|
|
38
42
|
def find_by_username(username)
|
|
39
|
-
|
|
43
|
+
query = sorcery_config.username_attribute_names.map {|name| {name => username}}
|
|
44
|
+
any_of(*query).first
|
|
40
45
|
end
|
|
41
46
|
|
|
42
47
|
def transaction(&blk)
|
|
@@ -26,6 +26,9 @@ module Sorcery
|
|
|
26
26
|
|
|
27
27
|
base.sorcery_config.before_authenticate << :prevent_locked_user_login
|
|
28
28
|
base.sorcery_config.after_config << :define_brute_force_protection_mongoid_fields if defined?(Mongoid) and base.ancestors.include?(Mongoid::Document)
|
|
29
|
+
if defined?(MongoMapper) and base.ancestors.include?(MongoMapper::Document)
|
|
30
|
+
base.sorcery_config.after_config << :define_brute_force_protection_mongo_mapper_fields
|
|
31
|
+
end
|
|
29
32
|
base.extend(ClassMethods)
|
|
30
33
|
base.send(:include, InstanceMethods)
|
|
31
34
|
end
|
|
@@ -37,6 +40,11 @@ module Sorcery
|
|
|
37
40
|
field sorcery_config.failed_logins_count_attribute_name, :type => Integer
|
|
38
41
|
field sorcery_config.lock_expires_at_attribute_name, :type => DateTime
|
|
39
42
|
end
|
|
43
|
+
|
|
44
|
+
def define_brute_force_protection_mongo_mapper_fields
|
|
45
|
+
key sorcery_config.failed_logins_count_attribute_name, Integer
|
|
46
|
+
key sorcery_config.lock_expires_at_attribute_name, DateTime
|
|
47
|
+
end
|
|
40
48
|
end
|
|
41
49
|
|
|
42
50
|
module InstanceMethods
|
|
@@ -54,13 +62,15 @@ module Sorcery
|
|
|
54
62
|
|
|
55
63
|
def lock!
|
|
56
64
|
config = sorcery_config
|
|
57
|
-
self.
|
|
65
|
+
self.send(:"#{config.lock_expires_at_attribute_name}=", Time.now.utc + config.login_lock_time_period)
|
|
66
|
+
self.save!
|
|
58
67
|
end
|
|
59
68
|
|
|
60
69
|
def unlock!
|
|
61
70
|
config = sorcery_config
|
|
62
|
-
self.
|
|
63
|
-
|
|
71
|
+
self.send(:"#{config.lock_expires_at_attribute_name}=", nil)
|
|
72
|
+
self.send(:"#{config.failed_logins_count_attribute_name}=", 0)
|
|
73
|
+
self.save!
|
|
64
74
|
end
|
|
65
75
|
|
|
66
76
|
def unlocked?
|
|
@@ -24,7 +24,10 @@ module Sorcery
|
|
|
24
24
|
base.send(:include, InstanceMethods)
|
|
25
25
|
|
|
26
26
|
base.sorcery_config.after_config << :define_remember_me_mongoid_fields if defined?(Mongoid) and base.ancestors.include?(Mongoid::Document)
|
|
27
|
-
|
|
27
|
+
if defined?(MongoMapper) and base.ancestors.include?(MongoMapper::Document)
|
|
28
|
+
base.sorcery_config.after_config << :define_remember_me_mongo_mapper_fields
|
|
29
|
+
end
|
|
30
|
+
|
|
28
31
|
base.extend(ClassMethods)
|
|
29
32
|
end
|
|
30
33
|
|
|
@@ -36,13 +39,17 @@ module Sorcery
|
|
|
36
39
|
field sorcery_config.remember_me_token_expires_at_attribute_name, :type => Time
|
|
37
40
|
end
|
|
38
41
|
|
|
42
|
+
def define_remember_me_mongo_mapper_fields
|
|
43
|
+
key sorcery_config.remember_me_token_attribute_name, String
|
|
44
|
+
key sorcery_config.remember_me_token_expires_at_attribute_name, Time
|
|
45
|
+
end
|
|
39
46
|
end
|
|
40
47
|
|
|
41
48
|
module InstanceMethods
|
|
42
49
|
# You shouldn't really use this one yourself - it's called by the controller's 'remember_me!' method.
|
|
43
50
|
def remember_me!
|
|
44
51
|
config = sorcery_config
|
|
45
|
-
self.send(:"#{config.remember_me_token_attribute_name}=", generate_random_token)
|
|
52
|
+
self.send(:"#{config.remember_me_token_attribute_name}=", TemporaryToken.generate_random_token)
|
|
46
53
|
self.send(:"#{config.remember_me_token_expires_at_attribute_name}=", Time.now + config.remember_me_for)
|
|
47
54
|
self.save!(:validate => false)
|
|
48
55
|
end
|