sorcery 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +29 -104
  3. data/CHANGELOG.md +22 -1
  4. data/Gemfile +2 -16
  5. data/README.md +124 -271
  6. data/Rakefile +2 -2
  7. data/gemfiles/{mongoid-rails40.gemfile → active_record-rails42.gemfile} +1 -3
  8. data/lib/generators/sorcery/helpers.rb +4 -4
  9. data/lib/generators/sorcery/install_generator.rb +25 -19
  10. data/lib/generators/sorcery/templates/initializer.rb +29 -53
  11. data/lib/generators/sorcery/templates/migration/activity_logging.rb +2 -2
  12. data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +1 -1
  13. data/lib/generators/sorcery/templates/migration/core.rb +3 -3
  14. data/lib/generators/sorcery/templates/migration/external.rb +3 -3
  15. data/lib/generators/sorcery/templates/migration/remember_me.rb +2 -2
  16. data/lib/generators/sorcery/templates/migration/reset_password.rb +2 -2
  17. data/lib/generators/sorcery/templates/migration/user_activation.rb +2 -2
  18. data/lib/sorcery/adapters/active_record_adapter.rb +7 -18
  19. data/lib/sorcery/controller/config.rb +20 -18
  20. data/lib/sorcery/controller/submodules/activity_logging.rb +7 -15
  21. data/lib/sorcery/controller/submodules/brute_force_protection.rb +1 -2
  22. data/lib/sorcery/controller/submodules/external.rb +23 -15
  23. data/lib/sorcery/controller/submodules/http_basic_auth.rb +16 -19
  24. data/lib/sorcery/controller/submodules/remember_me.rb +15 -10
  25. data/lib/sorcery/controller/submodules/session_timeout.rb +7 -8
  26. data/lib/sorcery/controller.rb +19 -21
  27. data/lib/sorcery/crypto_providers/aes256.rb +15 -15
  28. data/lib/sorcery/crypto_providers/bcrypt.rb +19 -21
  29. data/lib/sorcery/crypto_providers/common.rb +1 -1
  30. data/lib/sorcery/crypto_providers/md5.rb +5 -5
  31. data/lib/sorcery/crypto_providers/sha1.rb +5 -5
  32. data/lib/sorcery/crypto_providers/sha256.rb +2 -2
  33. data/lib/sorcery/crypto_providers/sha512.rb +3 -3
  34. data/lib/sorcery/engine.rb +3 -8
  35. data/lib/sorcery/model/config.rb +64 -49
  36. data/lib/sorcery/model/submodules/activity_logging.rb +31 -12
  37. data/lib/sorcery/model/submodules/brute_force_protection.rb +23 -23
  38. data/lib/sorcery/model/submodules/external.rb +3 -7
  39. data/lib/sorcery/model/submodules/remember_me.rb +19 -7
  40. data/lib/sorcery/model/submodules/reset_password.rb +32 -36
  41. data/lib/sorcery/model/submodules/user_activation.rb +38 -50
  42. data/lib/sorcery/model/temporary_token.rb +2 -2
  43. data/lib/sorcery/model.rb +27 -31
  44. data/lib/sorcery/protocols/oauth.rb +3 -9
  45. data/lib/sorcery/protocols/oauth2.rb +0 -2
  46. data/lib/sorcery/providers/base.rb +4 -4
  47. data/lib/sorcery/providers/facebook.rb +17 -9
  48. data/lib/sorcery/providers/github.rb +12 -5
  49. data/lib/sorcery/providers/google.rb +3 -5
  50. data/lib/sorcery/providers/heroku.rb +6 -8
  51. data/lib/sorcery/providers/jira.rb +12 -17
  52. data/lib/sorcery/providers/linkedin.rb +6 -8
  53. data/lib/sorcery/providers/liveid.rb +4 -7
  54. data/lib/sorcery/providers/paypal.rb +60 -0
  55. data/lib/sorcery/providers/salesforce.rb +3 -5
  56. data/lib/sorcery/providers/slack.rb +45 -0
  57. data/lib/sorcery/providers/twitter.rb +4 -6
  58. data/lib/sorcery/providers/vk.rb +3 -5
  59. data/lib/sorcery/providers/wechat.rb +79 -0
  60. data/lib/sorcery/providers/xing.rb +8 -11
  61. data/lib/sorcery/test_helpers/internal/rails.rb +16 -8
  62. data/lib/sorcery/test_helpers/internal.rb +10 -10
  63. data/lib/sorcery/test_helpers/rails/controller.rb +1 -1
  64. data/lib/sorcery/test_helpers/rails/integration.rb +5 -6
  65. data/lib/sorcery/version.rb +1 -1
  66. data/lib/sorcery.rb +0 -28
  67. data/sorcery.gemspec +25 -27
  68. data/spec/active_record/user_activation_spec.rb +2 -3
  69. data/spec/active_record/user_activity_logging_spec.rb +2 -4
  70. data/spec/active_record/user_brute_force_protection_spec.rb +3 -4
  71. data/spec/active_record/user_oauth_spec.rb +3 -4
  72. data/spec/active_record/user_remember_me_spec.rb +3 -4
  73. data/spec/active_record/user_reset_password_spec.rb +2 -3
  74. data/spec/active_record/user_spec.rb +7 -7
  75. data/spec/controllers/controller_activity_logging_spec.rb +13 -24
  76. data/spec/controllers/controller_brute_force_protection_spec.rb +6 -8
  77. data/spec/controllers/controller_http_basic_auth_spec.rb +19 -20
  78. data/spec/controllers/controller_oauth2_spec.rb +142 -102
  79. data/spec/controllers/controller_oauth_spec.rb +86 -66
  80. data/spec/controllers/controller_remember_me_spec.rb +35 -30
  81. data/spec/controllers/controller_session_timeout_spec.rb +14 -15
  82. data/spec/controllers/controller_spec.rb +77 -111
  83. data/spec/orm/active_record.rb +1 -1
  84. data/spec/rails_app/app/active_record/authentication.rb +1 -1
  85. data/spec/rails_app/app/active_record/user.rb +2 -2
  86. data/spec/rails_app/app/controllers/sorcery_controller.rb +89 -24
  87. data/spec/rails_app/app/mailers/sorcery_mailer.rb +16 -17
  88. data/spec/rails_app/config/application.rb +7 -7
  89. data/spec/rails_app/config/boot.rb +1 -1
  90. data/spec/rails_app/config/environments/test.rb +1 -1
  91. data/spec/rails_app/config/initializers/compatible_legacy_migration.rb +11 -0
  92. data/spec/rails_app/config/initializers/session_store.rb +3 -3
  93. data/spec/rails_app/config/routes.rb +11 -1
  94. data/spec/rails_app/config.ru +1 -1
  95. data/spec/rails_app/db/migrate/activation/20101224223622_add_activation_to_users.rb +4 -4
  96. data/spec/rails_app/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +8 -8
  97. data/spec/rails_app/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +5 -5
  98. data/spec/rails_app/db/migrate/core/20101224223620_create_users.rb +5 -5
  99. data/spec/rails_app/db/migrate/external/20101224223628_create_authentications_and_user_providers.rb +3 -3
  100. data/spec/rails_app/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb +6 -6
  101. data/spec/rails_app/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +5 -5
  102. data/spec/shared_examples/user_activation_shared_examples.rb +99 -58
  103. data/spec/shared_examples/user_activity_logging_shared_examples.rb +47 -41
  104. data/spec/shared_examples/user_brute_force_protection_shared_examples.rb +19 -24
  105. data/spec/shared_examples/user_oauth_shared_examples.rb +7 -10
  106. data/spec/shared_examples/user_remember_me_shared_examples.rb +90 -21
  107. data/spec/shared_examples/user_reset_password_shared_examples.rb +52 -54
  108. data/spec/shared_examples/user_shared_examples.rb +226 -116
  109. data/spec/sorcery_crypto_providers_spec.rb +63 -76
  110. data/spec/spec_helper.rb +17 -13
  111. metadata +28 -82
  112. data/gemfiles/mongo_mapper-rails40.gemfile +0 -9
  113. data/gemfiles/mongo_mapper-rails41.gemfile +0 -9
  114. data/gemfiles/mongoid-rails41.gemfile +0 -9
  115. data/gemfiles/mongoid3-rails32.gemfile +0 -9
  116. data/lib/sorcery/adapters/data_mapper_adapter.rb +0 -176
  117. data/lib/sorcery/adapters/mongo_mapper_adapter.rb +0 -110
  118. data/lib/sorcery/adapters/mongoid_adapter.rb +0 -97
  119. data/lib/sorcery/railties/tasks.rake +0 -6
  120. data/spec/data_mapper/user_activation_spec.rb +0 -10
  121. data/spec/data_mapper/user_activity_logging_spec.rb +0 -14
  122. data/spec/data_mapper/user_brute_force_protection_spec.rb +0 -9
  123. data/spec/data_mapper/user_oauth_spec.rb +0 -9
  124. data/spec/data_mapper/user_remember_me_spec.rb +0 -8
  125. data/spec/data_mapper/user_reset_password_spec.rb +0 -8
  126. data/spec/data_mapper/user_spec.rb +0 -27
  127. data/spec/mongo_mapper/user_activation_spec.rb +0 -9
  128. data/spec/mongo_mapper/user_activity_logging_spec.rb +0 -8
  129. data/spec/mongo_mapper/user_brute_force_protection_spec.rb +0 -8
  130. data/spec/mongo_mapper/user_oauth_spec.rb +0 -8
  131. data/spec/mongo_mapper/user_remember_me_spec.rb +0 -8
  132. data/spec/mongo_mapper/user_reset_password_spec.rb +0 -8
  133. data/spec/mongo_mapper/user_spec.rb +0 -37
  134. data/spec/mongoid/user_activation_spec.rb +0 -9
  135. data/spec/mongoid/user_activity_logging_spec.rb +0 -8
  136. data/spec/mongoid/user_brute_force_protection_spec.rb +0 -8
  137. data/spec/mongoid/user_oauth_spec.rb +0 -8
  138. data/spec/mongoid/user_remember_me_spec.rb +0 -8
  139. data/spec/mongoid/user_reset_password_spec.rb +0 -8
  140. data/spec/mongoid/user_spec.rb +0 -51
  141. data/spec/orm/data_mapper.rb +0 -48
  142. data/spec/orm/mongo_mapper.rb +0 -10
  143. data/spec/orm/mongoid.rb +0 -22
  144. data/spec/rails_app/app/data_mapper/authentication.rb +0 -8
  145. data/spec/rails_app/app/data_mapper/user.rb +0 -7
  146. data/spec/rails_app/app/mongo_mapper/authentication.rb +0 -6
  147. data/spec/rails_app/app/mongo_mapper/user.rb +0 -7
  148. data/spec/rails_app/app/mongoid/authentication.rb +0 -7
  149. data/spec/rails_app/app/mongoid/user.rb +0 -7
  150. data/spec/rails_app/log/development.log +0 -1791
@@ -8,33 +8,24 @@ module Sorcery
8
8
  module UserActivation
9
9
  def self.included(base)
10
10
  base.sorcery_config.class_eval do
11
- attr_accessor :activation_state_attribute_name, # the attribute name to hold activation state
12
- # (active/pending).
13
-
14
- :activation_token_attribute_name, # the attribute name to hold activation code
15
- # (sent by email).
16
-
17
- :activation_token_expires_at_attribute_name, # the attribute name to hold activation code
18
- # expiration date.
19
-
20
- :activation_token_expiration_period, # how many seconds before the activation code
21
- # expires. nil for never expires.
22
-
23
- :user_activation_mailer, # your mailer class. Required when
24
- # activation_mailer_disabled == false.
25
-
26
- :activation_mailer_disabled, # when true sorcery will not automatically
27
- # email activation details and allow you to
28
- # manually handle how and when email is sent
29
-
30
- :activation_needed_email_method_name, # activation needed email method on your
31
- # mailer class.
32
-
33
- :activation_success_email_method_name, # activation success email method on your
34
- # mailer class.
35
-
36
- :prevent_non_active_users_to_login # do you want to prevent or allow users that
37
- # did not activate by email to login?
11
+ # The attribute name to hold activation state (active/pending).
12
+ attr_accessor :activation_state_attribute_name
13
+ # The attribute name to hold activation code (sent by email).
14
+ attr_accessor :activation_token_attribute_name
15
+ # The attribute name to hold activation code expiration date.
16
+ attr_accessor :activation_token_expires_at_attribute_name
17
+ # How many seconds before the activation code expires. nil for never expires.
18
+ attr_accessor :activation_token_expiration_period
19
+ # Your mailer class. Required when activation_mailer_disabled == false.
20
+ attr_accessor :user_activation_mailer
21
+ # When true sorcery will not automatically email activation details and allow you to manually handle how and when email is sent
22
+ attr_accessor :activation_mailer_disabled
23
+ # Activation needed email method on your mailer class.
24
+ attr_accessor :activation_needed_email_method_name
25
+ # Activation success email method on your mailer class.
26
+ attr_accessor :activation_success_email_method_name
27
+ # Do you want to prevent or allow users that did not activate by email to login?
28
+ attr_accessor :prevent_non_active_users_to_login
38
29
  end
39
30
 
40
31
  base.sorcery_config.instance_eval do
@@ -52,9 +43,9 @@ module Sorcery
52
43
 
53
44
  base.class_eval do
54
45
  # don't setup activation if no password supplied - this user is created automatically
55
- sorcery_adapter.define_callback :before, :create, :setup_activation, :if => Proc.new { |user| user.send(sorcery_config.password_attribute_name).present? }
46
+ sorcery_adapter.define_callback :before, :create, :setup_activation, if: proc { |user| user.send(sorcery_config.password_attribute_name).present? }
56
47
  # don't send activation needed email if no crypted password created - this user is external (OAuth etc.)
57
- sorcery_adapter.define_callback :after, :create, :send_activation_needed_email!, :if => :send_activation_needed_email?
48
+ sorcery_adapter.define_callback :after, :create, :send_activation_needed_email!, if: :send_activation_needed_email?
58
49
  end
59
50
 
60
51
  base.sorcery_config.after_config << :validate_mailer_defined
@@ -63,8 +54,6 @@ module Sorcery
63
54
 
64
55
  base.extend(ClassMethods)
65
56
  base.send(:include, InstanceMethods)
66
-
67
-
68
57
  end
69
58
 
70
59
  module ClassMethods
@@ -81,12 +70,12 @@ module Sorcery
81
70
  # This submodule requires the developer to define his own mailer class to be used by it
82
71
  # when activation_mailer_disabled is false
83
72
  def validate_mailer_defined
84
- msg = "To use user_activation submodule, you must define a mailer (config.user_activation_mailer = YourMailerClass)."
85
- raise ArgumentError, msg if @sorcery_config.user_activation_mailer == nil and @sorcery_config.activation_mailer_disabled == false
73
+ message = 'To use user_activation submodule, you must define a mailer (config.user_activation_mailer = YourMailerClass).'
74
+ raise ArgumentError, message if @sorcery_config.user_activation_mailer.nil? && @sorcery_config.activation_mailer_disabled == false
86
75
  end
87
76
 
88
77
  def define_user_activation_fields
89
- self.class_eval do
78
+ class_eval do
90
79
  sorcery_adapter.define_field sorcery_config.activation_state_attribute_name, String
91
80
  sorcery_adapter.define_field sorcery_config.activation_token_attribute_name, String
92
81
  sorcery_adapter.define_field sorcery_config.activation_token_expires_at_attribute_name, Time
@@ -98,20 +87,22 @@ module Sorcery
98
87
  def setup_activation
99
88
  config = sorcery_config
100
89
  generated_activation_token = TemporaryToken.generate_random_token
101
- self.send(:"#{config.activation_token_attribute_name}=", generated_activation_token)
102
- self.send(:"#{config.activation_state_attribute_name}=", "pending")
103
- self.send(:"#{config.activation_token_expires_at_attribute_name}=", Time.now.in_time_zone + config.activation_token_expiration_period) if config.activation_token_expiration_period
90
+ send(:"#{config.activation_token_attribute_name}=", generated_activation_token)
91
+ send(:"#{config.activation_state_attribute_name}=", 'pending')
92
+ send(:"#{config.activation_token_expires_at_attribute_name}=", Time.now.in_time_zone + config.activation_token_expiration_period) if config.activation_token_expiration_period
104
93
  end
105
94
 
106
95
  # clears activation code, sets the user as 'active' and optionaly sends a success email.
107
96
  def activate!
108
97
  config = sorcery_config
109
- self.send(:"#{config.activation_token_attribute_name}=", nil)
110
- self.send(:"#{config.activation_state_attribute_name}=", "active")
98
+ send(:"#{config.activation_token_attribute_name}=", nil)
99
+ send(:"#{config.activation_state_attribute_name}=", 'active')
111
100
  send_activation_success_email! if send_activation_success_email?
112
- sorcery_adapter.save(:validate => false, :raise_on_failure => true)
101
+ sorcery_adapter.save(validate: false, raise_on_failure: true)
113
102
  end
114
103
 
104
+ attr_accessor :skip_activation_needed_email, :skip_activation_success_email
105
+
115
106
  protected
116
107
 
117
108
  # called automatically after user initial creation.
@@ -124,24 +115,21 @@ module Sorcery
124
115
  end
125
116
 
126
117
  def send_activation_success_email?
127
- !external? && (
128
- !(sorcery_config.activation_success_email_method_name.nil? ||
129
- sorcery_config.activation_mailer_disabled == true)
130
- )
118
+ !external? &&
119
+ !(sorcery_config.activation_success_email_method_name.nil? || sorcery_config.activation_mailer_disabled == true) &&
120
+ !skip_activation_success_email
131
121
  end
132
122
 
133
123
  def send_activation_needed_email?
134
- !external? && (
135
- !(sorcery_config.activation_needed_email_method_name.nil? ||
136
- sorcery_config.activation_mailer_disabled == true)
137
- )
124
+ !external? &&
125
+ !(sorcery_config.activation_needed_email_method_name.nil? || sorcery_config.activation_mailer_disabled == true) &&
126
+ !skip_activation_needed_email
138
127
  end
139
128
 
140
129
  def prevent_non_active_login
141
130
  config = sorcery_config
142
- config.prevent_non_active_users_to_login ? self.send(config.activation_state_attribute_name) == "active" : true
131
+ config.prevent_non_active_users_to_login ? send(config.activation_state_attribute_name) == 'active' : true
143
132
  end
144
-
145
133
  end
146
134
  end
147
135
  end
@@ -12,13 +12,13 @@ module Sorcery
12
12
 
13
13
  # Random code, used for salt and temporary tokens.
14
14
  def self.generate_random_token
15
- SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')
15
+ SecureRandom.urlsafe_base64(15).tr('lIO0', 'sxyz')
16
16
  end
17
17
 
18
18
  module ClassMethods
19
19
  def load_from_token(token, token_attr_name, token_expiration_date_attr)
20
20
  return nil if token.blank?
21
- user = sorcery_adapter.find_by_token(token_attr_name,token)
21
+ user = sorcery_adapter.find_by_token(token_attr_name, token)
22
22
  if !user.blank? && !user.send(token_expiration_date_attr).nil?
23
23
  return Time.now.in_time_zone < user.send(token_expiration_date_attr) ? user : nil
24
24
  end
data/lib/sorcery/model.rb CHANGED
@@ -17,7 +17,7 @@ module Sorcery
17
17
  include_required_submodules!
18
18
 
19
19
  # This runs the options block set in the initializer on the model class.
20
- ::Sorcery::Controller::Config.user_config.tap{|blk| blk.call(@sorcery_config) if blk}
20
+ ::Sorcery::Controller::Config.user_config.tap { |blk| blk.call(@sorcery_config) if blk }
21
21
 
22
22
  define_base_fields
23
23
  init_orm_hooks!
@@ -29,7 +29,7 @@ module Sorcery
29
29
  private
30
30
 
31
31
  def define_base_fields
32
- self.class_eval do
32
+ class_eval do
33
33
  sorcery_config.username_attribute_names.each do |username|
34
34
  sorcery_adapter.define_field username, String, length: 255
35
35
  end
@@ -39,17 +39,16 @@ module Sorcery
39
39
  sorcery_adapter.define_field sorcery_config.crypted_password_attribute_name, String, length: 255
40
40
  sorcery_adapter.define_field sorcery_config.salt_attribute_name, String, length: 255
41
41
  end
42
-
43
42
  end
44
43
 
45
44
  # includes required submodules into the model class,
46
45
  # which usually is called User.
47
46
  def include_required_submodules!
48
- self.class_eval do
47
+ class_eval do
49
48
  @sorcery_config.submodules = ::Sorcery::Controller::Config.submodules
50
49
  @sorcery_config.submodules.each do |mod|
51
50
  begin
52
- include Submodules.const_get(mod.to_s.split('_').map {|p| p.capitalize}.join)
51
+ include Submodules.const_get(mod.to_s.split('_').map(&:capitalize).join)
53
52
  rescue NameError
54
53
  # don't stop on a missing submodule. Needed because some submodules are only defined
55
54
  # in the controller side.
@@ -60,11 +59,11 @@ module Sorcery
60
59
 
61
60
  # add virtual password accessor and ORM callbacks.
62
61
  def init_orm_hooks!
63
- sorcery_adapter.define_callback :before, :validation, :encrypt_password, if: Proc.new {|record|
62
+ sorcery_adapter.define_callback :before, :validation, :encrypt_password, if: proc { |record|
64
63
  record.send(sorcery_config.password_attribute_name).present?
65
64
  }
66
65
 
67
- sorcery_adapter.define_callback :after, :save, :clear_virtual_password, if: Proc.new {|record|
66
+ sorcery_adapter.define_callback :after, :save, :clear_virtual_password, if: proc { |record|
68
67
  record.send(sorcery_config.password_attribute_name).present?
69
68
  }
70
69
 
@@ -82,7 +81,7 @@ module Sorcery
82
81
  # Finds the user by the username and compares the user's password to the one supplied to the method.
83
82
  # returns the user if success, nil otherwise.
84
83
  def authenticate(*credentials)
85
- raise ArgumentError, "at least 2 arguments required" if credentials.size < 2
84
+ raise ArgumentError, 'at least 2 arguments required' if credentials.size < 2
86
85
 
87
86
  return false if credentials[0].blank?
88
87
 
@@ -92,16 +91,20 @@ module Sorcery
92
91
 
93
92
  user = sorcery_adapter.find_by_credentials(credentials)
94
93
 
94
+ if user.respond_to?(:active_for_authentication?)
95
+ return nil unless user.active_for_authentication?
96
+ end
97
+
95
98
  set_encryption_attributes
96
99
 
97
- user if user && @sorcery_config.before_authenticate.all? {|c| user.send(c)} && user.valid_password?(credentials[1])
100
+ user if user && @sorcery_config.before_authenticate.all? { |c| user.send(c) } && user.valid_password?(credentials[1])
98
101
  end
99
102
 
100
103
  # encrypt tokens using current encryption_provider.
101
104
  def encrypt(*tokens)
102
105
  return tokens.first if @sorcery_config.encryption_provider.nil?
103
106
 
104
- set_encryption_attributes()
107
+ set_encryption_attributes
105
108
 
106
109
  CryptoProviders::AES256.key = @sorcery_config.encryption_key
107
110
  @sorcery_config.encryption_provider.encrypt(*tokens)
@@ -109,13 +112,13 @@ module Sorcery
109
112
 
110
113
  protected
111
114
 
112
- def set_encryption_attributes()
115
+ def set_encryption_attributes
113
116
  @sorcery_config.encryption_provider.stretches = @sorcery_config.stretches if @sorcery_config.encryption_provider.respond_to?(:stretches) && @sorcery_config.stretches
114
117
  @sorcery_config.encryption_provider.join_token = @sorcery_config.salt_join_token if @sorcery_config.encryption_provider.respond_to?(:join_token) && @sorcery_config.salt_join_token
115
118
  end
116
-
119
+
117
120
  def add_config_inheritance
118
- self.class_eval do
121
+ class_eval do
119
122
  def self.inherited(subclass)
120
123
  subclass.class_eval do
121
124
  class << self
@@ -127,7 +130,6 @@ module Sorcery
127
130
  end
128
131
  end
129
132
  end
130
-
131
133
  end
132
134
 
133
135
  module InstanceMethods
@@ -144,12 +146,12 @@ module Sorcery
144
146
 
145
147
  # Calls the configured encryption provider to compare the supplied password with the encrypted one.
146
148
  def valid_password?(pass)
147
- _crypted = self.send(sorcery_config.crypted_password_attribute_name)
148
- return _crypted == pass if sorcery_config.encryption_provider.nil?
149
+ crypted = send(sorcery_config.crypted_password_attribute_name)
150
+ return crypted == pass if sorcery_config.encryption_provider.nil?
149
151
 
150
- _salt = self.send(sorcery_config.salt_attribute_name) unless sorcery_config.salt_attribute_name.nil?
152
+ salt = send(sorcery_config.salt_attribute_name) unless sorcery_config.salt_attribute_name.nil?
151
153
 
152
- sorcery_config.encryption_provider.matches?(_crypted, pass, _salt)
154
+ sorcery_config.encryption_provider.matches?(crypted, pass, salt)
153
155
  end
154
156
 
155
157
  protected
@@ -158,16 +160,16 @@ module Sorcery
158
160
  # encrypts password with salt and saves it.
159
161
  def encrypt_password
160
162
  config = sorcery_config
161
- self.send(:"#{config.salt_attribute_name}=", new_salt = TemporaryToken.generate_random_token) if !config.salt_attribute_name.nil?
162
- self.send(:"#{config.crypted_password_attribute_name}=", self.class.encrypt(self.send(config.password_attribute_name),new_salt))
163
+ send(:"#{config.salt_attribute_name}=", new_salt = TemporaryToken.generate_random_token) unless config.salt_attribute_name.nil?
164
+ send(:"#{config.crypted_password_attribute_name}=", self.class.encrypt(send(config.password_attribute_name), new_salt))
163
165
  end
164
166
 
165
167
  def clear_virtual_password
166
168
  config = sorcery_config
167
- self.send(:"#{config.password_attribute_name}=", nil)
169
+ send(:"#{config.password_attribute_name}=", nil)
168
170
 
169
171
  if respond_to?(:"#{config.password_attribute_name}_confirmation=")
170
- self.send(:"#{config.password_attribute_name}_confirmation=", nil)
172
+ send(:"#{config.password_attribute_name}_confirmation=", nil)
171
173
  end
172
174
  end
173
175
 
@@ -175,17 +177,11 @@ module Sorcery
175
177
  # supports both the ActionMailer 3 way of calling, and the plain old Ruby object way.
176
178
  def generic_send_email(method, mailer)
177
179
  config = sorcery_config
178
- mail = config.send(mailer).send(config.send(method),self)
179
- if defined?(ActionMailer) and config.send(mailer).kind_of?(Class) and config.send(mailer) < ActionMailer::Base
180
- # Rails 4.2 deprecates #deliver
181
- if mail.respond_to?(:deliver_now)
182
- mail.deliver_now
183
- else
184
- mail.deliver
185
- end
180
+ mail = config.send(mailer).send(config.send(method), self)
181
+ if defined?(ActionMailer) && config.send(mailer).is_a?(Class) && config.send(mailer) < ActionMailer::Base
182
+ mail.send(config.email_delivery_method)
186
183
  end
187
184
  end
188
185
  end
189
-
190
186
  end
191
187
  end
@@ -3,12 +3,11 @@ require 'oauth'
3
3
  module Sorcery
4
4
  module Protocols
5
5
  module Oauth
6
-
7
6
  def oauth_version
8
7
  '1.0'
9
8
  end
10
9
 
11
- def get_request_token(token=nil,secret=nil)
10
+ def get_request_token(token = nil, secret = nil)
12
11
  return ::OAuth::RequestToken.new(get_consumer, token, secret) if token && secret
13
12
  get_consumer.get_request_token(oauth_callback: @callback_url)
14
13
  end
@@ -17,18 +16,14 @@ module Sorcery
17
16
  get_request_token(
18
17
  args[:request_token],
19
18
  args[:request_token_secret]
20
- ).authorize_url({
21
- oauth_callback: @callback_url
22
- })
19
+ ).authorize_url(oauth_callback: @callback_url)
23
20
  end
24
21
 
25
22
  def get_access_token(args)
26
23
  get_request_token(
27
24
  args[:request_token],
28
25
  args[:request_token_secret]
29
- ).get_access_token({
30
- oauth_verifier: args[:oauth_verifier]
31
- })
26
+ ).get_access_token(oauth_verifier: args[:oauth_verifier])
32
27
  end
33
28
 
34
29
  protected
@@ -36,7 +31,6 @@ module Sorcery
36
31
  def get_consumer
37
32
  ::OAuth::Consumer.new(@key, @secret, site: @site)
38
33
  end
39
-
40
34
  end
41
35
  end
42
36
  end
@@ -3,7 +3,6 @@ require 'oauth2'
3
3
  module Sorcery
4
4
  module Protocols
5
5
  module Oauth2
6
-
7
6
  def oauth_version
8
7
  '2.0'
9
8
  end
@@ -41,7 +40,6 @@ module Sorcery
41
40
  defaults.merge!(options)
42
41
  )
43
42
  end
44
-
45
43
  end
46
44
  end
47
45
  end
@@ -1,19 +1,20 @@
1
1
  module Sorcery
2
2
  module Providers
3
3
  class Base
4
-
5
4
  attr_reader :access_token
6
5
 
7
6
  attr_accessor :callback_url, :key, :original_callback_url, :secret,
8
7
  :site, :state, :user_info_mapping
9
8
 
10
- def has_callback?; true; end
9
+ def has_callback?
10
+ true
11
+ end
11
12
 
12
13
  def initialize
13
14
  @user_info_mapping = {}
14
15
  end
15
16
 
16
- def auth_hash(access_token, hash={})
17
+ def auth_hash(access_token, hash = {})
17
18
  return hash if access_token.nil?
18
19
 
19
20
  token_hash = hash.dup
@@ -32,7 +33,6 @@ module Sorcery
32
33
  def self.descendants
33
34
  ObjectSpace.each_object(Class).select { |klass| klass < self }
34
35
  end
35
-
36
36
  end
37
37
  end
38
38
  end
@@ -7,21 +7,22 @@ module Sorcery
7
7
  # ...
8
8
  #
9
9
  class Facebook < Base
10
-
11
10
  include Protocols::Oauth2
12
11
 
13
12
  attr_reader :mode, :param_name, :parse
14
13
  attr_accessor :access_permissions, :display, :scope, :token_url,
15
- :user_info_path
14
+ :user_info_path, :auth_path, :api_version
16
15
 
17
16
  def initialize
18
17
  super
19
18
 
20
19
  @site = 'https://graph.facebook.com'
21
- @user_info_path = '/me'
22
- @scope = 'email,offline_access'
20
+ @auth_site = 'https://www.facebook.com'
21
+ @user_info_path = 'me'
22
+ @scope = 'email'
23
23
  @display = 'page'
24
24
  @token_url = 'oauth/access_token'
25
+ @auth_path = 'dialog/oauth'
25
26
  @mode = :query
26
27
  @parse = :query
27
28
  @param_name = 'access_token'
@@ -38,26 +39,33 @@ module Sorcery
38
39
 
39
40
  # calculates and returns the url to which the user should be redirected,
40
41
  # to get authenticated at the external provider's site.
41
- def login_url(params, session)
42
+ def login_url(_params, _session)
42
43
  authorize_url
43
44
  end
44
45
 
45
46
  # overrides oauth2#authorize_url to allow customized scope.
46
47
  def authorize_url
48
+ # Fix: replace default oauth2 options, specially to prevent the Faraday gem which
49
+ # concatenates with "/", removing the Facebook api version
50
+ options = {
51
+ site: File.join(@site, api_version.to_s),
52
+ authorize_url: File.join(@auth_site, api_version.to_s, auth_path),
53
+ token_url: token_url
54
+ }
55
+
47
56
  @scope = access_permissions.present? ? access_permissions.join(',') : scope
48
- super
57
+ super(options)
49
58
  end
50
59
 
51
60
  # tries to login the user from access token
52
- def process_callback(params, session)
61
+ def process_callback(params, _session)
53
62
  args = {}.tap do |a|
54
63
  a[:code] = params[:code] if params[:code]
55
64
  end
56
65
 
57
66
  get_access_token(args, token_url: token_url, mode: mode,
58
- param_name: param_name, parse: parse)
67
+ param_name: param_name, parse: parse)
59
68
  end
60
-
61
69
  end
62
70
  end
63
71
  end
@@ -7,7 +7,6 @@ module Sorcery
7
7
  # ...
8
8
  #
9
9
  class Github < Base
10
-
11
10
  include Protocols::Oauth2
12
11
 
13
12
  attr_accessor :auth_path, :scope, :token_url, :user_info_path
@@ -26,19 +25,21 @@ module Sorcery
26
25
  response = access_token.get(user_info_path)
27
26
 
28
27
  auth_hash(access_token).tap do |h|
29
- h[:user_info] = JSON.parse(response.body)
28
+ h[:user_info] = JSON.parse(response.body).tap do |uih|
29
+ uih['email'] = primary_email(access_token) if scope =~ /user/
30
+ end
30
31
  h[:uid] = h[:user_info]['id']
31
32
  end
32
33
  end
33
34
 
34
35
  # calculates and returns the url to which the user should be redirected,
35
36
  # to get authenticated at the external provider's site.
36
- def login_url(params, session)
37
- authorize_url({ authorize_url: auth_path })
37
+ def login_url(_params, _session)
38
+ authorize_url(authorize_url: auth_path)
38
39
  end
39
40
 
40
41
  # tries to login the user from access token
41
- def process_callback(params, session)
42
+ def process_callback(params, _session)
42
43
  args = {}.tap do |a|
43
44
  a[:code] = params[:code] if params[:code]
44
45
  end
@@ -46,6 +47,12 @@ module Sorcery
46
47
  get_access_token(args, token_url: token_url, token_method: :post)
47
48
  end
48
49
 
50
+ def primary_email(access_token)
51
+ response = access_token.get(user_info_path + '/emails')
52
+ emails = JSON.parse(response.body)
53
+ primary = emails.find { |i| i['primary'] }
54
+ primary && primary['email'] || emails.first && emails.first['email']
55
+ end
49
56
  end
50
57
  end
51
58
  end
@@ -7,7 +7,6 @@ module Sorcery
7
7
  # ...
8
8
  #
9
9
  class Google < Base
10
-
11
10
  include Protocols::Oauth2
12
11
 
13
12
  attr_accessor :auth_url, :scope, :token_url, :user_info_url
@@ -33,19 +32,18 @@ module Sorcery
33
32
 
34
33
  # calculates and returns the url to which the user should be redirected,
35
34
  # to get authenticated at the external provider's site.
36
- def login_url(params, session)
37
- authorize_url({ authorize_url: auth_url })
35
+ def login_url(_params, _session)
36
+ authorize_url(authorize_url: auth_url)
38
37
  end
39
38
 
40
39
  # tries to login the user from access token
41
- def process_callback(params, session)
40
+ def process_callback(params, _session)
42
41
  args = {}.tap do |a|
43
42
  a[:code] = params[:code] if params[:code]
44
43
  end
45
44
 
46
45
  get_access_token(args, token_url: token_url, token_method: :post)
47
46
  end
48
-
49
47
  end
50
48
  end
51
49
  end
@@ -1,6 +1,5 @@
1
1
  module Sorcery
2
2
  module Providers
3
-
4
3
  # This class adds support for OAuth with heroku.com.
5
4
 
6
5
  # config.heroku.key = <key>
@@ -13,7 +12,6 @@ module Sorcery
13
12
  # The full path must be set for OAuth Callback URL when configuring the API Client Information on Heroku.
14
13
 
15
14
  class Heroku < Base
16
-
17
15
  include Protocols::Oauth2
18
16
 
19
17
  attr_accessor :auth_path, :scope, :token_url, :user_info_path
@@ -40,18 +38,18 @@ module Sorcery
40
38
  end
41
39
  end
42
40
 
43
- def login_url(params, session)
44
- authorize_url({ authorize_url: auth_path })
41
+ def login_url(_params, _session)
42
+ authorize_url(authorize_url: auth_path)
45
43
  end
46
44
 
47
45
  # tries to login the user from access token
48
- def process_callback(params, session)
49
- raise "Invalid state. Potential Cross Site Forgery" if params[:state] != state
50
- args = { }.tap do |a|
46
+ def process_callback(params, _session)
47
+ raise 'Invalid state. Potential Cross Site Forgery' if params[:state] != state
48
+ args = {}.tap do |a|
51
49
  a[:code] = params[:code] if params[:code]
52
50
  end
53
51
  get_access_token(args, token_url: token_url, token_method: :post)
54
52
  end
55
53
  end
56
54
  end
57
- end
55
+ end