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
@@ -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