authlogic 4.1.0 → 4.1.1
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +0 -4
- data/.rubocop_todo.yml +32 -33
- data/CHANGELOG.md +15 -0
- data/Rakefile +2 -4
- data/authlogic.gemspec +2 -1
- data/lib/authlogic/acts_as_authentic/base.rb +13 -13
- data/lib/authlogic/acts_as_authentic/logged_in_status.rb +3 -3
- data/lib/authlogic/acts_as_authentic/login.rb +4 -4
- data/lib/authlogic/acts_as_authentic/password.rb +99 -98
- data/lib/authlogic/acts_as_authentic/persistence_token.rb +3 -3
- data/lib/authlogic/acts_as_authentic/queries/find_with_case.rb +32 -32
- data/lib/authlogic/acts_as_authentic/restful_authentication.rb +14 -14
- data/lib/authlogic/acts_as_authentic/session_maintenance.rb +60 -60
- data/lib/authlogic/acts_as_authentic/single_access_token.rb +6 -6
- data/lib/authlogic/authenticates_many/association.rb +3 -3
- data/lib/authlogic/config.rb +9 -9
- data/lib/authlogic/controller_adapters/abstract_adapter.rb +28 -8
- data/lib/authlogic/controller_adapters/rails_adapter.rb +3 -3
- data/lib/authlogic/crypto_providers/aes256.rb +20 -20
- data/lib/authlogic/crypto_providers/bcrypt.rb +8 -8
- data/lib/authlogic/crypto_providers/scrypt.rb +8 -8
- data/lib/authlogic/session/activation.rb +3 -3
- data/lib/authlogic/session/brute_force_protection.rb +32 -32
- data/lib/authlogic/session/callbacks.rb +49 -35
- data/lib/authlogic/session/cookies.rb +58 -49
- data/lib/authlogic/session/foundation.rb +3 -3
- data/lib/authlogic/session/id.rb +9 -4
- data/lib/authlogic/session/klass.rb +6 -6
- data/lib/authlogic/session/magic_columns.rb +5 -17
- data/lib/authlogic/session/params.rb +3 -0
- data/lib/authlogic/session/password.rb +105 -104
- data/lib/authlogic/session/perishable_token.rb +5 -5
- data/lib/authlogic/session/persistence.rb +5 -4
- data/lib/authlogic/session/priority_record.rb +8 -8
- data/lib/authlogic/session/scopes.rb +23 -23
- data/lib/authlogic/session/timeout.rb +11 -11
- data/lib/authlogic/session/unauthorized_record.rb +6 -6
- data/lib/authlogic/session/validation.rb +9 -9
- data/lib/authlogic/test_case.rb +5 -0
- data/lib/authlogic/test_case/mock_request.rb +2 -2
- data/lib/authlogic/version.rb +4 -3
- data/test/acts_as_authentic_test/password_test.rb +23 -23
- data/test/test_helper.rb +96 -93
- metadata +18 -4
@@ -134,6 +134,7 @@ module Authlogic
|
|
134
134
|
configure_password_methods
|
135
135
|
self.class.configured_password_methods = true
|
136
136
|
end
|
137
|
+
instance_variable_set("@#{password_field}", nil)
|
137
138
|
super
|
138
139
|
end
|
139
140
|
|
@@ -179,136 +180,136 @@ module Authlogic
|
|
179
180
|
|
180
181
|
private
|
181
182
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
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
|
+
)
|
191
191
|
end
|
192
|
+
end
|
192
193
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
end
|
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
|
+
)
|
202
202
|
end
|
203
|
+
end
|
203
204
|
|
204
|
-
|
205
|
-
|
206
|
-
|
205
|
+
def authenticating_with_password?
|
206
|
+
login_field && (!send(login_field).nil? || !send("protected_#{password_field}").nil?)
|
207
|
+
end
|
207
208
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
209
|
+
def configure_password_methods
|
210
|
+
define_login_field_methods
|
211
|
+
define_password_field_methods
|
212
|
+
end
|
212
213
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
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
|
218
219
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
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)
|
223
224
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
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 <<-EOS, __FILE__, __LINE__ + 1
|
229
230
|
private
|
230
231
|
def protected_#{password_field}
|
231
232
|
@#{password_field}
|
232
233
|
end
|
233
234
|
EOS
|
234
|
-
|
235
|
+
end
|
235
236
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
end
|
247
|
-
validate_by_password__invalid_password
|
237
|
+
# In keeping with the metaphor of ActiveRecord, verification of the
|
238
|
+
# password is referred to as a "validation".
|
239
|
+
def validate_by_password
|
240
|
+
self.invalid_password = false
|
241
|
+
validate_by_password__blank_fields
|
242
|
+
return if errors.count > 0
|
243
|
+
self.attempted_record = search_for_record(find_by_login_method, send(login_field))
|
244
|
+
if attempted_record.blank?
|
245
|
+
add_login_not_found_error
|
246
|
+
return
|
248
247
|
end
|
248
|
+
validate_by_password__invalid_password
|
249
|
+
end
|
249
250
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
end
|
257
|
-
if send("protected_#{password_field}").blank?
|
258
|
-
errors.add(
|
259
|
-
password_field,
|
260
|
-
I18n.t("error_messages.password_blank", default: "cannot be blank")
|
261
|
-
)
|
262
|
-
end
|
251
|
+
def validate_by_password__blank_fields
|
252
|
+
if send(login_field).blank?
|
253
|
+
errors.add(
|
254
|
+
login_field,
|
255
|
+
I18n.t("error_messages.login_blank", default: "cannot be blank")
|
256
|
+
)
|
263
257
|
end
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
def validate_by_password__invalid_password
|
269
|
-
unless attempted_record.send(
|
270
|
-
verify_password_method,
|
271
|
-
send("protected_#{password_field}")
|
258
|
+
if send("protected_#{password_field}").blank?
|
259
|
+
errors.add(
|
260
|
+
password_field,
|
261
|
+
I18n.t("error_messages.password_blank", default: "cannot be blank")
|
272
262
|
)
|
273
|
-
self.invalid_password = true
|
274
|
-
add_invalid_password_error
|
275
|
-
end
|
276
263
|
end
|
264
|
+
end
|
277
265
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
266
|
+
# Verify the password, usually using `valid_password?` in
|
267
|
+
# `acts_as_authentic/password.rb`. If it cannot be verified, we
|
268
|
+
# refer to it as "invalid".
|
269
|
+
def validate_by_password__invalid_password
|
270
|
+
unless attempted_record.send(
|
271
|
+
verify_password_method,
|
272
|
+
send("protected_#{password_field}")
|
273
|
+
)
|
274
|
+
self.invalid_password = true
|
275
|
+
add_invalid_password_error
|
282
276
|
end
|
277
|
+
end
|
283
278
|
|
284
|
-
|
285
|
-
self.class.login_field
|
286
|
-
end
|
279
|
+
attr_accessor :invalid_password
|
287
280
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
self.class.generalize_credentials_error_messages
|
292
|
-
else
|
293
|
-
"#{login_field.to_s.humanize}/Password combination is not valid"
|
294
|
-
end
|
295
|
-
errors.add(
|
296
|
-
:base,
|
297
|
-
I18n.t("error_messages.general_credentials_error", default: error_message)
|
298
|
-
)
|
299
|
-
end
|
281
|
+
def find_by_login_method
|
282
|
+
self.class.find_by_login_method
|
283
|
+
end
|
300
284
|
|
301
|
-
|
302
|
-
|
303
|
-
|
285
|
+
def login_field
|
286
|
+
self.class.login_field
|
287
|
+
end
|
304
288
|
|
305
|
-
|
306
|
-
|
307
|
-
|
289
|
+
def add_general_credentials_error
|
290
|
+
error_message =
|
291
|
+
if self.class.generalize_credentials_error_messages.is_a? String
|
292
|
+
self.class.generalize_credentials_error_messages
|
293
|
+
else
|
294
|
+
"#{login_field.to_s.humanize}/Password combination is not valid"
|
295
|
+
end
|
296
|
+
errors.add(
|
297
|
+
:base,
|
298
|
+
I18n.t("error_messages.general_credentials_error", default: error_message)
|
299
|
+
)
|
300
|
+
end
|
308
301
|
|
309
|
-
|
310
|
-
|
311
|
-
|
302
|
+
def generalize_credentials_error_messages?
|
303
|
+
self.class.generalize_credentials_error_messages
|
304
|
+
end
|
305
|
+
|
306
|
+
def password_field
|
307
|
+
self.class.password_field
|
308
|
+
end
|
309
|
+
|
310
|
+
def verify_password_method
|
311
|
+
self.class.verify_password_method
|
312
|
+
end
|
312
313
|
end
|
313
314
|
end
|
314
315
|
end
|
@@ -13,12 +13,12 @@ module Authlogic
|
|
13
13
|
|
14
14
|
private
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
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
|
21
20
|
end
|
21
|
+
end
|
22
22
|
end
|
23
23
|
end
|
24
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
|
14
|
-
# a variety of methods. It basically tries to "log
|
15
|
-
# to explicitly log in. Check out
|
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
|
#
|
@@ -56,7 +57,7 @@ module Authlogic
|
|
56
57
|
def persisting?
|
57
58
|
return true unless record.nil?
|
58
59
|
self.attempted_record = nil
|
59
|
-
self.remember_me =
|
60
|
+
self.remember_me = cookie_credentials_remember_me?
|
60
61
|
before_persisting
|
61
62
|
persist
|
62
63
|
ensure_authentication_attempted
|
@@ -24,15 +24,15 @@ module Authlogic
|
|
24
24
|
|
25
25
|
private
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
def attempted_record=(value)
|
28
|
+
value = priority_record if value == priority_record
|
29
|
+
super
|
30
|
+
end
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
def save_record(alternate_record = nil)
|
33
|
+
r = alternate_record || record
|
34
|
+
super if r != priority_record
|
35
|
+
end
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
@@ -89,9 +89,9 @@ module Authlogic
|
|
89
89
|
|
90
90
|
private
|
91
91
|
|
92
|
-
|
93
|
-
|
94
|
-
|
92
|
+
def scope=(value)
|
93
|
+
RequestStore.store[:authlogic_scope] = value
|
94
|
+
end
|
95
95
|
end
|
96
96
|
|
97
97
|
module InstanceMethods
|
@@ -108,30 +108,30 @@ module Authlogic
|
|
108
108
|
|
109
109
|
private
|
110
110
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
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
115
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
end
|
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)
|
122
121
|
end
|
122
|
+
end
|
123
123
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
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)
|
134
133
|
end
|
134
|
+
end
|
135
135
|
end
|
136
136
|
end
|
137
137
|
end
|
@@ -83,20 +83,20 @@ module Authlogic
|
|
83
83
|
|
84
84
|
private
|
85
85
|
|
86
|
-
|
87
|
-
|
88
|
-
|
86
|
+
def reset_stale_state
|
87
|
+
self.stale_record = nil
|
88
|
+
end
|
89
89
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
end
|
90
|
+
def enforce_timeout
|
91
|
+
if stale?
|
92
|
+
self.stale_record = record
|
93
|
+
self.record = nil
|
95
94
|
end
|
95
|
+
end
|
96
96
|
|
97
|
-
|
98
|
-
|
99
|
-
|
97
|
+
def logout_on_timeout?
|
98
|
+
self.class.logout_on_timeout == true
|
99
|
+
end
|
100
100
|
end
|
101
101
|
end
|
102
102
|
end
|
@@ -44,13 +44,13 @@ module Authlogic
|
|
44
44
|
|
45
45
|
private
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
def authenticating_with_unauthorized_record?
|
48
|
+
!unauthorized_record.nil?
|
49
|
+
end
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
51
|
+
def validate_by_unauthorized_record
|
52
|
+
self.attempted_record = unauthorized_record
|
53
|
+
end
|
54
54
|
end
|
55
55
|
end
|
56
56
|
end
|
@@ -77,17 +77,17 @@ module Authlogic
|
|
77
77
|
|
78
78
|
private
|
79
79
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
)
|
80
|
+
def ensure_authentication_attempted
|
81
|
+
if errors.empty? && attempted_record.nil?
|
82
|
+
errors.add(
|
83
|
+
:base,
|
84
|
+
I18n.t(
|
85
|
+
"error_messages.no_authentication_details",
|
86
|
+
default: "You did not provide any details for authentication."
|
88
87
|
)
|
89
|
-
|
88
|
+
)
|
90
89
|
end
|
90
|
+
end
|
91
91
|
end
|
92
92
|
end
|
93
93
|
end
|