authlogic 3.4.6 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rubocop.yml +33 -0
  4. data/.rubocop_todo.yml +427 -0
  5. data/.travis.yml +24 -3
  6. data/CHANGELOG.md +9 -2
  7. data/CONTRIBUTING.md +40 -1
  8. data/Gemfile +1 -1
  9. data/README.md +295 -0
  10. data/Rakefile +10 -2
  11. data/authlogic.gemspec +6 -5
  12. data/lib/authlogic.rb +2 -2
  13. data/lib/authlogic/acts_as_authentic/base.rb +2 -2
  14. data/lib/authlogic/acts_as_authentic/email.rb +59 -14
  15. data/lib/authlogic/acts_as_authentic/logged_in_status.rb +4 -3
  16. data/lib/authlogic/acts_as_authentic/login.rb +62 -12
  17. data/lib/authlogic/acts_as_authentic/magic_columns.rb +17 -6
  18. data/lib/authlogic/acts_as_authentic/password.rb +107 -53
  19. data/lib/authlogic/acts_as_authentic/persistence_token.rb +10 -9
  20. data/lib/authlogic/acts_as_authentic/restful_authentication.rb +2 -0
  21. data/lib/authlogic/acts_as_authentic/session_maintenance.rb +48 -35
  22. data/lib/authlogic/acts_as_authentic/single_access_token.rb +19 -15
  23. data/lib/authlogic/acts_as_authentic/validations_scope.rb +2 -2
  24. data/lib/authlogic/authenticates_many/association.rb +6 -5
  25. data/lib/authlogic/authenticates_many/base.rb +22 -12
  26. data/lib/authlogic/config.rb +2 -1
  27. data/lib/authlogic/controller_adapters/abstract_adapter.rb +2 -1
  28. data/lib/authlogic/controller_adapters/rack_adapter.rb +3 -4
  29. data/lib/authlogic/controller_adapters/rails_adapter.rb +26 -14
  30. data/lib/authlogic/controller_adapters/sinatra_adapter.rb +1 -1
  31. data/lib/authlogic/crypto_providers/aes256.rb +16 -12
  32. data/lib/authlogic/crypto_providers/bcrypt.rb +10 -4
  33. data/lib/authlogic/crypto_providers/md5.rb +7 -7
  34. data/lib/authlogic/crypto_providers/scrypt.rb +10 -2
  35. data/lib/authlogic/crypto_providers/sha1.rb +3 -3
  36. data/lib/authlogic/crypto_providers/sha256.rb +3 -3
  37. data/lib/authlogic/crypto_providers/sha512.rb +4 -4
  38. data/lib/authlogic/crypto_providers/wordpress.rb +13 -13
  39. data/lib/authlogic/i18n.rb +22 -16
  40. data/lib/authlogic/i18n/translator.rb +1 -1
  41. data/lib/authlogic/random.rb +13 -12
  42. data/lib/authlogic/regex.rb +3 -3
  43. data/lib/authlogic/session/activation.rb +7 -6
  44. data/lib/authlogic/session/active_record_trickery.rb +1 -2
  45. data/lib/authlogic/session/base.rb +7 -6
  46. data/lib/authlogic/session/brute_force_protection.rb +58 -34
  47. data/lib/authlogic/session/callbacks.rb +16 -12
  48. data/lib/authlogic/session/cookies.rb +29 -14
  49. data/lib/authlogic/session/existence.rb +10 -10
  50. data/lib/authlogic/session/foundation.rb +11 -7
  51. data/lib/authlogic/session/http_auth.rb +6 -5
  52. data/lib/authlogic/session/id.rb +5 -4
  53. data/lib/authlogic/session/klass.rb +2 -1
  54. data/lib/authlogic/session/magic_columns.rb +21 -14
  55. data/lib/authlogic/session/magic_states.rb +25 -14
  56. data/lib/authlogic/session/params.rb +41 -26
  57. data/lib/authlogic/session/password.rb +62 -40
  58. data/lib/authlogic/session/perishable_token.rb +3 -2
  59. data/lib/authlogic/session/persistence.rb +3 -3
  60. data/lib/authlogic/session/priority_record.rb +5 -4
  61. data/lib/authlogic/session/scopes.rb +20 -9
  62. data/lib/authlogic/session/session.rb +9 -4
  63. data/lib/authlogic/session/timeout.rb +40 -23
  64. data/lib/authlogic/session/unauthorized_record.rb +6 -5
  65. data/lib/authlogic/session/validation.rb +18 -9
  66. data/lib/authlogic/test_case.rb +2 -2
  67. data/lib/authlogic/test_case/mock_controller.rb +9 -9
  68. data/lib/authlogic/test_case/mock_cookie_jar.rb +2 -2
  69. data/lib/authlogic/test_case/mock_logger.rb +1 -1
  70. data/lib/authlogic/test_case/mock_request.rb +2 -1
  71. data/lib/authlogic/test_case/rails_request_adapter.rb +5 -5
  72. data/test/acts_as_authentic_test/email_test.rb +29 -17
  73. data/test/acts_as_authentic_test/logged_in_status_test.rb +9 -3
  74. data/test/acts_as_authentic_test/login_test.rb +47 -13
  75. data/test/acts_as_authentic_test/magic_columns_test.rb +4 -4
  76. data/test/acts_as_authentic_test/password_test.rb +31 -21
  77. data/test/acts_as_authentic_test/perishable_token_test.rb +15 -15
  78. data/test/acts_as_authentic_test/session_maintenance_test.rb +20 -13
  79. data/test/acts_as_authentic_test/single_access_test.rb +8 -8
  80. data/test/authenticates_many_test.rb +4 -4
  81. data/test/crypto_provider_test/aes256_test.rb +2 -2
  82. data/test/crypto_provider_test/scrypt_test.rb +1 -1
  83. data/test/crypto_provider_test/sha1_test.rb +3 -3
  84. data/test/crypto_provider_test/sha256_test.rb +1 -1
  85. data/test/crypto_provider_test/sha512_test.rb +2 -2
  86. data/test/gemfiles/Gemfile.rails-3.2.x +2 -2
  87. data/test/gemfiles/Gemfile.rails-5.0.x +6 -0
  88. data/test/i18n_test.rb +5 -5
  89. data/test/libs/affiliate.rb +2 -2
  90. data/test/libs/company.rb +1 -1
  91. data/test/libs/employee.rb +2 -2
  92. data/test/libs/employee_session.rb +1 -1
  93. data/test/libs/ldaper.rb +1 -1
  94. data/test/libs/project.rb +1 -1
  95. data/test/random_test.rb +5 -4
  96. data/test/session_test/activation_test.rb +5 -5
  97. data/test/session_test/active_record_trickery_test.rb +7 -5
  98. data/test/session_test/cookies_test.rb +8 -6
  99. data/test/session_test/existence_test.rb +19 -13
  100. data/test/session_test/http_auth_test.rb +0 -3
  101. data/test/session_test/id_test.rb +2 -2
  102. data/test/session_test/klass_test.rb +1 -1
  103. data/test/session_test/magic_columns_test.rb +0 -3
  104. data/test/session_test/magic_states_test.rb +11 -11
  105. data/test/session_test/params_test.rb +10 -10
  106. data/test/session_test/password_test.rb +4 -5
  107. data/test/session_test/perishability_test.rb +3 -3
  108. data/test/session_test/scopes_test.rb +8 -8
  109. data/test/session_test/session_test.rb +5 -4
  110. data/test/session_test/timeout_test.rb +8 -8
  111. data/test/session_test/unauthorized_record_test.rb +2 -2
  112. data/test/session_test/validation_test.rb +3 -3
  113. data/test/test_helper.rb +9 -5
  114. metadata +54 -24
  115. 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. Set this to the name of the class method
27
- # that does this in the User model. Let's call it "find_by_username_or_email"
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 are all set. You can do anything you
36
- # want here. Maybe you allow users to have multiple logins and you want to search a has_many relationship, etc. The sky is the limit.
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 login attempt occurs.
46
- # When you show error messages for a bad login, it's considered good security practice to hide which field
47
- # the user has entered incorrectly (the login field or the password field). For a full explanation, see
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 / username. Keep in mind this is just for your
83
- # Authlogic::Session, if you want it can be something completely different than the field in your model. So if you wanted people to
84
- # login with a field called "login" and then find users by email this is compeltely doable. See the find_by_login_method configuration
85
- # option for more details.
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.is_a?(Array) ? value : [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
- errors.add(login_field, I18n.t('error_messages.login_blank', :default => "cannot be blank")) if send(login_field).blank?
183
- errors.add(password_field, I18n.t('error_messages.password_blank', :default => "cannot be blank")) if send("protected_#{password_field}").blank?
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 scope everything. This should help you:
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. Checkout Authlogic::AuthenticatesMany
8
- # 2. Want to scope the validations in your model? Ex: 2 users can have the same login under different accounts. See Authlogic::ActsAsAuthentic::Scope
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 name of the cookie / session. It works very similar to
26
- # ActiveRecord::Base#with_scopes. It accepts a hash with any of the following options:
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. This is used when trying to find the record.
29
- # * <tt>id:</tt> The id of the session, this gets merged with the real id. For information ids see the id method.
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
- # Eseentially what the above does is scope the searching of the object with the sql you provided. So instead of:
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 scopes your cookies. So the name of your cookie will be:
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 session is maintained in a before_save, when there is no id.
36
- # This is done for performance reasons and to save on queries.
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
- [controller.session[session_key], controller.session["#{session_key}_#{klass.primary_key}"]].collect { |i| i.nil? ? i : i.to_s }.compact
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 of time you will be asked to
4
- # log back in on your next request. You can do this with Authlogic easily, there are 2 parts to this:
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 10 minutes. In order for
19
- # this feature to be used you must have a last_request_at datetime column in your table for whatever model
20
- # you are authenticating with.
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 option. If this is set, after this amount of time has passed the user
35
- # will be marked as logged out. Obviously, since web based apps are on a per request basis, we have to define a time limit threshold that
36
- # determines when we consider a user to be "logged out". Meaning, if they login and then leave the website, when do mark them as logged out?
37
- # I recommend just using this as a fun feature on your website or reports, giving you a ballpark number of users logged in and active. This is
38
- # not meant to be a dead accurate representation of a users logged in state, since there is really no real way to do this with web based apps.
39
- # Think about a user that logs in and doesn't log out. There is no action that tells you that the user isn't technically still logged in and
40
- # active.
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 their session timesout. Similar to how financial sites work. Just set this option to
43
- # true and if your record returns true for stale? then they will be required to log back in.
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 stale, but you will not get a record. This allows you to determine if the
46
- # user needs to log back in because their session went stale, or because they just aren't logged in. Just call current_user_session.stale? as your flag.
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 out. This will only return true if you set logout_on_timeout to true in your configuration.
59
- # Basically how a bank website works. If you aren't active over a certain period of time your session becomes stale and requires you to log back in.
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