authlogic 3.8.0 → 4.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. checksums.yaml +7 -0
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +28 -0
  3. data/.github/ISSUE_TEMPLATE/feature_proposal.md +32 -0
  4. data/.github/triage.md +86 -0
  5. data/.gitignore +4 -3
  6. data/.rubocop.yml +109 -9
  7. data/.rubocop_todo.yml +38 -355
  8. data/.travis.yml +11 -35
  9. data/CHANGELOG.md +345 -2
  10. data/CONTRIBUTING.md +45 -14
  11. data/Gemfile +3 -2
  12. data/README.md +244 -90
  13. data/Rakefile +10 -10
  14. data/UPGRADING.md +22 -0
  15. data/authlogic.gemspec +34 -21
  16. data/doc/use_normal_rails_validation.md +82 -0
  17. data/gemfiles/Gemfile.rails-4.2.x +6 -0
  18. data/{test/gemfiles → gemfiles}/Gemfile.rails-5.1.x +2 -2
  19. data/{test/gemfiles → gemfiles}/Gemfile.rails-5.2.x +2 -2
  20. data/lib/authlogic/acts_as_authentic/base.rb +36 -24
  21. data/lib/authlogic/acts_as_authentic/email.rb +65 -31
  22. data/lib/authlogic/acts_as_authentic/logged_in_status.rb +14 -9
  23. data/lib/authlogic/acts_as_authentic/login.rb +61 -45
  24. data/lib/authlogic/acts_as_authentic/magic_columns.rb +6 -6
  25. data/lib/authlogic/acts_as_authentic/password.rb +267 -146
  26. data/lib/authlogic/acts_as_authentic/perishable_token.rb +24 -19
  27. data/lib/authlogic/acts_as_authentic/persistence_token.rb +10 -15
  28. data/lib/authlogic/acts_as_authentic/queries/find_with_case.rb +67 -0
  29. data/lib/authlogic/acts_as_authentic/restful_authentication.rb +50 -14
  30. data/lib/authlogic/acts_as_authentic/session_maintenance.rb +88 -60
  31. data/lib/authlogic/acts_as_authentic/single_access_token.rb +23 -11
  32. data/lib/authlogic/acts_as_authentic/validations_scope.rb +9 -6
  33. data/lib/authlogic/authenticates_many/association.rb +7 -7
  34. data/lib/authlogic/authenticates_many/base.rb +37 -21
  35. data/lib/authlogic/config.rb +21 -10
  36. data/lib/authlogic/controller_adapters/abstract_adapter.rb +38 -11
  37. data/lib/authlogic/controller_adapters/rack_adapter.rb +9 -5
  38. data/lib/authlogic/controller_adapters/rails_adapter.rb +12 -7
  39. data/lib/authlogic/controller_adapters/sinatra_adapter.rb +2 -2
  40. data/lib/authlogic/crypto_providers/aes256.rb +37 -32
  41. data/lib/authlogic/crypto_providers/bcrypt.rb +21 -15
  42. data/lib/authlogic/crypto_providers/md5.rb +4 -2
  43. data/lib/authlogic/crypto_providers/scrypt.rb +22 -17
  44. data/lib/authlogic/crypto_providers/sha1.rb +11 -5
  45. data/lib/authlogic/crypto_providers/sha256.rb +13 -9
  46. data/lib/authlogic/crypto_providers/sha512.rb +0 -21
  47. data/lib/authlogic/crypto_providers/wordpress.rb +32 -3
  48. data/lib/authlogic/crypto_providers.rb +91 -0
  49. data/lib/authlogic/i18n.rb +26 -19
  50. data/lib/authlogic/random.rb +10 -28
  51. data/lib/authlogic/regex.rb +59 -28
  52. data/lib/authlogic/session/activation.rb +10 -7
  53. data/lib/authlogic/session/active_record_trickery.rb +13 -9
  54. data/lib/authlogic/session/base.rb +15 -4
  55. data/lib/authlogic/session/brute_force_protection.rb +40 -33
  56. data/lib/authlogic/session/callbacks.rb +94 -46
  57. data/lib/authlogic/session/cookies.rb +130 -45
  58. data/lib/authlogic/session/existence.rb +21 -11
  59. data/lib/authlogic/session/foundation.rb +64 -14
  60. data/lib/authlogic/session/http_auth.rb +35 -28
  61. data/lib/authlogic/session/id.rb +9 -4
  62. data/lib/authlogic/session/klass.rb +15 -12
  63. data/lib/authlogic/session/magic_columns.rb +58 -55
  64. data/lib/authlogic/session/magic_states.rb +25 -19
  65. data/lib/authlogic/session/params.rb +42 -28
  66. data/lib/authlogic/session/password.rb +130 -120
  67. data/lib/authlogic/session/perishable_token.rb +5 -4
  68. data/lib/authlogic/session/persistence.rb +18 -12
  69. data/lib/authlogic/session/priority_record.rb +15 -12
  70. data/lib/authlogic/session/scopes.rb +51 -32
  71. data/lib/authlogic/session/session.rb +38 -28
  72. data/lib/authlogic/session/timeout.rb +13 -13
  73. data/lib/authlogic/session/unauthorized_record.rb +18 -13
  74. data/lib/authlogic/session/validation.rb +9 -9
  75. data/lib/authlogic/test_case/mock_controller.rb +5 -4
  76. data/lib/authlogic/test_case/mock_cookie_jar.rb +47 -3
  77. data/lib/authlogic/test_case/mock_request.rb +6 -3
  78. data/lib/authlogic/test_case/rails_request_adapter.rb +3 -2
  79. data/lib/authlogic/test_case.rb +70 -2
  80. data/lib/authlogic/version.rb +21 -0
  81. data/lib/authlogic.rb +51 -49
  82. data/test/acts_as_authentic_test/base_test.rb +3 -1
  83. data/test/acts_as_authentic_test/email_test.rb +43 -42
  84. data/test/acts_as_authentic_test/logged_in_status_test.rb +6 -4
  85. data/test/acts_as_authentic_test/login_test.rb +77 -80
  86. data/test/acts_as_authentic_test/magic_columns_test.rb +3 -1
  87. data/test/acts_as_authentic_test/password_test.rb +51 -37
  88. data/test/acts_as_authentic_test/perishable_token_test.rb +13 -5
  89. data/test/acts_as_authentic_test/persistence_token_test.rb +7 -1
  90. data/test/acts_as_authentic_test/restful_authentication_test.rb +14 -3
  91. data/test/acts_as_authentic_test/session_maintenance_test.rb +69 -15
  92. data/test/acts_as_authentic_test/single_access_test.rb +3 -1
  93. data/test/adapter_test.rb +23 -0
  94. data/test/authenticates_many_test.rb +3 -1
  95. data/test/config_test.rb +11 -9
  96. data/test/crypto_provider_test/aes256_test.rb +3 -1
  97. data/test/crypto_provider_test/bcrypt_test.rb +3 -1
  98. data/test/crypto_provider_test/scrypt_test.rb +3 -1
  99. data/test/crypto_provider_test/sha1_test.rb +3 -1
  100. data/test/crypto_provider_test/sha256_test.rb +3 -1
  101. data/test/crypto_provider_test/sha512_test.rb +3 -1
  102. data/test/crypto_provider_test/wordpress_test.rb +26 -0
  103. data/test/fixtures/companies.yml +2 -2
  104. data/test/fixtures/employees.yml +1 -1
  105. data/test/i18n_test.rb +6 -4
  106. data/test/libs/affiliate.rb +2 -0
  107. data/test/libs/company.rb +4 -2
  108. data/test/libs/employee.rb +2 -0
  109. data/test/libs/employee_session.rb +2 -0
  110. data/test/libs/ldaper.rb +2 -0
  111. data/test/libs/project.rb +2 -0
  112. data/test/libs/user.rb +2 -0
  113. data/test/libs/user_session.rb +4 -2
  114. data/test/random_test.rb +10 -38
  115. data/test/session_test/activation_test.rb +3 -1
  116. data/test/session_test/active_record_trickery_test.rb +7 -4
  117. data/test/session_test/brute_force_protection_test.rb +11 -9
  118. data/test/session_test/callbacks_test.rb +12 -4
  119. data/test/session_test/cookies_test.rb +48 -5
  120. data/test/session_test/existence_test.rb +18 -5
  121. data/test/session_test/foundation_test.rb +19 -1
  122. data/test/session_test/http_auth_test.rb +11 -7
  123. data/test/session_test/id_test.rb +3 -1
  124. data/test/session_test/klass_test.rb +3 -1
  125. data/test/session_test/magic_columns_test.rb +13 -13
  126. data/test/session_test/magic_states_test.rb +3 -1
  127. data/test/session_test/params_test.rb +13 -5
  128. data/test/session_test/password_test.rb +10 -8
  129. data/test/session_test/perishability_test.rb +3 -1
  130. data/test/session_test/persistence_test.rb +4 -1
  131. data/test/session_test/scopes_test.rb +16 -8
  132. data/test/session_test/session_test.rb +6 -4
  133. data/test/session_test/timeout_test.rb +4 -2
  134. data/test/session_test/unauthorized_record_test.rb +4 -2
  135. data/test/session_test/validation_test.rb +3 -1
  136. data/test/test_helper.rb +84 -45
  137. metadata +87 -73
  138. data/.github/ISSUE_TEMPLATE.md +0 -13
  139. data/test/gemfiles/Gemfile.rails-3.2.x +0 -7
  140. data/test/gemfiles/Gemfile.rails-4.0.x +0 -7
  141. data/test/gemfiles/Gemfile.rails-4.1.x +0 -7
  142. data/test/gemfiles/Gemfile.rails-4.2.x +0 -7
  143. data/test/gemfiles/Gemfile.rails-5.0.x +0 -6
@@ -22,7 +22,13 @@ module Authlogic
22
22
  rw_config(
23
23
  :crypted_password_field,
24
24
  value,
25
- first_column_to_exist(nil, :crypted_password, :encrypted_password, :password_hash, :pw_hash)
25
+ first_column_to_exist(
26
+ nil,
27
+ :crypted_password,
28
+ :encrypted_password,
29
+ :password_hash,
30
+ :pw_hash
31
+ )
26
32
  )
27
33
  end
28
34
  alias_method :crypted_password_field=, :crypted_password_field
@@ -91,6 +97,8 @@ module Authlogic
91
97
  #
92
98
  # * <tt>Default:</tt> true
93
99
  # * <tt>Accepts:</tt> Boolean
100
+ #
101
+ # @deprecated
94
102
  def validate_password_field(value = nil)
95
103
  rw_config(:validate_password_field, value, true)
96
104
  end
@@ -99,17 +107,28 @@ module Authlogic
99
107
  # A hash of options for the validates_length_of call for the password field.
100
108
  # Allows you to change this however you want.
101
109
  #
102
- # <b>Keep in mind this is ruby. I wanted to keep this as flexible as possible, so
103
- # you can completely replace the hash or merge options into it. Checkout the
104
- # convenience function merge_validates_length_of_password_field_options to merge
105
- # options.</b>
110
+ # **Keep in mind this is ruby. I wanted to keep this as flexible as
111
+ # possible, so you can completely replace the hash or merge options into
112
+ # it. Checkout the convenience function
113
+ # merge_validates_length_of_password_field_options to merge options.**
106
114
  #
107
115
  # * <tt>Default:</tt> {:minimum => 8, :if => :require_password?}
108
116
  # * <tt>Accepts:</tt> Hash of options accepted by validates_length_of
117
+ #
118
+ # @deprecated
109
119
  def validates_length_of_password_field_options(value = nil)
110
- rw_config(:validates_length_of_password_field_options, value, { :minimum => 8, :if => :require_password? })
120
+ deprecate_authlogic_config("validates_length_of_password_field_options") if value
121
+ rw_config(
122
+ :validates_length_of_password_field_options,
123
+ value,
124
+ minimum: 8,
125
+ if: :require_password?
126
+ )
111
127
  end
112
- alias_method :validates_length_of_password_field_options=, :validates_length_of_password_field_options
128
+ alias_method(
129
+ :validates_length_of_password_field_options=,
130
+ :validates_length_of_password_field_options
131
+ )
113
132
 
114
133
  # A convenience function to merge options into the
115
134
  # validates_length_of_login_field_options. So instead of:
@@ -120,29 +139,53 @@ module Authlogic
120
139
  # You can do this:
121
140
  #
122
141
  # merge_validates_length_of_password_field_options :my_option => my_value
142
+ #
143
+ # @deprecated
123
144
  def merge_validates_length_of_password_field_options(options = {})
124
- self.validates_length_of_password_field_options = validates_length_of_password_field_options.merge(options)
145
+ deprecate_authlogic_config(
146
+ "merge_validates_length_of_password_field_options"
147
+ )
148
+ self.validates_length_of_password_field_options =
149
+ validates_length_of_password_field_options.merge(options)
125
150
  end
126
151
 
127
- # A hash of options for the validates_confirmation_of call for the password field.
128
- # Allows you to change this however you want.
152
+ # A hash of options for the validates_confirmation_of call for the
153
+ # password field. Allows you to change this however you want.
129
154
  #
130
- # <b>Keep in mind this is ruby. I wanted to keep this as flexible as possible, so
131
- # you can completely replace the hash or merge options into it. Checkout the
132
- # convenience function merge_validates_length_of_password_field_options to merge
133
- # options.</b>
155
+ # **Keep in mind this is ruby. I wanted to keep this as flexible as
156
+ # possible, so you can completely replace the hash or merge options into
157
+ # it. Checkout the convenience function
158
+ # merge_validates_length_of_password_field_options to merge options.**
134
159
  #
135
160
  # * <tt>Default:</tt> {:if => :require_password?}
136
161
  # * <tt>Accepts:</tt> Hash of options accepted by validates_confirmation_of
162
+ #
163
+ # @deprecated
137
164
  def validates_confirmation_of_password_field_options(value = nil)
138
- rw_config(:validates_confirmation_of_password_field_options, value, { :if => :require_password? })
165
+ if value
166
+ deprecate_authlogic_config(
167
+ "validates_confirmation_of_password_field_options"
168
+ )
169
+ end
170
+ rw_config(
171
+ :validates_confirmation_of_password_field_options,
172
+ value,
173
+ if: :require_password?
174
+ )
139
175
  end
140
- alias_method :validates_confirmation_of_password_field_options=, :validates_confirmation_of_password_field_options
176
+ alias_method :validates_confirmation_of_password_field_options=,
177
+ :validates_confirmation_of_password_field_options
141
178
 
142
179
  # See merge_validates_length_of_password_field_options. The same thing, except for
143
180
  # validates_confirmation_of_password_field_options
181
+ #
182
+ # @deprecated
144
183
  def merge_validates_confirmation_of_password_field_options(options = {})
145
- self.validates_confirmation_of_password_field_options = validates_confirmation_of_password_field_options.merge(options)
184
+ deprecate_authlogic_config(
185
+ "merge_validates_confirmation_of_password_field_options"
186
+ )
187
+ self.validates_confirmation_of_password_field_options =
188
+ validates_confirmation_of_password_field_options.merge(options)
146
189
  end
147
190
 
148
191
  # A hash of options for the validates_length_of call for the password_confirmation
@@ -155,7 +198,14 @@ module Authlogic
155
198
  #
156
199
  # * <tt>Default:</tt> validates_length_of_password_field_options
157
200
  # * <tt>Accepts:</tt> Hash of options accepted by validates_length_of
201
+ #
202
+ # @deprecated
158
203
  def validates_length_of_password_confirmation_field_options(value = nil)
204
+ if value
205
+ deprecate_authlogic_config(
206
+ "validates_length_of_password_confirmation_field_options"
207
+ )
208
+ end
159
209
  rw_config(
160
210
  :validates_length_of_password_confirmation_field_options,
161
211
  value,
@@ -169,74 +219,101 @@ module Authlogic
169
219
 
170
220
  # See merge_validates_length_of_password_field_options. The same thing, except for
171
221
  # validates_length_of_password_confirmation_field_options
222
+ #
223
+ # @deprecated
172
224
  def merge_validates_length_of_password_confirmation_field_options(options = {})
225
+ deprecate_authlogic_config(
226
+ "merge_validates_length_of_password_confirmation_field_options"
227
+ )
173
228
  self.validates_length_of_password_confirmation_field_options =
174
229
  validates_length_of_password_confirmation_field_options.merge(options)
175
230
  end
176
231
 
177
- # The class you want to use to encrypt and verify your encrypted passwords. See
178
- # the Authlogic::CryptoProviders module for more info on the available methods and
179
- # how to create your own.
232
+ # The class you want to use to encrypt and verify your encrypted
233
+ # passwords. See the Authlogic::CryptoProviders module for more info on
234
+ # the available methods and how to create your own.
235
+ #
236
+ # The family of adaptive hash functions (BCrypt, SCrypt, PBKDF2) is the
237
+ # best choice for password storage today. We recommend SCrypt. Other
238
+ # one-way functions like SHA512 are inferior, but widely used.
239
+ # Reverisbile functions like AES256 are the worst choice.
240
+ #
241
+ # You can use the `transition_from_crypto_providers` option to gradually
242
+ # transition to a better crypto provider without causing your users any
243
+ # pain.
180
244
  #
181
245
  # * <tt>Default:</tt> CryptoProviders::SCrypt
182
246
  # * <tt>Accepts:</tt> Class
183
247
  def crypto_provider(value = nil)
248
+ CryptoProviders::Guidance.new(value).impart_wisdom
184
249
  rw_config(:crypto_provider, value, CryptoProviders::SCrypt)
185
250
  end
186
251
  alias_method :crypto_provider=, :crypto_provider
187
252
 
188
- # Let's say you originally encrypted your passwords with Sha1. Sha1 is starting to
189
- # join the party with MD5 and you want to switch to something stronger. No
190
- # problem, just specify your new and improved algorithm with the crypt_provider
191
- # option and then let Authlogic know you are transitioning from Sha1 using this
192
- # option. Authlogic will take care of everything, including transitioning your
193
- # users to the new algorithm. The next time a user logs in, they will be granted
194
- # access using the old algorithm and their password will be resaved with the new
195
- # algorithm. All new users will obviously use the new algorithm as well.
253
+ # Let's say you originally encrypted your passwords with Sha1. Sha1 is
254
+ # starting to join the party with MD5 and you want to switch to
255
+ # something stronger. No problem, just specify your new and improved
256
+ # algorithm with the crypt_provider option and then let Authlogic know
257
+ # you are transitioning from Sha1 using this option. Authlogic will take
258
+ # care of everything, including transitioning your users to the new
259
+ # algorithm. The next time a user logs in, they will be granted access
260
+ # using the old algorithm and their password will be resaved with the
261
+ # new algorithm. All new users will obviously use the new algorithm as
262
+ # well.
196
263
  #
197
- # Lastly, if you want to transition again, you can pass an array of crypto
198
- # providers. So you can transition from as many algorithms as you want.
264
+ # Lastly, if you want to transition again, you can pass an array of
265
+ # crypto providers. So you can transition from as many algorithms as you
266
+ # want.
199
267
  #
200
268
  # * <tt>Default:</tt> nil
201
269
  # * <tt>Accepts:</tt> Class or Array
202
270
  def transition_from_crypto_providers(value = nil)
203
- rw_config(:transition_from_crypto_providers, (!value.nil? && [value].flatten.compact) || value, [])
271
+ rw_config(
272
+ :transition_from_crypto_providers,
273
+ (!value.nil? && [value].flatten.compact) || value,
274
+ []
275
+ )
204
276
  end
205
277
  alias_method :transition_from_crypto_providers=, :transition_from_crypto_providers
206
278
  end
207
279
 
208
280
  # Callbacks / hooks to allow other modules to modify the behavior of this module.
209
281
  module Callbacks
210
- METHODS = [
211
- "before_password_set", "after_password_set",
212
- "before_password_verification", "after_password_verification"
213
- ]
282
+ # Does the order of this array matter?
283
+ METHODS = %w[
284
+ before_password_set
285
+ after_password_set
286
+ before_password_verification
287
+ after_password_verification
288
+ ].freeze
214
289
 
215
290
  def self.included(klass)
216
291
  return if klass.crypted_password_field.nil?
217
- klass.define_callbacks *METHODS
292
+ klass.define_callbacks(*METHODS)
218
293
 
219
294
  # If Rails 3, support the new callback syntax
220
- if klass.send(klass.respond_to?(:singleton_class) ? :singleton_class : :metaclass).method_defined?(:set_callback)
295
+ if klass.singleton_class.method_defined?(:set_callback)
221
296
  METHODS.each do |method|
222
- klass.class_eval <<-"end_eval", __FILE__, __LINE__
297
+ klass.class_eval <<-EOS, __FILE__, __LINE__ + 1
223
298
  def self.#{method}(*methods, &block)
224
299
  set_callback :#{method}, *methods, &block
225
300
  end
226
- end_eval
301
+ EOS
227
302
  end
228
303
  end
229
304
  end
230
305
 
231
- private
232
-
233
- METHODS.each do |method|
234
- class_eval <<-"end_eval", __FILE__, __LINE__
235
- def #{method}
236
- run_callbacks(:#{method}) { |result, object| result == false }
237
- end
238
- end_eval
239
- end
306
+ # TODO: Ideally, once this module is included, the included copies of
307
+ # the following methods would be private. This cannot be accomplished
308
+ # by using calling `private` here in the module. Maybe we can set the
309
+ # privacy inside `included`?
310
+ METHODS.each do |method|
311
+ class_eval <<-EOS, __FILE__, __LINE__ + 1
312
+ def #{method}
313
+ run_callbacks(:#{method}) { |result, object| result == false }
314
+ end
315
+ EOS
316
+ end
240
317
  end
241
318
 
242
319
  # The methods related to the password field.
@@ -251,8 +328,14 @@ module Authlogic
251
328
  validates_length_of :password, validates_length_of_password_field_options
252
329
 
253
330
  if require_password_confirmation
254
- validates_confirmation_of :password, validates_confirmation_of_password_field_options
255
- validates_length_of :password_confirmation, validates_length_of_password_confirmation_field_options
331
+ validates_confirmation_of(
332
+ :password,
333
+ validates_confirmation_of_password_field_options
334
+ )
335
+ validates_length_of(
336
+ :password_confirmation,
337
+ validates_length_of_password_confirmation_field_options
338
+ )
256
339
  end
257
340
  end
258
341
 
@@ -260,9 +343,11 @@ module Authlogic
260
343
  end
261
344
  end
262
345
 
346
+ # :nodoc:
263
347
  module InstanceMethods
264
348
  # The password
265
349
  def password
350
+ return nil unless defined?(@password)
266
351
  @password
267
352
  end
268
353
 
@@ -272,40 +357,48 @@ module Authlogic
272
357
  return if ignore_blank_passwords? && pass.blank?
273
358
  before_password_set
274
359
  @password = pass
275
- send("#{password_salt_field}=", Authlogic::Random.friendly_token) if password_salt_field
276
- encryptor_arguments_type = act_like_restful_authentication? ? :restful_authentication : nil
360
+ if password_salt_field
361
+ send("#{password_salt_field}=", Authlogic::Random.friendly_token)
362
+ end
363
+ encryptor_args_type = act_like_restful_authentication? ? :restful_authentication : nil
277
364
  send(
278
365
  "#{crypted_password_field}=",
279
- crypto_provider.encrypt(*encrypt_arguments(@password, false, encryptor_arguments_type))
366
+ crypto_provider.encrypt(
367
+ *encrypt_arguments(@password, false, encryptor_args_type)
368
+ )
280
369
  )
281
370
  @password_changed = true
282
371
  after_password_set
283
372
  end
284
373
 
285
- # Accepts a raw password to determine if it is the correct password or not.
286
- # Notice the second argument. That defaults to the value of
287
- # check_passwords_against_database. See that method for more information, but
288
- # basically it just tells Authlogic to check the password against the value in
289
- # the database or the value in the object.
290
- def valid_password?(attempted_password, check_against_database = check_passwords_against_database?)
291
- crypted =
292
- if check_against_database && send("#{crypted_password_field}_changed?")
293
- send("#{crypted_password_field}_was")
294
- else
295
- send(crypted_password_field)
296
- end
297
-
374
+ # Accepts a raw password to determine if it is the correct password.
375
+ #
376
+ # - attempted_password [String] - password entered by user
377
+ # - check_against_database [boolean] - Should we check the password
378
+ # against the value in the database or the value in the object?
379
+ # Default taken from config option check_passwords_against_database.
380
+ # See config method for more information.
381
+ def valid_password?(
382
+ attempted_password,
383
+ check_against_database = check_passwords_against_database?
384
+ )
385
+ crypted = crypted_password_to_validate_against(check_against_database)
298
386
  return false if attempted_password.blank? || crypted.blank?
299
387
  before_password_verification
300
388
 
301
389
  crypto_providers.each_with_index do |encryptor, index|
302
- if encryptor_matches?(crypted, encryptor, index, attempted_password, check_against_database)
303
- if transition_password?(index, encryptor, crypted, check_against_database)
304
- transition_password(attempted_password)
305
- end
306
- after_password_verification
307
- return true
390
+ next unless encryptor_matches?(
391
+ crypted,
392
+ encryptor,
393
+ index,
394
+ attempted_password,
395
+ check_against_database
396
+ )
397
+ if transition_password?(index, encryptor, check_against_database)
398
+ transition_password(attempted_password)
308
399
  end
400
+ after_password_verification
401
+ return true
309
402
  end
310
403
 
311
404
  false
@@ -322,102 +415,130 @@ module Authlogic
322
415
  # Resets the password to a random friendly token and then saves the record.
323
416
  def reset_password!
324
417
  reset_password
325
- save_without_session_maintenance(:validate => false)
418
+ save_without_session_maintenance(validate: false)
326
419
  end
327
420
  alias_method :randomize_password!, :reset_password!
328
421
 
329
422
  private
330
423
 
331
- def check_passwords_against_database?
332
- self.class.check_passwords_against_database == true
424
+ def crypted_password_to_validate_against(check_against_database)
425
+ if check_against_database && send("#{crypted_password_field}_changed?")
426
+ send("#{crypted_password_field}_was")
427
+ else
428
+ send(crypted_password_field)
333
429
  end
430
+ end
334
431
 
335
- def crypto_providers
336
- [crypto_provider] + transition_from_crypto_providers
337
- end
432
+ def check_passwords_against_database?
433
+ self.class.check_passwords_against_database == true
434
+ end
338
435
 
339
- # Returns an array of arguments to be passed to a crypto provider, either its
340
- # `matches?` or its `encrypt` method.
341
- def encrypt_arguments(raw_password, check_against_database, arguments_type = nil)
342
- salt = nil
343
- if password_salt_field
344
- salt =
345
- if check_against_database && send("#{password_salt_field}_changed?")
346
- send("#{password_salt_field}_was")
347
- else
348
- send(password_salt_field)
349
- end
350
- end
436
+ def crypto_providers
437
+ [crypto_provider] + transition_from_crypto_providers
438
+ end
351
439
 
352
- case arguments_type
353
- when :restful_authentication
354
- [REST_AUTH_SITE_KEY, salt, raw_password, REST_AUTH_SITE_KEY].compact
355
- when nil
356
- [raw_password, salt].compact
357
- else
358
- raise "Invalid encryptor arguments_type: #{arguments_type}"
359
- end
440
+ # Returns an array of arguments to be passed to a crypto provider, either its
441
+ # `matches?` or its `encrypt` method.
442
+ def encrypt_arguments(raw_password, check_against_database, arguments_type = nil)
443
+ salt = nil
444
+ if password_salt_field
445
+ salt =
446
+ if check_against_database && send("#{password_salt_field}_changed?")
447
+ send("#{password_salt_field}_was")
448
+ else
449
+ send(password_salt_field)
450
+ end
360
451
  end
361
452
 
362
- # Given `encryptor`, does `attempted_password` match the `crypted` password?
363
- def encryptor_matches?(crypted, encryptor, index, attempted_password, check_against_database)
364
- # The arguments_type for the transitioning from restful_authentication
365
- acting_restful = act_like_restful_authentication? && index == 0
366
- transitioning = transition_from_restful_authentication? &&
367
- index > 0 &&
368
- encryptor == Authlogic::CryptoProviders::Sha1
369
- restful = acting_restful || transitioning
370
- arguments_type = restful ? :restful_authentication : nil
371
- encryptor_args = encrypt_arguments(attempted_password, check_against_database, arguments_type)
372
- encryptor.matches?(crypted, *encryptor_args)
453
+ case arguments_type
454
+ when :restful_authentication
455
+ [REST_AUTH_SITE_KEY, salt, raw_password, REST_AUTH_SITE_KEY].compact
456
+ when nil
457
+ [raw_password, salt].compact
458
+ else
459
+ raise "Invalid encryptor arguments_type: #{arguments_type}"
373
460
  end
461
+ end
374
462
 
375
- # Determines if we need to transition the password.
376
- # If the index > 0 then we are using an "transition from" crypto provider.
377
- # If the encryptor has a cost and the cost it outdated.
378
- # If we aren't using database values
379
- # If we are using database values, only if the password hasn't changed so we don't overwrite any changes
380
- def transition_password?(index, encryptor, crypted, check_against_database)
381
- (index > 0 || (encryptor.respond_to?(:cost_matches?) && !encryptor.cost_matches?(send(crypted_password_field)))) &&
382
- (!check_against_database || !send("#{crypted_password_field}_changed?"))
383
- end
463
+ # Given `encryptor`, does `attempted_password` match the `crypted` password?
464
+ def encryptor_matches?(
465
+ crypted,
466
+ encryptor,
467
+ index,
468
+ attempted_password,
469
+ check_against_database
470
+ )
471
+ # The arguments_type for the transitioning from restful_authentication
472
+ acting_restful = act_like_restful_authentication? && index.zero?
473
+ transitioning = transition_from_restful_authentication? &&
474
+ index > 0 &&
475
+ encryptor == Authlogic::CryptoProviders::Sha1
476
+ restful = acting_restful || transitioning
477
+ arguments_type = restful ? :restful_authentication : nil
478
+ encryptor_args = encrypt_arguments(
479
+ attempted_password,
480
+ check_against_database,
481
+ arguments_type
482
+ )
483
+ encryptor.matches?(crypted, *encryptor_args)
484
+ end
384
485
 
385
- def transition_password(attempted_password)
386
- self.password = attempted_password
387
- save(:validate => false)
388
- end
486
+ # Determines if we need to transition the password.
487
+ #
488
+ # - If the index > 0 then we are using an "transition from" crypto
489
+ # provider.
490
+ # - If the encryptor has a cost and the cost it outdated.
491
+ # - If we aren't using database values
492
+ # - If we are using database values, only if the password hasn't
493
+ # changed so we don't overwrite any changes
494
+ def transition_password?(index, encryptor, check_against_database)
495
+ (
496
+ index > 0 ||
497
+ (encryptor.respond_to?(:cost_matches?) &&
498
+ !encryptor.cost_matches?(send(crypted_password_field)))
499
+ ) &&
500
+ (
501
+ !check_against_database ||
502
+ !send("#{crypted_password_field}_changed?")
503
+ )
504
+ end
389
505
 
390
- def require_password?
391
- new_record? || password_changed? || send(crypted_password_field).blank?
392
- end
506
+ def transition_password(attempted_password)
507
+ self.password = attempted_password
508
+ save(validate: false)
509
+ end
393
510
 
394
- def ignore_blank_passwords?
395
- self.class.ignore_blank_passwords == true
396
- end
511
+ def require_password?
512
+ new_record? || password_changed? || send(crypted_password_field).blank?
513
+ end
397
514
 
398
- def password_changed?
399
- @password_changed == true
400
- end
515
+ def ignore_blank_passwords?
516
+ self.class.ignore_blank_passwords == true
517
+ end
401
518
 
402
- def reset_password_changed
403
- @password_changed = nil
404
- end
519
+ def password_changed?
520
+ defined?(@password_changed) && @password_changed == true
521
+ end
405
522
 
406
- def crypted_password_field
407
- self.class.crypted_password_field
408
- end
523
+ def reset_password_changed
524
+ @password_changed = nil
525
+ end
409
526
 
410
- def password_salt_field
411
- self.class.password_salt_field
412
- end
527
+ def crypted_password_field
528
+ self.class.crypted_password_field
529
+ end
413
530
 
414
- def crypto_provider
415
- self.class.crypto_provider
416
- end
531
+ def password_salt_field
532
+ self.class.password_salt_field
533
+ end
417
534
 
418
- def transition_from_crypto_providers
419
- self.class.transition_from_crypto_providers
420
- end
535
+ def crypto_provider
536
+ self.class.crypto_provider
537
+ end
538
+
539
+ def transition_from_crypto_providers
540
+ self.class.transition_from_crypto_providers
541
+ end
421
542
  end
422
543
  end
423
544
  end