sorcery 0.8.5 → 0.9.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 (163) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/.travis.yml +122 -5
  4. data/CHANGELOG.md +37 -1
  5. data/Gemfile +10 -18
  6. data/README.md +159 -88
  7. data/gemfiles/active_record-rails40.gemfile +7 -0
  8. data/gemfiles/active_record-rails41.gemfile +7 -0
  9. data/gemfiles/mongo_mapper-rails40.gemfile +9 -0
  10. data/gemfiles/mongo_mapper-rails41.gemfile +9 -0
  11. data/gemfiles/mongoid-rails40.gemfile +9 -0
  12. data/gemfiles/mongoid-rails41.gemfile +9 -0
  13. data/gemfiles/mongoid3-rails32.gemfile +9 -0
  14. data/lib/generators/sorcery/USAGE +1 -1
  15. data/lib/generators/sorcery/install_generator.rb +19 -5
  16. data/lib/generators/sorcery/templates/initializer.rb +34 -9
  17. data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +3 -1
  18. data/lib/generators/sorcery/templates/migration/core.rb +2 -2
  19. data/lib/generators/sorcery/templates/migration/external.rb +3 -1
  20. data/lib/sorcery/adapters/active_record_adapter.rb +120 -0
  21. data/lib/sorcery/adapters/base_adapter.rb +30 -0
  22. data/lib/sorcery/adapters/data_mapper_adapter.rb +176 -0
  23. data/lib/sorcery/adapters/mongo_mapper_adapter.rb +110 -0
  24. data/lib/sorcery/adapters/mongoid_adapter.rb +97 -0
  25. data/lib/sorcery/controller/config.rb +65 -0
  26. data/lib/sorcery/controller/submodules/activity_logging.rb +16 -21
  27. data/lib/sorcery/controller/submodules/brute_force_protection.rb +6 -6
  28. data/lib/sorcery/controller/submodules/external.rb +35 -40
  29. data/lib/sorcery/controller/submodules/remember_me.rb +4 -4
  30. data/lib/sorcery/controller/submodules/session_timeout.rb +10 -6
  31. data/lib/sorcery/controller.rb +10 -74
  32. data/lib/sorcery/model/config.rb +96 -0
  33. data/lib/sorcery/model/submodules/activity_logging.rb +30 -13
  34. data/lib/sorcery/model/submodules/brute_force_protection.rb +21 -21
  35. data/lib/sorcery/model/submodules/external.rb +53 -9
  36. data/lib/sorcery/model/submodules/remember_me.rb +15 -19
  37. data/lib/sorcery/model/submodules/reset_password.rb +33 -34
  38. data/lib/sorcery/model/submodules/user_activation.rb +36 -47
  39. data/lib/sorcery/model/temporary_token.rb +4 -4
  40. data/lib/sorcery/model.rb +73 -173
  41. data/lib/sorcery/protocols/oauth.rb +42 -0
  42. data/lib/sorcery/protocols/oauth2.rb +47 -0
  43. data/lib/sorcery/providers/base.rb +38 -0
  44. data/lib/sorcery/providers/facebook.rb +63 -0
  45. data/lib/sorcery/providers/github.rb +51 -0
  46. data/lib/sorcery/providers/google.rb +51 -0
  47. data/lib/sorcery/providers/heroku.rb +57 -0
  48. data/lib/sorcery/providers/jira.rb +77 -0
  49. data/lib/sorcery/providers/linkedin.rb +66 -0
  50. data/lib/sorcery/providers/liveid.rb +53 -0
  51. data/lib/sorcery/providers/salesforce.rb +50 -0
  52. data/lib/sorcery/providers/twitter.rb +59 -0
  53. data/lib/sorcery/providers/vk.rb +63 -0
  54. data/lib/sorcery/providers/xing.rb +64 -0
  55. data/lib/sorcery/test_helpers/internal/rails.rb +14 -3
  56. data/lib/sorcery/test_helpers/internal.rb +7 -3
  57. data/lib/sorcery/test_helpers/rails/controller.rb +21 -0
  58. data/lib/sorcery/test_helpers/rails/integration.rb +26 -0
  59. data/lib/sorcery/version.rb +3 -0
  60. data/lib/sorcery.rb +82 -58
  61. data/sorcery.gemspec +19 -19
  62. data/spec/active_record/user_activation_spec.rb +1 -1
  63. data/spec/active_record/user_activity_logging_spec.rb +10 -1
  64. data/spec/active_record/user_brute_force_protection_spec.rb +1 -1
  65. data/spec/active_record/user_oauth_spec.rb +1 -1
  66. data/spec/active_record/user_remember_me_spec.rb +1 -1
  67. data/spec/active_record/user_reset_password_spec.rb +1 -1
  68. data/spec/active_record/user_spec.rb +7 -8
  69. data/spec/controllers/controller_activity_logging_spec.rb +124 -0
  70. data/spec/controllers/controller_brute_force_protection_spec.rb +43 -0
  71. data/spec/controllers/controller_http_basic_auth_spec.rb +68 -0
  72. data/spec/controllers/controller_oauth2_spec.rb +414 -0
  73. data/spec/controllers/controller_oauth_spec.rb +240 -0
  74. data/spec/controllers/controller_remember_me_spec.rb +117 -0
  75. data/spec/controllers/controller_session_timeout_spec.rb +80 -0
  76. data/spec/controllers/controller_spec.rb +218 -0
  77. data/spec/data_mapper/user_activation_spec.rb +10 -0
  78. data/spec/data_mapper/user_activity_logging_spec.rb +14 -0
  79. data/spec/data_mapper/user_brute_force_protection_spec.rb +9 -0
  80. data/spec/data_mapper/user_oauth_spec.rb +9 -0
  81. data/spec/data_mapper/user_remember_me_spec.rb +8 -0
  82. data/spec/data_mapper/user_reset_password_spec.rb +8 -0
  83. data/spec/data_mapper/user_spec.rb +27 -0
  84. data/spec/mongo_mapper/user_activation_spec.rb +1 -2
  85. data/spec/mongo_mapper/user_activity_logging_spec.rb +1 -1
  86. data/spec/mongo_mapper/user_brute_force_protection_spec.rb +1 -1
  87. data/spec/mongo_mapper/user_oauth_spec.rb +1 -1
  88. data/spec/mongo_mapper/user_remember_me_spec.rb +1 -1
  89. data/spec/mongo_mapper/user_reset_password_spec.rb +1 -1
  90. data/spec/mongo_mapper/user_spec.rb +7 -8
  91. data/spec/mongoid/user_activation_spec.rb +1 -2
  92. data/spec/mongoid/user_activity_logging_spec.rb +1 -2
  93. data/spec/mongoid/user_brute_force_protection_spec.rb +1 -2
  94. data/spec/mongoid/user_oauth_spec.rb +1 -2
  95. data/spec/mongoid/user_remember_me_spec.rb +1 -2
  96. data/spec/mongoid/user_reset_password_spec.rb +1 -2
  97. data/spec/mongoid/user_spec.rb +21 -9
  98. data/spec/orm/active_record.rb +14 -0
  99. data/spec/orm/data_mapper.rb +48 -0
  100. data/spec/orm/mongo_mapper.rb +1 -1
  101. data/spec/orm/mongoid.rb +5 -0
  102. data/spec/rails_app/app/controllers/sorcery_controller.rb +125 -59
  103. data/spec/rails_app/app/data_mapper/authentication.rb +8 -0
  104. data/spec/rails_app/app/data_mapper/user.rb +7 -0
  105. data/spec/rails_app/app/mongo_mapper/user.rb +2 -0
  106. data/spec/rails_app/config/routes.rb +27 -13
  107. data/spec/rails_app/db/migrate/core/20101224223620_create_users.rb +2 -2
  108. data/spec/shared_examples/user_activation_shared_examples.rb +108 -91
  109. data/spec/shared_examples/user_activity_logging_shared_examples.rb +83 -15
  110. data/spec/shared_examples/user_brute_force_protection_shared_examples.rb +140 -21
  111. data/spec/shared_examples/user_oauth_shared_examples.rb +21 -16
  112. data/spec/shared_examples/user_remember_me_shared_examples.rb +36 -24
  113. data/spec/shared_examples/user_reset_password_shared_examples.rb +138 -117
  114. data/spec/shared_examples/user_shared_examples.rb +297 -150
  115. data/spec/sorcery_crypto_providers_spec.rb +28 -28
  116. data/spec/spec_helper.rb +12 -18
  117. metadata +99 -165
  118. data/Gemfile.rails4 +0 -24
  119. data/VERSION +0 -1
  120. data/lib/sorcery/controller/submodules/external/protocols/oauth1.rb +0 -46
  121. data/lib/sorcery/controller/submodules/external/protocols/oauth2.rb +0 -50
  122. data/lib/sorcery/controller/submodules/external/providers/base.rb +0 -21
  123. data/lib/sorcery/controller/submodules/external/providers/facebook.rb +0 -99
  124. data/lib/sorcery/controller/submodules/external/providers/github.rb +0 -93
  125. data/lib/sorcery/controller/submodules/external/providers/google.rb +0 -92
  126. data/lib/sorcery/controller/submodules/external/providers/linkedin.rb +0 -103
  127. data/lib/sorcery/controller/submodules/external/providers/liveid.rb +0 -93
  128. data/lib/sorcery/controller/submodules/external/providers/twitter.rb +0 -94
  129. data/lib/sorcery/controller/submodules/external/providers/vk.rb +0 -101
  130. data/lib/sorcery/controller/submodules/external/providers/xing.rb +0 -98
  131. data/lib/sorcery/model/adapters/active_record.rb +0 -49
  132. data/lib/sorcery/model/adapters/mongo_mapper.rb +0 -56
  133. data/lib/sorcery/model/adapters/mongoid.rb +0 -88
  134. data/lib/sorcery/test_helpers/rails.rb +0 -16
  135. data/lib/sorcery/test_helpers.rb +0 -5
  136. data/spec/active_record/controller_activity_logging_spec.rb +0 -140
  137. data/spec/active_record/controller_brute_force_protection_spec.rb +0 -136
  138. data/spec/active_record/controller_http_basic_auth_spec.rb +0 -59
  139. data/spec/active_record/controller_oauth2_spec.rb +0 -417
  140. data/spec/active_record/controller_oauth_spec.rb +0 -212
  141. data/spec/active_record/controller_remember_me_spec.rb +0 -96
  142. data/spec/active_record/controller_session_timeout_spec.rb +0 -55
  143. data/spec/active_record/controller_spec.rb +0 -182
  144. data/spec/active_record/integration_spec.rb +0 -23
  145. data/spec/mongo_mapper/controller_spec.rb +0 -175
  146. data/spec/mongoid/controller_activity_logging_spec.rb +0 -111
  147. data/spec/mongoid/controller_spec.rb +0 -186
  148. data/spec/rails_app/public/404.html +0 -26
  149. data/spec/rails_app/public/422.html +0 -26
  150. data/spec/rails_app/public/500.html +0 -26
  151. data/spec/rails_app/public/favicon.ico +0 -0
  152. data/spec/rails_app/public/images/rails.png +0 -0
  153. data/spec/rails_app/public/javascripts/application.js +0 -2
  154. data/spec/rails_app/public/javascripts/controls.js +0 -965
  155. data/spec/rails_app/public/javascripts/dragdrop.js +0 -974
  156. data/spec/rails_app/public/javascripts/effects.js +0 -1123
  157. data/spec/rails_app/public/javascripts/prototype.js +0 -6001
  158. data/spec/rails_app/public/javascripts/rails.js +0 -175
  159. data/spec/rails_app/public/robots.txt +0 -5
  160. data/spec/rails_app/public/stylesheets/.gitkeep +0 -0
  161. data/spec/shared_examples/controller_oauth2_shared_examples.rb +0 -56
  162. data/spec/shared_examples/controller_oauth_shared_examples.rb +0 -69
  163. /data/lib/sorcery/{controller/submodules/external/protocols → protocols}/certs/ca-bundle.crt +0 -0
@@ -10,16 +10,16 @@ module Sorcery
10
10
  base.sorcery_config.class_eval do
11
11
  attr_accessor :activation_state_attribute_name, # the attribute name to hold activation state
12
12
  # (active/pending).
13
-
13
+
14
14
  :activation_token_attribute_name, # the attribute name to hold activation code
15
15
  # (sent by email).
16
-
16
+
17
17
  :activation_token_expires_at_attribute_name, # the attribute name to hold activation code
18
- # expiration date.
19
-
18
+ # expiration date.
19
+
20
20
  :activation_token_expiration_period, # how many seconds before the activation code
21
21
  # expires. nil for never expires.
22
-
22
+
23
23
  :user_activation_mailer, # your mailer class. Required when
24
24
  # activation_mailer_disabled == false.
25
25
 
@@ -29,14 +29,14 @@ module Sorcery
29
29
 
30
30
  :activation_needed_email_method_name, # activation needed email method on your
31
31
  # mailer class.
32
-
32
+
33
33
  :activation_success_email_method_name, # activation success email method on your
34
34
  # mailer class.
35
-
35
+
36
36
  :prevent_non_active_users_to_login # do you want to prevent or allow users that
37
37
  # did not activate by email to login?
38
38
  end
39
-
39
+
40
40
  base.sorcery_config.instance_eval do
41
41
  @defaults.merge!(:@activation_state_attribute_name => :activation_state,
42
42
  :@activation_token_attribute_name => :activation_token,
@@ -49,27 +49,24 @@ module Sorcery
49
49
  :@prevent_non_active_users_to_login => true)
50
50
  reset!
51
51
  end
52
-
52
+
53
53
  base.class_eval do
54
54
  # don't setup activation if no password supplied - this user is created automatically
55
- before_create :setup_activation, :if => Proc.new { |user| user.send(sorcery_config.password_attribute_name).present? }
55
+ sorcery_adapter.define_callback :before, :create, :setup_activation, :if => Proc.new { |user| user.send(sorcery_config.password_attribute_name).present? }
56
56
  # don't send activation needed email if no crypted password created - this user is external (OAuth etc.)
57
- after_create :send_activation_needed_email!, :if => :send_activation_needed_email?
57
+ sorcery_adapter.define_callback :after, :create, :send_activation_needed_email!, :if => :send_activation_needed_email?
58
58
  end
59
-
59
+
60
60
  base.sorcery_config.after_config << :validate_mailer_defined
61
- base.sorcery_config.after_config << :define_user_activation_mongoid_fields if defined?(Mongoid) and base.ancestors.include?(Mongoid::Document)
62
- if defined?(MongoMapper) and base.ancestors.include?(MongoMapper::Document)
63
- base.sorcery_config.after_config << :define_user_activation_mongo_mapper_fields
64
- end
61
+ base.sorcery_config.after_config << :define_user_activation_fields
65
62
  base.sorcery_config.before_authenticate << :prevent_non_active_login
66
-
63
+
67
64
  base.extend(ClassMethods)
68
65
  base.send(:include, InstanceMethods)
69
66
 
70
67
 
71
68
  end
72
-
69
+
73
70
  module ClassMethods
74
71
  # Find user by token, also checks for expiration.
75
72
  # Returns the user if token found and is valid.
@@ -78,9 +75,9 @@ module Sorcery
78
75
  token_expiration_date_attr = @sorcery_config.activation_token_expires_at_attribute_name
79
76
  load_from_token(token, token_attr_name, token_expiration_date_attr)
80
77
  end
81
-
78
+
82
79
  protected
83
-
80
+
84
81
  # This submodule requires the developer to define his own mailer class to be used by it
85
82
  # when activation_mailer_disabled is false
86
83
  def validate_mailer_defined
@@ -88,42 +85,34 @@ module Sorcery
88
85
  raise ArgumentError, msg if @sorcery_config.user_activation_mailer == nil and @sorcery_config.activation_mailer_disabled == false
89
86
  end
90
87
 
91
- def define_user_activation_mongoid_fields
92
- self.class_eval do
93
- field sorcery_config.activation_state_attribute_name, :type => String
94
- field sorcery_config.activation_token_attribute_name, :type => String
95
- field sorcery_config.activation_token_expires_at_attribute_name, :type => Time
96
- end
97
- end
98
-
99
- def define_user_activation_mongo_mapper_fields
88
+ def define_user_activation_fields
100
89
  self.class_eval do
101
- key sorcery_config.activation_state_attribute_name, String
102
- key sorcery_config.activation_token_attribute_name, String
103
- key sorcery_config.activation_token_expires_at_attribute_name, Time
90
+ sorcery_adapter.define_field sorcery_config.activation_state_attribute_name, String
91
+ sorcery_adapter.define_field sorcery_config.activation_token_attribute_name, String
92
+ sorcery_adapter.define_field sorcery_config.activation_token_expires_at_attribute_name, Time
104
93
  end
105
94
  end
106
95
  end
107
-
96
+
108
97
  module InstanceMethods
98
+ def setup_activation
99
+ config = sorcery_config
100
+ 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
104
+ end
105
+
109
106
  # clears activation code, sets the user as 'active' and optionaly sends a success email.
110
107
  def activate!
111
108
  config = sorcery_config
112
109
  self.send(:"#{config.activation_token_attribute_name}=", nil)
113
110
  self.send(:"#{config.activation_state_attribute_name}=", "active")
114
111
  send_activation_success_email! if send_activation_success_email?
115
- save!(:validate => false) # don't run validations
112
+ sorcery_adapter.save(:validate => false, :raise_on_failure => true)
116
113
  end
117
-
118
- protected
119
114
 
120
- def setup_activation
121
- config = sorcery_config
122
- generated_activation_token = TemporaryToken.generate_random_token
123
- self.send(:"#{config.activation_token_attribute_name}=", generated_activation_token)
124
- self.send(:"#{config.activation_state_attribute_name}=", "pending")
125
- 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
126
- end
115
+ protected
127
116
 
128
117
  # called automatically after user initial creation.
129
118
  def send_activation_needed_email!
@@ -133,21 +122,21 @@ module Sorcery
133
122
  def send_activation_success_email!
134
123
  generic_send_email(:activation_success_email_method_name, :user_activation_mailer)
135
124
  end
136
-
125
+
137
126
  def send_activation_success_email?
138
127
  !external? && (
139
128
  !(sorcery_config.activation_success_email_method_name.nil? ||
140
129
  sorcery_config.activation_mailer_disabled == true)
141
130
  )
142
131
  end
143
-
132
+
144
133
  def send_activation_needed_email?
145
134
  !external? && (
146
135
  !(sorcery_config.activation_needed_email_method_name.nil? ||
147
136
  sorcery_config.activation_mailer_disabled == true)
148
137
  )
149
138
  end
150
-
139
+
151
140
  def prevent_non_active_login
152
141
  config = sorcery_config
153
142
  config.prevent_non_active_users_to_login ? self.send(config.activation_state_attribute_name) == "active" : true
@@ -157,4 +146,4 @@ module Sorcery
157
146
  end
158
147
  end
159
148
  end
160
- end
149
+ end
@@ -3,22 +3,22 @@ require 'securerandom'
3
3
  module Sorcery
4
4
  module Model
5
5
  # This module encapsulates the logic for temporary token.
6
- # A temporary token is created to identify a user in scenarios
6
+ # A temporary token is created to identify a user in scenarios
7
7
  # such as reseting password and activating the user by email.
8
8
  module TemporaryToken
9
9
  def self.included(base)
10
10
  base.extend(ClassMethods)
11
11
  end
12
-
12
+
13
13
  # Random code, used for salt and temporary tokens.
14
14
  def self.generate_random_token
15
15
  SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')
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 = find_by_sorcery_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
@@ -7,91 +7,70 @@ module Sorcery
7
7
  # which when called adds the other capabilities to the class.
8
8
  # This method is also the place to configure the plugin in the Model layer.
9
9
  module Model
10
- def self.included(klass)
11
- klass.class_eval do
12
- class << self
13
- def authenticates_with_sorcery!
14
- @sorcery_config = Config.new
15
- self.class_eval do
16
- extend ClassMethods # included here, before submodules, so they can be overriden by them.
17
- include InstanceMethods
18
- include TemporaryToken
19
- end
10
+ def authenticates_with_sorcery!
11
+ @sorcery_config = Config.new
20
12
 
21
- include_required_submodules!
13
+ extend ClassMethods # included here, before submodules, so they can be overriden by them.
14
+ include InstanceMethods
15
+ include TemporaryToken
22
16
 
23
- # This runs the options block set in the initializer on the model class.
24
- ::Sorcery::Controller::Config.user_config.tap{|blk| blk.call(@sorcery_config) if blk}
17
+ include_required_submodules!
25
18
 
26
- init_mongoid_support! if defined?(Mongoid) and self.ancestors.include?(Mongoid::Document)
27
- init_mongo_mapper_support! if defined?(MongoMapper) and self.ancestors.include?(MongoMapper::Document)
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}
28
21
 
29
- init_orm_hooks!
22
+ define_base_fields
23
+ init_orm_hooks!
30
24
 
31
- @sorcery_config.after_config << :add_config_inheritance if @sorcery_config.subclasses_inherit_config
32
- @sorcery_config.after_config.each { |c| send(c) }
33
- end
25
+ @sorcery_config.after_config << :add_config_inheritance if @sorcery_config.subclasses_inherit_config
26
+ @sorcery_config.after_config.each { |c| send(c) }
27
+ end
34
28
 
35
- protected
36
-
37
- # includes required submodules into the model class,
38
- # which usually is called User.
39
- def include_required_submodules!
40
- self.class_eval do
41
- @sorcery_config.submodules = ::Sorcery::Controller::Config.submodules
42
- @sorcery_config.submodules.each do |mod|
43
- begin
44
- include Submodules.const_get(mod.to_s.split("_").map {|p| p.capitalize}.join(""))
45
- rescue NameError
46
- # don't stop on a missing submodule. Needed because some submodules are only defined
47
- # in the controller side.
48
- end
49
- end
50
- end
51
- end
29
+ private
52
30
 
53
- # defines mongoid fields on the model class,
54
- # using 1.8.x hash syntax to perserve compatibility.
55
- def init_mongoid_support!
56
- self.class_eval do
57
- sorcery_config.username_attribute_names.each do |username|
58
- field username, :type => String
59
- end
60
- field sorcery_config.email_attribute_name, :type => String unless sorcery_config.username_attribute_names.include?(sorcery_config.email_attribute_name)
61
- field sorcery_config.crypted_password_attribute_name, :type => String
62
- field sorcery_config.salt_attribute_name, :type => String
63
- end
64
- end
31
+ def define_base_fields
32
+ self.class_eval do
33
+ sorcery_config.username_attribute_names.each do |username|
34
+ sorcery_adapter.define_field username, String, length: 255
35
+ end
36
+ unless sorcery_config.username_attribute_names.include?(sorcery_config.email_attribute_name)
37
+ sorcery_adapter.define_field sorcery_config.email_attribute_name, String, length: 255
38
+ end
39
+ sorcery_adapter.define_field sorcery_config.crypted_password_attribute_name, String, length: 255
40
+ sorcery_adapter.define_field sorcery_config.salt_attribute_name, String, length: 255
41
+ end
65
42
 
66
- # defines mongo_mapper fields on the model class,
67
- def init_mongo_mapper_support!
68
- self.class_eval do
69
- sorcery_config.username_attribute_names.each do |username|
70
- key username, String
71
- end
72
- key sorcery_config.email_attribute_name, String unless sorcery_config.username_attribute_names.include?(sorcery_config.email_attribute_name)
73
- key sorcery_config.crypted_password_attribute_name, String
74
- key sorcery_config.salt_attribute_name, String
75
- end
76
- end
43
+ end
77
44
 
78
- # add virtual password accessor and ORM callbacks.
79
- def init_orm_hooks!
80
- self.class_eval do
81
- attr_accessor @sorcery_config.password_attribute_name
82
- #attr_protected @sorcery_config.crypted_password_attribute_name, @sorcery_config.salt_attribute_name
83
- before_save :encrypt_password, :if => Proc.new { |record|
84
- record.send(sorcery_config.password_attribute_name).present?
85
- }
86
- after_save :clear_virtual_password, :if => Proc.new { |record|
87
- record.send(sorcery_config.password_attribute_name).present?
88
- }
89
- end
45
+ # includes required submodules into the model class,
46
+ # which usually is called User.
47
+ def include_required_submodules!
48
+ self.class_eval do
49
+ @sorcery_config.submodules = ::Sorcery::Controller::Config.submodules
50
+ @sorcery_config.submodules.each do |mod|
51
+ begin
52
+ include Submodules.const_get(mod.to_s.split('_').map {|p| p.capitalize}.join)
53
+ rescue NameError
54
+ # don't stop on a missing submodule. Needed because some submodules are only defined
55
+ # in the controller side.
90
56
  end
91
57
  end
92
58
  end
93
59
  end
94
60
 
61
+ # add virtual password accessor and ORM callbacks.
62
+ def init_orm_hooks!
63
+ sorcery_adapter.define_callback :before, :validation, :encrypt_password, if: Proc.new {|record|
64
+ record.send(sorcery_config.password_attribute_name).present?
65
+ }
66
+
67
+ sorcery_adapter.define_callback :after, :save, :clear_virtual_password, if: Proc.new {|record|
68
+ record.send(sorcery_config.password_attribute_name).present?
69
+ }
70
+
71
+ attr_accessor sorcery_config.password_attribute_name
72
+ end
73
+
95
74
  module ClassMethods
96
75
  # Returns the class instance variable for configuration, when called by the class itself.
97
76
  def sorcery_config
@@ -111,12 +90,11 @@ module Sorcery
111
90
  credentials[0].downcase!
112
91
  end
113
92
 
114
- user = find_by_credentials(credentials)
93
+ user = sorcery_adapter.find_by_credentials(credentials)
115
94
 
116
95
  set_encryption_attributes
117
96
 
118
- _salt = user.send(@sorcery_config.salt_attribute_name) if user && !@sorcery_config.salt_attribute_name.nil? && !@sorcery_config.encryption_provider.nil?
119
- user if user && @sorcery_config.before_authenticate.all? {|c| user.send(c)} && credentials_match?(user.send(@sorcery_config.crypted_password_attribute_name),credentials[1],_salt)
97
+ user if user && @sorcery_config.before_authenticate.all? {|c| user.send(c)} && user.valid_password?(credentials[1])
120
98
  end
121
99
 
122
100
  # encrypt tokens using current encryption_provider.
@@ -135,13 +113,7 @@ module Sorcery
135
113
  @sorcery_config.encryption_provider.stretches = @sorcery_config.stretches if @sorcery_config.encryption_provider.respond_to?(:stretches) && @sorcery_config.stretches
136
114
  @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
137
115
  end
138
-
139
- # Calls the configured encryption provider to compare the supplied password with the encrypted one.
140
- def credentials_match?(crypted, *tokens)
141
- return crypted == tokens.join if @sorcery_config.encryption_provider.nil?
142
- @sorcery_config.encryption_provider.matches?(crypted, *tokens)
143
- end
144
-
116
+
145
117
  def add_config_inheritance
146
118
  self.class_eval do
147
119
  def self.inherited(subclass)
@@ -170,6 +142,16 @@ module Sorcery
170
142
  send(sorcery_config.crypted_password_attribute_name).nil?
171
143
  end
172
144
 
145
+ # Calls the configured encryption provider to compare the supplied password with the encrypted one.
146
+ 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
+
150
+ _salt = self.send(sorcery_config.salt_attribute_name) unless sorcery_config.salt_attribute_name.nil?
151
+
152
+ sorcery_config.encryption_provider.matches?(_crypted, pass, _salt)
153
+ end
154
+
173
155
  protected
174
156
 
175
157
  # creates new salt and saves it.
@@ -183,6 +165,10 @@ module Sorcery
183
165
  def clear_virtual_password
184
166
  config = sorcery_config
185
167
  self.send(:"#{config.password_attribute_name}=", nil)
168
+
169
+ if respond_to?(:"#{config.password_attribute_name}_confirmation=")
170
+ self.send(:"#{config.password_attribute_name}_confirmation=", nil)
171
+ end
186
172
  end
187
173
 
188
174
  # calls the requested email method on the configured mailer
@@ -191,100 +177,14 @@ module Sorcery
191
177
  config = sorcery_config
192
178
  mail = config.send(mailer).send(config.send(method),self)
193
179
  if defined?(ActionMailer) and config.send(mailer).kind_of?(Class) and config.send(mailer) < ActionMailer::Base
194
- mail.deliver
195
- end
196
- end
197
- end
198
-
199
- # Each class which calls 'activate_sorcery!' receives an instance of this class.
200
- # Every submodule which gets loaded may add accessors to this class so that all
201
- # options will be configured from a single place.
202
- class Config
203
-
204
- attr_accessor :username_attribute_names, # change default username attribute, for example, to use :email
205
- # as the login.
206
-
207
- :password_attribute_name, # change *virtual* password attribute, the one which is used
208
- # until an encrypted one is generated.
209
-
210
- :email_attribute_name, # change default email attribute.
211
-
212
- :downcase_username_before_authenticating, # downcase the username before trying to authenticate, default is false
213
-
214
- :crypted_password_attribute_name, # change default crypted_password attribute.
215
- :salt_join_token, # what pattern to use to join the password with the salt
216
- :salt_attribute_name, # change default salt attribute.
217
- :stretches, # how many times to apply encryption to the password.
218
- :encryption_key, # encryption key used to encrypt reversible encryptions such as
219
- # AES256.
220
-
221
- :subclasses_inherit_config, # make this configuration inheritable for subclasses. Useful for
222
- # ActiveRecord's STI.
223
-
224
- :submodules, # configured in config/application.rb
225
- :before_authenticate, # an array of method names to call before authentication
226
- # completes. used internally.
227
-
228
- :after_config # an array of method names to call after configuration by user.
229
- # used internally.
230
-
231
- attr_reader :encryption_provider, # change default encryption_provider.
232
- :custom_encryption_provider, # use an external encryption class.
233
- :encryption_algorithm # encryption algorithm name. See 'encryption_algorithm=' below
234
- # for available options.
235
-
236
- def initialize
237
- @defaults = {
238
- :@submodules => [],
239
- :@username_attribute_names => [:email],
240
- :@password_attribute_name => :password,
241
- :@downcase_username_before_authenticating => false,
242
- :@email_attribute_name => :email,
243
- :@crypted_password_attribute_name => :crypted_password,
244
- :@encryption_algorithm => :bcrypt,
245
- :@encryption_provider => CryptoProviders::BCrypt,
246
- :@custom_encryption_provider => nil,
247
- :@encryption_key => nil,
248
- :@salt_join_token => "",
249
- :@salt_attribute_name => :salt,
250
- :@stretches => nil,
251
- :@subclasses_inherit_config => false,
252
- :@before_authenticate => [],
253
- :@after_config => []
254
- }
255
- reset!
256
- end
257
-
258
- # Resets all configuration options to their default values.
259
- def reset!
260
- @defaults.each do |k,v|
261
- instance_variable_set(k,v)
262
- end
263
- end
264
-
265
- def username_attribute_names=(fields)
266
- @username_attribute_names = fields.kind_of?(Array) ? fields : [fields]
267
- end
268
-
269
- def custom_encryption_provider=(provider)
270
- @custom_encryption_provider = @encryption_provider = provider
271
- end
272
-
273
- def encryption_algorithm=(algo)
274
- @encryption_algorithm = algo
275
- @encryption_provider = case @encryption_algorithm.to_sym
276
- when :none then nil
277
- when :md5 then CryptoProviders::MD5
278
- when :sha1 then CryptoProviders::SHA1
279
- when :sha256 then CryptoProviders::SHA256
280
- when :sha512 then CryptoProviders::SHA512
281
- when :aes256 then CryptoProviders::AES256
282
- when :bcrypt then CryptoProviders::BCrypt
283
- when :custom then @custom_encryption_provider
284
- else raise ArgumentError.new("Encryption algorithm supplied, #{algo}, is invalid")
180
+ # Rails 4.2 deprecates #deliver
181
+ if mail.respond_to?(:deliver_now)
182
+ mail.deliver_now
183
+ else
184
+ mail.deliver
185
+ end
285
186
  end
286
187
  end
287
-
288
188
  end
289
189
 
290
190
  end
@@ -0,0 +1,42 @@
1
+ require 'oauth'
2
+
3
+ module Sorcery
4
+ module Protocols
5
+ module Oauth
6
+
7
+ def oauth_version
8
+ '1.0'
9
+ end
10
+
11
+ def get_request_token(token=nil,secret=nil)
12
+ return ::OAuth::RequestToken.new(get_consumer, token, secret) if token && secret
13
+ get_consumer.get_request_token(oauth_callback: @callback_url)
14
+ end
15
+
16
+ def authorize_url(args)
17
+ get_request_token(
18
+ args[:request_token],
19
+ args[:request_token_secret]
20
+ ).authorize_url({
21
+ oauth_callback: @callback_url
22
+ })
23
+ end
24
+
25
+ def get_access_token(args)
26
+ get_request_token(
27
+ args[:request_token],
28
+ args[:request_token_secret]
29
+ ).get_access_token({
30
+ oauth_verifier: args[:oauth_verifier]
31
+ })
32
+ end
33
+
34
+ protected
35
+
36
+ def get_consumer
37
+ ::OAuth::Consumer.new(@key, @secret, site: @site)
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,47 @@
1
+ require 'oauth2'
2
+
3
+ module Sorcery
4
+ module Protocols
5
+ module Oauth2
6
+
7
+ def oauth_version
8
+ '2.0'
9
+ end
10
+
11
+ def authorize_url(options = {})
12
+ client = build_client(options)
13
+ client.auth_code.authorize_url(
14
+ redirect_uri: @callback_url,
15
+ scope: @scope,
16
+ display: @display,
17
+ state: @state
18
+ )
19
+ end
20
+
21
+ def get_access_token(args, options = {})
22
+ client = build_client(options)
23
+ client.auth_code.get_token(
24
+ args[:code],
25
+ {
26
+ redirect_uri: @callback_url,
27
+ parse: options.delete(:parse)
28
+ },
29
+ options
30
+ )
31
+ end
32
+
33
+ def build_client(options = {})
34
+ defaults = {
35
+ site: @site,
36
+ ssl: { ca_file: Sorcery::Controller::Config.ca_file }
37
+ }
38
+ ::OAuth2::Client.new(
39
+ @key,
40
+ @secret,
41
+ defaults.merge!(options)
42
+ )
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,38 @@
1
+ module Sorcery
2
+ module Providers
3
+ class Base
4
+
5
+ attr_reader :access_token
6
+
7
+ attr_accessor :callback_url, :key, :original_callback_url, :secret,
8
+ :site, :state, :user_info_mapping
9
+
10
+ def has_callback?; true; end
11
+
12
+ def initialize
13
+ @user_info_mapping = {}
14
+ end
15
+
16
+ def auth_hash(access_token, hash={})
17
+ return hash if access_token.nil?
18
+
19
+ token_hash = hash.dup
20
+ token_hash[:token] = access_token.token if access_token.respond_to?(:token)
21
+ token_hash[:refresh_token] = access_token.refresh_token if access_token.respond_to?(:refresh_token)
22
+ token_hash[:expires_at] = access_token.expires_at if access_token.respond_to?(:expires_at)
23
+ token_hash[:expires_in] = access_token.expires_at if access_token.respond_to?(:expires_in)
24
+ token_hash
25
+ end
26
+
27
+ def self.name
28
+ super.gsub(/Sorcery::Providers::/, '').downcase
29
+ end
30
+
31
+ # Ensure that all descendant classes are loaded before run this
32
+ def self.descendants
33
+ ObjectSpace.each_object(Class).select { |klass| klass < self }
34
+ end
35
+
36
+ end
37
+ end
38
+ end