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.

Files changed (43) hide show
  1. data/Gemfile +4 -4
  2. data/Gemfile.lock +5 -22
  3. data/README.rdoc +2 -2
  4. data/Rakefile +1 -0
  5. data/VERSION +1 -1
  6. data/lib/generators/sorcery/templates/initializer.rb +24 -13
  7. data/lib/generators/sorcery/templates/migration/activity_logging.rb +2 -0
  8. data/lib/sorcery/controller/submodules/activity_logging.rb +12 -1
  9. data/lib/sorcery/controller/submodules/external/protocols/oauth1.rb +14 -3
  10. data/lib/sorcery/controller/submodules/external/protocols/oauth2.rb +5 -1
  11. data/lib/sorcery/controller/submodules/external/providers/base.rb +21 -0
  12. data/lib/sorcery/controller/submodules/external/providers/facebook.rb +13 -12
  13. data/lib/sorcery/controller/submodules/external/providers/github.rb +4 -3
  14. data/lib/sorcery/controller/submodules/external/providers/google.rb +4 -3
  15. data/lib/sorcery/controller/submodules/external/providers/linkedin.rb +13 -12
  16. data/lib/sorcery/controller/submodules/external/providers/liveid.rb +5 -4
  17. data/lib/sorcery/controller/submodules/external/providers/twitter.rb +15 -14
  18. data/lib/sorcery/controller/submodules/external/providers/vk.rb +6 -5
  19. data/lib/sorcery/controller/submodules/external/providers/xing.rb +97 -0
  20. data/lib/sorcery/controller/submodules/external.rb +72 -39
  21. data/lib/sorcery/controller.rb +5 -2
  22. data/lib/sorcery/model/submodules/activity_logging.rb +3 -0
  23. data/lib/sorcery/model/submodules/brute_force_protection.rb +14 -12
  24. data/lib/sorcery/model.rb +1 -1
  25. data/lib/sorcery/railties/tasks.rake +1 -7
  26. data/lib/sorcery.rb +3 -1
  27. data/sorcery.gemspec +11 -12
  28. data/spec/Gemfile +1 -1
  29. data/spec/Gemfile.lock +1 -1
  30. data/spec/rails3/Gemfile.lock +3 -3
  31. data/spec/rails3/app/models/user.rb +1 -1
  32. data/spec/rails3/app/views/sorcery_mailer/send_unlock_token_email.text.erb +1 -1
  33. data/spec/rails3/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +2 -0
  34. data/spec/rails3/spec/controller_activity_logging_spec.rb +15 -0
  35. data/spec/rails3/spec/controller_brute_force_protection_spec.rb +14 -6
  36. data/spec/rails3/spec/controller_spec.rb +32 -27
  37. data/spec/rails3_mongo_mapper/Gemfile.lock +3 -3
  38. data/spec/rails3_mongo_mapper/spec/controller_spec.rb +32 -27
  39. data/spec/rails3_mongoid/Gemfile.lock +3 -3
  40. data/spec/rails3_mongoid/spec/controller_activity_logging_spec.rb +6 -0
  41. data/spec/rails3_mongoid/spec/controller_spec.rb +33 -28
  42. data/spec/shared_examples/user_activity_logging_shared_examples.rb +5 -0
  43. 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 => @access_token.token,
55
- :uids => @access_token.params["user_id"],
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 = @access_token.get(@user_info_url, :params => params)
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
- @access_token = self.get_access_token(args, options)
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
- # sends user to authenticate at the provider's website.
33
- # after authentication the user is redirected to the callback defined in the provider config
34
- def login_at(provider_name, args = {})
35
- provider = Config.send(provider_name)
36
- if provider.callback_url.present? && provider.callback_url[0] == '/'
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.callback_url}"
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
- provider = Config.send(provider_name)
54
- provider.process_callback(params,session)
55
- user_hash = provider.get_user_hash
56
- if user = user_class.load_from_provider(provider_name,user_hash[:uid].to_s)
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
- provider_name = provider_name.to_sym
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
- provider_name = provider_name.to_sym
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
- provider_name = provider_name.to_sym
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
@@ -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
- def login(*credentials)
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
- before_logout!(current_user)
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.1"
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-01-25"
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.21"
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.5.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<ruby-debug19>, [">= 0"])
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.5.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<ruby-debug19>, [">= 0"])
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.5.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<ruby-debug19>, [">= 0"])
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
@@ -1,4 +1,4 @@
1
- source 'http://rubygems.org'
1
+ source 'https://rubygems.org'
2
2
 
3
3
  gem "rails", '3.0.3'
4
4
  gem 'bcrypt-ruby', :require => 'bcrypt'
data/spec/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- sorcery (0.7.13)
4
+ sorcery (0.8.1)
5
5
  bcrypt-ruby (~> 3.0.0)
6
6
  oauth (~> 0.4.4)
7
7
  oauth2 (~> 0.8.0)
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../../
3
3
  specs:
4
- sorcery (0.7.13)
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.4)
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.0)
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 <% @url %> for unlock your account.
1
+ Please visit <%= @url %> for unlock your account.
@@ -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