authlogic 3.8.0 → 6.0.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 +7 -0
- data/lib/authlogic/acts_as_authentic/base.rb +33 -36
- data/lib/authlogic/acts_as_authentic/email.rb +8 -141
- data/lib/authlogic/acts_as_authentic/logged_in_status.rb +17 -10
- data/lib/authlogic/acts_as_authentic/login.rb +14 -165
- data/lib/authlogic/acts_as_authentic/magic_columns.rb +13 -10
- data/lib/authlogic/acts_as_authentic/password.rb +186 -254
- data/lib/authlogic/acts_as_authentic/perishable_token.rb +30 -22
- data/lib/authlogic/acts_as_authentic/persistence_token.rb +19 -18
- data/lib/authlogic/acts_as_authentic/queries/case_sensitivity.rb +53 -0
- data/lib/authlogic/acts_as_authentic/queries/find_with_case.rb +83 -0
- data/lib/authlogic/acts_as_authentic/session_maintenance.rb +94 -62
- data/lib/authlogic/acts_as_authentic/single_access_token.rb +28 -14
- data/lib/authlogic/config.rb +29 -10
- data/lib/authlogic/controller_adapters/abstract_adapter.rb +43 -13
- data/lib/authlogic/controller_adapters/rack_adapter.rb +11 -5
- data/lib/authlogic/controller_adapters/rails_adapter.rb +11 -29
- data/lib/authlogic/controller_adapters/sinatra_adapter.rb +8 -2
- data/lib/authlogic/cookie_credentials.rb +63 -0
- data/lib/authlogic/crypto_providers/bcrypt.rb +24 -18
- data/lib/authlogic/crypto_providers/md5/v2.rb +35 -0
- data/lib/authlogic/crypto_providers/md5.rb +8 -6
- data/lib/authlogic/crypto_providers/scrypt.rb +24 -17
- data/lib/authlogic/crypto_providers/sha1/v2.rb +41 -0
- data/lib/authlogic/crypto_providers/sha1.rb +12 -5
- data/lib/authlogic/crypto_providers/sha256/v2.rb +58 -0
- data/lib/authlogic/crypto_providers/sha256.rb +18 -9
- data/lib/authlogic/crypto_providers/sha512/v2.rb +39 -0
- data/lib/authlogic/crypto_providers/sha512.rb +9 -26
- data/lib/authlogic/crypto_providers.rb +77 -1
- data/lib/authlogic/errors.rb +35 -0
- data/lib/authlogic/i18n/translator.rb +4 -1
- data/lib/authlogic/i18n.rb +29 -20
- data/lib/authlogic/random.rb +12 -28
- data/lib/authlogic/session/base.rb +2087 -33
- data/lib/authlogic/session/magic_column/assigns_last_request_at.rb +46 -0
- data/lib/authlogic/test_case/mock_controller.rb +7 -4
- data/lib/authlogic/test_case/mock_cookie_jar.rb +19 -3
- data/lib/authlogic/test_case/mock_logger.rb +2 -0
- data/lib/authlogic/test_case/mock_request.rb +8 -3
- data/lib/authlogic/test_case/rails_request_adapter.rb +5 -2
- data/lib/authlogic/test_case.rb +74 -2
- data/lib/authlogic/version.rb +22 -0
- data/lib/authlogic.rb +33 -54
- metadata +208 -234
- data/.github/ISSUE_TEMPLATE.md +0 -13
- data/.gitignore +0 -14
- data/.rubocop.yml +0 -33
- data/.rubocop_todo.yml +0 -391
- data/.travis.yml +0 -48
- data/CHANGELOG.md +0 -5
- data/CONTRIBUTING.md +0 -60
- data/Gemfile +0 -5
- data/LICENSE +0 -20
- data/README.md +0 -294
- data/Rakefile +0 -21
- data/authlogic.gemspec +0 -27
- data/lib/authlogic/acts_as_authentic/restful_authentication.rb +0 -70
- data/lib/authlogic/acts_as_authentic/validations_scope.rb +0 -32
- data/lib/authlogic/authenticates_many/association.rb +0 -50
- data/lib/authlogic/authenticates_many/base.rb +0 -65
- data/lib/authlogic/crypto_providers/aes256.rb +0 -66
- data/lib/authlogic/crypto_providers/wordpress.rb +0 -43
- data/lib/authlogic/regex.rb +0 -48
- data/lib/authlogic/session/activation.rb +0 -70
- data/lib/authlogic/session/active_record_trickery.rb +0 -61
- data/lib/authlogic/session/brute_force_protection.rb +0 -120
- data/lib/authlogic/session/callbacks.rb +0 -105
- data/lib/authlogic/session/cookies.rb +0 -244
- data/lib/authlogic/session/existence.rb +0 -93
- data/lib/authlogic/session/foundation.rb +0 -55
- data/lib/authlogic/session/http_auth.rb +0 -100
- data/lib/authlogic/session/id.rb +0 -48
- data/lib/authlogic/session/klass.rb +0 -70
- data/lib/authlogic/session/magic_columns.rb +0 -116
- data/lib/authlogic/session/magic_states.rb +0 -76
- data/lib/authlogic/session/params.rb +0 -116
- data/lib/authlogic/session/password.rb +0 -308
- data/lib/authlogic/session/perishable_token.rb +0 -23
- data/lib/authlogic/session/persistence.rb +0 -71
- data/lib/authlogic/session/priority_record.rb +0 -35
- data/lib/authlogic/session/scopes.rb +0 -119
- data/lib/authlogic/session/session.rb +0 -67
- data/lib/authlogic/session/timeout.rb +0 -103
- data/lib/authlogic/session/unauthorized_record.rb +0 -51
- data/lib/authlogic/session/validation.rb +0 -93
- data/test/acts_as_authentic_test/base_test.rb +0 -25
- data/test/acts_as_authentic_test/email_test.rb +0 -240
- data/test/acts_as_authentic_test/logged_in_status_test.rb +0 -62
- data/test/acts_as_authentic_test/login_test.rb +0 -156
- data/test/acts_as_authentic_test/magic_columns_test.rb +0 -27
- data/test/acts_as_authentic_test/password_test.rb +0 -249
- data/test/acts_as_authentic_test/perishable_token_test.rb +0 -90
- data/test/acts_as_authentic_test/persistence_token_test.rb +0 -56
- data/test/acts_as_authentic_test/restful_authentication_test.rb +0 -37
- data/test/acts_as_authentic_test/session_maintenance_test.rb +0 -96
- data/test/acts_as_authentic_test/single_access_test.rb +0 -44
- data/test/authenticates_many_test.rb +0 -31
- data/test/config_test.rb +0 -36
- data/test/crypto_provider_test/aes256_test.rb +0 -14
- data/test/crypto_provider_test/bcrypt_test.rb +0 -14
- data/test/crypto_provider_test/scrypt_test.rb +0 -14
- data/test/crypto_provider_test/sha1_test.rb +0 -23
- data/test/crypto_provider_test/sha256_test.rb +0 -14
- data/test/crypto_provider_test/sha512_test.rb +0 -14
- data/test/fixtures/companies.yml +0 -5
- data/test/fixtures/employees.yml +0 -17
- data/test/fixtures/projects.yml +0 -3
- data/test/fixtures/users.yml +0 -41
- 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
- data/test/gemfiles/Gemfile.rails-4.2.x +0 -7
- data/test/gemfiles/Gemfile.rails-5.0.x +0 -6
- data/test/gemfiles/Gemfile.rails-5.1.x +0 -6
- data/test/gemfiles/Gemfile.rails-5.2.x +0 -6
- data/test/i18n/lol.yml +0 -4
- data/test/i18n_test.rb +0 -33
- data/test/libs/affiliate.rb +0 -7
- data/test/libs/company.rb +0 -6
- data/test/libs/employee.rb +0 -7
- data/test/libs/employee_session.rb +0 -2
- data/test/libs/ldaper.rb +0 -3
- data/test/libs/project.rb +0 -3
- data/test/libs/user.rb +0 -7
- data/test/libs/user_session.rb +0 -25
- data/test/random_test.rb +0 -43
- data/test/session_test/activation_test.rb +0 -43
- data/test/session_test/active_record_trickery_test.rb +0 -75
- data/test/session_test/brute_force_protection_test.rb +0 -108
- data/test/session_test/callbacks_test.rb +0 -34
- data/test/session_test/cookies_test.rb +0 -201
- data/test/session_test/credentials_test.rb +0 -0
- data/test/session_test/existence_test.rb +0 -75
- data/test/session_test/foundation_test.rb +0 -6
- data/test/session_test/http_auth_test.rb +0 -56
- data/test/session_test/id_test.rb +0 -17
- data/test/session_test/klass_test.rb +0 -40
- data/test/session_test/magic_columns_test.rb +0 -62
- data/test/session_test/magic_states_test.rb +0 -58
- data/test/session_test/params_test.rb +0 -53
- data/test/session_test/password_test.rb +0 -105
- data/test/session_test/perishability_test.rb +0 -15
- data/test/session_test/persistence_test.rb +0 -32
- data/test/session_test/scopes_test.rb +0 -60
- data/test/session_test/session_test.rb +0 -78
- data/test/session_test/timeout_test.rb +0 -82
- data/test/session_test/unauthorized_record_test.rb +0 -13
- data/test/session_test/validation_test.rb +0 -23
- data/test/test_helper.rb +0 -233
@@ -1,308 +0,0 @@
|
|
1
|
-
module Authlogic
|
2
|
-
module Session
|
3
|
-
# Handles authenticating via a traditional username and password.
|
4
|
-
module Password
|
5
|
-
def self.included(klass)
|
6
|
-
klass.class_eval do
|
7
|
-
extend Config
|
8
|
-
include InstanceMethods
|
9
|
-
validate :validate_by_password, :if => :authenticating_with_password?
|
10
|
-
|
11
|
-
class << self
|
12
|
-
attr_accessor :configured_password_methods
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
# Password configuration
|
18
|
-
module Config
|
19
|
-
# Authlogic tries to validate the credentials passed to it. One part of
|
20
|
-
# validation is actually finding the user and making sure it exists.
|
21
|
-
# What method it uses the do this is up to you.
|
22
|
-
#
|
23
|
-
# Let's say you have a UserSession that is authenticating a User. By
|
24
|
-
# default UserSession will call User.find_by_login(login). You can
|
25
|
-
# change what method UserSession calls by specifying it here. Then in
|
26
|
-
# your User model you can make that method do anything you want, giving
|
27
|
-
# you complete control of how users are found by the UserSession.
|
28
|
-
#
|
29
|
-
# Let's take an example: You want to allow users to login by username or
|
30
|
-
# email. Set this to the name of the class method that does this in the
|
31
|
-
# User model. Let's call it "find_by_username_or_email"
|
32
|
-
#
|
33
|
-
# class User < ActiveRecord::Base
|
34
|
-
# def self.find_by_username_or_email(login)
|
35
|
-
# find_by_username(login) || find_by_email(login)
|
36
|
-
# end
|
37
|
-
# end
|
38
|
-
#
|
39
|
-
# Now just specify the name of this method for this configuration option
|
40
|
-
# and you are all set. You can do anything you want here. Maybe you
|
41
|
-
# allow users to have multiple logins and you want to search a has_many
|
42
|
-
# relationship, etc. The sky is the limit.
|
43
|
-
#
|
44
|
-
# * <tt>Default:</tt> "find_by_smart_case_login_field"
|
45
|
-
# * <tt>Accepts:</tt> Symbol or String
|
46
|
-
def find_by_login_method(value = nil)
|
47
|
-
rw_config(:find_by_login_method, value, "find_by_smart_case_login_field")
|
48
|
-
end
|
49
|
-
alias_method :find_by_login_method=, :find_by_login_method
|
50
|
-
|
51
|
-
# The text used to identify credentials (username/password) combination
|
52
|
-
# when a bad login attempt occurs. When you show error messages for a
|
53
|
-
# bad login, it's considered good security practice to hide which field
|
54
|
-
# the user has entered incorrectly (the login field or the password
|
55
|
-
# field). For a full explanation, see
|
56
|
-
# http://www.gnucitizen.org/blog/username-enumeration-vulnerabilities/
|
57
|
-
#
|
58
|
-
# Example of use:
|
59
|
-
#
|
60
|
-
# class UserSession < Authlogic::Session::Base
|
61
|
-
# generalize_credentials_error_messages true
|
62
|
-
# end
|
63
|
-
#
|
64
|
-
# This would make the error message for bad logins and bad passwords
|
65
|
-
# look identical:
|
66
|
-
#
|
67
|
-
# Login/Password combination is not valid
|
68
|
-
#
|
69
|
-
# Alternatively you may use a custom message:
|
70
|
-
#
|
71
|
-
# class UserSession < AuthLogic::Session::Base
|
72
|
-
# generalize_credentials_error_messages "Your login information is invalid"
|
73
|
-
# end
|
74
|
-
#
|
75
|
-
# This will instead show your custom error message when the UserSession is invalid.
|
76
|
-
#
|
77
|
-
# The downside to enabling this is that is can be too vague for a user
|
78
|
-
# that has a hard time remembering their username and password
|
79
|
-
# combinations. It also disables the ability to to highlight the field
|
80
|
-
# with the error when you use form_for.
|
81
|
-
#
|
82
|
-
# If you are developing an app where security is an extreme priority
|
83
|
-
# (such as a financial application), then you should enable this.
|
84
|
-
# Otherwise, leaving this off is fine.
|
85
|
-
#
|
86
|
-
# * <tt>Default</tt> false
|
87
|
-
# * <tt>Accepts:</tt> Boolean
|
88
|
-
def generalize_credentials_error_messages(value = nil)
|
89
|
-
rw_config(:generalize_credentials_error_messages, value, false)
|
90
|
-
end
|
91
|
-
alias_method :generalize_credentials_error_messages=, :generalize_credentials_error_messages
|
92
|
-
|
93
|
-
# The name of the method you want Authlogic to create for storing the
|
94
|
-
# login / username. Keep in mind this is just for your
|
95
|
-
# Authlogic::Session, if you want it can be something completely
|
96
|
-
# different than the field in your model. So if you wanted people to
|
97
|
-
# login with a field called "login" and then find users by email this is
|
98
|
-
# completely doable. See the find_by_login_method configuration option
|
99
|
-
# for more details.
|
100
|
-
#
|
101
|
-
# * <tt>Default:</tt> klass.login_field || klass.email_field
|
102
|
-
# * <tt>Accepts:</tt> Symbol or String
|
103
|
-
def login_field(value = nil)
|
104
|
-
rw_config(:login_field, value, klass.login_field || klass.email_field)
|
105
|
-
end
|
106
|
-
alias_method :login_field=, :login_field
|
107
|
-
|
108
|
-
# Works exactly like login_field, but for the password instead. Returns
|
109
|
-
# :password if a login_field exists.
|
110
|
-
#
|
111
|
-
# * <tt>Default:</tt> :password
|
112
|
-
# * <tt>Accepts:</tt> Symbol or String
|
113
|
-
def password_field(value = nil)
|
114
|
-
rw_config(:password_field, value, login_field && :password)
|
115
|
-
end
|
116
|
-
alias_method :password_field=, :password_field
|
117
|
-
|
118
|
-
# The name of the method in your model used to verify the password. This
|
119
|
-
# should be an instance method. It should also be prepared to accept a
|
120
|
-
# raw password and a crytped password.
|
121
|
-
#
|
122
|
-
# * <tt>Default:</tt> "valid_password?"
|
123
|
-
# * <tt>Accepts:</tt> Symbol or String
|
124
|
-
def verify_password_method(value = nil)
|
125
|
-
rw_config(:verify_password_method, value, "valid_password?")
|
126
|
-
end
|
127
|
-
alias_method :verify_password_method=, :verify_password_method
|
128
|
-
end
|
129
|
-
|
130
|
-
# Password-related instance methods
|
131
|
-
module InstanceMethods
|
132
|
-
E_AC_PARAMETERS = <<-STR.strip_heredoc.freeze
|
133
|
-
You have passed an ActionController::Parameters to Authlogic 3. That's
|
134
|
-
OK for now, but in Authlogic 4, it will raise an error. Please
|
135
|
-
replace:
|
136
|
-
|
137
|
-
UserSession.new(user_session_params)
|
138
|
-
UserSession.create(user_session_params)
|
139
|
-
|
140
|
-
with
|
141
|
-
|
142
|
-
UserSession.new(user_session_params.to_h)
|
143
|
-
UserSession.create(user_session_params.to_h)
|
144
|
-
|
145
|
-
And don't forget to `permit`!
|
146
|
-
|
147
|
-
During the transition of rails to Strong Parameters, it has been
|
148
|
-
common for Authlogic users to forget to `permit` their params. They
|
149
|
-
would pass their params into Authlogic, we'd call `to_h`, and they'd
|
150
|
-
be surprised when authentication failed.
|
151
|
-
|
152
|
-
In 2018, people are still making this mistake. We'd like to help them
|
153
|
-
and make authlogic a little simpler at the same time, so in Authlogic
|
154
|
-
3.7.0, we deprecated the use of ActionController::Parameters.
|
155
|
-
|
156
|
-
We discussed this issue thoroughly between late 2016 and early
|
157
|
-
2018. Notable discussions include:
|
158
|
-
|
159
|
-
- https://github.com/binarylogic/authlogic/issues/512
|
160
|
-
- https://github.com/binarylogic/authlogic/pull/558
|
161
|
-
- https://github.com/binarylogic/authlogic/pull/577
|
162
|
-
STR
|
163
|
-
|
164
|
-
def initialize(*args)
|
165
|
-
if !self.class.configured_password_methods
|
166
|
-
configure_password_methods
|
167
|
-
self.class.configured_password_methods = true
|
168
|
-
end
|
169
|
-
super
|
170
|
-
end
|
171
|
-
|
172
|
-
# Returns the login_field / password_field credentials combination in
|
173
|
-
# hash form.
|
174
|
-
def credentials
|
175
|
-
if authenticating_with_password?
|
176
|
-
details = {}
|
177
|
-
details[login_field.to_sym] = send(login_field)
|
178
|
-
details[password_field.to_sym] = "<protected>"
|
179
|
-
details
|
180
|
-
else
|
181
|
-
super
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
# Accepts the login_field / password_field credentials combination in
|
186
|
-
# hash form.
|
187
|
-
def credentials=(value)
|
188
|
-
super
|
189
|
-
values = parse_param_val(value) # add strong parameters check
|
190
|
-
|
191
|
-
if values.first.is_a?(Hash)
|
192
|
-
values.first.with_indifferent_access.slice(login_field, password_field).each do |field, value|
|
193
|
-
next if value.blank?
|
194
|
-
send("#{field}=", value)
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
def invalid_password?
|
200
|
-
invalid_password == true
|
201
|
-
end
|
202
|
-
|
203
|
-
private
|
204
|
-
|
205
|
-
def configure_password_methods
|
206
|
-
if login_field
|
207
|
-
self.class.send(:attr_writer, login_field) if !respond_to?("#{login_field}=")
|
208
|
-
self.class.send(:attr_reader, login_field) if !respond_to?(login_field)
|
209
|
-
end
|
210
|
-
|
211
|
-
if password_field
|
212
|
-
self.class.send(:attr_writer, password_field) if !respond_to?("#{password_field}=")
|
213
|
-
self.class.send(:define_method, password_field) {} if !respond_to?(password_field)
|
214
|
-
|
215
|
-
# The password should not be accessible publicly. This way forms
|
216
|
-
# using form_for don't fill the password with the attempted
|
217
|
-
# password. To prevent this we just create this method that is
|
218
|
-
# private.
|
219
|
-
self.class.class_eval <<-"end_eval", __FILE__, __LINE__
|
220
|
-
private
|
221
|
-
def protected_#{password_field}
|
222
|
-
@#{password_field}
|
223
|
-
end
|
224
|
-
end_eval
|
225
|
-
end
|
226
|
-
end
|
227
|
-
|
228
|
-
def authenticating_with_password?
|
229
|
-
login_field && (!send(login_field).nil? || !send("protected_#{password_field}").nil?)
|
230
|
-
end
|
231
|
-
|
232
|
-
def validate_by_password
|
233
|
-
self.invalid_password = false
|
234
|
-
|
235
|
-
# check for blank fields
|
236
|
-
if send(login_field).blank?
|
237
|
-
errors.add(login_field, I18n.t('error_messages.login_blank', :default => "cannot be blank"))
|
238
|
-
end
|
239
|
-
if send("protected_#{password_field}").blank?
|
240
|
-
errors.add(password_field, I18n.t('error_messages.password_blank', :default => "cannot be blank"))
|
241
|
-
end
|
242
|
-
return if errors.count > 0
|
243
|
-
|
244
|
-
self.attempted_record = search_for_record(find_by_login_method, send(login_field))
|
245
|
-
if attempted_record.blank?
|
246
|
-
generalize_credentials_error_messages? ?
|
247
|
-
add_general_credentials_error :
|
248
|
-
errors.add(login_field, I18n.t('error_messages.login_not_found', :default => "is not valid"))
|
249
|
-
return
|
250
|
-
end
|
251
|
-
|
252
|
-
# check for invalid password
|
253
|
-
if !attempted_record.send(verify_password_method, send("protected_#{password_field}"))
|
254
|
-
self.invalid_password = true
|
255
|
-
generalize_credentials_error_messages? ?
|
256
|
-
add_general_credentials_error :
|
257
|
-
errors.add(password_field, I18n.t('error_messages.password_invalid', :default => "is not valid"))
|
258
|
-
return
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
attr_accessor :invalid_password
|
263
|
-
|
264
|
-
def find_by_login_method
|
265
|
-
self.class.find_by_login_method
|
266
|
-
end
|
267
|
-
|
268
|
-
def login_field
|
269
|
-
self.class.login_field
|
270
|
-
end
|
271
|
-
|
272
|
-
def add_general_credentials_error
|
273
|
-
error_message =
|
274
|
-
if self.class.generalize_credentials_error_messages.is_a? String
|
275
|
-
self.class.generalize_credentials_error_messages
|
276
|
-
else
|
277
|
-
"#{login_field.to_s.humanize}/Password combination is not valid"
|
278
|
-
end
|
279
|
-
errors.add(:base, I18n.t('error_messages.general_credentials_error', :default => error_message))
|
280
|
-
end
|
281
|
-
|
282
|
-
def generalize_credentials_error_messages?
|
283
|
-
self.class.generalize_credentials_error_messages
|
284
|
-
end
|
285
|
-
|
286
|
-
def password_field
|
287
|
-
self.class.password_field
|
288
|
-
end
|
289
|
-
|
290
|
-
def verify_password_method
|
291
|
-
self.class.verify_password_method
|
292
|
-
end
|
293
|
-
|
294
|
-
# In Rails 5 the ActionController::Parameters no longer inherits from HashWithIndifferentAccess.
|
295
|
-
# See: http://guides.rubyonrails.org/upgrading_ruby_on_rails.html#actioncontroller-parameters-no-longer-inherits-from-hashwithindifferentaccess
|
296
|
-
# This method converts the ActionController::Parameters to a Hash
|
297
|
-
def parse_param_val(value)
|
298
|
-
if value.first.class.name == "ActionController::Parameters"
|
299
|
-
ActiveSupport::Deprecation.warn(E_AC_PARAMETERS)
|
300
|
-
[value.first.to_h]
|
301
|
-
else
|
302
|
-
value.is_a?(Array) ? value : [value]
|
303
|
-
end
|
304
|
-
end
|
305
|
-
end
|
306
|
-
end
|
307
|
-
end
|
308
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
module Authlogic
|
2
|
-
module Session
|
3
|
-
# Maintains the perishable token, which is helpful for confirming records or
|
4
|
-
# authorizing records to reset their password. All that this module does is
|
5
|
-
# reset it after a session have been saved, just keep it changing. The more
|
6
|
-
# it changes, the tighter the security.
|
7
|
-
#
|
8
|
-
# See Authlogic::ActsAsAuthentic::PerishableToken for more information.
|
9
|
-
module PerishableToken
|
10
|
-
def self.included(klass)
|
11
|
-
klass.after_save :reset_perishable_token!
|
12
|
-
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
def reset_perishable_token!
|
17
|
-
if record.respond_to?(:reset_perishable_token) && !record.disable_perishable_token_maintenance?
|
18
|
-
record.reset_perishable_token
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,71 +0,0 @@
|
|
1
|
-
module Authlogic
|
2
|
-
module Session
|
3
|
-
# Responsible for allowing you to persist your sessions.
|
4
|
-
module Persistence
|
5
|
-
def self.included(klass)
|
6
|
-
klass.class_eval do
|
7
|
-
extend ClassMethods
|
8
|
-
include InstanceMethods
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
module ClassMethods
|
13
|
-
# This is how you persist a session. This finds the record for the current session using
|
14
|
-
# a variety of methods. It basically tries to "log in" the user without the user having
|
15
|
-
# to explicitly log in. Check out the other Authlogic::Session modules for more information.
|
16
|
-
#
|
17
|
-
# The best way to use this method is something like:
|
18
|
-
#
|
19
|
-
# helper_method :current_user_session, :current_user
|
20
|
-
#
|
21
|
-
# def current_user_session
|
22
|
-
# return @current_user_session if defined?(@current_user_session)
|
23
|
-
# @current_user_session = UserSession.find
|
24
|
-
# end
|
25
|
-
#
|
26
|
-
# def current_user
|
27
|
-
# return @current_user if defined?(@current_user)
|
28
|
-
# @current_user = current_user_session && current_user_session.user
|
29
|
-
# end
|
30
|
-
#
|
31
|
-
# Also, this method accepts a single parameter as the id, to find session that you marked with an id:
|
32
|
-
#
|
33
|
-
# UserSession.find(:secure)
|
34
|
-
#
|
35
|
-
# See the id method for more information on ids.
|
36
|
-
def find(id = nil, priority_record = nil)
|
37
|
-
session = new({ :priority_record => priority_record }, id)
|
38
|
-
session.priority_record = priority_record
|
39
|
-
if session.persisting?
|
40
|
-
session
|
41
|
-
else
|
42
|
-
nil
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
module InstanceMethods
|
48
|
-
# Let's you know if the session is being persisted or not, meaning the user does not have to explicitly log in
|
49
|
-
# in order to be logged in. If the session has no associated record, it will try to find a record and persist
|
50
|
-
# the session. This is the method that the class level method find uses to ultimately persist the session.
|
51
|
-
def persisting?
|
52
|
-
return true if !record.nil?
|
53
|
-
self.attempted_record = nil
|
54
|
-
self.remember_me = !cookie_credentials.nil? && !cookie_credentials[2].nil?
|
55
|
-
before_persisting
|
56
|
-
persist
|
57
|
-
ensure_authentication_attempted
|
58
|
-
if errors.empty? && !attempted_record.nil?
|
59
|
-
self.record = attempted_record
|
60
|
-
after_persisting
|
61
|
-
save_record
|
62
|
-
self.new_session = false
|
63
|
-
true
|
64
|
-
else
|
65
|
-
false
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
module Authlogic
|
2
|
-
module Session
|
3
|
-
# The point of this module is to avoid the StaleObjectError raised when lock_version is implemented in ActiveRecord.
|
4
|
-
# We accomplish this by using a "priority record". Meaning this record is used if possible, it gets priority.
|
5
|
-
# This way we don't save a record behind the scenes thus making an object being used stale.
|
6
|
-
module PriorityRecord
|
7
|
-
def self.included(klass)
|
8
|
-
klass.class_eval do
|
9
|
-
attr_accessor :priority_record
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
# Setting priority record if it is passed. The only way it can be passed is through an array:
|
14
|
-
#
|
15
|
-
# session.credentials = [real_user_object, priority_user_object]
|
16
|
-
def credentials=(value)
|
17
|
-
super
|
18
|
-
values = value.is_a?(Array) ? value : [value]
|
19
|
-
self.priority_record = values[1] if values[1].class < ::ActiveRecord::Base
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def attempted_record=(value)
|
25
|
-
value = priority_record if value == priority_record
|
26
|
-
super
|
27
|
-
end
|
28
|
-
|
29
|
-
def save_record(alternate_record = nil)
|
30
|
-
r = alternate_record || record
|
31
|
-
super if r != priority_record
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,119 +0,0 @@
|
|
1
|
-
require 'request_store'
|
2
|
-
|
3
|
-
module Authlogic
|
4
|
-
module Session
|
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:
|
7
|
-
#
|
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
|
12
|
-
module Scopes # :nodoc:
|
13
|
-
def self.included(klass)
|
14
|
-
klass.class_eval do
|
15
|
-
extend ClassMethods
|
16
|
-
include InstanceMethods
|
17
|
-
attr_writer :scope
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
# = Scopes
|
22
|
-
module ClassMethods
|
23
|
-
# The current scope set, should be used in the block passed to with_scope.
|
24
|
-
def scope
|
25
|
-
RequestStore.store[:authlogic_scope]
|
26
|
-
end
|
27
|
-
|
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:
|
32
|
-
#
|
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.
|
37
|
-
#
|
38
|
-
# Here is how you use it:
|
39
|
-
#
|
40
|
-
# UserSession.with_scope(:find_options => {:conditions => "account_id = 2"}, :id => "account_2") do
|
41
|
-
# UserSession.find
|
42
|
-
# end
|
43
|
-
#
|
44
|
-
# Essentially what the above does is scope the searching of the object with the
|
45
|
-
# sql you provided. So instead of:
|
46
|
-
#
|
47
|
-
# User.where("login = 'ben'").first
|
48
|
-
#
|
49
|
-
# it would be:
|
50
|
-
#
|
51
|
-
# User.where("login = 'ben' and account_id = 2").first
|
52
|
-
#
|
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:
|
55
|
-
#
|
56
|
-
# account_2_user_credentials
|
57
|
-
#
|
58
|
-
# instead of:
|
59
|
-
#
|
60
|
-
# user_credentials
|
61
|
-
#
|
62
|
-
# What is also nifty about scoping with an :id is that it merges your id's. So if you do:
|
63
|
-
#
|
64
|
-
# UserSession.with_scope(:find_options => {:conditions => "account_id = 2"}, :id => "account_2") do
|
65
|
-
# session = UserSession.new
|
66
|
-
# session.id = :secure
|
67
|
-
# end
|
68
|
-
#
|
69
|
-
# The name of your cookies will be:
|
70
|
-
#
|
71
|
-
# secure_account_2_user_credentials
|
72
|
-
def with_scope(options = {}, &block)
|
73
|
-
raise ArgumentError.new("You must provide a block") unless block_given?
|
74
|
-
self.scope = options
|
75
|
-
result = yield
|
76
|
-
self.scope = nil
|
77
|
-
result
|
78
|
-
end
|
79
|
-
|
80
|
-
private
|
81
|
-
|
82
|
-
def scope=(value)
|
83
|
-
RequestStore.store[:authlogic_scope] = value
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
module InstanceMethods
|
88
|
-
# Setting the scope if it exists upon instantiation.
|
89
|
-
def initialize(*args)
|
90
|
-
self.scope = self.class.scope
|
91
|
-
super
|
92
|
-
end
|
93
|
-
|
94
|
-
# The scope of the current object
|
95
|
-
def scope
|
96
|
-
@scope ||= {}
|
97
|
-
end
|
98
|
-
|
99
|
-
private
|
100
|
-
|
101
|
-
# Used for things like cookie_key, session_key, etc.
|
102
|
-
def build_key(last_part)
|
103
|
-
[scope[:id], super].compact.join("_")
|
104
|
-
end
|
105
|
-
|
106
|
-
def search_for_record(*args)
|
107
|
-
session_scope = if scope[:find_options].is_a?(ActiveRecord::Relation)
|
108
|
-
scope[:find_options]
|
109
|
-
else
|
110
|
-
klass.send(:where, scope[:find_options] && scope[:find_options][:conditions] || {})
|
111
|
-
end
|
112
|
-
session_scope.scoping do
|
113
|
-
klass.send(*args)
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
@@ -1,67 +0,0 @@
|
|
1
|
-
module Authlogic
|
2
|
-
module Session
|
3
|
-
# Handles all parts of authentication that deal with sessions. Such as persisting a session and saving / destroy a session.
|
4
|
-
module Session
|
5
|
-
def self.included(klass)
|
6
|
-
klass.class_eval do
|
7
|
-
extend Config
|
8
|
-
include InstanceMethods
|
9
|
-
persist :persist_by_session
|
10
|
-
after_save :update_session
|
11
|
-
after_destroy :update_session
|
12
|
-
after_persisting :update_session, :unless => :single_access?
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
# Configuration for the session feature.
|
17
|
-
module Config
|
18
|
-
# Works exactly like cookie_key, but for sessions. See cookie_key for more info.
|
19
|
-
#
|
20
|
-
# * <tt>Default:</tt> cookie_key
|
21
|
-
# * <tt>Accepts:</tt> Symbol or String
|
22
|
-
def session_key(value = nil)
|
23
|
-
rw_config(:session_key, value, cookie_key)
|
24
|
-
end
|
25
|
-
alias_method :session_key=, :session_key
|
26
|
-
end
|
27
|
-
|
28
|
-
# Instance methods for the session feature.
|
29
|
-
module InstanceMethods
|
30
|
-
private
|
31
|
-
|
32
|
-
# Tries to validate the session from information in the session
|
33
|
-
def persist_by_session
|
34
|
-
persistence_token, record_id = session_credentials
|
35
|
-
if !persistence_token.nil?
|
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.
|
39
|
-
record = record_id.nil? ?
|
40
|
-
search_for_record("find_by_persistence_token", persistence_token.to_s) :
|
41
|
-
search_for_record("find_by_#{klass.primary_key}", record_id.to_s)
|
42
|
-
self.unauthorized_record = record if record && record.persistence_token == persistence_token
|
43
|
-
valid?
|
44
|
-
else
|
45
|
-
false
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def session_credentials
|
50
|
-
[
|
51
|
-
controller.session[session_key],
|
52
|
-
controller.session["#{session_key}_#{klass.primary_key}"]
|
53
|
-
].collect { |i| i.nil? ? i : i.to_s }.compact
|
54
|
-
end
|
55
|
-
|
56
|
-
def session_key
|
57
|
-
build_key(self.class.session_key)
|
58
|
-
end
|
59
|
-
|
60
|
-
def update_session
|
61
|
-
controller.session[session_key] = record && record.persistence_token
|
62
|
-
controller.session["#{session_key}_#{klass.primary_key}"] = record && record.send(record.class.primary_key)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|