authlogic 3.4.6 → 4.2.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.
- checksums.yaml +5 -5
- data/.github/ISSUE_TEMPLATE.md +13 -0
- data/.github/triage.md +87 -0
- data/.gitignore +4 -0
- data/.rubocop.yml +127 -0
- data/.rubocop_todo.yml +65 -0
- data/.travis.yml +18 -10
- data/CHANGELOG.md +156 -6
- data/CONTRIBUTING.md +71 -3
- data/Gemfile +2 -2
- data/README.md +386 -0
- data/Rakefile +13 -7
- data/UPGRADING.md +22 -0
- data/authlogic.gemspec +33 -22
- data/lib/authlogic.rb +60 -52
- data/lib/authlogic/acts_as_authentic/base.rb +40 -26
- data/lib/authlogic/acts_as_authentic/email.rb +96 -32
- data/lib/authlogic/acts_as_authentic/logged_in_status.rb +36 -12
- data/lib/authlogic/acts_as_authentic/login.rb +114 -49
- data/lib/authlogic/acts_as_authentic/magic_columns.rb +17 -6
- data/lib/authlogic/acts_as_authentic/password.rb +296 -139
- data/lib/authlogic/acts_as_authentic/perishable_token.rb +34 -20
- data/lib/authlogic/acts_as_authentic/persistence_token.rb +20 -24
- data/lib/authlogic/acts_as_authentic/queries/find_with_case.rb +67 -0
- data/lib/authlogic/acts_as_authentic/restful_authentication.rb +68 -23
- data/lib/authlogic/acts_as_authentic/session_maintenance.rb +128 -85
- data/lib/authlogic/acts_as_authentic/single_access_token.rb +41 -25
- data/lib/authlogic/acts_as_authentic/validations_scope.rb +8 -8
- data/lib/authlogic/authenticates_many/association.rb +22 -14
- data/lib/authlogic/authenticates_many/base.rb +35 -16
- data/lib/authlogic/config.rb +10 -10
- data/lib/authlogic/controller_adapters/abstract_adapter.rb +40 -12
- data/lib/authlogic/controller_adapters/rack_adapter.rb +15 -8
- data/lib/authlogic/controller_adapters/rails_adapter.rb +42 -22
- data/lib/authlogic/controller_adapters/sinatra_adapter.rb +3 -3
- data/lib/authlogic/crypto_providers.rb +91 -0
- data/lib/authlogic/crypto_providers/aes256.rb +42 -14
- data/lib/authlogic/crypto_providers/bcrypt.rb +35 -20
- data/lib/authlogic/crypto_providers/md5.rb +11 -9
- data/lib/authlogic/crypto_providers/scrypt.rb +26 -13
- data/lib/authlogic/crypto_providers/sha1.rb +14 -8
- data/lib/authlogic/crypto_providers/sha256.rb +16 -12
- data/lib/authlogic/crypto_providers/sha512.rb +8 -24
- data/lib/authlogic/crypto_providers/wordpress.rb +44 -15
- data/lib/authlogic/i18n.rb +33 -20
- data/lib/authlogic/i18n/translator.rb +1 -1
- data/lib/authlogic/random.rb +12 -29
- data/lib/authlogic/regex.rb +59 -27
- data/lib/authlogic/session/activation.rb +36 -23
- data/lib/authlogic/session/active_record_trickery.rb +13 -10
- data/lib/authlogic/session/base.rb +20 -8
- data/lib/authlogic/session/brute_force_protection.rb +87 -56
- data/lib/authlogic/session/callbacks.rb +99 -49
- data/lib/authlogic/session/cookies.rb +128 -59
- data/lib/authlogic/session/existence.rb +29 -19
- data/lib/authlogic/session/foundation.rb +70 -16
- data/lib/authlogic/session/http_auth.rb +39 -31
- data/lib/authlogic/session/id.rb +27 -15
- data/lib/authlogic/session/klass.rb +17 -13
- data/lib/authlogic/session/magic_columns.rb +78 -59
- data/lib/authlogic/session/magic_states.rb +50 -27
- data/lib/authlogic/session/params.rb +79 -50
- data/lib/authlogic/session/password.rb +197 -118
- data/lib/authlogic/session/perishable_token.rb +12 -6
- data/lib/authlogic/session/persistence.rb +20 -14
- data/lib/authlogic/session/priority_record.rb +20 -16
- data/lib/authlogic/session/scopes.rb +63 -33
- data/lib/authlogic/session/session.rb +40 -25
- data/lib/authlogic/session/timeout.rb +51 -34
- data/lib/authlogic/session/unauthorized_record.rb +24 -18
- data/lib/authlogic/session/validation.rb +32 -21
- data/lib/authlogic/test_case.rb +123 -35
- data/lib/authlogic/test_case/mock_controller.rb +14 -13
- data/lib/authlogic/test_case/mock_cookie_jar.rb +14 -5
- data/lib/authlogic/test_case/mock_logger.rb +1 -1
- data/lib/authlogic/test_case/mock_request.rb +9 -4
- data/lib/authlogic/test_case/rails_request_adapter.rb +8 -7
- data/lib/authlogic/version.rb +21 -0
- data/test/acts_as_authentic_test/base_test.rb +1 -1
- data/test/acts_as_authentic_test/email_test.rb +80 -63
- data/test/acts_as_authentic_test/logged_in_status_test.rb +14 -8
- data/test/acts_as_authentic_test/login_test.rb +91 -49
- data/test/acts_as_authentic_test/magic_columns_test.rb +13 -13
- data/test/acts_as_authentic_test/password_test.rb +82 -60
- data/test/acts_as_authentic_test/perishable_token_test.rb +31 -25
- data/test/acts_as_authentic_test/persistence_token_test.rb +9 -5
- data/test/acts_as_authentic_test/restful_authentication_test.rb +18 -9
- data/test/acts_as_authentic_test/session_maintenance_test.rb +86 -22
- data/test/acts_as_authentic_test/single_access_test.rb +15 -15
- data/test/adapter_test.rb +21 -0
- data/test/authenticates_many_test.rb +26 -11
- data/test/config_test.rb +9 -9
- data/test/crypto_provider_test/aes256_test.rb +3 -3
- data/test/crypto_provider_test/bcrypt_test.rb +1 -1
- data/test/crypto_provider_test/scrypt_test.rb +2 -2
- data/test/crypto_provider_test/sha1_test.rb +4 -4
- data/test/crypto_provider_test/sha256_test.rb +2 -2
- data/test/crypto_provider_test/sha512_test.rb +3 -3
- data/test/crypto_provider_test/wordpress_test.rb +24 -0
- data/test/gemfiles/Gemfile.rails-4.2.x +2 -2
- data/test/gemfiles/Gemfile.rails-5.0.x +6 -0
- data/test/gemfiles/Gemfile.rails-5.1.x +6 -0
- data/test/gemfiles/Gemfile.rails-5.2.x +6 -0
- data/test/gemfiles/Gemfile.rails-master +6 -0
- data/test/i18n_test.rb +9 -9
- data/test/libs/affiliate.rb +2 -2
- data/test/libs/company.rb +4 -4
- data/test/libs/employee.rb +2 -2
- data/test/libs/employee_session.rb +1 -1
- data/test/libs/ldaper.rb +1 -1
- data/test/libs/project.rb +1 -1
- data/test/libs/user_session.rb +2 -2
- data/test/random_test.rb +9 -38
- data/test/session_test/activation_test.rb +7 -7
- data/test/session_test/active_record_trickery_test.rb +9 -6
- data/test/session_test/brute_force_protection_test.rb +26 -21
- data/test/session_test/callbacks_test.rb +10 -4
- data/test/session_test/cookies_test.rb +54 -20
- data/test/session_test/existence_test.rb +45 -23
- data/test/session_test/foundation_test.rb +17 -1
- data/test/session_test/http_auth_test.rb +11 -12
- data/test/session_test/id_test.rb +3 -3
- data/test/session_test/klass_test.rb +2 -2
- data/test/session_test/magic_columns_test.rb +15 -17
- data/test/session_test/magic_states_test.rb +17 -19
- data/test/session_test/params_test.rb +26 -20
- data/test/session_test/password_test.rb +11 -12
- data/test/session_test/perishability_test.rb +5 -5
- data/test/session_test/persistence_test.rb +4 -3
- data/test/session_test/scopes_test.rb +15 -9
- data/test/session_test/session_test.rb +7 -6
- data/test/session_test/timeout_test.rb +16 -14
- data/test/session_test/unauthorized_record_test.rb +3 -3
- data/test/session_test/validation_test.rb +5 -5
- data/test/test_helper.rb +115 -49
- metadata +107 -36
- data/README.rdoc +0 -232
- data/test/gemfiles/Gemfile.rails-3.2.x +0 -7
- data/test/gemfiles/Gemfile.rails-4.0.x +0 -7
- data/test/gemfiles/Gemfile.rails-4.1.x +0 -7
@@ -1,7 +1,10 @@
|
|
1
1
|
module Authlogic
|
2
2
|
module Session
|
3
|
-
# Handles all authentication that deals with cookies, such as persisting,
|
3
|
+
# Handles all authentication that deals with cookies, such as persisting,
|
4
|
+
# saving, and destroying.
|
4
5
|
module Cookies
|
6
|
+
VALID_SAME_SITE_VALUES = [nil, "Lax", "Strict"].freeze
|
7
|
+
|
5
8
|
def self.included(klass)
|
6
9
|
klass.class_eval do
|
7
10
|
extend Config
|
@@ -14,8 +17,10 @@ module Authlogic
|
|
14
17
|
|
15
18
|
# Configuration for the cookie feature set.
|
16
19
|
module Config
|
17
|
-
# The name of the cookie or the key in the cookies hash. Be sure and use
|
18
|
-
#
|
20
|
+
# The name of the cookie or the key in the cookies hash. Be sure and use
|
21
|
+
# a unique name. If you have multiple sessions and they use the same
|
22
|
+
# cookie it will cause problems. Also, if a id is set it will be
|
23
|
+
# inserted into the beginning of the string. Example:
|
19
24
|
#
|
20
25
|
# session = UserSession.new
|
21
26
|
# session.cookie_key => "user_credentials"
|
@@ -48,25 +53,42 @@ module Authlogic
|
|
48
53
|
end
|
49
54
|
alias_method :remember_me_for=, :remember_me_for
|
50
55
|
|
51
|
-
# Should the cookie be set as secure? If true, the cookie will only be sent over
|
56
|
+
# Should the cookie be set as secure? If true, the cookie will only be sent over
|
57
|
+
# SSL connections
|
52
58
|
#
|
53
|
-
# * <tt>Default:</tt>
|
59
|
+
# * <tt>Default:</tt> true
|
54
60
|
# * <tt>Accepts:</tt> Boolean
|
55
61
|
def secure(value = nil)
|
56
|
-
rw_config(:secure, value,
|
62
|
+
rw_config(:secure, value, true)
|
57
63
|
end
|
58
64
|
alias_method :secure=, :secure
|
59
65
|
|
60
|
-
# Should the cookie be set as httponly? If true, the cookie will not be
|
66
|
+
# Should the cookie be set as httponly? If true, the cookie will not be
|
67
|
+
# accessible from javascript
|
61
68
|
#
|
62
|
-
# * <tt>Default:</tt>
|
69
|
+
# * <tt>Default:</tt> true
|
63
70
|
# * <tt>Accepts:</tt> Boolean
|
64
71
|
def httponly(value = nil)
|
65
|
-
rw_config(:httponly, value,
|
72
|
+
rw_config(:httponly, value, true)
|
66
73
|
end
|
67
74
|
alias_method :httponly=, :httponly
|
68
75
|
|
69
|
-
# Should the cookie be
|
76
|
+
# Should the cookie be prevented from being send along with cross-site
|
77
|
+
# requests?
|
78
|
+
#
|
79
|
+
# * <tt>Default:</tt> nil
|
80
|
+
# * <tt>Accepts:</tt> String, one of nil, 'Lax' or 'Strict'
|
81
|
+
def same_site(value = nil)
|
82
|
+
unless VALID_SAME_SITE_VALUES.include?(value)
|
83
|
+
msg = "Invalid same_site value: #{value}. Valid: #{VALID_SAME_SITE_VALUES.inspect}"
|
84
|
+
raise ArgumentError.new(msg)
|
85
|
+
end
|
86
|
+
rw_config(:same_site, value)
|
87
|
+
end
|
88
|
+
alias_method :same_site=, :same_site
|
89
|
+
|
90
|
+
# Should the cookie be signed? If the controller adapter supports it, this is a
|
91
|
+
# measure against cookie tampering.
|
70
92
|
def sign_cookie(value = nil)
|
71
93
|
if value && !controller.cookies.respond_to?(:signed)
|
72
94
|
raise "Signed cookies not supported with #{controller.class}!"
|
@@ -76,7 +98,8 @@ module Authlogic
|
|
76
98
|
alias_method :sign_cookie=, :sign_cookie
|
77
99
|
end
|
78
100
|
|
79
|
-
# The methods available for an Authlogic::Session::Base object that make up the
|
101
|
+
# The methods available for an Authlogic::Session::Base object that make up the
|
102
|
+
# cookie feature set.
|
80
103
|
module InstanceMethods
|
81
104
|
# Allows you to set the remember_me option when passing credentials.
|
82
105
|
def credentials=(value)
|
@@ -84,10 +107,12 @@ module Authlogic
|
|
84
107
|
values = value.is_a?(Array) ? value : [value]
|
85
108
|
case values.first
|
86
109
|
when Hash
|
87
|
-
|
110
|
+
if values.first.with_indifferent_access.key?(:remember_me)
|
111
|
+
self.remember_me = values.first.with_indifferent_access[:remember_me]
|
112
|
+
end
|
88
113
|
else
|
89
|
-
r = values.find { |
|
90
|
-
self.remember_me = r
|
114
|
+
r = values.find { |val| val.is_a?(TrueClass) || val.is_a?(FalseClass) }
|
115
|
+
self.remember_me = r unless r.nil?
|
91
116
|
end
|
92
117
|
end
|
93
118
|
|
@@ -97,7 +122,9 @@ module Authlogic
|
|
97
122
|
@remember_me = self.class.remember_me
|
98
123
|
end
|
99
124
|
|
100
|
-
# Accepts a boolean as a flag to remember the session or not. Basically
|
125
|
+
# Accepts a boolean as a flag to remember the session or not. Basically
|
126
|
+
# to expire the cookie at the end of the session or keep it for
|
127
|
+
# "remember_me_until".
|
101
128
|
def remember_me=(value)
|
102
129
|
@remember_me = value
|
103
130
|
end
|
@@ -107,13 +134,15 @@ module Authlogic
|
|
107
134
|
remember_me == true || remember_me == "true" || remember_me == "1"
|
108
135
|
end
|
109
136
|
|
110
|
-
# How long to remember the user if remember_me is true. This is based on the class
|
137
|
+
# How long to remember the user if remember_me is true. This is based on the class
|
138
|
+
# level configuration: remember_me_for
|
111
139
|
def remember_me_for
|
112
140
|
return unless remember_me?
|
113
141
|
self.class.remember_me_for
|
114
142
|
end
|
115
143
|
|
116
|
-
# When to expire the cookie. See remember_me_for configuration option to change
|
144
|
+
# When to expire the cookie. See remember_me_for configuration option to change
|
145
|
+
# this.
|
117
146
|
def remember_me_until
|
118
147
|
return unless remember_me?
|
119
148
|
remember_me_for.from_now
|
@@ -131,7 +160,8 @@ module Authlogic
|
|
131
160
|
@secure = self.class.secure
|
132
161
|
end
|
133
162
|
|
134
|
-
# Accepts a boolean as to whether the cookie should be marked as secure. If true
|
163
|
+
# Accepts a boolean as to whether the cookie should be marked as secure. If true
|
164
|
+
# the cookie will only ever be sent over an SSL connection.
|
135
165
|
def secure=(value)
|
136
166
|
@secure = value
|
137
167
|
end
|
@@ -141,13 +171,14 @@ module Authlogic
|
|
141
171
|
secure == true || secure == "true" || secure == "1"
|
142
172
|
end
|
143
173
|
|
144
|
-
# If the cookie should be marked as httponly (not
|
174
|
+
# If the cookie should be marked as httponly (not accessible via javascript)
|
145
175
|
def httponly
|
146
176
|
return @httponly if defined?(@httponly)
|
147
177
|
@httponly = self.class.httponly
|
148
178
|
end
|
149
179
|
|
150
|
-
# Accepts a boolean as to whether the cookie should be marked as
|
180
|
+
# Accepts a boolean as to whether the cookie should be marked as
|
181
|
+
# httponly. If true, the cookie will not be accessible from javascript
|
151
182
|
def httponly=(value)
|
152
183
|
@httponly = value
|
153
184
|
end
|
@@ -157,13 +188,29 @@ module Authlogic
|
|
157
188
|
httponly == true || httponly == "true" || httponly == "1"
|
158
189
|
end
|
159
190
|
|
191
|
+
# If the cookie should be marked as SameSite with 'Lax' or 'Strict' flag.
|
192
|
+
def same_site
|
193
|
+
return @same_site if defined?(@same_site)
|
194
|
+
@same_site = self.class.same_site(nil)
|
195
|
+
end
|
196
|
+
|
197
|
+
# Accepts nil, 'Lax' or 'Strict' as possible flags.
|
198
|
+
def same_site=(value)
|
199
|
+
unless VALID_SAME_SITE_VALUES.include?(value)
|
200
|
+
msg = "Invalid same_site value: #{value}. Valid: #{VALID_SAME_SITE_VALUES.inspect}"
|
201
|
+
raise ArgumentError.new(msg)
|
202
|
+
end
|
203
|
+
@same_site = value
|
204
|
+
end
|
205
|
+
|
160
206
|
# If the cookie should be signed
|
161
207
|
def sign_cookie
|
162
208
|
return @sign_cookie if defined?(@sign_cookie)
|
163
209
|
@sign_cookie = self.class.sign_cookie
|
164
210
|
end
|
165
211
|
|
166
|
-
# Accepts a boolean as to whether the cookie should be signed. If true
|
212
|
+
# Accepts a boolean as to whether the cookie should be signed. If true
|
213
|
+
# the cookie will be saved and verified using a signature.
|
167
214
|
def sign_cookie=(value)
|
168
215
|
@sign_cookie = value
|
169
216
|
end
|
@@ -174,53 +221,75 @@ module Authlogic
|
|
174
221
|
end
|
175
222
|
|
176
223
|
private
|
177
|
-
def cookie_key
|
178
|
-
build_key(self.class.cookie_key)
|
179
|
-
end
|
180
224
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
else
|
185
|
-
cookie = controller.cookies[cookie_key]
|
186
|
-
end
|
187
|
-
cookie && cookie.split("::")
|
188
|
-
end
|
225
|
+
def cookie_key
|
226
|
+
build_key(self.class.cookie_key)
|
227
|
+
end
|
189
228
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
229
|
+
# Returns an array of cookie elements. See cookie format in
|
230
|
+
# `generate_cookie_for_saving`. If no cookie is found, returns nil.
|
231
|
+
def cookie_credentials
|
232
|
+
cookie = cookie_jar[cookie_key]
|
233
|
+
cookie && cookie.split("::")
|
234
|
+
end
|
235
|
+
|
236
|
+
# The third element of the cookie indicates whether the user wanted
|
237
|
+
# to be remembered (Actually, it's a timestamp, `remember_me_until`)
|
238
|
+
# See cookie format in `generate_cookie_for_saving`.
|
239
|
+
def cookie_credentials_remember_me?
|
240
|
+
!cookie_credentials.nil? && !cookie_credentials[2].nil?
|
241
|
+
end
|
242
|
+
|
243
|
+
def cookie_jar
|
244
|
+
if self.class.sign_cookie
|
245
|
+
controller.cookies.signed
|
246
|
+
else
|
247
|
+
controller.cookies
|
200
248
|
end
|
249
|
+
end
|
201
250
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
251
|
+
# Tries to validate the session from information in the cookie
|
252
|
+
def persist_by_cookie
|
253
|
+
persistence_token, record_id = cookie_credentials
|
254
|
+
if persistence_token.present?
|
255
|
+
record = search_for_record("find_by_#{klass.primary_key}", record_id)
|
256
|
+
if record && record.persistence_token == persistence_token
|
257
|
+
self.unauthorized_record = record
|
207
258
|
end
|
259
|
+
valid?
|
260
|
+
else
|
261
|
+
false
|
208
262
|
end
|
263
|
+
end
|
209
264
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
:secure => secure,
|
216
|
-
:httponly => httponly,
|
217
|
-
:domain => controller.cookie_domain
|
218
|
-
}
|
265
|
+
def save_cookie
|
266
|
+
if sign_cookie?
|
267
|
+
controller.cookies.signed[cookie_key] = generate_cookie_for_saving
|
268
|
+
else
|
269
|
+
controller.cookies[cookie_key] = generate_cookie_for_saving
|
219
270
|
end
|
271
|
+
end
|
220
272
|
|
221
|
-
|
222
|
-
|
223
|
-
|
273
|
+
def generate_cookie_for_saving
|
274
|
+
value = format(
|
275
|
+
"%s::%s%s",
|
276
|
+
record.persistence_token,
|
277
|
+
record.send(record.class.primary_key),
|
278
|
+
remember_me? ? "::#{remember_me_until.iso8601}" : ""
|
279
|
+
)
|
280
|
+
{
|
281
|
+
value: value,
|
282
|
+
expires: remember_me_until,
|
283
|
+
secure: secure,
|
284
|
+
httponly: httponly,
|
285
|
+
same_site: same_site,
|
286
|
+
domain: controller.cookie_domain
|
287
|
+
}
|
288
|
+
end
|
289
|
+
|
290
|
+
def destroy_cookie
|
291
|
+
controller.cookies.delete cookie_key, domain: controller.cookie_domain
|
292
|
+
end
|
224
293
|
end
|
225
294
|
end
|
226
295
|
end
|
@@ -1,13 +1,19 @@
|
|
1
1
|
module Authlogic
|
2
2
|
module Session
|
3
|
-
# Provides methods to create and destroy objects. Basically controls their
|
3
|
+
# Provides methods to create and destroy objects. Basically controls their
|
4
|
+
# "existence".
|
4
5
|
module Existence
|
5
6
|
class SessionInvalidError < ::StandardError # :nodoc:
|
6
7
|
def initialize(session)
|
7
|
-
|
8
|
+
message = I18n.t(
|
9
|
+
"error_messages.session_invalid",
|
10
|
+
default: "Your session is invalid and has the following errors:"
|
11
|
+
)
|
12
|
+
message += " #{session.errors.full_messages.to_sentence}"
|
13
|
+
super message
|
8
14
|
end
|
9
15
|
end
|
10
|
-
|
16
|
+
|
11
17
|
def self.included(klass)
|
12
18
|
klass.class_eval do
|
13
19
|
extend ClassMethods
|
@@ -15,9 +21,9 @@ module Authlogic
|
|
15
21
|
attr_accessor :new_session, :record
|
16
22
|
end
|
17
23
|
end
|
18
|
-
|
24
|
+
|
19
25
|
module ClassMethods
|
20
|
-
# A
|
26
|
+
# A convenience method. The same as:
|
21
27
|
#
|
22
28
|
# session = UserSession.new(*args)
|
23
29
|
# session.save
|
@@ -30,7 +36,7 @@ module Authlogic
|
|
30
36
|
session.save(&block)
|
31
37
|
session
|
32
38
|
end
|
33
|
-
|
39
|
+
|
34
40
|
# Same as create but calls create!, which raises an exception when validation fails.
|
35
41
|
def create!(*args)
|
36
42
|
session = new(*args)
|
@@ -38,10 +44,11 @@ module Authlogic
|
|
38
44
|
session
|
39
45
|
end
|
40
46
|
end
|
41
|
-
|
47
|
+
|
42
48
|
module InstanceMethods
|
43
|
-
# Clears all errors and the associated record, you should call this
|
44
|
-
# the user to authenticate again if
|
49
|
+
# Clears all errors and the associated record, you should call this
|
50
|
+
# terminate a session, thus requiring the user to authenticate again if
|
51
|
+
# it is needed.
|
45
52
|
def destroy
|
46
53
|
before_destroy
|
47
54
|
save_record
|
@@ -50,17 +57,19 @@ module Authlogic
|
|
50
57
|
after_destroy
|
51
58
|
true
|
52
59
|
end
|
53
|
-
|
54
|
-
# Returns true if the session is new, meaning no action has been taken
|
55
|
-
# has not taken place.
|
60
|
+
|
61
|
+
# Returns true if the session is new, meaning no action has been taken
|
62
|
+
# on it and a successful save has not taken place.
|
56
63
|
def new_session?
|
57
64
|
new_session != false
|
58
65
|
end
|
59
|
-
|
60
|
-
# After you have specified all of the details for your session you can
|
61
|
-
# run validation checks and find the
|
62
|
-
#
|
63
|
-
|
66
|
+
|
67
|
+
# After you have specified all of the details for your session you can
|
68
|
+
# try to save it. This will run validation checks and find the
|
69
|
+
# associated record, if all validation passes. If validation does not
|
70
|
+
# pass, the save will fail and the errors will be stored in the errors
|
71
|
+
# object.
|
72
|
+
def save
|
64
73
|
result = nil
|
65
74
|
if valid?
|
66
75
|
self.record = attempted_record
|
@@ -81,7 +90,8 @@ module Authlogic
|
|
81
90
|
result
|
82
91
|
end
|
83
92
|
|
84
|
-
# Same as save but raises an exception of validation errors when
|
93
|
+
# Same as save but raises an exception of validation errors when
|
94
|
+
# validation fails
|
85
95
|
def save!
|
86
96
|
result = save
|
87
97
|
raise SessionInvalidError.new(self) unless result
|
@@ -90,4 +100,4 @@ module Authlogic
|
|
90
100
|
end
|
91
101
|
end
|
92
102
|
end
|
93
|
-
end
|
103
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module Authlogic
|
2
2
|
module Session
|
3
|
-
# Sort of like an interface, it sets the foundation for the class, such as the
|
4
|
-
# other modules to overwrite methods and call super
|
5
|
-
# throughout Authlogic.
|
3
|
+
# Sort of like an interface, it sets the foundation for the class, such as the
|
4
|
+
# required methods. This also allows other modules to overwrite methods and call super
|
5
|
+
# on them. It's also a place to put "utility" methods used throughout Authlogic.
|
6
6
|
module Foundation
|
7
7
|
def self.included(klass)
|
8
8
|
klass.class_eval do
|
@@ -12,39 +12,93 @@ module Authlogic
|
|
12
12
|
end
|
13
13
|
|
14
14
|
module InstanceMethods
|
15
|
+
E_AC_PARAMETERS = <<-EOS.strip_heredoc.freeze
|
16
|
+
Passing an ActionController::Parameters to Authlogic is not allowed.
|
17
|
+
|
18
|
+
In Authlogic 3, especially during the transition of rails to Strong
|
19
|
+
Parameters, it was common for Authlogic users to forget to `permit`
|
20
|
+
their params. They would pass their params into Authlogic, we'd call
|
21
|
+
`to_h`, and they'd be surprised when authentication failed.
|
22
|
+
|
23
|
+
In 2018, people are still making this mistake. We'd like to help them
|
24
|
+
and make authlogic a little simpler at the same time, so in Authlogic
|
25
|
+
3.7.0, we deprecated the use of ActionController::Parameters. Instead,
|
26
|
+
pass a plain Hash. Please replace:
|
27
|
+
|
28
|
+
UserSession.new(user_session_params)
|
29
|
+
UserSession.create(user_session_params)
|
30
|
+
|
31
|
+
with
|
32
|
+
|
33
|
+
UserSession.new(user_session_params.to_h)
|
34
|
+
UserSession.create(user_session_params.to_h)
|
35
|
+
|
36
|
+
And don't forget to `permit`!
|
37
|
+
|
38
|
+
We discussed this issue thoroughly between late 2016 and early
|
39
|
+
2018. Notable discussions include:
|
40
|
+
|
41
|
+
- https://github.com/binarylogic/authlogic/issues/512
|
42
|
+
- https://github.com/binarylogic/authlogic/pull/558
|
43
|
+
- https://github.com/binarylogic/authlogic/pull/577
|
44
|
+
EOS
|
45
|
+
|
15
46
|
def initialize(*args)
|
16
47
|
self.credentials = args
|
17
48
|
end
|
18
49
|
|
19
|
-
# The credentials you passed to create your session. See credentials= for more
|
50
|
+
# The credentials you passed to create your session. See credentials= for more
|
51
|
+
# info.
|
20
52
|
def credentials
|
21
53
|
[]
|
22
54
|
end
|
23
55
|
|
24
|
-
# Set your credentials before you save your session.
|
56
|
+
# Set your credentials before you save your session. There are many
|
57
|
+
# method signatures.
|
25
58
|
#
|
26
|
-
#
|
59
|
+
# ```
|
60
|
+
# # A hash of credentials is most common
|
61
|
+
# session.credentials = { login: "foo", password: "bar", remember_me: true }
|
27
62
|
#
|
28
|
-
#
|
63
|
+
# # You must pass an actual Hash, `ActionController::Parameters` is
|
64
|
+
# # specifically not allowed.
|
29
65
|
#
|
30
|
-
#
|
66
|
+
# # You can pass an array of objects:
|
67
|
+
# session.credentials = [my_user_object, true]
|
31
68
|
#
|
32
|
-
#
|
33
|
-
#
|
69
|
+
# # If you need to set an id (see `Authlogic::Session::Id`) pass it
|
70
|
+
# # last. It needs be the last item in the array you pass, since the id
|
71
|
+
# # is something that you control yourself, it should never be set from
|
72
|
+
# # a hash or a form. Examples:
|
73
|
+
# session.credentials = [
|
74
|
+
# {:login => "foo", :password => "bar", :remember_me => true},
|
75
|
+
# :my_id
|
76
|
+
# ]
|
77
|
+
# session.credentials = [my_user_object, true, :my_id]
|
34
78
|
#
|
35
|
-
#
|
36
|
-
#
|
79
|
+
# # Finally, there's priority_record
|
80
|
+
# [{ priority_record: my_object }, :my_id]
|
81
|
+
# ```
|
37
82
|
def credentials=(values)
|
83
|
+
normalized = Array.wrap(values)
|
84
|
+
if normalized.first.class.name == "ActionController::Parameters"
|
85
|
+
raise TypeError.new(E_AC_PARAMETERS)
|
86
|
+
end
|
38
87
|
end
|
39
88
|
|
40
89
|
def inspect
|
41
|
-
|
90
|
+
format(
|
91
|
+
"#<%s: %s>",
|
92
|
+
self.class.name,
|
93
|
+
credentials.blank? ? "no credentials provided" : credentials.inspect
|
94
|
+
)
|
42
95
|
end
|
43
96
|
|
44
97
|
private
|
45
|
-
|
46
|
-
|
47
|
-
|
98
|
+
|
99
|
+
def build_key(last_part)
|
100
|
+
last_part
|
101
|
+
end
|
48
102
|
end
|
49
103
|
end
|
50
104
|
end
|