authlogic 4.1.0 → 4.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|