sorcery 0.8.1 → 0.8.2
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.
- data/Gemfile +4 -4
- data/Gemfile.lock +5 -22
- data/README.rdoc +2 -2
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/lib/generators/sorcery/templates/initializer.rb +24 -13
- data/lib/generators/sorcery/templates/migration/activity_logging.rb +2 -0
- data/lib/sorcery/controller/submodules/activity_logging.rb +12 -1
- data/lib/sorcery/controller/submodules/external/protocols/oauth1.rb +14 -3
- data/lib/sorcery/controller/submodules/external/protocols/oauth2.rb +5 -1
- data/lib/sorcery/controller/submodules/external/providers/base.rb +21 -0
- data/lib/sorcery/controller/submodules/external/providers/facebook.rb +13 -12
- data/lib/sorcery/controller/submodules/external/providers/github.rb +4 -3
- data/lib/sorcery/controller/submodules/external/providers/google.rb +4 -3
- data/lib/sorcery/controller/submodules/external/providers/linkedin.rb +13 -12
- data/lib/sorcery/controller/submodules/external/providers/liveid.rb +5 -4
- data/lib/sorcery/controller/submodules/external/providers/twitter.rb +15 -14
- data/lib/sorcery/controller/submodules/external/providers/vk.rb +6 -5
- data/lib/sorcery/controller/submodules/external/providers/xing.rb +97 -0
- data/lib/sorcery/controller/submodules/external.rb +72 -39
- data/lib/sorcery/controller.rb +5 -2
- data/lib/sorcery/model/submodules/activity_logging.rb +3 -0
- data/lib/sorcery/model/submodules/brute_force_protection.rb +14 -12
- data/lib/sorcery/model.rb +1 -1
- data/lib/sorcery/railties/tasks.rake +1 -7
- data/lib/sorcery.rb +3 -1
- data/sorcery.gemspec +11 -12
- data/spec/Gemfile +1 -1
- data/spec/Gemfile.lock +1 -1
- data/spec/rails3/Gemfile.lock +3 -3
- data/spec/rails3/app/models/user.rb +1 -1
- data/spec/rails3/app/views/sorcery_mailer/send_unlock_token_email.text.erb +1 -1
- data/spec/rails3/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +2 -0
- data/spec/rails3/spec/controller_activity_logging_spec.rb +15 -0
- data/spec/rails3/spec/controller_brute_force_protection_spec.rb +14 -6
- data/spec/rails3/spec/controller_spec.rb +32 -27
- data/spec/rails3_mongo_mapper/Gemfile.lock +3 -3
- data/spec/rails3_mongo_mapper/spec/controller_spec.rb +32 -27
- data/spec/rails3_mongoid/Gemfile.lock +3 -3
- data/spec/rails3_mongoid/spec/controller_activity_logging_spec.rb +6 -0
- data/spec/rails3_mongoid/spec/controller_spec.rb +33 -28
- data/spec/shared_examples/user_activity_logging_shared_examples.rb +5 -0
- metadata +138 -59
@@ -27,6 +27,7 @@ module Sorcery
|
|
27
27
|
end
|
28
28
|
|
29
29
|
module VkClient
|
30
|
+
include Base::BaseClient
|
30
31
|
class << self
|
31
32
|
attr_accessor :key,
|
32
33
|
:secret,
|
@@ -47,16 +48,16 @@ module Sorcery
|
|
47
48
|
@user_info_mapping = {}
|
48
49
|
end
|
49
50
|
|
50
|
-
def get_user_hash
|
51
|
+
def get_user_hash(access_token)
|
51
52
|
user_hash = {}
|
52
53
|
|
53
54
|
params = {
|
54
|
-
:access_token =>
|
55
|
-
:uids =>
|
55
|
+
:access_token => access_token.token,
|
56
|
+
:uids => access_token.params["user_id"],
|
56
57
|
:fields => @user_info_mapping.values.join(",")
|
57
58
|
}
|
58
59
|
|
59
|
-
response =
|
60
|
+
response = access_token.get(@user_info_url, :params => params)
|
60
61
|
if user_hash[:user_info] = JSON.parse(response.body)
|
61
62
|
user_hash[:user_info] = user_hash[:user_info]["response"][0]
|
62
63
|
# add full_name - useful if you do not store it in separate fields
|
@@ -84,7 +85,7 @@ module Sorcery
|
|
84
85
|
:token_url => @token_path,
|
85
86
|
:token_method => :post
|
86
87
|
}
|
87
|
-
|
88
|
+
return self.get_access_token(args, options)
|
88
89
|
end
|
89
90
|
|
90
91
|
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module Sorcery
|
2
|
+
module Controller
|
3
|
+
module Submodules
|
4
|
+
module External
|
5
|
+
module Providers
|
6
|
+
# This module adds support for OAuth with xing.com.
|
7
|
+
# When included in the 'config.providers' option, it adds a new option, 'config.xing'.
|
8
|
+
# Via this new option you can configure Xing specific settings like your app's key and secret.
|
9
|
+
#
|
10
|
+
# config.xing.key = <key>
|
11
|
+
# config.xing.secret = <secret>
|
12
|
+
# ...
|
13
|
+
#
|
14
|
+
module Xing
|
15
|
+
def self.included(base)
|
16
|
+
base.module_eval do
|
17
|
+
class << self
|
18
|
+
attr_reader :xing
|
19
|
+
|
20
|
+
def merge_xing_defaults!
|
21
|
+
@defaults.merge!(:@xing => XingClient)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
merge_xing_defaults!
|
25
|
+
update!
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
module XingClient
|
30
|
+
include Base::BaseClient
|
31
|
+
class << self
|
32
|
+
attr_accessor :key,
|
33
|
+
:secret,
|
34
|
+
:callback_url,
|
35
|
+
:site,
|
36
|
+
:authorize_path,
|
37
|
+
:request_token_path,
|
38
|
+
:access_token_path,
|
39
|
+
:user_info_path,
|
40
|
+
:user_info_mapping
|
41
|
+
attr_reader :access_token
|
42
|
+
|
43
|
+
include Protocols::Oauth1
|
44
|
+
|
45
|
+
# Override included get_consumer method to provide authorize_path
|
46
|
+
def get_consumer
|
47
|
+
::OAuth::Consumer.new(@key, @secret, @configuration)
|
48
|
+
end
|
49
|
+
|
50
|
+
def init
|
51
|
+
@configuration = {
|
52
|
+
site: "https://api.xing.com/v1",
|
53
|
+
authorize_path: '/authorize',
|
54
|
+
request_token_path: '/request_token',
|
55
|
+
access_token_path: '/access_token'
|
56
|
+
}
|
57
|
+
@user_info_path = "/users/me"
|
58
|
+
end
|
59
|
+
|
60
|
+
def get_user_hash(access_token)
|
61
|
+
user_hash = {}
|
62
|
+
response = access_token.get(@user_info_path)
|
63
|
+
user_hash[:user_info] = JSON.parse(response.body)['users'].first
|
64
|
+
user_hash[:uid] = user_hash[:user_info]['id'].to_s
|
65
|
+
user_hash
|
66
|
+
end
|
67
|
+
|
68
|
+
def has_callback?
|
69
|
+
true
|
70
|
+
end
|
71
|
+
|
72
|
+
# calculates and returns the url to which the user should be redirected,
|
73
|
+
# to get authenticated at the external provider's site.
|
74
|
+
def login_url(params,session)
|
75
|
+
req_token = self.get_request_token
|
76
|
+
session[:request_token] = req_token.token
|
77
|
+
session[:request_token_secret] = req_token.secret
|
78
|
+
self.authorize_url({:request_token => req_token.token, :request_token_secret => req_token.secret})
|
79
|
+
end
|
80
|
+
|
81
|
+
# tries to login the user from access token
|
82
|
+
def process_callback(params, session)
|
83
|
+
args = {}
|
84
|
+
args.merge!({:oauth_verifier => params[:oauth_verifier], :request_token => session[:request_token], :request_token_secret => session[:request_token_secret]})
|
85
|
+
args.merge!({:code => params[:code]}) if params[:code]
|
86
|
+
return self.get_access_token(args)
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
init
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -2,7 +2,7 @@ module Sorcery
|
|
2
2
|
module Controller
|
3
3
|
module Submodules
|
4
4
|
# This submodule helps you login users from external auth providers such as Twitter.
|
5
|
-
# This is the controller part which handles the http requests and tokens passed between the app and the provider.
|
5
|
+
# This is the controller part which handles the http requests and tokens passed between the app and the @provider.
|
6
6
|
module External
|
7
7
|
def self.included(base)
|
8
8
|
base.send(:include, InstanceMethods)
|
@@ -29,57 +29,94 @@ module Sorcery
|
|
29
29
|
module InstanceMethods
|
30
30
|
protected
|
31
31
|
|
32
|
-
#
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
32
|
+
# save the singleton ProviderClient instance into @provider
|
33
|
+
def sorcery_get_provider(provider_name)
|
34
|
+
Config.send(provider_name.to_sym)
|
35
|
+
end
|
36
|
+
|
37
|
+
# get the login URL from the provider, if applicable. Returns nil if the provider
|
38
|
+
# does not provide a login URL. (as of v0.8.1 all providers provide a login URL)
|
39
|
+
def sorcery_login_url(provider_name)
|
40
|
+
@provider = sorcery_get_provider provider_name
|
41
|
+
sorcery_fixup_callback_url @provider
|
42
|
+
if @provider.respond_to?(:login_url) && @provider.has_callback?
|
43
|
+
return @provider.login_url(params, session)
|
44
|
+
else
|
45
|
+
return nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# get the user hash from a provider using information from the params and session.
|
50
|
+
def sorcery_fetch_user_hash(provider_name)
|
51
|
+
# the application should never ask for user hashes from two different providers
|
52
|
+
# on the same request. But if they do, we should be ready: on the second request,
|
53
|
+
# clear out the instance variables if the provider is different
|
54
|
+
provider = sorcery_get_provider provider_name
|
55
|
+
if @provider.nil? || @provider != provider
|
56
|
+
@provider = provider
|
57
|
+
@access_token = nil
|
58
|
+
@user_hash = nil
|
59
|
+
end
|
60
|
+
|
61
|
+
# delegate to the provider for the access token and the user hash.
|
62
|
+
# cache them in instance variables.
|
63
|
+
@access_token ||= @provider.process_callback(params, session) # sends request to oauth agent to get the token
|
64
|
+
@user_hash ||= @provider.get_user_hash(@access_token) # uses the token to send another request to the oauth agent requesting user info
|
65
|
+
end
|
66
|
+
|
67
|
+
# for backwards compatibility
|
68
|
+
def access_token(*args)
|
69
|
+
@access_token
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
# this method should be somewhere else. It only does something once per application per provider.
|
74
|
+
def sorcery_fixup_callback_url(provider)
|
75
|
+
provider.original_callback_url ||= provider.callback_url
|
76
|
+
if provider.original_callback_url.present? && provider.original_callback_url[0] == '/'
|
37
77
|
uri = URI.parse(request.url.gsub(/\?.*$/,''))
|
38
78
|
uri.path = ''
|
39
79
|
uri.query = nil
|
40
80
|
uri.scheme = 'https' if(request.env['HTTP_X_FORWARDED_PROTO'] == 'https')
|
41
81
|
host = uri.to_s
|
42
|
-
provider.callback_url = "#{host}#{provider.
|
43
|
-
end
|
44
|
-
if provider.has_callback?
|
45
|
-
redirect_to provider.login_url(params,session)
|
46
|
-
else
|
47
|
-
#provider.login(args)
|
82
|
+
provider.callback_url = "#{host}#{@provider.original_callback_url}"
|
48
83
|
end
|
49
84
|
end
|
50
85
|
|
86
|
+
# sends user to authenticate at the provider's website.
|
87
|
+
# after authentication the user is redirected to the callback defined in the provider config
|
88
|
+
def login_at(provider_name, args = {})
|
89
|
+
redirect_to sorcery_login_url(provider_name)
|
90
|
+
end
|
91
|
+
|
51
92
|
# tries to login the user from provider's callback
|
52
93
|
def login_from(provider_name)
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
94
|
+
sorcery_fetch_user_hash provider_name
|
95
|
+
|
96
|
+
if user = user_class.load_from_provider(provider_name, @user_hash[:uid].to_s)
|
97
|
+
# we found the user.
|
98
|
+
# clear the session
|
57
99
|
return_to_url = session[:return_to_url]
|
58
100
|
reset_session
|
59
101
|
session[:return_to_url] = return_to_url
|
102
|
+
|
103
|
+
# sign in the user
|
60
104
|
auto_login(user)
|
61
105
|
after_login!(user)
|
106
|
+
|
107
|
+
# return the user
|
62
108
|
user
|
63
109
|
end
|
64
110
|
end
|
65
111
|
|
66
|
-
# get provider access account
|
67
|
-
def access_token(provider_name)
|
68
|
-
provider = Config.send(provider_name)
|
69
|
-
provider.access_token
|
70
|
-
end
|
71
|
-
|
72
112
|
# If user is logged, he can add all available providers into his account
|
73
113
|
def add_provider_to_user(provider_name)
|
74
|
-
|
75
|
-
provider = Config.send(provider_name)
|
76
|
-
provider.process_callback(params,session)
|
77
|
-
user_hash = provider.get_user_hash
|
114
|
+
sorcery_fetch_user_hash provider_name
|
78
115
|
config = user_class.sorcery_config
|
79
116
|
|
80
117
|
# first check to see if user has a particular authentication already
|
81
|
-
unless (current_user.send(config.authentications_class.to_s.downcase.pluralize).send("find_by_#{config.provider_attribute_name}_and_#{config.provider_uid_attribute_name}", provider_name, user_hash[:uid].to_s))
|
82
|
-
user = current_user.send(config.authentications_class.to_s.downcase.pluralize).build(config.provider_uid_attribute_name => user_hash[:uid], config.provider_attribute_name => provider_name.to_s)
|
118
|
+
unless (current_user.send(config.authentications_class.to_s.downcase.pluralize).send("find_by_#{config.provider_attribute_name}_and_#{config.provider_uid_attribute_name}", provider_name, @user_hash[:uid].to_s))
|
119
|
+
user = current_user.send(config.authentications_class.to_s.downcase.pluralize).build(config.provider_uid_attribute_name => @user_hash[:uid], config.provider_attribute_name => provider_name.to_s)
|
83
120
|
user.save(:validate => false)
|
84
121
|
else
|
85
122
|
user = false
|
@@ -92,18 +129,16 @@ module Sorcery
|
|
92
129
|
# If a provider doesn't give required informations or username/email is already taken,
|
93
130
|
# we store provider/user infos into a session and can be rendered into registration form
|
94
131
|
def create_and_validate_from(provider_name)
|
95
|
-
|
96
|
-
provider = Config.send(provider_name)
|
97
|
-
user_hash = provider.get_user_hash
|
132
|
+
sorcery_fetch_user_hash provider_name
|
98
133
|
config = user_class.sorcery_config
|
99
134
|
|
100
|
-
attrs = user_attrs(provider.user_info_mapping, user_hash)
|
135
|
+
attrs = user_attrs(@provider.user_info_mapping, @user_hash)
|
101
136
|
|
102
137
|
user = user_class.new(attrs)
|
103
|
-
user.send(config.authentications_class.to_s.downcase.pluralize).build(config.provider_uid_attribute_name => user_hash[:uid], config.provider_attribute_name => provider_name)
|
138
|
+
user.send(config.authentications_class.to_s.downcase.pluralize).build(config.provider_uid_attribute_name => @user_hash[:uid], config.provider_attribute_name => provider_name)
|
104
139
|
|
105
140
|
session[:incomplete_user] = {
|
106
|
-
:provider => {config.provider_uid_attribute_name => user_hash[:uid], config.provider_attribute_name => provider_name},
|
141
|
+
:provider => {config.provider_uid_attribute_name => @user_hash[:uid], config.provider_attribute_name => provider_name},
|
107
142
|
:user_hash => attrs
|
108
143
|
} unless user.save
|
109
144
|
|
@@ -127,12 +162,10 @@ module Sorcery
|
|
127
162
|
# create_from(provider) {|user| user.some_check }
|
128
163
|
#
|
129
164
|
def create_from(provider_name)
|
130
|
-
|
131
|
-
provider = Config.send(provider_name)
|
132
|
-
user_hash = provider.get_user_hash
|
165
|
+
sorcery_fetch_user_hash provider_name
|
133
166
|
config = user_class.sorcery_config
|
134
167
|
|
135
|
-
attrs = user_attrs(provider.user_info_mapping, user_hash)
|
168
|
+
attrs = user_attrs(@provider.user_info_mapping, @user_hash)
|
136
169
|
|
137
170
|
user_class.transaction do
|
138
171
|
@user = user_class.new()
|
@@ -145,7 +178,7 @@ module Sorcery
|
|
145
178
|
end
|
146
179
|
|
147
180
|
@user.save(:validate => false)
|
148
|
-
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]})
|
181
|
+
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]})
|
149
182
|
end
|
150
183
|
@user
|
151
184
|
end
|
data/lib/sorcery/controller.rb
CHANGED
@@ -28,7 +28,7 @@ module Sorcery
|
|
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
32
|
@current_user = nil
|
33
33
|
user = user_class.authenticate(*credentials)
|
34
34
|
if user
|
@@ -37,6 +37,8 @@ module Sorcery
|
|
37
37
|
old_session.each_pair do |k,v|
|
38
38
|
session[k.to_sym] = v
|
39
39
|
end
|
40
|
+
form_authenticity_token
|
41
|
+
|
40
42
|
auto_login(user)
|
41
43
|
after_login!(user, credentials)
|
42
44
|
current_user
|
@@ -49,7 +51,8 @@ module Sorcery
|
|
49
51
|
# Resets the session and runs hooks before and after.
|
50
52
|
def logout
|
51
53
|
if logged_in?
|
52
|
-
|
54
|
+
@current_user = current_user if @current_user.nil?
|
55
|
+
before_logout!(@current_user)
|
53
56
|
reset_session
|
54
57
|
after_logout!
|
55
58
|
@current_user = nil
|
@@ -14,6 +14,7 @@ module Sorcery
|
|
14
14
|
attr_accessor :last_login_at_attribute_name, # last login attribute name.
|
15
15
|
:last_logout_at_attribute_name, # last logout attribute name.
|
16
16
|
:last_activity_at_attribute_name, # last activity attribute name.
|
17
|
+
:last_login_from_ip_address_name, # last activity login source
|
17
18
|
:activity_timeout # how long since last activity is
|
18
19
|
#the user defined logged out?
|
19
20
|
end
|
@@ -22,6 +23,7 @@ module Sorcery
|
|
22
23
|
@defaults.merge!(:@last_login_at_attribute_name => :last_login_at,
|
23
24
|
:@last_logout_at_attribute_name => :last_logout_at,
|
24
25
|
:@last_activity_at_attribute_name => :last_activity_at,
|
26
|
+
:@last_login_from_ip_address_name => :last_login_from_ip_address,
|
25
27
|
:@activity_timeout => 10 * 60)
|
26
28
|
reset!
|
27
29
|
end
|
@@ -42,6 +44,7 @@ module Sorcery
|
|
42
44
|
field sorcery_config.last_login_at_attribute_name, :type => Time
|
43
45
|
field sorcery_config.last_logout_at_attribute_name, :type => Time
|
44
46
|
field sorcery_config.last_activity_at_attribute_name, :type => Time
|
47
|
+
field sorcery_config.last_login_from_ip_address_name, :type => String
|
45
48
|
end
|
46
49
|
end
|
47
50
|
end
|
@@ -1,18 +1,18 @@
|
|
1
1
|
module Sorcery
|
2
2
|
module Model
|
3
3
|
module Submodules
|
4
|
-
# This module helps protect user accounts by locking them down after too many failed attemps
|
4
|
+
# This module helps protect user accounts by locking them down after too many failed attemps
|
5
5
|
# to login were detected.
|
6
|
-
# This is the model part of the submodule which provides configuration options and methods
|
6
|
+
# This is the model part of the submodule which provides configuration options and methods
|
7
7
|
# for locking and unlocking the user.
|
8
8
|
module BruteForceProtection
|
9
9
|
def self.included(base)
|
10
10
|
base.sorcery_config.class_eval do
|
11
11
|
attr_accessor :failed_logins_count_attribute_name, # failed logins attribute name.
|
12
|
-
:lock_expires_at_attribute_name, # this field indicates whether user
|
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, # how long the user should be banned.
|
15
|
+
:login_lock_time_period, # how long the user should be banned.
|
16
16
|
# in seconds. 0 for permanent.
|
17
17
|
|
18
18
|
:unlock_token_attribute_name, # Unlock token attribute name
|
@@ -20,7 +20,7 @@ module Sorcery
|
|
20
20
|
:unlock_token_mailer_disabled, # When true, dont send unlock token via email
|
21
21
|
:unlock_token_mailer # Mailer class
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
base.sorcery_config.instance_eval do
|
25
25
|
@defaults.merge!(:@failed_logins_count_attribute_name => :failed_logins_count,
|
26
26
|
:@lock_expires_at_attribute_name => :lock_expires_at,
|
@@ -33,7 +33,7 @@ module Sorcery
|
|
33
33
|
:@unlock_token_mailer => nil)
|
34
34
|
reset!
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
base.sorcery_config.before_authenticate << :prevent_locked_user_login
|
38
38
|
base.sorcery_config.after_config << :define_brute_force_protection_mongoid_fields if defined?(Mongoid) and base.ancestors.include?(Mongoid::Document)
|
39
39
|
if defined?(MongoMapper) and base.ancestors.include?(MongoMapper::Document)
|
@@ -42,7 +42,7 @@ module Sorcery
|
|
42
42
|
base.extend(ClassMethods)
|
43
43
|
base.send(:include, InstanceMethods)
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
module ClassMethods
|
47
47
|
def load_from_unlock_token(token)
|
48
48
|
return nil if token.blank?
|
@@ -64,7 +64,7 @@ module Sorcery
|
|
64
64
|
key sorcery_config.unlock_token_attribute_name, String
|
65
65
|
end
|
66
66
|
end
|
67
|
-
|
67
|
+
|
68
68
|
module InstanceMethods
|
69
69
|
# Called by the controller to increment the failed logins counter.
|
70
70
|
# Calls 'lock!' if login retries limit was reached.
|
@@ -75,7 +75,7 @@ module Sorcery
|
|
75
75
|
self.update_many_attributes(config.failed_logins_count_attribute_name => self.send(config.failed_logins_count_attribute_name))
|
76
76
|
self.lock! if self.send(config.failed_logins_count_attribute_name) >= config.consecutive_login_retries_amount_limit
|
77
77
|
end
|
78
|
-
|
78
|
+
|
79
79
|
# /!\
|
80
80
|
# Moved out of protected for use like activate! in controller
|
81
81
|
# /!\
|
@@ -95,11 +95,13 @@ module Sorcery
|
|
95
95
|
|
96
96
|
unless config.unlock_token_mailer_disabled || config.unlock_token_mailer.nil?
|
97
97
|
attributes[config.unlock_token_attribute_name] = TemporaryToken.generate_random_token
|
98
|
+
self.update_many_attributes(attributes)
|
98
99
|
send_unlock_token_email!
|
100
|
+
else
|
101
|
+
self.update_many_attributes(attributes)
|
99
102
|
end
|
100
|
-
self.update_many_attributes(attributes)
|
101
103
|
end
|
102
|
-
|
104
|
+
|
103
105
|
def unlocked?
|
104
106
|
config = sorcery_config
|
105
107
|
self.send(config.lock_expires_at_attribute_name).nil?
|
@@ -108,7 +110,7 @@ module Sorcery
|
|
108
110
|
def send_unlock_token_email!
|
109
111
|
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
112
|
end
|
111
|
-
|
113
|
+
|
112
114
|
# Prevents a locked user from logging in, and unlocks users that expired their lock time.
|
113
115
|
# Runs as a hook before authenticate.
|
114
116
|
def prevent_locked_user_login
|
data/lib/sorcery/model.rb
CHANGED
@@ -79,7 +79,7 @@ module Sorcery
|
|
79
79
|
def init_orm_hooks!
|
80
80
|
self.class_eval do
|
81
81
|
attr_accessor @sorcery_config.password_attribute_name
|
82
|
-
attr_protected @sorcery_config.crypted_password_attribute_name, @sorcery_config.salt_attribute_name
|
82
|
+
#attr_protected @sorcery_config.crypted_password_attribute_name, @sorcery_config.salt_attribute_name
|
83
83
|
before_save :encrypt_password, :if => Proc.new { |record|
|
84
84
|
record.send(sorcery_config.password_attribute_name).present?
|
85
85
|
}
|
@@ -1,12 +1,6 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
|
3
1
|
namespace :sorcery do
|
4
2
|
desc "Adds sorcery's initializer file"
|
5
3
|
task :bootstrap do
|
6
4
|
warn "This task is obsolete.\nUse \"rails g sorcery:install\" now.\nSee README for more information."
|
7
|
-
|
8
|
-
src = File.join(File.dirname(__FILE__), '..', 'initializers', 'initializer.rb')
|
9
|
-
target = File.join(Rails.root, "config", "initializers", "sorcery.rb")
|
10
|
-
FileUtils.cp(src, target)
|
11
5
|
end
|
12
|
-
end
|
6
|
+
end
|
data/lib/sorcery.rb
CHANGED
@@ -31,6 +31,7 @@ module Sorcery
|
|
31
31
|
autoload :Oauth2, 'sorcery/controller/submodules/external/protocols/oauth2'
|
32
32
|
end
|
33
33
|
module Providers
|
34
|
+
autoload :Base, 'sorcery/controller/submodules/external/providers/base'
|
34
35
|
autoload :Twitter, 'sorcery/controller/submodules/external/providers/twitter'
|
35
36
|
autoload :Facebook, 'sorcery/controller/submodules/external/providers/facebook'
|
36
37
|
autoload :Github, 'sorcery/controller/submodules/external/providers/github'
|
@@ -38,6 +39,7 @@ module Sorcery
|
|
38
39
|
autoload :Liveid, 'sorcery/controller/submodules/external/providers/liveid'
|
39
40
|
autoload :Linkedin, 'sorcery/controller/submodules/external/providers/linkedin'
|
40
41
|
autoload :Vk, 'sorcery/controller/submodules/external/providers/vk'
|
42
|
+
autoload :Xing, 'sorcery/controller/submodules/external/providers/xing'
|
41
43
|
end
|
42
44
|
end
|
43
45
|
end
|
@@ -81,4 +83,4 @@ module Sorcery
|
|
81
83
|
end
|
82
84
|
|
83
85
|
require 'sorcery/engine' if defined?(Rails) && Rails::VERSION::MAJOR >= 3
|
84
|
-
end
|
86
|
+
end
|
data/sorcery.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "sorcery"
|
8
|
-
s.version = "0.8.
|
8
|
+
s.version = "0.8.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Noam Ben Ari"]
|
12
|
-
s.date = "2013-
|
12
|
+
s.date = "2013-07-05"
|
13
13
|
s.description = "Provides common authentication needs such as signing in/out, activating by email and resetting password."
|
14
14
|
s.email = "nbenari@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -44,6 +44,7 @@ Gem::Specification.new do |s|
|
|
44
44
|
"lib/sorcery/controller/submodules/external/protocols/certs/ca-bundle.crt",
|
45
45
|
"lib/sorcery/controller/submodules/external/protocols/oauth1.rb",
|
46
46
|
"lib/sorcery/controller/submodules/external/protocols/oauth2.rb",
|
47
|
+
"lib/sorcery/controller/submodules/external/providers/base.rb",
|
47
48
|
"lib/sorcery/controller/submodules/external/providers/facebook.rb",
|
48
49
|
"lib/sorcery/controller/submodules/external/providers/github.rb",
|
49
50
|
"lib/sorcery/controller/submodules/external/providers/google.rb",
|
@@ -51,6 +52,7 @@ Gem::Specification.new do |s|
|
|
51
52
|
"lib/sorcery/controller/submodules/external/providers/liveid.rb",
|
52
53
|
"lib/sorcery/controller/submodules/external/providers/twitter.rb",
|
53
54
|
"lib/sorcery/controller/submodules/external/providers/vk.rb",
|
55
|
+
"lib/sorcery/controller/submodules/external/providers/xing.rb",
|
54
56
|
"lib/sorcery/controller/submodules/http_basic_auth.rb",
|
55
57
|
"lib/sorcery/controller/submodules/remember_me.rb",
|
56
58
|
"lib/sorcery/controller/submodules/session_timeout.rb",
|
@@ -304,7 +306,7 @@ Gem::Specification.new do |s|
|
|
304
306
|
s.homepage = "http://github.com/NoamB/sorcery"
|
305
307
|
s.licenses = ["MIT"]
|
306
308
|
s.require_paths = ["lib"]
|
307
|
-
s.rubygems_version = "1.8.
|
309
|
+
s.rubygems_version = "1.8.24"
|
308
310
|
s.summary = "Magical authentication for Rails 3 applications"
|
309
311
|
|
310
312
|
if s.respond_to? :specification_version then
|
@@ -316,11 +318,10 @@ Gem::Specification.new do |s|
|
|
316
318
|
s.add_runtime_dependency(%q<bcrypt-ruby>, ["~> 3.0.0"])
|
317
319
|
s.add_development_dependency(%q<abstract>, [">= 1.0.0"])
|
318
320
|
s.add_development_dependency(%q<rails>, [">= 3.0.0"])
|
319
|
-
s.add_development_dependency(%q<json>, [">= 1.
|
321
|
+
s.add_development_dependency(%q<json>, [">= 1.7.7"])
|
320
322
|
s.add_development_dependency(%q<rspec>, ["~> 2.5.0"])
|
321
323
|
s.add_development_dependency(%q<rspec-rails>, ["~> 2.5.0"])
|
322
|
-
s.add_development_dependency(%q<
|
323
|
-
s.add_development_dependency(%q<sqlite3-ruby>, [">= 0"])
|
324
|
+
s.add_development_dependency(%q<sqlite3>, [">= 0"])
|
324
325
|
s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
|
325
326
|
s.add_development_dependency(%q<bundler>, [">= 1.1.0"])
|
326
327
|
s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
|
@@ -335,11 +336,10 @@ Gem::Specification.new do |s|
|
|
335
336
|
s.add_dependency(%q<bcrypt-ruby>, ["~> 3.0.0"])
|
336
337
|
s.add_dependency(%q<abstract>, [">= 1.0.0"])
|
337
338
|
s.add_dependency(%q<rails>, [">= 3.0.0"])
|
338
|
-
s.add_dependency(%q<json>, [">= 1.
|
339
|
+
s.add_dependency(%q<json>, [">= 1.7.7"])
|
339
340
|
s.add_dependency(%q<rspec>, ["~> 2.5.0"])
|
340
341
|
s.add_dependency(%q<rspec-rails>, ["~> 2.5.0"])
|
341
|
-
s.add_dependency(%q<
|
342
|
-
s.add_dependency(%q<sqlite3-ruby>, [">= 0"])
|
342
|
+
s.add_dependency(%q<sqlite3>, [">= 0"])
|
343
343
|
s.add_dependency(%q<yard>, ["~> 0.6.0"])
|
344
344
|
s.add_dependency(%q<bundler>, [">= 1.1.0"])
|
345
345
|
s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
|
@@ -355,11 +355,10 @@ Gem::Specification.new do |s|
|
|
355
355
|
s.add_dependency(%q<bcrypt-ruby>, ["~> 3.0.0"])
|
356
356
|
s.add_dependency(%q<abstract>, [">= 1.0.0"])
|
357
357
|
s.add_dependency(%q<rails>, [">= 3.0.0"])
|
358
|
-
s.add_dependency(%q<json>, [">= 1.
|
358
|
+
s.add_dependency(%q<json>, [">= 1.7.7"])
|
359
359
|
s.add_dependency(%q<rspec>, ["~> 2.5.0"])
|
360
360
|
s.add_dependency(%q<rspec-rails>, ["~> 2.5.0"])
|
361
|
-
s.add_dependency(%q<
|
362
|
-
s.add_dependency(%q<sqlite3-ruby>, [">= 0"])
|
361
|
+
s.add_dependency(%q<sqlite3>, [">= 0"])
|
363
362
|
s.add_dependency(%q<yard>, ["~> 0.6.0"])
|
364
363
|
s.add_dependency(%q<bundler>, [">= 1.1.0"])
|
365
364
|
s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
|
data/spec/Gemfile
CHANGED
data/spec/Gemfile.lock
CHANGED
data/spec/rails3/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ../../
|
3
3
|
specs:
|
4
|
-
sorcery (0.
|
4
|
+
sorcery (0.8.1)
|
5
5
|
bcrypt-ruby (~> 3.0.0)
|
6
6
|
oauth (~> 0.4.4)
|
7
7
|
oauth2 (~> 0.8.0)
|
@@ -54,7 +54,7 @@ GEM
|
|
54
54
|
diff-lcs (1.1.3)
|
55
55
|
erubis (2.6.6)
|
56
56
|
abstract (>= 1.0.0)
|
57
|
-
faraday (0.8.
|
57
|
+
faraday (0.8.5)
|
58
58
|
multipart-post (~> 1.1)
|
59
59
|
ffi (1.0.11)
|
60
60
|
httpauth (0.2.0)
|
@@ -75,7 +75,7 @@ GEM
|
|
75
75
|
multipart-post (1.1.5)
|
76
76
|
nokogiri (1.5.0)
|
77
77
|
oauth (0.4.7)
|
78
|
-
oauth2 (0.8.
|
78
|
+
oauth2 (0.8.1)
|
79
79
|
faraday (~> 0.8)
|
80
80
|
httpauth (~> 0.1)
|
81
81
|
jwt (~> 0.1.4)
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class User < ActiveRecord::Base
|
2
|
-
attr_accessible :email, :password, :password_confirmation, :authentications_attributes
|
2
|
+
attr_accessible :username, :email, :password, :password_confirmation, :authentications_attributes
|
3
3
|
|
4
4
|
has_many :authentications, :dependent => :destroy
|
5
5
|
accepts_nested_attributes_for :authentications
|
@@ -1 +1 @@
|
|
1
|
-
Please visit
|
1
|
+
Please visit <%= @url %> for unlock your account.
|
data/spec/rails3/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb
CHANGED
@@ -3,6 +3,7 @@ class AddActivityLoggingToUsers < ActiveRecord::Migration
|
|
3
3
|
add_column :users, :last_login_at, :datetime, :default => nil
|
4
4
|
add_column :users, :last_logout_at, :datetime, :default => nil
|
5
5
|
add_column :users, :last_activity_at, :datetime, :default => nil
|
6
|
+
add_column :users, :last_login_from_ip_address, :string, :default => nil
|
6
7
|
|
7
8
|
add_index :users, [:last_logout_at, :last_activity_at]
|
8
9
|
end
|
@@ -13,5 +14,6 @@ class AddActivityLoggingToUsers < ActiveRecord::Migration
|
|
13
14
|
remove_column :users, :last_activity_at
|
14
15
|
remove_column :users, :last_logout_at
|
15
16
|
remove_column :users, :last_login_at
|
17
|
+
remove_column :users, :last_login_from_ip_address
|
16
18
|
end
|
17
19
|
end
|