authlogic 3.8.0 → 4.5.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 (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
@@ -6,7 +6,7 @@ module Authlogic
6
6
  klass.class_eval do
7
7
  extend Config
8
8
  include InstanceMethods
9
- validate :validate_by_password, :if => :authenticating_with_password?
9
+ validate :validate_by_password, if: :authenticating_with_password?
10
10
 
11
11
  class << self
12
12
  attr_accessor :configured_password_methods
@@ -119,7 +119,7 @@ module Authlogic
119
119
  # should be an instance method. It should also be prepared to accept a
120
120
  # raw password and a crytped password.
121
121
  #
122
- # * <tt>Default:</tt> "valid_password?"
122
+ # * <tt>Default:</tt> "valid_password?" defined in acts_as_authentic/password.rb
123
123
  # * <tt>Accepts:</tt> Symbol or String
124
124
  def verify_password_method(value = nil)
125
125
  rw_config(:verify_password_method, value, "valid_password?")
@@ -127,45 +127,14 @@ module Authlogic
127
127
  alias_method :verify_password_method=, :verify_password_method
128
128
  end
129
129
 
130
- # Password-related instance methods
130
+ # Password related instance methods
131
131
  module InstanceMethods
132
- E_AC_PARAMETERS = <<-STR.strip_heredoc.freeze
133
- You have passed an ActionController::Parameters to Authlogic 3. That's
134
- OK for now, but in Authlogic 4, it will raise an error. Please
135
- replace:
136
-
137
- UserSession.new(user_session_params)
138
- UserSession.create(user_session_params)
139
-
140
- with
141
-
142
- UserSession.new(user_session_params.to_h)
143
- UserSession.create(user_session_params.to_h)
144
-
145
- And don't forget to `permit`!
146
-
147
- During the transition of rails to Strong Parameters, it has been
148
- common for Authlogic users to forget to `permit` their params. They
149
- would pass their params into Authlogic, we'd call `to_h`, and they'd
150
- be surprised when authentication failed.
151
-
152
- In 2018, people are still making this mistake. We'd like to help them
153
- and make authlogic a little simpler at the same time, so in Authlogic
154
- 3.7.0, we deprecated the use of ActionController::Parameters.
155
-
156
- We discussed this issue thoroughly between late 2016 and early
157
- 2018. Notable discussions include:
158
-
159
- - https://github.com/binarylogic/authlogic/issues/512
160
- - https://github.com/binarylogic/authlogic/pull/558
161
- - https://github.com/binarylogic/authlogic/pull/577
162
- STR
163
-
164
132
  def initialize(*args)
165
- if !self.class.configured_password_methods
133
+ unless self.class.configured_password_methods
166
134
  configure_password_methods
167
135
  self.class.configured_password_methods = true
168
136
  end
137
+ instance_variable_set("@#{password_field}", nil)
169
138
  super
170
139
  end
171
140
 
@@ -184,14 +153,23 @@ module Authlogic
184
153
 
185
154
  # Accepts the login_field / password_field credentials combination in
186
155
  # hash form.
156
+ #
157
+ # You must pass an actual Hash, `ActionController::Parameters` is
158
+ # specifically not allowed.
159
+ #
160
+ # See `Authlogic::Session::Foundation#credentials=` for an overview of
161
+ # all method signatures.
187
162
  def credentials=(value)
188
163
  super
189
- values = parse_param_val(value) # add strong parameters check
190
-
164
+ values = Array.wrap(value)
191
165
  if values.first.is_a?(Hash)
192
- values.first.with_indifferent_access.slice(login_field, password_field).each do |field, value|
193
- next if value.blank?
194
- send("#{field}=", value)
166
+ sliced = values
167
+ .first
168
+ .with_indifferent_access
169
+ .slice(login_field, password_field)
170
+ sliced.each do |field, val|
171
+ next if val.blank?
172
+ send("#{field}=", val)
195
173
  end
196
174
  end
197
175
  end
@@ -202,106 +180,138 @@ module Authlogic
202
180
 
203
181
  private
204
182
 
205
- def configure_password_methods
206
- if login_field
207
- self.class.send(:attr_writer, login_field) if !respond_to?("#{login_field}=")
208
- self.class.send(:attr_reader, login_field) if !respond_to?(login_field)
209
- end
210
-
211
- if password_field
212
- self.class.send(:attr_writer, password_field) if !respond_to?("#{password_field}=")
213
- self.class.send(:define_method, password_field) {} if !respond_to?(password_field)
214
-
215
- # The password should not be accessible publicly. This way forms
216
- # using form_for don't fill the password with the attempted
217
- # password. To prevent this we just create this method that is
218
- # private.
219
- self.class.class_eval <<-"end_eval", __FILE__, __LINE__
220
- private
221
- def protected_#{password_field}
222
- @#{password_field}
223
- end
224
- end_eval
225
- end
183
+ def add_invalid_password_error
184
+ if generalize_credentials_error_messages?
185
+ add_general_credentials_error
186
+ else
187
+ errors.add(
188
+ password_field,
189
+ I18n.t("error_messages.password_invalid", default: "is not valid")
190
+ )
226
191
  end
192
+ end
227
193
 
228
- def authenticating_with_password?
229
- login_field && (!send(login_field).nil? || !send("protected_#{password_field}").nil?)
194
+ def add_login_not_found_error
195
+ if generalize_credentials_error_messages?
196
+ add_general_credentials_error
197
+ else
198
+ errors.add(
199
+ login_field,
200
+ I18n.t("error_messages.login_not_found", default: "is not valid")
201
+ )
230
202
  end
203
+ end
231
204
 
232
- def validate_by_password
233
- self.invalid_password = false
205
+ def authenticating_with_password?
206
+ login_field && (!send(login_field).nil? || !send("protected_#{password_field}").nil?)
207
+ end
234
208
 
235
- # check for blank fields
236
- if send(login_field).blank?
237
- errors.add(login_field, I18n.t('error_messages.login_blank', :default => "cannot be blank"))
238
- end
239
- if send("protected_#{password_field}").blank?
240
- errors.add(password_field, I18n.t('error_messages.password_blank', :default => "cannot be blank"))
241
- end
242
- return if errors.count > 0
209
+ def configure_password_methods
210
+ define_login_field_methods
211
+ define_password_field_methods
212
+ end
243
213
 
244
- self.attempted_record = search_for_record(find_by_login_method, send(login_field))
245
- if attempted_record.blank?
246
- generalize_credentials_error_messages? ?
247
- add_general_credentials_error :
248
- errors.add(login_field, I18n.t('error_messages.login_not_found', :default => "is not valid"))
249
- return
250
- end
214
+ def define_login_field_methods
215
+ return unless login_field
216
+ self.class.send(:attr_writer, login_field) unless respond_to?("#{login_field}=")
217
+ self.class.send(:attr_reader, login_field) unless respond_to?(login_field)
218
+ end
251
219
 
252
- # check for invalid password
253
- if !attempted_record.send(verify_password_method, send("protected_#{password_field}"))
254
- self.invalid_password = true
255
- generalize_credentials_error_messages? ?
256
- add_general_credentials_error :
257
- errors.add(password_field, I18n.t('error_messages.password_invalid', :default => "is not valid"))
258
- return
259
- end
260
- end
220
+ def define_password_field_methods
221
+ return unless password_field
222
+ self.class.send(:attr_writer, password_field) unless respond_to?("#{password_field}=")
223
+ self.class.send(:define_method, password_field) {} unless respond_to?(password_field)
224
+
225
+ # The password should not be accessible publicly. This way forms
226
+ # using form_for don't fill the password with the attempted
227
+ # password. To prevent this we just create this method that is
228
+ # private.
229
+ self.class.class_eval(
230
+ <<-EOS, __FILE__, __LINE__ + 1
231
+ private
232
+ def protected_#{password_field}
233
+ @#{password_field}
234
+ end
235
+ EOS
236
+ )
237
+ end
261
238
 
262
- attr_accessor :invalid_password
239
+ # In keeping with the metaphor of ActiveRecord, verification of the
240
+ # password is referred to as a "validation".
241
+ def validate_by_password
242
+ self.invalid_password = false
243
+ validate_by_password__blank_fields
244
+ return if errors.count > 0
245
+ self.attempted_record = search_for_record(find_by_login_method, send(login_field))
246
+ if attempted_record.blank?
247
+ add_login_not_found_error
248
+ return
249
+ end
250
+ validate_by_password__invalid_password
251
+ end
263
252
 
264
- def find_by_login_method
265
- self.class.find_by_login_method
253
+ def validate_by_password__blank_fields
254
+ if send(login_field).blank?
255
+ errors.add(
256
+ login_field,
257
+ I18n.t("error_messages.login_blank", default: "cannot be blank")
258
+ )
259
+ end
260
+ if send("protected_#{password_field}").blank?
261
+ errors.add(
262
+ password_field,
263
+ I18n.t("error_messages.password_blank", default: "cannot be blank")
264
+ )
266
265
  end
266
+ end
267
267
 
268
- def login_field
269
- self.class.login_field
268
+ # Verify the password, usually using `valid_password?` in
269
+ # `acts_as_authentic/password.rb`. If it cannot be verified, we
270
+ # refer to it as "invalid".
271
+ def validate_by_password__invalid_password
272
+ unless attempted_record.send(
273
+ verify_password_method,
274
+ send("protected_#{password_field}")
275
+ )
276
+ self.invalid_password = true
277
+ add_invalid_password_error
270
278
  end
279
+ end
280
+
281
+ attr_accessor :invalid_password
282
+
283
+ def find_by_login_method
284
+ self.class.find_by_login_method
285
+ end
286
+
287
+ def login_field
288
+ self.class.login_field
289
+ end
271
290
 
272
- def add_general_credentials_error
273
- error_message =
291
+ def add_general_credentials_error
292
+ error_message =
274
293
  if self.class.generalize_credentials_error_messages.is_a? String
275
294
  self.class.generalize_credentials_error_messages
276
295
  else
277
296
  "#{login_field.to_s.humanize}/Password combination is not valid"
278
297
  end
279
- errors.add(:base, I18n.t('error_messages.general_credentials_error', :default => error_message))
280
- end
281
-
282
- def generalize_credentials_error_messages?
283
- self.class.generalize_credentials_error_messages
284
- end
298
+ errors.add(
299
+ :base,
300
+ I18n.t("error_messages.general_credentials_error", default: error_message)
301
+ )
302
+ end
285
303
 
286
- def password_field
287
- self.class.password_field
288
- end
304
+ def generalize_credentials_error_messages?
305
+ self.class.generalize_credentials_error_messages
306
+ end
289
307
 
290
- def verify_password_method
291
- self.class.verify_password_method
292
- end
308
+ def password_field
309
+ self.class.password_field
310
+ end
293
311
 
294
- # In Rails 5 the ActionController::Parameters no longer inherits from HashWithIndifferentAccess.
295
- # See: http://guides.rubyonrails.org/upgrading_ruby_on_rails.html#actioncontroller-parameters-no-longer-inherits-from-hashwithindifferentaccess
296
- # This method converts the ActionController::Parameters to a Hash
297
- def parse_param_val(value)
298
- if value.first.class.name == "ActionController::Parameters"
299
- ActiveSupport::Deprecation.warn(E_AC_PARAMETERS)
300
- [value.first.to_h]
301
- else
302
- value.is_a?(Array) ? value : [value]
303
- end
304
- end
312
+ def verify_password_method
313
+ self.class.verify_password_method
314
+ end
305
315
  end
306
316
  end
307
317
  end
@@ -13,11 +13,12 @@ module Authlogic
13
13
 
14
14
  private
15
15
 
16
- def reset_perishable_token!
17
- if record.respond_to?(:reset_perishable_token) && !record.disable_perishable_token_maintenance?
18
- record.reset_perishable_token
19
- end
16
+ def reset_perishable_token!
17
+ if record.respond_to?(:reset_perishable_token) &&
18
+ !record.disable_perishable_token_maintenance?
19
+ record.reset_perishable_token
20
20
  end
21
+ end
21
22
  end
22
23
  end
23
24
  end
@@ -10,9 +10,10 @@ module Authlogic
10
10
  end
11
11
 
12
12
  module ClassMethods
13
- # This is how you persist a session. This finds the record for the current session using
14
- # a variety of methods. It basically tries to "log in" the user without the user having
15
- # to explicitly log in. Check out the other Authlogic::Session modules for more information.
13
+ # This is how you persist a session. This finds the record for the
14
+ # current session using a variety of methods. It basically tries to "log
15
+ # in" the user without the user having to explicitly log in. Check out
16
+ # the other Authlogic::Session modules for more information.
16
17
  #
17
18
  # The best way to use this method is something like:
18
19
  #
@@ -28,30 +29,35 @@ module Authlogic
28
29
  # @current_user = current_user_session && current_user_session.user
29
30
  # end
30
31
  #
31
- # Also, this method accepts a single parameter as the id, to find session that you marked with an id:
32
+ # Also, this method accepts a single parameter as the id, to find
33
+ # session that you marked with an id:
32
34
  #
33
35
  # UserSession.find(:secure)
34
36
  #
35
37
  # See the id method for more information on ids.
36
38
  def find(id = nil, priority_record = nil)
37
- session = new({ :priority_record => priority_record }, id)
39
+ session = new({ priority_record: priority_record }, id)
38
40
  session.priority_record = priority_record
39
41
  if session.persisting?
40
42
  session
41
- else
42
- nil
43
43
  end
44
44
  end
45
45
  end
46
46
 
47
47
  module InstanceMethods
48
- # Let's you know if the session is being persisted or not, meaning the user does not have to explicitly log in
49
- # in order to be logged in. If the session has no associated record, it will try to find a record and persist
50
- # the session. This is the method that the class level method find uses to ultimately persist the session.
48
+ # Returns boolean indicating if the session is being persisted or not,
49
+ # meaning the user does not have to explicitly log in in order to be
50
+ # logged in.
51
+ #
52
+ # If the session has no associated record, it will try to find a record
53
+ # and persist the session.
54
+ #
55
+ # This is the method that the class level method find uses to ultimately
56
+ # persist the session.
51
57
  def persisting?
52
- return true if !record.nil?
58
+ return true unless record.nil?
53
59
  self.attempted_record = nil
54
- self.remember_me = !cookie_credentials.nil? && !cookie_credentials[2].nil?
60
+ self.remember_me = cookie_credentials_remember_me?
55
61
  before_persisting
56
62
  persist
57
63
  ensure_authentication_attempted
@@ -1,8 +1,10 @@
1
1
  module Authlogic
2
2
  module Session
3
- # The point of this module is to avoid the StaleObjectError raised when lock_version is implemented in ActiveRecord.
4
- # We accomplish this by using a "priority record". Meaning this record is used if possible, it gets priority.
5
- # This way we don't save a record behind the scenes thus making an object being used stale.
3
+ # The point of this module is to avoid the StaleObjectError raised when
4
+ # lock_version is implemented in ActiveRecord. We accomplish this by using a
5
+ # "priority record". Meaning this record is used if possible, it gets
6
+ # priority. This way we don't save a record behind the scenes thus making an
7
+ # object being used stale.
6
8
  module PriorityRecord
7
9
  def self.included(klass)
8
10
  klass.class_eval do
@@ -10,7 +12,8 @@ module Authlogic
10
12
  end
11
13
  end
12
14
 
13
- # Setting priority record if it is passed. The only way it can be passed is through an array:
15
+ # Setting priority record if it is passed. The only way it can be passed
16
+ # is through an array:
14
17
  #
15
18
  # session.credentials = [real_user_object, priority_user_object]
16
19
  def credentials=(value)
@@ -21,15 +24,15 @@ module Authlogic
21
24
 
22
25
  private
23
26
 
24
- def attempted_record=(value)
25
- value = priority_record if value == priority_record
26
- super
27
- end
27
+ def attempted_record=(value)
28
+ value = priority_record if value == priority_record
29
+ super
30
+ end
28
31
 
29
- def save_record(alternate_record = nil)
30
- r = alternate_record || record
31
- super if r != priority_record
32
- end
32
+ def save_record(alternate_record = nil)
33
+ r = alternate_record || record
34
+ super if r != priority_record
35
+ end
33
36
  end
34
37
  end
35
38
  end
@@ -1,4 +1,4 @@
1
- require 'request_store'
1
+ require "request_store"
2
2
 
3
3
  module Authlogic
4
4
  module Session
@@ -25,10 +25,10 @@ module Authlogic
25
25
  RequestStore.store[:authlogic_scope]
26
26
  end
27
27
 
28
- # What with_scopes focuses on is scoping the query when finding the object and the
29
- # name of the cookie / session. It works very similar to
30
- # ActiveRecord::Base#with_scopes. It accepts a hash with any of the following
31
- # options:
28
+ # What with_scopes focuses on is scoping the query when finding the
29
+ # object and the name of the cookie / session. It works very similar to
30
+ # ActiveRecord::Base#with_scopes. It accepts a hash with any of the
31
+ # following options:
32
32
  #
33
33
  # * <tt>find_options:</tt> any options you can pass into ActiveRecord::Base.find.
34
34
  # This is used when trying to find the record.
@@ -37,21 +37,27 @@ module Authlogic
37
37
  #
38
38
  # Here is how you use it:
39
39
  #
40
- # UserSession.with_scope(:find_options => {:conditions => "account_id = 2"}, :id => "account_2") do
41
- # UserSession.find
42
- # end
40
+ # ```
41
+ # UserSession.with_scope(find_options: {conditions: "account_id = 2"}, id: "account_2") do
42
+ # UserSession.find
43
+ # end
44
+ # ```
43
45
  #
44
- # Essentially what the above does is scope the searching of the object with the
45
- # sql you provided. So instead of:
46
+ # Essentially what the above does is scope the searching of the object
47
+ # with the sql you provided. So instead of:
46
48
  #
47
- # User.where("login = 'ben'").first
49
+ # ```
50
+ # User.where("login = 'ben'").first
51
+ # ```
48
52
  #
49
53
  # it would be:
50
54
  #
51
- # User.where("login = 'ben' and account_id = 2").first
55
+ # ```
56
+ # User.where("login = 'ben' and account_id = 2").first
57
+ # ```
52
58
  #
53
- # You will also notice the :id option. This works just like the id method. It
54
- # scopes your cookies. So the name of your cookie will be:
59
+ # You will also notice the :id option. This works just like the id
60
+ # method. It scopes your cookies. So the name of your cookie will be:
55
61
  #
56
62
  # account_2_user_credentials
57
63
  #
@@ -59,9 +65,13 @@ module Authlogic
59
65
  #
60
66
  # user_credentials
61
67
  #
62
- # What is also nifty about scoping with an :id is that it merges your id's. So if you do:
68
+ # What is also nifty about scoping with an :id is that it merges your
69
+ # id's. So if you do:
63
70
  #
64
- # UserSession.with_scope(:find_options => {:conditions => "account_id = 2"}, :id => "account_2") do
71
+ # UserSession.with_scope(
72
+ # find_options: { conditions: "account_id = 2"},
73
+ # id: "account_2"
74
+ # ) do
65
75
  # session = UserSession.new
66
76
  # session.id = :secure
67
77
  # end
@@ -69,7 +79,7 @@ module Authlogic
69
79
  # The name of your cookies will be:
70
80
  #
71
81
  # secure_account_2_user_credentials
72
- def with_scope(options = {}, &block)
82
+ def with_scope(options = {})
73
83
  raise ArgumentError.new("You must provide a block") unless block_given?
74
84
  self.scope = options
75
85
  result = yield
@@ -79,9 +89,9 @@ module Authlogic
79
89
 
80
90
  private
81
91
 
82
- def scope=(value)
83
- RequestStore.store[:authlogic_scope] = value
84
- end
92
+ def scope=(value)
93
+ RequestStore.store[:authlogic_scope] = value
94
+ end
85
95
  end
86
96
 
87
97
  module InstanceMethods
@@ -98,21 +108,30 @@ module Authlogic
98
108
 
99
109
  private
100
110
 
101
- # Used for things like cookie_key, session_key, etc.
102
- def build_key(last_part)
103
- [scope[:id], super].compact.join("_")
111
+ # Used for things like cookie_key, session_key, etc.
112
+ def build_key(last_part)
113
+ [scope[:id], super].compact.join("_")
114
+ end
115
+
116
+ # `args[0]` is the name of an AR method, like
117
+ # `find_by_single_access_token`.
118
+ def search_for_record(*args)
119
+ search_scope.scoping do
120
+ klass.send(*args)
104
121
  end
122
+ end
105
123
 
106
- def search_for_record(*args)
107
- session_scope = if scope[:find_options].is_a?(ActiveRecord::Relation)
108
- scope[:find_options]
109
- else
110
- klass.send(:where, scope[:find_options] && scope[:find_options][:conditions] || {})
111
- end
112
- session_scope.scoping do
113
- klass.send(*args)
114
- end
124
+ # Returns an AR relation representing the scope of the search. The
125
+ # relation is either provided directly by, or defined by
126
+ # `find_options`.
127
+ def search_scope
128
+ if scope[:find_options].is_a?(ActiveRecord::Relation)
129
+ scope[:find_options]
130
+ else
131
+ conditions = scope[:find_options] && scope[:find_options][:conditions] || {}
132
+ klass.send(:where, conditions)
115
133
  end
134
+ end
116
135
  end
117
136
  end
118
137
  end
@@ -1,6 +1,7 @@
1
1
  module Authlogic
2
2
  module Session
3
- # Handles all parts of authentication that deal with sessions. Such as persisting a session and saving / destroy a session.
3
+ # Handles all parts of authentication that deal with sessions. Such as persisting a
4
+ # session and saving / destroy a session.
4
5
  module Session
5
6
  def self.included(klass)
6
7
  klass.class_eval do
@@ -9,7 +10,7 @@ module Authlogic
9
10
  persist :persist_by_session
10
11
  after_save :update_session
11
12
  after_destroy :update_session
12
- after_persisting :update_session, :unless => :single_access?
13
+ after_persisting :update_session, unless: :single_access?
13
14
  end
14
15
  end
15
16
 
@@ -29,38 +30,47 @@ module Authlogic
29
30
  module InstanceMethods
30
31
  private
31
32
 
32
- # Tries to validate the session from information in the session
33
- def persist_by_session
34
- persistence_token, record_id = session_credentials
35
- if !persistence_token.nil?
36
- # Allow finding by persistence token, because when records are created the
37
- # session is maintained in a before_save, when there is no id. This is done
38
- # for performance reasons and to save on queries.
39
- record = record_id.nil? ?
40
- search_for_record("find_by_persistence_token", persistence_token.to_s) :
41
- search_for_record("find_by_#{klass.primary_key}", record_id.to_s)
42
- self.unauthorized_record = record if record && record.persistence_token == persistence_token
43
- valid?
44
- else
45
- false
33
+ # Tries to validate the session from information in the session
34
+ def persist_by_session
35
+ persistence_token, record_id = session_credentials
36
+ if !persistence_token.nil?
37
+ record = persist_by_session_search(persistence_token, record_id)
38
+ if record && record.persistence_token == persistence_token
39
+ self.unauthorized_record = record
46
40
  end
41
+ valid?
42
+ else
43
+ false
47
44
  end
45
+ end
48
46
 
49
- def session_credentials
50
- [
51
- controller.session[session_key],
52
- controller.session["#{session_key}_#{klass.primary_key}"]
53
- ].collect { |i| i.nil? ? i : i.to_s }.compact
47
+ # Allow finding by persistence token, because when records are created
48
+ # the session is maintained in a before_save, when there is no id.
49
+ # This is done for performance reasons and to save on queries.
50
+ def persist_by_session_search(persistence_token, record_id)
51
+ if record_id.nil?
52
+ search_for_record("find_by_persistence_token", persistence_token.to_s)
53
+ else
54
+ search_for_record("find_by_#{klass.primary_key}", record_id.to_s)
54
55
  end
56
+ end
55
57
 
56
- def session_key
57
- build_key(self.class.session_key)
58
- end
58
+ def session_credentials
59
+ [
60
+ controller.session[session_key],
61
+ controller.session["#{session_key}_#{klass.primary_key}"]
62
+ ].collect { |i| i.nil? ? i : i.to_s }.compact
63
+ end
59
64
 
60
- def update_session
61
- controller.session[session_key] = record && record.persistence_token
62
- controller.session["#{session_key}_#{klass.primary_key}"] = record && record.send(record.class.primary_key)
63
- end
65
+ def session_key
66
+ build_key(self.class.session_key)
67
+ end
68
+
69
+ def update_session
70
+ controller.session[session_key] = record && record.persistence_token
71
+ compound_key = "#{session_key}_#{klass.primary_key}"
72
+ controller.session[compound_key] = record && record.send(record.class.primary_key)
73
+ end
64
74
  end
65
75
  end
66
76
  end