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