authlogic 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of authlogic might be problematic. Click here for more details.
- data/CHANGELOG.rdoc +19 -0
- data/Manifest +29 -15
- data/README.rdoc +17 -15
- data/Rakefile +1 -1
- data/authlogic.gemspec +7 -7
- data/lib/authlogic.rb +21 -4
- data/lib/authlogic/controller_adapters/abstract_adapter.rb +19 -4
- data/lib/authlogic/controller_adapters/merb_adapter.rb +0 -27
- data/lib/authlogic/controller_adapters/rails_adapter.rb +0 -14
- data/lib/authlogic/crypto_providers/sha1.rb +24 -0
- data/lib/authlogic/crypto_providers/sha512.rb +30 -0
- data/lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic.rb +89 -0
- data/lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/credentials.rb +144 -0
- data/lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/logged_in.rb +41 -0
- data/lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/persistence.rb +62 -0
- data/lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/session_maintenance.rb +83 -0
- data/lib/authlogic/orm_adapters/active_record_adapter/authenticates_many.rb +58 -0
- data/lib/authlogic/{active_record/scoped_session.rb → session/authenticates_many_association.rb} +12 -3
- data/lib/authlogic/session/base.rb +63 -93
- data/lib/authlogic/session/callbacks.rb +15 -3
- data/lib/authlogic/session/config.rb +130 -26
- data/lib/authlogic/session/cookies.rb +39 -0
- data/lib/authlogic/session/openid.rb +106 -0
- data/lib/authlogic/session/params.rb +28 -0
- data/lib/authlogic/session/session.rb +33 -0
- data/lib/authlogic/testing/shoulda_macros.rb +17 -0
- data/lib/authlogic/version.rb +1 -1
- data/test/fixtures/users.yml +2 -2
- data/{test_libs → test/libs}/aes128_crypto_provider.rb +0 -0
- data/{test_libs → test/libs}/mock_controller.rb +7 -0
- data/{test_libs → test/libs}/mock_cookie_jar.rb +0 -0
- data/{test_libs → test/libs}/mock_request.rb +0 -0
- data/{test_libs → test/libs}/ordered_hash.rb +0 -0
- data/test/orm_adapters_tests/active_record_adapter_tests/acts_as_authentic_test.rb +217 -0
- data/test/orm_adapters_tests/active_record_adapter_tests/authenticates_many_test.rb +32 -0
- data/test/session_tests/active_record_trickery_test.rb +14 -0
- data/test/session_tests/authenticates_many_association_test.rb +20 -0
- data/test/session_tests/base_test.rb +264 -0
- data/test/session_tests/config_test.rb +165 -0
- data/test/session_tests/cookies_test.rb +32 -0
- data/test/session_tests/params_test.rb +16 -0
- data/test/session_tests/scopes_test.rb +60 -0
- data/test/session_tests/session_test.rb +45 -0
- data/test/test_helper.rb +14 -5
- metadata +57 -29
- data/lib/authlogic/active_record/acts_as_authentic.rb +0 -297
- data/lib/authlogic/active_record/authenticates_many.rb +0 -56
- data/lib/authlogic/sha512_crypto_provider.rb +0 -18
- data/test/active_record_acts_as_authentic_test.rb +0 -213
- data/test/active_record_authenticates_many_test.rb +0 -28
- data/test/user_session_active_record_trickery_test.rb +0 -12
- data/test/user_session_base_test.rb +0 -316
- data/test/user_session_config_test.rb +0 -144
- data/test/user_session_scopes_test.rb +0 -19
@@ -1,297 +0,0 @@
|
|
1
|
-
module Authlogic
|
2
|
-
module ActiveRecord # :nodoc:
|
3
|
-
# = Acts As Authentic
|
4
|
-
# Provides the acts_as_authentic method to include in your models to help with authentication. See method below.
|
5
|
-
module ActsAsAuthentic
|
6
|
-
# Call this method in your model to add in basic authentication madness that your authlogic session expects.
|
7
|
-
#
|
8
|
-
# === Methods
|
9
|
-
# For example purposes lets assume you have a User model.
|
10
|
-
#
|
11
|
-
# Class method name Description
|
12
|
-
# User.crypto_provider The class that you set in your :crypto_provider option
|
13
|
-
# User.forget_all! Finds all records, loops through them, and calls forget! on each record. This is paginated to save on memory.
|
14
|
-
# User.unique_token returns unique token generated by your :crypto_provider
|
15
|
-
#
|
16
|
-
# Named Scopes
|
17
|
-
# User.logged_in Find all users who are logged in, based on your :logged_in_timeout option.
|
18
|
-
# User.logged_out Same as above, but logged out.
|
19
|
-
#
|
20
|
-
# Isntace method name
|
21
|
-
# user.password= Method name based on the :password_field option. This is used to set the password. Pass the *raw* password to this.
|
22
|
-
# user.confirm_password= Confirms the password, needed to change the password.
|
23
|
-
# user.valid_password?(pass) Determines if the password passed is valid. The password could be encrypted or raw.
|
24
|
-
# user.reset_password! Basically resets the password to a random password using only letters and numbers.
|
25
|
-
# user.logged_in? Based on the :logged_in_timeout option. Tells you if the user is logged in or not.
|
26
|
-
# user.forget! Changes their remember token, making their cookie and session invalid. A way to log the user out withouth changing their password.
|
27
|
-
#
|
28
|
-
# === Options
|
29
|
-
#
|
30
|
-
# * <tt>session_class:</tt> default: "#{name}Session",
|
31
|
-
# This is the related session class. A lot of the configuration will be based off of the configuration values of this class.
|
32
|
-
#
|
33
|
-
# * <tt>crypto_provider:</tt> default: Authlogic::Sha512CryptoProvider,
|
34
|
-
# This is the class that provides your encryption. By default Authlogic provides its own crypto provider that uses Sha512 encrypton.
|
35
|
-
#
|
36
|
-
# * <tt>login_field:</tt> default: options[:session_class].login_field,
|
37
|
-
# The name of the field used for logging in, this is guess based on what columns are in your db. Only specify if you aren't using:
|
38
|
-
# login, username, or email
|
39
|
-
#
|
40
|
-
# * <tt>login_field_type:</tt> default: options[:login_field] == :email ? :email : :login,
|
41
|
-
# Tells authlogic how to validation the field, what regex to use, etc. If the field name is email it will automatically use email,
|
42
|
-
# otherwise it uses login.
|
43
|
-
#
|
44
|
-
# * <tt>login_field_regex:</tt> default: if email then typical email regex, otherwise typical login regex.
|
45
|
-
# This is used in validates_format_of for the login_field.
|
46
|
-
#
|
47
|
-
# * <tt>login_field_regex_message:</tt> the message to use when the validates_format_of for the login field fails.
|
48
|
-
#
|
49
|
-
# * <tt>password_field:</tt> default: options[:session_class].password_field,
|
50
|
-
# This is the name of the field to set the password, *NOT* the field the encrypted password is stored.
|
51
|
-
#
|
52
|
-
# * <tt>crypted_password_field:</tt> default: depends on which columns are present,
|
53
|
-
# The name of the database field where your encrypted password is stored. If the name of the field is different from any of the following
|
54
|
-
# you need to specify it with this option: crypted_password, encrypted_password, password_hash, pw_hash
|
55
|
-
#
|
56
|
-
# * <tt>password_salt_field:</tt> default: depends on which columns are present,
|
57
|
-
# This is the name of the field in your database that stores your password salt. If the name of the field is different from any of the
|
58
|
-
# following then you need to specify it with this option: password_salt, pw_salt, salt
|
59
|
-
#
|
60
|
-
# * <tt>remember_token_field:</tt> default: options[:session_class].remember_token_field,
|
61
|
-
# This is the name of the field your remember_token is stored. The remember token is a unique token that is stored in the users cookie and
|
62
|
-
# session. This way you have complete control of when session expire and you don't have to change passwords to expire sessions. This also
|
63
|
-
# ensures that stale sessions can not be persisted. By stale, I mean sessions that are logged in using an outdated password. If the name
|
64
|
-
# of the field is anything other than the following you need to specify it with this option: remember_token, remember_key, cookie_token,
|
65
|
-
# cookie_key
|
66
|
-
#
|
67
|
-
# * <tt>scope:</tt> default: nil,
|
68
|
-
# This scopes validations. If all of your users belong to an account you might want to scope everything to the account. Just pass :account_id
|
69
|
-
#
|
70
|
-
# * <tt>logged_in_timeout:</tt> default: 10.minutes,
|
71
|
-
# This is really just a nifty feature to tell if a user is logged in or not. It's based on activity. So if the user in inactive longer than
|
72
|
-
# the value you pass here they are assumed "logged out".
|
73
|
-
#
|
74
|
-
# * <tt>session_ids:</tt> default: [nil],
|
75
|
-
# The sessions that we want to automatically reset when a user is created or updated so you don't have to worry about this. Set to [] to disable.
|
76
|
-
# Should be an array of ids. See the Authlogic::Session documentation for information on ids. The order is important.
|
77
|
-
# The first id should be your main session, the session they need to log into first. This is generally nil. When you don't specify an id
|
78
|
-
# in your session you are really just inexplicitly saying you want to use the id of nil.
|
79
|
-
def acts_as_authentic(options = {})
|
80
|
-
# If we don't have a database, skip all of this, solves initial setup errors
|
81
|
-
begin
|
82
|
-
column_names
|
83
|
-
rescue Exception
|
84
|
-
return
|
85
|
-
end
|
86
|
-
|
87
|
-
# Setup default options
|
88
|
-
begin
|
89
|
-
options[:session_class] ||= "#{name}Session".constantize
|
90
|
-
rescue NameError
|
91
|
-
raise NameError.new("You must create a #{name}Session class before a model can act_as_authentic. If that is not the name of the class pass the class constant via the :session_class option.")
|
92
|
-
end
|
93
|
-
|
94
|
-
options[:crypto_provider] ||= Sha512CryptoProvider
|
95
|
-
options[:crypto_provider_type] ||= options[:crypto_provider].respond_to?(:decrypt) ? :encryption : :hash
|
96
|
-
options[:login_field] ||= options[:session_class].login_field
|
97
|
-
options[:login_field_type] ||= options[:login_field] == :email ? :email : :login
|
98
|
-
options[:password_field] ||= options[:session_class].password_field
|
99
|
-
options[:crypted_password_field] ||=
|
100
|
-
(column_names.include?("crypted_password") && :crypted_password) ||
|
101
|
-
(column_names.include?("encrypted_password") && :encrypted_password) ||
|
102
|
-
(column_names.include?("password_hash") && :password_hash) ||
|
103
|
-
(column_names.include?("pw_hash") && :pw_hash) ||
|
104
|
-
:crypted_password
|
105
|
-
options[:password_salt_field] ||=
|
106
|
-
(column_names.include?("password_salt") && :password_salt) ||
|
107
|
-
(column_names.include?("pw_salt") && :pw_salt) ||
|
108
|
-
(column_names.include?("salt") && :salt) ||
|
109
|
-
:password_salt
|
110
|
-
options[:remember_token_field] ||= options[:session_class].remember_token_field
|
111
|
-
options[:logged_in_timeout] ||= 10.minutes
|
112
|
-
options[:session_ids] ||= [nil]
|
113
|
-
|
114
|
-
# Validations
|
115
|
-
case options[:login_field_type]
|
116
|
-
when :email
|
117
|
-
validates_length_of options[:login_field], :within => 6..100
|
118
|
-
email_name_regex = '[\w\.%\+\-]+'
|
119
|
-
domain_head_regex = '(?:[A-Z0-9\-]+\.)+'
|
120
|
-
domain_tld_regex = '(?:[A-Z]{2}|com|org|net|edu|gov|mil|biz|info|mobi|name|aero|jobs|museum)'
|
121
|
-
options[:login_field_regex] ||= /\A#{email_name_regex}@#{domain_head_regex}#{domain_tld_regex}\z/i
|
122
|
-
options[:login_field_regex_message] ||= "should look like an email address."
|
123
|
-
validates_format_of options[:login_field], :with => options[:login_field_regex], :message => options[:login_field_regex_message]
|
124
|
-
else
|
125
|
-
validates_length_of options[:login_field], :within => 2..100
|
126
|
-
options[:login_field_regex] ||= /\A\w[\w\.\-_@ ]+\z/
|
127
|
-
options[:login_field_regex_message] ||= "use only letters, numbers, spaces, and .-_@ please."
|
128
|
-
validates_format_of options[:login_field], :with => options[:login_field_regex], :message => options[:login_field_regex_message]
|
129
|
-
end
|
130
|
-
|
131
|
-
validates_uniqueness_of options[:login_field], :scope => options[:scope]
|
132
|
-
validates_uniqueness_of options[:remember_token_field]
|
133
|
-
validate :validate_password
|
134
|
-
validates_numericality_of :login_count, :only_integer => :true, :greater_than_or_equal_to => 0, :allow_nil => true if column_names.include?("login_count")
|
135
|
-
|
136
|
-
if column_names.include?("last_request_at")
|
137
|
-
named_scope :logged_in, lambda { {:conditions => ["last_request_at > ?", options[:logged_in_timeout].ago]} }
|
138
|
-
named_scope :logged_out, lambda { {:conditions => ["last_request_at is NULL or last_request_at <= ?", options[:logged_in_timeout].ago]} }
|
139
|
-
end
|
140
|
-
|
141
|
-
before_save :get_session_information, :if => :update_sessions?
|
142
|
-
after_save :maintain_sessions!, :if => :update_sessions?
|
143
|
-
|
144
|
-
# Attributes
|
145
|
-
attr_writer "confirm_#{options[:password_field]}"
|
146
|
-
attr_accessor "tried_to_set_#{options[:password_field]}"
|
147
|
-
|
148
|
-
# Class methods
|
149
|
-
class_eval <<-"end_eval", __FILE__, __LINE__
|
150
|
-
def self.unique_token
|
151
|
-
# Force using the Sha512 because all that we are doing is creating a unique token, a hash is perfect for this
|
152
|
-
Authlogic::Sha512CryptoProvider.encrypt(Time.now.to_s + (1..10).collect{ rand.to_s }.join)
|
153
|
-
end
|
154
|
-
|
155
|
-
def self.crypto_provider
|
156
|
-
#{options[:crypto_provider]}
|
157
|
-
end
|
158
|
-
|
159
|
-
def self.forget_all!
|
160
|
-
# Paginate these to save on memory
|
161
|
-
records = nil
|
162
|
-
i = 0
|
163
|
-
begin
|
164
|
-
records = find(:all, :limit => 50, :offset => i)
|
165
|
-
records.each { |record| record.forget! }
|
166
|
-
i += 50
|
167
|
-
end while !records.blank?
|
168
|
-
end
|
169
|
-
end_eval
|
170
|
-
|
171
|
-
# Instance methods
|
172
|
-
if column_names.include?("last_request_at")
|
173
|
-
class_eval <<-"end_eval", __FILE__, __LINE__
|
174
|
-
def logged_in?
|
175
|
-
!last_request_at.nil? && last_request_at > #{options[:logged_in_timeout].to_i}.seconds.ago
|
176
|
-
end
|
177
|
-
end_eval
|
178
|
-
end
|
179
|
-
|
180
|
-
class_eval <<-"end_eval", __FILE__, __LINE__
|
181
|
-
def #{options[:password_field]}=(pass)
|
182
|
-
return if pass.blank?
|
183
|
-
self.tried_to_set_#{options[:password_field]} = true
|
184
|
-
@#{options[:password_field]} = pass
|
185
|
-
self.#{options[:remember_token_field]} = self.class.unique_token
|
186
|
-
self.#{options[:password_salt_field]} = self.class.unique_token
|
187
|
-
self.#{options[:crypted_password_field]} = crypto_provider.encrypt(@#{options[:password_field]} + #{options[:password_salt_field]})
|
188
|
-
end
|
189
|
-
|
190
|
-
def valid_#{options[:password_field]}?(attempted_password)
|
191
|
-
return false if attempted_password.blank? || #{options[:crypted_password_field]}.blank? || #{options[:password_salt_field]}.blank?
|
192
|
-
attempted_password == #{options[:crypted_password_field]} ||
|
193
|
-
(crypto_provider.respond_to?(:decrypt) && crypto_provider.decrypt(#{options[:crypted_password_field]}) == attempted_password + #{options[:password_salt_field]}) ||
|
194
|
-
(!crypto_provider.respond_to?(:decrypt) && crypto_provider.encrypt(attempted_password + #{options[:password_salt_field]}) == #{options[:crypted_password_field]})
|
195
|
-
end
|
196
|
-
end_eval
|
197
|
-
|
198
|
-
class_eval <<-"end_eval", __FILE__, __LINE__
|
199
|
-
def #{options[:password_field]}; end
|
200
|
-
def confirm_#{options[:password_field]}; end
|
201
|
-
|
202
|
-
def crypto_provider
|
203
|
-
self.class.crypto_provider
|
204
|
-
end
|
205
|
-
|
206
|
-
def forget!
|
207
|
-
self.#{options[:remember_token_field]} = self.class.unique_token
|
208
|
-
save_without_session_maintenance(false)
|
209
|
-
end
|
210
|
-
|
211
|
-
def reset_#{options[:password_field]}!
|
212
|
-
chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
|
213
|
-
newpass = ""
|
214
|
-
1.upto(10) { |i| newpass << chars[rand(chars.size-1)] }
|
215
|
-
self.#{options[:password_field]} = newpass
|
216
|
-
self.confirm_#{options[:password_field]} = newpass
|
217
|
-
save_without_session_maintenance(false)
|
218
|
-
end
|
219
|
-
alias_method :randomize_password!, :reset_password!
|
220
|
-
|
221
|
-
def save_without_session_maintenance(*args)
|
222
|
-
@skip_session_maintenance = true
|
223
|
-
result = save(*args)
|
224
|
-
@skip_session_maintenance = false
|
225
|
-
result
|
226
|
-
end
|
227
|
-
|
228
|
-
protected
|
229
|
-
def update_sessions?
|
230
|
-
!@skip_session_maintenance && #{options[:session_class]}.activated? && !#{options[:session_ids].inspect}.blank? && #{options[:remember_token_field]}_changed?
|
231
|
-
end
|
232
|
-
|
233
|
-
def get_session_information
|
234
|
-
# Need to determine if we are completely logged out, or logged in as another user
|
235
|
-
@_sessions = []
|
236
|
-
@_logged_out = true
|
237
|
-
|
238
|
-
#{options[:session_ids].inspect}.each do |session_id|
|
239
|
-
session = #{options[:session_class]}.find(*[session_id].compact)
|
240
|
-
if session
|
241
|
-
if !session.record.blank?
|
242
|
-
@_logged_out = false
|
243
|
-
@_sessions << session if session.record == self
|
244
|
-
end
|
245
|
-
end
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
def maintain_sessions!
|
250
|
-
if @_logged_out
|
251
|
-
create_session!
|
252
|
-
elsif !@_sessions.blank?
|
253
|
-
update_sessions!
|
254
|
-
end
|
255
|
-
end
|
256
|
-
|
257
|
-
def create_session!
|
258
|
-
# We only want to automatically login into the first session, since this is the main session. The other sessions are sessions
|
259
|
-
# that need to be created after logging into the main session.
|
260
|
-
session_id = #{options[:session_ids].inspect}.first
|
261
|
-
|
262
|
-
# If we are already logged in, ignore this completely. All that we care about is updating ourself.
|
263
|
-
next if #{options[:session_class]}.find(*[session_id].compact)
|
264
|
-
|
265
|
-
# Log me in
|
266
|
-
args = [self, session_id].compact
|
267
|
-
#{options[:session_class]}.create(*args)
|
268
|
-
end
|
269
|
-
|
270
|
-
def update_sessions!
|
271
|
-
# We found sessions above, let's update them with the new info
|
272
|
-
@_sessions.each do |stale_session|
|
273
|
-
stale_session.unauthorized_record = self
|
274
|
-
stale_session.save
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
278
|
-
def tried_to_set_password?
|
279
|
-
tried_to_set_password == true
|
280
|
-
end
|
281
|
-
|
282
|
-
def validate_password
|
283
|
-
if new_record? || tried_to_set_#{options[:password_field]}?
|
284
|
-
if @#{options[:password_field]}.blank?
|
285
|
-
errors.add(:#{options[:password_field]}, "can not be blank")
|
286
|
-
else
|
287
|
-
errors.add(:confirm_#{options[:password_field]}, "did not match") if @confirm_#{options[:password_field]} != @#{options[:password_field]}
|
288
|
-
end
|
289
|
-
end
|
290
|
-
end
|
291
|
-
end_eval
|
292
|
-
end
|
293
|
-
end
|
294
|
-
end
|
295
|
-
end
|
296
|
-
|
297
|
-
ActiveRecord::Base.extend Authlogic::ActiveRecord::ActsAsAuthentic
|
@@ -1,56 +0,0 @@
|
|
1
|
-
module Authlogic
|
2
|
-
module ActiveRecord
|
3
|
-
# = Authenticates Many
|
4
|
-
#
|
5
|
-
# This allows you to scope your authentication. For example, let's say all users belong to an account, you want to make sure only users
|
6
|
-
# that belong to that account can actually login into that account. Simple, just do:
|
7
|
-
#
|
8
|
-
# class Account < ActiveRecord::Base
|
9
|
-
# authenticates_many :user_sessions
|
10
|
-
# end
|
11
|
-
#
|
12
|
-
# Now you can scope sessions just like everything else in ActiveRecord:
|
13
|
-
#
|
14
|
-
# @account.user_sessions.new(*args)
|
15
|
-
# @account.user_sessions.create(*args)
|
16
|
-
# @account.user_sessions.find(*args)
|
17
|
-
# # ... etc
|
18
|
-
#
|
19
|
-
# For more information on scopes check out the scopes section in the README.
|
20
|
-
module AuthenticatesMany
|
21
|
-
# Allows you set essentially set up a relationship with your sessions. See module definition above for more details.
|
22
|
-
#
|
23
|
-
# === Options
|
24
|
-
#
|
25
|
-
# * <tt>session_class:</tt> default: "#{name}Session",
|
26
|
-
# This is the related session class.
|
27
|
-
#
|
28
|
-
# * <tt>relationship_name:</tt> default: options[:session_class].klass_name.underscore.pluralize,
|
29
|
-
# This is the name of the relationship you want to use to scope everything. For example an Account has many Users. There should be a relationship
|
30
|
-
# called :users that you defined with a has_many. The reason we use the relationship is so you don't have to repeat yourself. The relatonship
|
31
|
-
# could have all kinds of custom options. So instead of repeating yourself we essentially use the scope that the relationship creates.
|
32
|
-
#
|
33
|
-
# * <tt>find_options:</tt> default: nil,
|
34
|
-
# By default the find options are created from the relationship you specify with :relationship_name. But if you want to override this and
|
35
|
-
# manually specify find_options you can do it here. Specify options just as you would in ActiveRecord::Base.find.
|
36
|
-
#
|
37
|
-
# * <tt>scope_cookies:</tt> default: false
|
38
|
-
# By the nature of cookies they scope theirself if you are using subdomains to access accounts. If you aren't using subdomains you need to have
|
39
|
-
# separate cookies for each account, assuming a user is logging into mroe than one account. Authlogic can take care of this for you by
|
40
|
-
# prefixing the name of the cookie and sessin with the model id. You just need to tell Authlogic to do this by passing this option.
|
41
|
-
def authenticates_many(name, options = {})
|
42
|
-
options[:session_class] ||= name.to_s.classify.constantize
|
43
|
-
options[:relationship_name] ||= options[:session_class].klass_name.underscore.pluralize
|
44
|
-
class_eval <<-"end_eval", __FILE__, __LINE__
|
45
|
-
def #{name}
|
46
|
-
find_options = #{options[:find_options].inspect} || #{options[:relationship_name]}.scope(:find)
|
47
|
-
find_options.delete_if { |key, value| ![:conditions, :include, :joins].include?(key.to_sym) || value.nil? }
|
48
|
-
@#{name} ||= Authlogic::ActiveRecord::ScopedSession.new(#{options[:session_class]}, find_options, #{options[:scope_cookies] ? "self.class.model_name.underscore + '_' + self.send(self.class.primary_key).to_s" : "nil"})
|
49
|
-
end
|
50
|
-
end_eval
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
ActiveRecord::Base.extend Authlogic::ActiveRecord::AuthenticatesMany
|
@@ -1,18 +0,0 @@
|
|
1
|
-
require "digest/sha2"
|
2
|
-
|
3
|
-
module Authlogic
|
4
|
-
# = Sha512 Crypto Provider
|
5
|
-
#
|
6
|
-
# The acts_as_authentic method allows you to pass a :crypto_provider option. This allows you to use any type of encryption you like. Just create a class with a class level encrypt and decrypt method.
|
7
|
-
# The password will be passed as the single parameter to each of these methods so you can do your magic.
|
8
|
-
#
|
9
|
-
# If you are encrypting via a hash just don't include a decrypt method, since hashes can't be decrypted. Authlogic will notice this adjust accordingly.
|
10
|
-
class Sha512CryptoProvider
|
11
|
-
STRETCHES = 20
|
12
|
-
def self.encrypt(pass)
|
13
|
-
digest = pass
|
14
|
-
STRETCHES.times { digest = Digest::SHA512.hexdigest(digest) }
|
15
|
-
digest
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,213 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
-
|
3
|
-
class ActiveRecordActsAsAuthenticTest < ActiveSupport::TestCase
|
4
|
-
def test_user_validations
|
5
|
-
user = User.new
|
6
|
-
assert !user.valid?
|
7
|
-
assert user.errors.on(:login)
|
8
|
-
assert user.errors.on(:password)
|
9
|
-
|
10
|
-
user.login = "a"
|
11
|
-
assert !user.valid?
|
12
|
-
assert user.errors.on(:login)
|
13
|
-
assert user.errors.on(:password)
|
14
|
-
|
15
|
-
user.login = "%ben*"
|
16
|
-
assert !user.valid?
|
17
|
-
assert user.errors.on(:login)
|
18
|
-
assert user.errors.on(:password)
|
19
|
-
|
20
|
-
user.login = "bjohnson"
|
21
|
-
assert !user.valid?
|
22
|
-
assert user.errors.on(:login)
|
23
|
-
assert user.errors.on(:password)
|
24
|
-
|
25
|
-
user.login = "my login"
|
26
|
-
assert !user.valid?
|
27
|
-
assert !user.errors.on(:login)
|
28
|
-
assert user.errors.on(:password)
|
29
|
-
|
30
|
-
user.password = "my pass"
|
31
|
-
assert !user.valid?
|
32
|
-
assert !user.errors.on(:password)
|
33
|
-
assert user.errors.on(:confirm_password)
|
34
|
-
|
35
|
-
user.confirm_password = "my pizass"
|
36
|
-
assert !user.valid?
|
37
|
-
assert !user.errors.on(:password)
|
38
|
-
assert user.errors.on(:confirm_password)
|
39
|
-
|
40
|
-
user.confirm_password = "my pass"
|
41
|
-
assert user.valid?
|
42
|
-
end
|
43
|
-
|
44
|
-
def test_employee_validations
|
45
|
-
employee = Employee.new
|
46
|
-
employee.password = "pass"
|
47
|
-
employee.confirm_password = "pass"
|
48
|
-
|
49
|
-
assert !employee.valid?
|
50
|
-
assert employee.errors.on(:email)
|
51
|
-
|
52
|
-
employee.email = "fdsf"
|
53
|
-
assert !employee.valid?
|
54
|
-
assert employee.errors.on(:email)
|
55
|
-
|
56
|
-
employee.email = "fake@email.fake"
|
57
|
-
assert !employee.valid?
|
58
|
-
assert employee.errors.on(:email)
|
59
|
-
|
60
|
-
employee.email = "notfake@email.com"
|
61
|
-
assert employee.valid?
|
62
|
-
end
|
63
|
-
|
64
|
-
def test_named_scopes
|
65
|
-
assert_equal 0, User.logged_in.count
|
66
|
-
assert_equal User.count, User.logged_out.count
|
67
|
-
http_basic_auth_for(users(:ben)) { UserSession.find }
|
68
|
-
assert_equal 1, User.logged_in.count
|
69
|
-
assert_equal User.count - 1, User.logged_out.count
|
70
|
-
end
|
71
|
-
|
72
|
-
def test_unique_token
|
73
|
-
assert_equal 128, User.unique_token.length
|
74
|
-
assert_equal 128, Employee.unique_token.length # make sure encryptions use hashes also
|
75
|
-
|
76
|
-
unique_tokens = []
|
77
|
-
1000.times { unique_tokens << User.unique_token }
|
78
|
-
unique_tokens.uniq!
|
79
|
-
|
80
|
-
assert_equal 1000, unique_tokens.size
|
81
|
-
end
|
82
|
-
|
83
|
-
def test_crypto_provider
|
84
|
-
assert_equal Authlogic::Sha512CryptoProvider, User.crypto_provider
|
85
|
-
assert_equal AES128CryptoProvider, Employee.crypto_provider
|
86
|
-
end
|
87
|
-
|
88
|
-
def test_forget_all
|
89
|
-
http_basic_auth_for(users(:ben)) { UserSession.find }
|
90
|
-
http_basic_auth_for(users(:zack)) { UserSession.find(:ziggity_zack) }
|
91
|
-
assert UserSession.find
|
92
|
-
assert UserSession.find(:ziggity_zack)
|
93
|
-
User.forget_all!
|
94
|
-
assert !UserSession.find
|
95
|
-
assert !UserSession.find(:ziggity_zack)
|
96
|
-
end
|
97
|
-
|
98
|
-
def test_logged_in
|
99
|
-
ben = users(:ben)
|
100
|
-
assert !ben.logged_in?
|
101
|
-
http_basic_auth_for(ben) { UserSession.find }
|
102
|
-
assert ben.reload.logged_in?
|
103
|
-
end
|
104
|
-
|
105
|
-
def test_password
|
106
|
-
user = User.new
|
107
|
-
user.password = "sillywilly"
|
108
|
-
assert user.crypted_password
|
109
|
-
assert user.password_salt
|
110
|
-
assert user.remember_token
|
111
|
-
assert_equal true, user.tried_to_set_password
|
112
|
-
assert_equal nil, user.password
|
113
|
-
|
114
|
-
employee = Employee.new
|
115
|
-
employee.password = "awesome"
|
116
|
-
assert employee.crypted_password
|
117
|
-
assert employee.remember_token
|
118
|
-
assert_equal true, employee.tried_to_set_password
|
119
|
-
assert_equal nil, employee.password
|
120
|
-
end
|
121
|
-
|
122
|
-
def test_valid_password
|
123
|
-
ben = users(:ben)
|
124
|
-
assert ben.valid_password?("benrocks")
|
125
|
-
assert ben.valid_password?(ben.crypted_password)
|
126
|
-
|
127
|
-
drew = employees(:drew)
|
128
|
-
assert drew.valid_password?("drewrocks")
|
129
|
-
assert drew.valid_password?(drew.crypted_password)
|
130
|
-
end
|
131
|
-
|
132
|
-
def test_forget
|
133
|
-
ben = users(:ben)
|
134
|
-
zack = users(:zack)
|
135
|
-
http_basic_auth_for(ben) { UserSession.find }
|
136
|
-
http_basic_auth_for(zack) { UserSession.find(:ziggity_zack) }
|
137
|
-
|
138
|
-
assert ben.reload.logged_in?
|
139
|
-
assert zack.reload.logged_in?
|
140
|
-
|
141
|
-
ben.forget!
|
142
|
-
|
143
|
-
assert !UserSession.find
|
144
|
-
assert UserSession.find(:ziggity_zack)
|
145
|
-
end
|
146
|
-
|
147
|
-
def test_reset_password
|
148
|
-
ben = users(:ben)
|
149
|
-
UserSession.create(ben)
|
150
|
-
old_password = ben.crypted_password
|
151
|
-
old_salt = ben.password_salt
|
152
|
-
old_remember_token = ben.remember_token
|
153
|
-
ben.reset_password!
|
154
|
-
ben.reload
|
155
|
-
assert_not_equal old_password, ben.crypted_password
|
156
|
-
assert_not_equal old_salt, ben.password_salt
|
157
|
-
assert_not_equal old_remember_token, ben.remember_token
|
158
|
-
assert !UserSession.find
|
159
|
-
end
|
160
|
-
|
161
|
-
def test_login_after_create
|
162
|
-
assert User.create(:login => "awesome", :password => "saweet", :confirm_password => "saweet")
|
163
|
-
assert UserSession.find
|
164
|
-
end
|
165
|
-
|
166
|
-
def test_update_session_after_password_modify
|
167
|
-
ben = users(:ben)
|
168
|
-
UserSession.create(ben)
|
169
|
-
old_session_key = @controller.session["user_credentials"]
|
170
|
-
old_cookie_key = @controller.cookies["user_credentials"]
|
171
|
-
ben.password = "newpass"
|
172
|
-
ben.confirm_password = "newpass"
|
173
|
-
ben.save
|
174
|
-
assert @controller.session["user_credentials"]
|
175
|
-
assert @controller.cookies["user_credentials"]
|
176
|
-
assert_not_equal @controller.session["user_credentials"], old_session_key
|
177
|
-
assert_not_equal @controller.cookies["user_credentials"], old_cookie_key
|
178
|
-
end
|
179
|
-
|
180
|
-
def test_no_session_update_after_modify
|
181
|
-
ben = users(:ben)
|
182
|
-
UserSession.create(ben)
|
183
|
-
old_session_key = @controller.session["user_credentials"]
|
184
|
-
old_cookie_key = @controller.cookies["user_credentials"]
|
185
|
-
ben.first_name = "Ben"
|
186
|
-
ben.save
|
187
|
-
assert_equal @controller.session["user_credentials"], old_session_key
|
188
|
-
assert_equal @controller.cookies["user_credentials"], old_cookie_key
|
189
|
-
end
|
190
|
-
|
191
|
-
def test_updating_other_user
|
192
|
-
ben = users(:ben)
|
193
|
-
UserSession.create(ben)
|
194
|
-
old_session_key = @controller.session["user_credentials"]
|
195
|
-
old_cookie_key = @controller.cookies["user_credentials"]
|
196
|
-
zack = users(:zack)
|
197
|
-
zack.password = "newpass"
|
198
|
-
zack.confirm_password = "newpass"
|
199
|
-
zack.save
|
200
|
-
assert_equal @controller.session["user_credentials"], old_session_key
|
201
|
-
assert_equal @controller.cookies["user_credentials"], old_cookie_key
|
202
|
-
end
|
203
|
-
|
204
|
-
def test_resetting_password_when_logged_out
|
205
|
-
ben = users(:ben)
|
206
|
-
assert !UserSession.find
|
207
|
-
ben.password = "newpass"
|
208
|
-
ben.confirm_password = "newpass"
|
209
|
-
ben.save
|
210
|
-
assert UserSession.find
|
211
|
-
assert_equal ben, UserSession.find.record
|
212
|
-
end
|
213
|
-
end
|