authlogic 3.4.6 → 3.5.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 +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +33 -0
- data/.rubocop_todo.yml +427 -0
- data/.travis.yml +24 -3
- data/CHANGELOG.md +9 -2
- data/CONTRIBUTING.md +40 -1
- data/Gemfile +1 -1
- data/README.md +295 -0
- data/Rakefile +10 -2
- data/authlogic.gemspec +6 -5
- data/lib/authlogic.rb +2 -2
- data/lib/authlogic/acts_as_authentic/base.rb +2 -2
- data/lib/authlogic/acts_as_authentic/email.rb +59 -14
- data/lib/authlogic/acts_as_authentic/logged_in_status.rb +4 -3
- data/lib/authlogic/acts_as_authentic/login.rb +62 -12
- data/lib/authlogic/acts_as_authentic/magic_columns.rb +17 -6
- data/lib/authlogic/acts_as_authentic/password.rb +107 -53
- data/lib/authlogic/acts_as_authentic/persistence_token.rb +10 -9
- data/lib/authlogic/acts_as_authentic/restful_authentication.rb +2 -0
- data/lib/authlogic/acts_as_authentic/session_maintenance.rb +48 -35
- data/lib/authlogic/acts_as_authentic/single_access_token.rb +19 -15
- data/lib/authlogic/acts_as_authentic/validations_scope.rb +2 -2
- data/lib/authlogic/authenticates_many/association.rb +6 -5
- data/lib/authlogic/authenticates_many/base.rb +22 -12
- data/lib/authlogic/config.rb +2 -1
- data/lib/authlogic/controller_adapters/abstract_adapter.rb +2 -1
- data/lib/authlogic/controller_adapters/rack_adapter.rb +3 -4
- data/lib/authlogic/controller_adapters/rails_adapter.rb +26 -14
- data/lib/authlogic/controller_adapters/sinatra_adapter.rb +1 -1
- data/lib/authlogic/crypto_providers/aes256.rb +16 -12
- data/lib/authlogic/crypto_providers/bcrypt.rb +10 -4
- data/lib/authlogic/crypto_providers/md5.rb +7 -7
- data/lib/authlogic/crypto_providers/scrypt.rb +10 -2
- data/lib/authlogic/crypto_providers/sha1.rb +3 -3
- data/lib/authlogic/crypto_providers/sha256.rb +3 -3
- data/lib/authlogic/crypto_providers/sha512.rb +4 -4
- data/lib/authlogic/crypto_providers/wordpress.rb +13 -13
- data/lib/authlogic/i18n.rb +22 -16
- data/lib/authlogic/i18n/translator.rb +1 -1
- data/lib/authlogic/random.rb +13 -12
- data/lib/authlogic/regex.rb +3 -3
- data/lib/authlogic/session/activation.rb +7 -6
- data/lib/authlogic/session/active_record_trickery.rb +1 -2
- data/lib/authlogic/session/base.rb +7 -6
- data/lib/authlogic/session/brute_force_protection.rb +58 -34
- data/lib/authlogic/session/callbacks.rb +16 -12
- data/lib/authlogic/session/cookies.rb +29 -14
- data/lib/authlogic/session/existence.rb +10 -10
- data/lib/authlogic/session/foundation.rb +11 -7
- data/lib/authlogic/session/http_auth.rb +6 -5
- data/lib/authlogic/session/id.rb +5 -4
- data/lib/authlogic/session/klass.rb +2 -1
- data/lib/authlogic/session/magic_columns.rb +21 -14
- data/lib/authlogic/session/magic_states.rb +25 -14
- data/lib/authlogic/session/params.rb +41 -26
- data/lib/authlogic/session/password.rb +62 -40
- data/lib/authlogic/session/perishable_token.rb +3 -2
- data/lib/authlogic/session/persistence.rb +3 -3
- data/lib/authlogic/session/priority_record.rb +5 -4
- data/lib/authlogic/session/scopes.rb +20 -9
- data/lib/authlogic/session/session.rb +9 -4
- data/lib/authlogic/session/timeout.rb +40 -23
- data/lib/authlogic/session/unauthorized_record.rb +6 -5
- data/lib/authlogic/session/validation.rb +18 -9
- data/lib/authlogic/test_case.rb +2 -2
- data/lib/authlogic/test_case/mock_controller.rb +9 -9
- data/lib/authlogic/test_case/mock_cookie_jar.rb +2 -2
- data/lib/authlogic/test_case/mock_logger.rb +1 -1
- data/lib/authlogic/test_case/mock_request.rb +2 -1
- data/lib/authlogic/test_case/rails_request_adapter.rb +5 -5
- data/test/acts_as_authentic_test/email_test.rb +29 -17
- data/test/acts_as_authentic_test/logged_in_status_test.rb +9 -3
- data/test/acts_as_authentic_test/login_test.rb +47 -13
- data/test/acts_as_authentic_test/magic_columns_test.rb +4 -4
- data/test/acts_as_authentic_test/password_test.rb +31 -21
- data/test/acts_as_authentic_test/perishable_token_test.rb +15 -15
- data/test/acts_as_authentic_test/session_maintenance_test.rb +20 -13
- data/test/acts_as_authentic_test/single_access_test.rb +8 -8
- data/test/authenticates_many_test.rb +4 -4
- data/test/crypto_provider_test/aes256_test.rb +2 -2
- data/test/crypto_provider_test/scrypt_test.rb +1 -1
- data/test/crypto_provider_test/sha1_test.rb +3 -3
- data/test/crypto_provider_test/sha256_test.rb +1 -1
- data/test/crypto_provider_test/sha512_test.rb +2 -2
- data/test/gemfiles/Gemfile.rails-3.2.x +2 -2
- data/test/gemfiles/Gemfile.rails-5.0.x +6 -0
- data/test/i18n_test.rb +5 -5
- data/test/libs/affiliate.rb +2 -2
- data/test/libs/company.rb +1 -1
- 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/random_test.rb +5 -4
- data/test/session_test/activation_test.rb +5 -5
- data/test/session_test/active_record_trickery_test.rb +7 -5
- data/test/session_test/cookies_test.rb +8 -6
- data/test/session_test/existence_test.rb +19 -13
- data/test/session_test/http_auth_test.rb +0 -3
- data/test/session_test/id_test.rb +2 -2
- data/test/session_test/klass_test.rb +1 -1
- data/test/session_test/magic_columns_test.rb +0 -3
- data/test/session_test/magic_states_test.rb +11 -11
- data/test/session_test/params_test.rb +10 -10
- data/test/session_test/password_test.rb +4 -5
- data/test/session_test/perishability_test.rb +3 -3
- data/test/session_test/scopes_test.rb +8 -8
- data/test/session_test/session_test.rb +5 -4
- data/test/session_test/timeout_test.rb +8 -8
- data/test/session_test/unauthorized_record_test.rb +2 -2
- data/test/session_test/validation_test.rb +3 -3
- data/test/test_helper.rb +9 -5
- metadata +54 -24
- data/README.rdoc +0 -232
@@ -7,13 +7,13 @@ module Authlogic
|
|
7
7
|
extend Config
|
8
8
|
include InstanceMethods
|
9
9
|
validate :validate_by_password, :if => :authenticating_with_password?
|
10
|
-
|
10
|
+
|
11
11
|
class << self
|
12
12
|
attr_accessor :configured_password_methods
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
# Password configuration
|
18
18
|
module Config
|
19
19
|
# Authlogic tries to validate the credentials passed to it. One part of validation is actually finding the user and
|
@@ -23,8 +23,9 @@ module Authlogic
|
|
23
23
|
# You can change what method UserSession calls by specifying it here. Then in your User model you can make that method do
|
24
24
|
# anything you want, giving you complete control of how users are found by the UserSession.
|
25
25
|
#
|
26
|
-
# Let's take an example: You want to allow users to login by username or email.
|
27
|
-
# that does this in the User model. Let's
|
26
|
+
# Let's take an example: You want to allow users to login by username or email.
|
27
|
+
# Set this to the name of the class method that does this in the User model. Let's
|
28
|
+
# call it "find_by_username_or_email"
|
28
29
|
#
|
29
30
|
# class User < ActiveRecord::Base
|
30
31
|
# def self.find_by_username_or_email(login)
|
@@ -32,8 +33,10 @@ module Authlogic
|
|
32
33
|
# end
|
33
34
|
# end
|
34
35
|
#
|
35
|
-
# Now just specify the name of this method for this configuration option and you
|
36
|
-
#
|
36
|
+
# Now just specify the name of this method for this configuration option and you
|
37
|
+
# are all set. You can do anything you want here. Maybe you allow users to have
|
38
|
+
# multiple logins and you want to search a has_many relationship, etc. The sky is
|
39
|
+
# the limit.
|
37
40
|
#
|
38
41
|
# * <tt>Default:</tt> "find_by_smart_case_login_field"
|
39
42
|
# * <tt>Accepts:</tt> Symbol or String
|
@@ -41,10 +44,11 @@ module Authlogic
|
|
41
44
|
rw_config(:find_by_login_method, value, "find_by_smart_case_login_field")
|
42
45
|
end
|
43
46
|
alias_method :find_by_login_method=, :find_by_login_method
|
44
|
-
|
45
|
-
# The text used to identify credentials (username/password) combination when a bad
|
46
|
-
# When you show error messages for a bad login, it's
|
47
|
-
#
|
47
|
+
|
48
|
+
# The text used to identify credentials (username/password) combination when a bad
|
49
|
+
# login attempt occurs. When you show error messages for a bad login, it's
|
50
|
+
# considered good security practice to hide which field the user has entered
|
51
|
+
# incorrectly (the login field or the password field). For a full explanation, see
|
48
52
|
# http://www.gnucitizen.org/blog/username-enumeration-vulnerabilities/
|
49
53
|
#
|
50
54
|
# Example of use:
|
@@ -56,9 +60,9 @@ module Authlogic
|
|
56
60
|
# This would make the error message for bad logins and bad passwords look identical:
|
57
61
|
#
|
58
62
|
# Login/Password combination is not valid
|
59
|
-
#
|
63
|
+
#
|
60
64
|
# Alternatively you may use a custom message:
|
61
|
-
#
|
65
|
+
#
|
62
66
|
# class UserSession < AuthLogic::Session::Base
|
63
67
|
# generalize_credentials_error_messages "Your login information is invalid"
|
64
68
|
# end
|
@@ -71,18 +75,20 @@ module Authlogic
|
|
71
75
|
#
|
72
76
|
# If you are developing an app where security is an extreme priority (such as a financial application),
|
73
77
|
# then you should enable this. Otherwise, leaving this off is fine.
|
74
|
-
#
|
78
|
+
#
|
75
79
|
# * <tt>Default</tt> false
|
76
80
|
# * <tt>Accepts:</tt> Boolean
|
77
81
|
def generalize_credentials_error_messages(value = nil)
|
78
82
|
rw_config(:generalize_credentials_error_messages, value, false)
|
79
83
|
end
|
80
84
|
alias_method :generalize_credentials_error_messages=, :generalize_credentials_error_messages
|
81
|
-
|
82
|
-
# The name of the method you want Authlogic to create for storing the login /
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#
|
85
|
+
|
86
|
+
# The name of the method you want Authlogic to create for storing the login /
|
87
|
+
# username. Keep in mind this is just for your Authlogic::Session, if you want it
|
88
|
+
# can be something completely different than the field in your model. So if you
|
89
|
+
# wanted people to login with a field called "login" and then find users by email
|
90
|
+
# this is completely doable. See the find_by_login_method configuration option for
|
91
|
+
# more details.
|
86
92
|
#
|
87
93
|
# * <tt>Default:</tt> klass.login_field || klass.email_field
|
88
94
|
# * <tt>Accepts:</tt> Symbol or String
|
@@ -90,7 +96,7 @@ module Authlogic
|
|
90
96
|
rw_config(:login_field, value, klass.login_field || klass.email_field)
|
91
97
|
end
|
92
98
|
alias_method :login_field=, :login_field
|
93
|
-
|
99
|
+
|
94
100
|
# Works exactly like login_field, but for the password instead. Returns :password if a login_field exists.
|
95
101
|
#
|
96
102
|
# * <tt>Default:</tt> :password
|
@@ -99,7 +105,7 @@ module Authlogic
|
|
99
105
|
rw_config(:password_field, value, login_field && :password)
|
100
106
|
end
|
101
107
|
alias_method :password_field=, :password_field
|
102
|
-
|
108
|
+
|
103
109
|
# The name of the method in your model used to verify the password. This should be an instance method. It should also
|
104
110
|
# be prepared to accept a raw password and a crytped password.
|
105
111
|
#
|
@@ -110,7 +116,7 @@ module Authlogic
|
|
110
116
|
end
|
111
117
|
alias_method :verify_password_method=, :verify_password_method
|
112
118
|
end
|
113
|
-
|
119
|
+
|
114
120
|
# Password related instance methods
|
115
121
|
module InstanceMethods
|
116
122
|
def initialize(*args)
|
@@ -120,7 +126,7 @@ module Authlogic
|
|
120
126
|
end
|
121
127
|
super
|
122
128
|
end
|
123
|
-
|
129
|
+
|
124
130
|
# Returns the login_field / password_field credentials combination in hash form.
|
125
131
|
def credentials
|
126
132
|
if authenticating_with_password?
|
@@ -132,11 +138,12 @@ module Authlogic
|
|
132
138
|
super
|
133
139
|
end
|
134
140
|
end
|
135
|
-
|
141
|
+
|
136
142
|
# Accepts the login_field / password_field credentials combination in hash form.
|
137
143
|
def credentials=(value)
|
138
144
|
super
|
139
|
-
values = value
|
145
|
+
values = parse_param_val(value) # add strong parameters check
|
146
|
+
|
140
147
|
if values.first.is_a?(Hash)
|
141
148
|
values.first.with_indifferent_access.slice(login_field, password_field).each do |field, value|
|
142
149
|
next if value.blank?
|
@@ -144,18 +151,19 @@ module Authlogic
|
|
144
151
|
end
|
145
152
|
end
|
146
153
|
end
|
147
|
-
|
154
|
+
|
148
155
|
def invalid_password?
|
149
156
|
invalid_password == true
|
150
157
|
end
|
151
|
-
|
158
|
+
|
152
159
|
private
|
160
|
+
|
153
161
|
def configure_password_methods
|
154
162
|
if login_field
|
155
163
|
self.class.send(:attr_writer, login_field) if !respond_to?("#{login_field}=")
|
156
164
|
self.class.send(:attr_reader, login_field) if !respond_to?(login_field)
|
157
165
|
end
|
158
|
-
|
166
|
+
|
159
167
|
if password_field
|
160
168
|
self.class.send(:attr_writer, password_field) if !respond_to?("#{password_field}=")
|
161
169
|
self.class.send(:define_method, password_field) {} if !respond_to?(password_field)
|
@@ -174,16 +182,19 @@ module Authlogic
|
|
174
182
|
def authenticating_with_password?
|
175
183
|
login_field && (!send(login_field).nil? || !send("protected_#{password_field}").nil?)
|
176
184
|
end
|
177
|
-
|
185
|
+
|
178
186
|
def validate_by_password
|
179
187
|
self.invalid_password = false
|
180
|
-
|
188
|
+
|
181
189
|
# check for blank fields
|
182
|
-
|
183
|
-
|
190
|
+
if send(login_field).blank?
|
191
|
+
errors.add(login_field, I18n.t('error_messages.login_blank', :default => "cannot be blank"))
|
192
|
+
end
|
193
|
+
if send("protected_#{password_field}").blank?
|
194
|
+
errors.add(password_field, I18n.t('error_messages.password_blank', :default => "cannot be blank"))
|
195
|
+
end
|
184
196
|
return if errors.count > 0
|
185
197
|
|
186
|
-
# check for unknown login
|
187
198
|
self.attempted_record = search_for_record(find_by_login_method, send(login_field))
|
188
199
|
if attempted_record.blank?
|
189
200
|
generalize_credentials_error_messages? ?
|
@@ -201,19 +212,19 @@ module Authlogic
|
|
201
212
|
return
|
202
213
|
end
|
203
214
|
end
|
204
|
-
|
215
|
+
|
205
216
|
attr_accessor :invalid_password
|
206
|
-
|
217
|
+
|
207
218
|
def find_by_login_method
|
208
219
|
self.class.find_by_login_method
|
209
220
|
end
|
210
|
-
|
221
|
+
|
211
222
|
def login_field
|
212
223
|
self.class.login_field
|
213
224
|
end
|
214
|
-
|
225
|
+
|
215
226
|
def add_general_credentials_error
|
216
|
-
error_message =
|
227
|
+
error_message =
|
217
228
|
if self.class.generalize_credentials_error_messages.is_a? String
|
218
229
|
self.class.generalize_credentials_error_messages
|
219
230
|
else
|
@@ -221,18 +232,29 @@ module Authlogic
|
|
221
232
|
end
|
222
233
|
errors.add(:base, I18n.t('error_messages.general_credentials_error', :default => error_message))
|
223
234
|
end
|
224
|
-
|
235
|
+
|
225
236
|
def generalize_credentials_error_messages?
|
226
237
|
self.class.generalize_credentials_error_messages
|
227
238
|
end
|
228
|
-
|
239
|
+
|
229
240
|
def password_field
|
230
241
|
self.class.password_field
|
231
242
|
end
|
232
|
-
|
243
|
+
|
233
244
|
def verify_password_method
|
234
245
|
self.class.verify_password_method
|
235
246
|
end
|
247
|
+
|
248
|
+
# In Rails 5 the ActionController::Parameters no longer inherits from HashWithIndifferentAccess.
|
249
|
+
# See: http://guides.rubyonrails.org/upgrading_ruby_on_rails.html#actioncontroller-parameters-no-longer-inherits-from-hashwithindifferentaccess
|
250
|
+
# This method converts the ActionController::Parameters to a Hash
|
251
|
+
def parse_param_val(value)
|
252
|
+
if value.first.class.name == "ActionController::Parameters"
|
253
|
+
[value.first.to_h]
|
254
|
+
else
|
255
|
+
value.is_a?(Array) ? value : [value]
|
256
|
+
end
|
257
|
+
end
|
236
258
|
end
|
237
259
|
end
|
238
260
|
end
|
@@ -8,11 +8,12 @@ module Authlogic
|
|
8
8
|
def self.included(klass)
|
9
9
|
klass.after_save :reset_perishable_token!
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
private
|
13
|
+
|
13
14
|
def reset_perishable_token!
|
14
15
|
record.reset_perishable_token if record.respond_to?(:reset_perishable_token) && !record.disable_perishable_token_maintenance?
|
15
16
|
end
|
16
17
|
end
|
17
18
|
end
|
18
|
-
end
|
19
|
+
end
|
@@ -8,7 +8,7 @@ module Authlogic
|
|
8
8
|
include InstanceMethods
|
9
9
|
end
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
module ClassMethods
|
13
13
|
# This is how you persist a session. This finds the record for the current session using
|
14
14
|
# a variety of methods. It basically tries to "log in" the user without the user having
|
@@ -34,7 +34,7 @@ module Authlogic
|
|
34
34
|
#
|
35
35
|
# See the id method for more information on ids.
|
36
36
|
def find(id = nil, priority_record = nil)
|
37
|
-
session = new({:priority_record => priority_record}, id)
|
37
|
+
session = new({ :priority_record => priority_record }, id)
|
38
38
|
session.priority_record = priority_record
|
39
39
|
if session.persisting?
|
40
40
|
session
|
@@ -43,7 +43,7 @@ module Authlogic
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
module InstanceMethods
|
48
48
|
# Let's you know if the session is being persisted or not, meaning the user does not have to explicitly log in
|
49
49
|
# in order to be logged in. If the session has no associated record, it will try to find a record and persist
|
@@ -9,7 +9,7 @@ module Authlogic
|
|
9
9
|
attr_accessor :priority_record
|
10
10
|
end
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
# Setting priority record if it is passed. The only way it can be passed is through an array:
|
14
14
|
#
|
15
15
|
# session.credentials = [real_user_object, priority_user_object]
|
@@ -18,17 +18,18 @@ module Authlogic
|
|
18
18
|
values = value.is_a?(Array) ? value : [value]
|
19
19
|
self.priority_record = values[1] if values[1].class < ::ActiveRecord::Base
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
private
|
23
|
+
|
23
24
|
def attempted_record=(value)
|
24
25
|
value = priority_record if value == priority_record
|
25
26
|
super
|
26
27
|
end
|
27
|
-
|
28
|
+
|
28
29
|
def save_record(alternate_record = nil)
|
29
30
|
r = alternate_record || record
|
30
31
|
super if r != priority_record
|
31
32
|
end
|
32
33
|
end
|
33
34
|
end
|
34
|
-
end
|
35
|
+
end
|
@@ -2,10 +2,13 @@ require 'request_store'
|
|
2
2
|
|
3
3
|
module Authlogic
|
4
4
|
module Session
|
5
|
-
# Authentication can be scoped, and it's easy, you just need to define how you want to
|
5
|
+
# Authentication can be scoped, and it's easy, you just need to define how you want to
|
6
|
+
# scope everything. This should help you:
|
6
7
|
#
|
7
|
-
# 1. Want to scope by a parent object? Ex: An account has many users.
|
8
|
-
#
|
8
|
+
# 1. Want to scope by a parent object? Ex: An account has many users.
|
9
|
+
# Checkout Authlogic::AuthenticatesMany
|
10
|
+
# 2. Want to scope the validations in your model? Ex: 2 users can have the same login
|
11
|
+
# under different accounts. See Authlogic::ActsAsAuthentic::Scope
|
9
12
|
module Scopes # :nodoc:
|
10
13
|
def self.included(klass)
|
11
14
|
klass.class_eval do
|
@@ -22,11 +25,15 @@ module Authlogic
|
|
22
25
|
RequestStore.store[:authlogic_scope]
|
23
26
|
end
|
24
27
|
|
25
|
-
# What with_scopes focuses on is scoping the query when finding the object and the
|
26
|
-
#
|
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:
|
27
32
|
#
|
28
|
-
# * <tt>find_options:</tt> any options you can pass into ActiveRecord::Base.find.
|
29
|
-
#
|
33
|
+
# * <tt>find_options:</tt> any options you can pass into ActiveRecord::Base.find.
|
34
|
+
# This is used when trying to find the record.
|
35
|
+
# * <tt>id:</tt> The id of the session, this gets merged with the real id. For
|
36
|
+
# information ids see the id method.
|
30
37
|
#
|
31
38
|
# Here is how you use it:
|
32
39
|
#
|
@@ -34,7 +41,8 @@ module Authlogic
|
|
34
41
|
# UserSession.find
|
35
42
|
# end
|
36
43
|
#
|
37
|
-
#
|
44
|
+
# Essentially what the above does is scope the searching of the object with the
|
45
|
+
# sql you provided. So instead of:
|
38
46
|
#
|
39
47
|
# User.where("login = 'ben'").first
|
40
48
|
#
|
@@ -42,7 +50,8 @@ module Authlogic
|
|
42
50
|
#
|
43
51
|
# User.where("login = 'ben' and account_id = 2").first
|
44
52
|
#
|
45
|
-
# You will also notice the :id option. This works just like the id method. It
|
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:
|
46
55
|
#
|
47
56
|
# account_2_user_credentials
|
48
57
|
#
|
@@ -69,6 +78,7 @@ module Authlogic
|
|
69
78
|
end
|
70
79
|
|
71
80
|
private
|
81
|
+
|
72
82
|
def scope=(value)
|
73
83
|
RequestStore.store[:authlogic_scope] = value
|
74
84
|
end
|
@@ -87,6 +97,7 @@ module Authlogic
|
|
87
97
|
end
|
88
98
|
|
89
99
|
private
|
100
|
+
|
90
101
|
# Used for things like cookie_key, session_key, etc.
|
91
102
|
def build_key(last_part)
|
92
103
|
[scope[:id], super].compact.join("_")
|
@@ -28,12 +28,14 @@ module Authlogic
|
|
28
28
|
# Instance methods for the session feature.
|
29
29
|
module InstanceMethods
|
30
30
|
private
|
31
|
+
|
31
32
|
# Tries to validate the session from information in the session
|
32
33
|
def persist_by_session
|
33
34
|
persistence_token, record_id = session_credentials
|
34
35
|
if !persistence_token.nil?
|
35
|
-
# Allow finding by persistence token, because when records are created the
|
36
|
-
#
|
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.
|
37
39
|
record = record_id.nil? ?
|
38
40
|
search_for_record("find_by_persistence_token", persistence_token.to_s) :
|
39
41
|
search_for_record("find_by_#{klass.primary_key}", record_id.to_s)
|
@@ -45,7 +47,10 @@ module Authlogic
|
|
45
47
|
end
|
46
48
|
|
47
49
|
def session_credentials
|
48
|
-
[
|
50
|
+
[
|
51
|
+
controller.session[session_key],
|
52
|
+
controller.session["#{session_key}_#{klass.primary_key}"]
|
53
|
+
].collect { |i| i.nil? ? i : i.to_s }.compact
|
49
54
|
end
|
50
55
|
|
51
56
|
def session_key
|
@@ -59,4 +64,4 @@ module Authlogic
|
|
59
64
|
end
|
60
65
|
end
|
61
66
|
end
|
62
|
-
end
|
67
|
+
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
module Authlogic
|
2
2
|
module Session
|
3
|
-
# Think about financial websites, if you are inactive for a certain period
|
4
|
-
# log back in on your next request. You can do
|
3
|
+
# Think about financial websites, if you are inactive for a certain period
|
4
|
+
# of time you will be asked to log back in on your next request. You can do
|
5
|
+
# this with Authlogic easily, there are 2 parts to this:
|
5
6
|
#
|
6
7
|
# 1. Define the timeout threshold:
|
7
8
|
#
|
@@ -15,9 +16,10 @@ module Authlogic
|
|
15
16
|
# logout_on_timeout true # default if false
|
16
17
|
# end
|
17
18
|
#
|
18
|
-
# This will require a user to log back in if they are inactive for more than
|
19
|
-
# this feature to be used you must have a
|
20
|
-
# you are
|
19
|
+
# This will require a user to log back in if they are inactive for more than
|
20
|
+
# 10 minutes. In order for this feature to be used you must have a
|
21
|
+
# last_request_at datetime column in your table for whatever model you are
|
22
|
+
# authenticating with.
|
21
23
|
module Timeout
|
22
24
|
def self.included(klass)
|
23
25
|
klass.class_eval do
|
@@ -28,22 +30,33 @@ module Authlogic
|
|
28
30
|
attr_accessor :stale_record
|
29
31
|
end
|
30
32
|
end
|
31
|
-
|
33
|
+
|
32
34
|
# Configuration for the timeout feature.
|
33
35
|
module Config
|
34
|
-
# With acts_as_authentic you get a :logged_in_timeout configuration
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
36
|
+
# With acts_as_authentic you get a :logged_in_timeout configuration
|
37
|
+
# option. If this is set, after this amount of time has passed the user
|
38
|
+
# will be marked as logged out. Obviously, since web based apps are on a
|
39
|
+
# per request basis, we have to define a time limit threshold that
|
40
|
+
# determines when we consider a user to be "logged out". Meaning, if
|
41
|
+
# they login and then leave the website, when do mark them as logged
|
42
|
+
# out? I recommend just using this as a fun feature on your website or
|
43
|
+
# reports, giving you a ballpark number of users logged in and active.
|
44
|
+
# This is not meant to be a dead accurate representation of a users
|
45
|
+
# logged in state, since there is really no real way to do this with web
|
46
|
+
# based apps. Think about a user that logs in and doesn't log out. There
|
47
|
+
# is no action that tells you that the user isn't technically still
|
48
|
+
# logged in and active.
|
41
49
|
#
|
42
|
-
# That being said, you can use that feature to require a new login if
|
43
|
-
#
|
50
|
+
# That being said, you can use that feature to require a new login if
|
51
|
+
# their session times out. Similar to how financial sites work. Just set
|
52
|
+
# this option to true and if your record returns true for stale? then
|
53
|
+
# they will be required to log back in.
|
44
54
|
#
|
45
|
-
# Lastly, UserSession.find will still return a object is the session is
|
46
|
-
#
|
55
|
+
# Lastly, UserSession.find will still return a object is the session is
|
56
|
+
# stale, but you will not get a record. This allows you to determine if
|
57
|
+
# the user needs to log back in because their session went stale, or
|
58
|
+
# because they just aren't logged in. Just call
|
59
|
+
# current_user_session.stale? as your flag.
|
47
60
|
#
|
48
61
|
# * <tt>Default:</tt> false
|
49
62
|
# * <tt>Accepts:</tt> Boolean
|
@@ -52,11 +65,14 @@ module Authlogic
|
|
52
65
|
end
|
53
66
|
alias_method :logout_on_timeout=, :logout_on_timeout
|
54
67
|
end
|
55
|
-
|
68
|
+
|
56
69
|
# Instance methods for the timeout feature.
|
57
70
|
module InstanceMethods
|
58
|
-
# Tells you if the record is stale or not. Meaning the record has timed
|
59
|
-
#
|
71
|
+
# Tells you if the record is stale or not. Meaning the record has timed
|
72
|
+
# out. This will only return true if you set logout_on_timeout to true
|
73
|
+
# in your configuration. Basically how a bank website works. If you
|
74
|
+
# aren't active over a certain period of time your session becomes stale
|
75
|
+
# and requires you to log back in.
|
60
76
|
def stale?
|
61
77
|
if remember_me?
|
62
78
|
remember_me_expired?
|
@@ -64,19 +80,20 @@ module Authlogic
|
|
64
80
|
!stale_record.nil? || (logout_on_timeout? && record && record.logged_out?)
|
65
81
|
end
|
66
82
|
end
|
67
|
-
|
83
|
+
|
68
84
|
private
|
85
|
+
|
69
86
|
def reset_stale_state
|
70
87
|
self.stale_record = nil
|
71
88
|
end
|
72
|
-
|
89
|
+
|
73
90
|
def enforce_timeout
|
74
91
|
if stale?
|
75
92
|
self.stale_record = record
|
76
93
|
self.record = nil
|
77
94
|
end
|
78
95
|
end
|
79
|
-
|
96
|
+
|
80
97
|
def logout_on_timeout?
|
81
98
|
self.class.logout_on_timeout == true
|
82
99
|
end
|