authlogic 2.0.5 → 2.0.6
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 -1
- data/README.rdoc +20 -9
- data/lib/authlogic/acts_as_authentic/base.rb +6 -3
- data/lib/authlogic/acts_as_authentic/email.rb +24 -4
- data/lib/authlogic/acts_as_authentic/logged_in_status.rb +19 -13
- data/lib/authlogic/acts_as_authentic/login.rb +34 -2
- data/lib/authlogic/acts_as_authentic/password.rb +114 -81
- data/lib/authlogic/acts_as_authentic/single_access_token.rb +1 -1
- data/lib/authlogic/controller_adapters/rails_adapter.rb +2 -2
- data/lib/authlogic/crypto_providers/aes256.rb +2 -2
- data/lib/authlogic/crypto_providers/bcrypt.rb +3 -1
- data/lib/authlogic/crypto_providers/sha1.rb +2 -2
- data/lib/authlogic/session/active_record_trickery.rb +1 -1
- data/lib/authlogic/session/cookies.rb +6 -4
- data/lib/authlogic/session/password.rb +25 -17
- data/lib/authlogic/session/priority_record.rb +1 -1
- data/lib/authlogic/session/session.rb +1 -1
- data/lib/authlogic/test_case/controller_adapter.rb +2 -3
- data/lib/authlogic/test_case/mock_controller.rb +1 -5
- data/lib/authlogic/test_case/mock_request.rb +13 -1
- data/lib/authlogic/version.rb +1 -1
- data/shoulda_macros/authlogic.rb +2 -1
- data/test/acts_as_authentic_test/base_test.rb +6 -0
- data/test/acts_as_authentic_test/email_test.rb +12 -1
- data/test/acts_as_authentic_test/login_test.rb +12 -1
- data/test/acts_as_authentic_test/password_test.rb +10 -0
- data/test/session_test/active_record_trickery_test.rb +1 -0
- data/test/session_test/cookies_test.rb +1 -1
- metadata +3 -3
data/CHANGELOG.rdoc
CHANGED
@@ -1,6 +1,24 @@
|
|
1
|
+
== 2.0.6
|
2
|
+
|
3
|
+
* Don't use second, use [1] instead so older rails systems don't complain.
|
4
|
+
* Update email regular expression to be less TLD specific: (?:[A-Z]{2,4}|museum|travel)
|
5
|
+
* Update shoulda macro for 2.0
|
6
|
+
* validates_length_of_password_confirmation_field_options defaults to validates_confirmation_of_password_field_options
|
7
|
+
* Use MockCookieJar in tests instead of a Hash.
|
8
|
+
* Cookies now store the record id as well, for faster lookup. Also to avoid the need to use sessions since sessions are lazily loaded in rails 2.3+
|
9
|
+
* Add configuration option for Authlogic::ActsAsAuthentic: ignore_blank_passwords
|
10
|
+
* Fix cookie_domain in rails adapter
|
11
|
+
* Make password and login fields optional. This allows you to have an alternate authentication method as your main authentication source. Such as OpenID, LDAP, or whatever you want.
|
12
|
+
* Reset the @password_changed instance variable after the record has been saved.
|
13
|
+
* Add referer and user_agent to mock requests for testing purposes.
|
14
|
+
* Add :case_sensitive => false to validates_uniqueness_of calls on the login and email fields.
|
15
|
+
* MockRequest not tries to use controller.env['REMOTE_ADDR'] for the IP address in tests.
|
16
|
+
* Add in custom find_with_email and find_with_login methods to perform case insensitive searches for databases that are case sensitive by default. This is only done if the :case_insensitive option for validates_uniqueness_of_login_field_options or validates_uniqueness_of_email_field_options is set to false. Which, as of this version, it is. If you are using MySQL this has been the default behavior all along. If you are using SQLite or Postgres this has NOT been the default behavior.
|
17
|
+
* Added in exception explaining that you are using the old configuration for acts_as_authentic with an example of the new format.
|
18
|
+
|
1
19
|
== 2.0.5 released 2009-3-30
|
2
20
|
|
3
|
-
* Stub out authenticate_with_http_basic for TestCase::
|
21
|
+
* Stub out authenticate_with_http_basic for TestCase::ControllerAdapter.
|
4
22
|
* Added second parameter for add_acts_as_authentic module to specify the position: append or prepend.
|
5
23
|
|
6
24
|
== 2.0.4 released 2009-3-28
|
data/README.rdoc
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Authlogic is a clean, simple, and unobtrusive ruby authentication solution.
|
4
4
|
|
5
|
-
What inspired me to create Authlogic was the messiness of the current authentication solutions. Put simply, they just didn't feel right
|
5
|
+
What inspired me to create Authlogic was the messiness of the current authentication solutions. Put simply, they just didn't feel right, because the logic was not organized properly. As you may know, a common misconception with the MVC design pattern is that the model "M" is only for data access logic, which is wrong. A model is a place for domain logic. This is why the RESTful design pattern and the current authentication solutions don't play nice. Authlogic solves this by placing the session maintenance logic into its own domain (aka "model"). Moving session maintenance into its own domain has its benefits:
|
6
6
|
|
7
|
-
1. It's easier to update and stay current with the latest security practices. Since authlogic sits in between you and your session it can assist in keeping your security
|
7
|
+
1. It's easier to update and stay current with the latest security practices. Since authlogic sits in between you and your session it can assist in keeping your security up to date. For example: upgrading your hashing algorithm, helping you transition to a new algorithm, etc. Since all of this logic is in the Authlogic library, staying up to date is as easy as updating the library.
|
8
8
|
2. It ties everything together on the domain level. Take a new user registration for example, no reason to manually log the user in, authlogic handles this for you via callbacks. The same applies to a user changing their password. Authlogic handles maintaining the session for you.
|
9
|
-
3. Your application can stay clean
|
9
|
+
3. Your application can stay clean, focused, and free of redundant authentication code from app to app. Meaning generators are *NOT* necessary. Not any more neccessary than any other control
|
10
10
|
4. A byproduct of #3 is that you don't have to test the same code over and over in each of your apps. You don't test the internals of ActiveRecord in each of your apps, so why would you test the internals of Authlogic? It's already been thoroughly tested for you. Focus on your application, and get rid of the noise by testing your application specific code and not generated code that you didn't write.
|
11
11
|
5. You get to write your own code, just like you do for any other model. Meaning the code you write is specific to your application, the way you want it, and more importantly you understand it.
|
12
12
|
6. You are not restricted to a single session. Think about Apple's me.com, where they need you to authenticate a second time before changing your billing information. Why not just create a second session for this? It works just like your initial session. Then your billing controller can require an "ultra secure" session.
|
@@ -16,17 +16,26 @@ Authlogic can do all of this and much more, keep reading to see...
|
|
16
16
|
== Helpful links
|
17
17
|
|
18
18
|
* <b>Documentation:</b> http://authlogic.rubyforge.org
|
19
|
+
* <b>Live example with OpenID "add on" & source code:</b> http://authlogicexample.binarylogic.com
|
19
20
|
* <b>Tutorial: Authlogic basic setup:</b> http://www.binarylogic.com/2008/11/3/tutorial-authlogic-basic-setup
|
20
21
|
* <b>Tutorial: Reset passwords with Authlogic the RESTful way:</b> http://www.binarylogic.com/2008/11/16/tutorial-reset-passwords-with-authlogic
|
21
|
-
* <b>Tutorial: Using OpenID with Authlogic:</b> http://www.binarylogic.com/2008/11/21/tutorial-using-openid-with-authlogic
|
22
|
-
* <b>Live example of the tutorials above (with source):</b> http://authlogicexample.binarylogic.com
|
23
22
|
* <b>Tutorial: Easily migrate from restful_authentication:</b> http://www.binarylogic.com/2008/11/23/tutorial-easily-migrate-from-restful_authentication-to-authlogic
|
24
23
|
* <b>Tutorial: Upgrade passwords easily with Authlogic:</b> http://www.binarylogic.com/2008/11/23/tutorial-upgrade-passwords-easily-with-authlogic
|
25
24
|
* <b>Bugs / feature suggestions:</b> http://binarylogic.lighthouseapp.com/projects/18752-authlogic
|
26
25
|
* <b>Google group:</b> http://groups.google.com/group/authlogic
|
27
26
|
|
28
|
-
|
29
|
-
|
27
|
+
<b>Before contacting me, please read:</b>
|
28
|
+
|
29
|
+
If you find a bug or a problem please post it on lighthouse. If you need help with something, please use google groups. I check both regularly and get emails when anything happens, so that is the best place to get help.
|
30
|
+
|
31
|
+
Please do not email me directly with issues regarding Authlogic. This is an inefficient way to get help because it doesn't help people who have the same problem in the future.
|
32
|
+
|
33
|
+
== Authlogic "add ons"
|
34
|
+
|
35
|
+
* <b>Authlogic OpenID addon:</b> http://github.com/binarylogic/authlogic_openid
|
36
|
+
* <b>Authlogic LDAP addon:</b> http://github.com/binarylogic/authlogic_ldap
|
37
|
+
|
38
|
+
If you create one of your own, please let me know about it so I can add it to this list.
|
30
39
|
|
31
40
|
== Documentation
|
32
41
|
|
@@ -184,7 +193,7 @@ This will create a file that looks similar to:
|
|
184
193
|
The user model should have the following columns. The names of these columns can be changed with configuration. Better yet, Authlogic tries to guess these names by checking for the existence of common names. See the sub modules of Authlogic::Session for more details, but chances are you won't have to specify any configuration for your field names, even if they aren't the same names as below.
|
185
194
|
|
186
195
|
t.string :login, :null => false # optional, you can use email instead, or both
|
187
|
-
t.string :crypted_password, :null => false #
|
196
|
+
t.string :crypted_password, :null => false # optional, see below
|
188
197
|
t.string :password_salt, :null => false # optional, but highly recommended
|
189
198
|
t.string :persistence_token, :null => false # required
|
190
199
|
t.string :single_access_token, :null => false # optional, see Authlogic::Session::Params
|
@@ -197,6 +206,8 @@ The user model should have the following columns. The names of these columns can
|
|
197
206
|
t.string :current_login_ip # optional, see Authlogic::Session::MagicColumns
|
198
207
|
t.string :last_login_ip # optional, see Authlogic::Session::MagicColumns
|
199
208
|
|
209
|
+
Notice the login and crypted_password fields are optional. If you prefer, you could use OpenID, LDAP, or whatever you want as your main authentication source and not even provide your own authentication system. I recommend providing your own as an option though. Your interface, such as the registration form, can dictate which method is the default. Lastly, adding 3rd party authentication methods should be as easy as installing an Authlogic "add on" gem. See "Authligic add ons" above.
|
210
|
+
|
200
211
|
=== 4. Set up your model
|
201
212
|
|
202
213
|
Make sure you have a model that you will be authenticating with. Since we are using the User model it should look something like:
|
@@ -266,4 +277,4 @@ A lot of them forced me to name my password column as "this", or the key of my c
|
|
266
277
|
I am not trying to "bash" any other authentication solutions. These are just my opinions, formulate your own opinion. I released Authlogic because I was "scratching my own itch". It has made my life easier and I enjoy using it, hopefully it does the same for you.
|
267
278
|
|
268
279
|
|
269
|
-
Copyright (c)
|
280
|
+
Copyright (c) 2009 {Ben Johnson of Binary Logic}(http://www.binarylogic.com), released under the MIT license
|
@@ -23,7 +23,7 @@ module Authlogic
|
|
23
23
|
# end
|
24
24
|
#
|
25
25
|
# See the various sub modules for the configuration they provide.
|
26
|
-
def acts_as_authentic(&block)
|
26
|
+
def acts_as_authentic(unsupported_options = nil, &block)
|
27
27
|
# Stop all configuration if the DB is not set up
|
28
28
|
begin
|
29
29
|
column_names
|
@@ -31,6 +31,9 @@ module Authlogic
|
|
31
31
|
return
|
32
32
|
end
|
33
33
|
|
34
|
+
raise ArgumentError.new("You are using the old v1.X.X configuration method for Authlogic. Instead of " +
|
35
|
+
"passing a hash of configuration options to acts_as_authentic, pass a block: acts_as_authentic { |c| c.my_option = my_value }") if !unsupported_options.nil?
|
36
|
+
|
34
37
|
yield self if block_given?
|
35
38
|
acts_as_authentic_modules.each { |mod| include mod }
|
36
39
|
end
|
@@ -73,9 +76,9 @@ module Authlogic
|
|
73
76
|
end
|
74
77
|
end
|
75
78
|
|
76
|
-
def first_column_to_exist(*columns_to_check)
|
79
|
+
def first_column_to_exist(*columns_to_check)
|
77
80
|
columns_to_check.each { |column_name| return column_name.to_sym if column_names.include?(column_name.to_s) }
|
78
|
-
columns_to_check.first
|
81
|
+
columns_to_check.first && columns_to_check.first.to_sym
|
79
82
|
end
|
80
83
|
|
81
84
|
end
|
@@ -19,7 +19,7 @@ module Authlogic
|
|
19
19
|
# * <tt>Default:</tt> :email, if it exists
|
20
20
|
# * <tt>Accepts:</tt> Symbol
|
21
21
|
def email_field(value = nil)
|
22
|
-
config(:email_field, value, first_column_to_exist(nil, :email))
|
22
|
+
config(:email_field, value, first_column_to_exist(nil, :email, :email_address))
|
23
23
|
end
|
24
24
|
alias_method :email_field=, :email_field
|
25
25
|
|
@@ -52,10 +52,10 @@ module Authlogic
|
|
52
52
|
|
53
53
|
# A hash of options for the validates_uniqueness_of call for the email field. Allows you to change this however you want.
|
54
54
|
#
|
55
|
-
# * <tt>Default:</tt> {:scope => validations_scope, :if => "#{email_field}_changed?".to_sym}
|
55
|
+
# * <tt>Default:</tt> {:case_sensitive => false, :scope => validations_scope, :if => "#{email_field}_changed?".to_sym}
|
56
56
|
# * <tt>Accepts:</tt> Hash of options accepted by validates_uniqueness_of
|
57
57
|
def validates_uniqueness_of_email_field_options(value = nil)
|
58
|
-
config(:validates_uniqueness_of_email_field_options, value, {:scope => validations_scope, :if => "#{email_field}_changed?".to_sym})
|
58
|
+
config(:validates_uniqueness_of_email_field_options, value, {:case_sensitive => false, :scope => validations_scope, :if => "#{email_field}_changed?".to_sym})
|
59
59
|
end
|
60
60
|
alias_method :validates_uniqueness_of_email_field_options=, :validates_uniqueness_of_email_field_options
|
61
61
|
|
@@ -64,7 +64,7 @@ module Authlogic
|
|
64
64
|
return @email_regex if @email_regex
|
65
65
|
email_name_regex = '[\w\.%\+\-]+'
|
66
66
|
domain_head_regex = '(?:[A-Z0-9\-]+\.)+'
|
67
|
-
domain_tld_regex = '(?:[A-Z]{2}|
|
67
|
+
domain_tld_regex = '(?:[A-Z]{2,4}|museum|travel)'
|
68
68
|
@email_regex = /\A#{email_name_regex}@#{domain_head_regex}#{domain_tld_regex}\z/i
|
69
69
|
end
|
70
70
|
end
|
@@ -73,6 +73,8 @@ module Authlogic
|
|
73
73
|
module Methods
|
74
74
|
def self.included(klass)
|
75
75
|
klass.class_eval do
|
76
|
+
extend ClassMethods
|
77
|
+
|
76
78
|
if validate_email_field && email_field
|
77
79
|
validates_length_of email_field, validates_length_of_email_field_options
|
78
80
|
validates_format_of email_field, validates_format_of_email_field_options
|
@@ -80,6 +82,24 @@ module Authlogic
|
|
80
82
|
end
|
81
83
|
end
|
82
84
|
end
|
85
|
+
|
86
|
+
# Class methods relating to the email field
|
87
|
+
module ClassMethods
|
88
|
+
# Calls alias_method if your email_field name is "out of the norm".
|
89
|
+
def self.included(klass)
|
90
|
+
klass.send(:alias_method, "find_with_email", "find_with_#{email_field}") if klass.email_field != :email
|
91
|
+
end
|
92
|
+
|
93
|
+
# Please see the find_with_login method in Authlogic::ActsAsAuthentic::Login module. It's the same exact thing
|
94
|
+
# but for the login field instead of the email field.
|
95
|
+
def find_with_email(email)
|
96
|
+
if validates_uniqueness_of_email_field_options[:case_sensitive] == false
|
97
|
+
first(:conditions => ["LOWER(#{quoted_table_name}.#{email_field}) = ?", email.downcase])
|
98
|
+
else
|
99
|
+
send("find_by_#{email_field}", email)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
83
103
|
end
|
84
104
|
end
|
85
105
|
end
|
@@ -27,27 +27,33 @@ module Authlogic
|
|
27
27
|
# All methods for the logged in status feature seat.
|
28
28
|
module Methods
|
29
29
|
def self.included(klass)
|
30
|
+
return if !klass.column_names.include?("last_request_at")
|
31
|
+
|
30
32
|
klass.class_eval do
|
33
|
+
include InstanceMethods
|
34
|
+
|
31
35
|
named_scope :logged_in, lambda { {:conditions => ["last_request_at > ?", logged_in_timeout.seconds.ago]} }
|
32
36
|
named_scope :logged_out, lambda { {:conditions => ["last_request_at is NULL or last_request_at <= ?", logged_in_timeout.seconds.ago]} }
|
33
37
|
end
|
34
38
|
end
|
35
39
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
# Opposite of logged_in?
|
43
|
-
def logged_out?
|
44
|
-
!logged_in?
|
45
|
-
end
|
40
|
+
module InstanceMethods
|
41
|
+
# Returns true if the last_request_at > logged_in_timeout.
|
42
|
+
def logged_in?
|
43
|
+
raise "Can not determine the records login state because there is no last_request_at column" if !respond_to?(:last_request_at)
|
44
|
+
!last_request_at.nil? && last_request_at > logged_in_timeout.seconds.ago
|
45
|
+
end
|
46
46
|
|
47
|
-
|
48
|
-
def
|
49
|
-
|
47
|
+
# Opposite of logged_in?
|
48
|
+
def logged_out?
|
49
|
+
!logged_in?
|
50
50
|
end
|
51
|
+
|
52
|
+
private
|
53
|
+
def logged_in_timeout
|
54
|
+
self.class.logged_in_timeout
|
55
|
+
end
|
56
|
+
end
|
51
57
|
end
|
52
58
|
end
|
53
59
|
end
|
@@ -49,18 +49,21 @@ module Authlogic
|
|
49
49
|
|
50
50
|
# A hash of options for the validates_uniqueness_of call for the login field. Allows you to change this however you want.
|
51
51
|
#
|
52
|
-
# * <tt>Default:</tt> {:scope => validations_scope, :if => "#{login_field}_changed?".to_sym}
|
52
|
+
# * <tt>Default:</tt> {:case_sensitive => false, :scope => validations_scope, :if => "#{login_field}_changed?".to_sym}
|
53
53
|
# * <tt>Accepts:</tt> Hash of options accepted by validates_uniqueness_of
|
54
54
|
def validates_uniqueness_of_login_field_options(value = nil)
|
55
|
-
config(:validates_uniqueness_of_login_field_options, value, {:scope => validations_scope, :if => "#{login_field}_changed?".to_sym})
|
55
|
+
config(:validates_uniqueness_of_login_field_options, value, {:case_sensitive => false, :scope => validations_scope, :if => "#{login_field}_changed?".to_sym})
|
56
56
|
end
|
57
57
|
alias_method :validates_uniqueness_of_login_field_options=, :validates_uniqueness_of_login_field_options
|
58
58
|
end
|
59
59
|
|
60
60
|
# All methods relating to the login field
|
61
61
|
module Methods
|
62
|
+
# Adds in various validations, modules, etc.
|
62
63
|
def self.included(klass)
|
63
64
|
klass.class_eval do
|
65
|
+
extend ClassMethods
|
66
|
+
|
64
67
|
if validate_login_field && login_field
|
65
68
|
validates_length_of login_field, validates_length_of_login_field_options
|
66
69
|
validates_format_of login_field, validates_format_of_login_field_options
|
@@ -68,6 +71,35 @@ module Authlogic
|
|
68
71
|
end
|
69
72
|
end
|
70
73
|
end
|
74
|
+
|
75
|
+
# Class methods relating to the login field.
|
76
|
+
module ClassMethods
|
77
|
+
# Calls alias_method if your login_field name is "out of the norm".
|
78
|
+
def self.included(klass)
|
79
|
+
klass.send(:alias_method, "find_with_login", "find_with_#{login_field}") if klass.login_field != :login
|
80
|
+
end
|
81
|
+
|
82
|
+
# This method allows you to find a record with the given login. If you notice, with ActiveRecord you have the
|
83
|
+
# validates_uniqueness_of validation function. They give you a :case_sensitive option. I handle this in the same
|
84
|
+
# manner that they handle that. If you set false for the :case_sensitive option in validates_uniqueness_of_login_field_options
|
85
|
+
# this method will modify the query to look something like:
|
86
|
+
#
|
87
|
+
# first(:conditions => ["LOWER(#{quoted_table_name}.#{login_field}) = ?", login.downcase])
|
88
|
+
#
|
89
|
+
# If you don't specify this it calls the good old find_by_* method:
|
90
|
+
#
|
91
|
+
# find_by_login(login)
|
92
|
+
#
|
93
|
+
# The only reason I need to do the above is for Postgres and SQLite since they perform case sensitive searches with the
|
94
|
+
# find_by_* methods.
|
95
|
+
def find_with_login(login)
|
96
|
+
if validates_uniqueness_of_login_field_options[:case_sensitive] == false
|
97
|
+
first(:conditions => ["LOWER(#{quoted_table_name}.#{login_field}) = ?", login.downcase])
|
98
|
+
else
|
99
|
+
send("find_by_#{login_field}", login)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
71
103
|
end
|
72
104
|
end
|
73
105
|
end
|
@@ -18,7 +18,7 @@ module Authlogic
|
|
18
18
|
# * <tt>Default:</tt> :crypted_password, :encrypted_password, :password_hash, or :pw_hash
|
19
19
|
# * <tt>Accepts:</tt> Symbol
|
20
20
|
def crypted_password_field(value = nil)
|
21
|
-
config(:crypted_password_field, value, first_column_to_exist(:crypted_password, :encrypted_password, :password_hash, :pw_hash))
|
21
|
+
config(:crypted_password_field, value, first_column_to_exist(nil, :crypted_password, :encrypted_password, :password_hash, :pw_hash))
|
22
22
|
end
|
23
23
|
alias_method :crypted_password_field=, :crypted_password_field
|
24
24
|
|
@@ -31,6 +31,22 @@ module Authlogic
|
|
31
31
|
end
|
32
32
|
alias_method :password_salt_field=, :password_salt_field
|
33
33
|
|
34
|
+
# By default passwords are required when a record is new or the crypted_password is blank, but if both of these things
|
35
|
+
# are met a password is not required. In this case, blank passwords are ignored.
|
36
|
+
#
|
37
|
+
# Think about a profile page, where the user can edit all of their information, including changing their password.
|
38
|
+
# If they do not want to change their password they just leave the fields blank. This will try to set the password to
|
39
|
+
# a blank value, in which case is incorrect behavior. As such, Authlogic ignores this. But let's say you have a completely
|
40
|
+
# separate page for resetting passwords, you might not want to ignore blank passwords. If this is the case for you, then
|
41
|
+
# just set this value to false.
|
42
|
+
#
|
43
|
+
# * <tt>Default:</tt> true
|
44
|
+
# * <tt>Accepts:</tt> Boolean
|
45
|
+
def ignore_blank_passwords(value = nil)
|
46
|
+
config(:ignore_blank_passwords, value, true)
|
47
|
+
end
|
48
|
+
alias_method :ignore_blank_passwords=, :ignore_blank_passwords
|
49
|
+
|
34
50
|
# Whether or not to validate the password field.
|
35
51
|
#
|
36
52
|
# * <tt>Default:</tt> true
|
@@ -60,10 +76,10 @@ module Authlogic
|
|
60
76
|
|
61
77
|
# A hash of options for the validates_length_of call for the password_confirmation field. Allows you to change this however you want.
|
62
78
|
#
|
63
|
-
# * <tt>Default:</tt>
|
79
|
+
# * <tt>Default:</tt> validates_length_of_password_field_options
|
64
80
|
# * <tt>Accepts:</tt> Hash of options accepted by validates_length_of
|
65
81
|
def validates_length_of_password_confirmation_field_options(value = nil)
|
66
|
-
config(:validates_length_of_password_confirmation_field_options, value,
|
82
|
+
config(:validates_length_of_password_confirmation_field_options, value, validates_length_of_password_field_options)
|
67
83
|
end
|
68
84
|
alias_method :validates_length_of_password_confirmation_field_options=, :validates_length_of_password_confirmation_field_options
|
69
85
|
|
@@ -102,6 +118,7 @@ module Authlogic
|
|
102
118
|
]
|
103
119
|
|
104
120
|
def self.included(klass)
|
121
|
+
return if !klass.column_names.include?(klass.crypted_password_field.to_s)
|
105
122
|
klass.define_callbacks *METHODS
|
106
123
|
end
|
107
124
|
|
@@ -118,112 +135,128 @@ module Authlogic
|
|
118
135
|
# The methods related to the password field.
|
119
136
|
module Methods
|
120
137
|
def self.included(klass)
|
138
|
+
return if !klass.column_names.include?(klass.crypted_password_field.to_s)
|
139
|
+
|
121
140
|
klass.class_eval do
|
141
|
+
include InstanceMethods
|
142
|
+
|
122
143
|
if validate_password_field
|
123
144
|
validates_length_of :password, validates_length_of_password_field_options
|
124
145
|
validates_confirmation_of :password, validates_confirmation_of_password_field_options
|
125
146
|
validates_length_of :password_confirmation, validates_length_of_password_confirmation_field_options
|
126
147
|
end
|
148
|
+
|
149
|
+
after_save :reset_password_changed
|
127
150
|
end
|
128
151
|
end
|
129
152
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
153
|
+
module InstanceMethods
|
154
|
+
# The password
|
155
|
+
def password
|
156
|
+
@password
|
157
|
+
end
|
134
158
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
159
|
+
# This is a virtual method. Once a password is passed to it, it will create new password salt as well as encrypt
|
160
|
+
# the password.
|
161
|
+
def password=(pass)
|
162
|
+
return if ignore_blank_passwords? && pass.blank?
|
163
|
+
before_password_set
|
164
|
+
@password = pass
|
165
|
+
send("#{password_salt_field}=", Authlogic::Random.friendly_token) if password_salt_field
|
166
|
+
send("#{crypted_password_field}=", crypto_provider.encrypt(*encrypt_arguments(@password, act_like_restful_authentication? ? :restful_authentication : nil)))
|
167
|
+
@password_changed = true
|
168
|
+
after_password_set
|
169
|
+
end
|
146
170
|
|
147
|
-
|
148
|
-
|
149
|
-
|
171
|
+
# Accepts a raw password to determine if it is the correct password or not.
|
172
|
+
def valid_password?(attempted_password)
|
173
|
+
return false if attempted_password.blank? || send(crypted_password_field).blank?
|
150
174
|
|
151
|
-
|
175
|
+
before_password_verification
|
152
176
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
177
|
+
crypto_providers = [crypto_provider] + transition_from_crypto_providers
|
178
|
+
crypto_providers.each_with_index do |encryptor, index|
|
179
|
+
# The arguments_type of for the transitioning from restful_authentication
|
180
|
+
arguments_type = (act_like_restful_authentication? && index == 0) ||
|
181
|
+
(transition_from_restful_authentication? && index > 0 && encryptor == Authlogic::CryptoProviders::Sha1) ?
|
182
|
+
:restful_authentication : nil
|
159
183
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
184
|
+
if encryptor.matches?(send(crypted_password_field), *encrypt_arguments(attempted_password, arguments_type))
|
185
|
+
# If we are transitioning from an older encryption algorithm and the password is still using the old algorithm
|
186
|
+
# then let's reset the password using the new algorithm. If the algorithm has a cost (BCrypt) and the cost has changed, update the password with
|
187
|
+
# the new cost.
|
188
|
+
if index > 0 || (encryptor.respond_to?(:cost_matches?) && !encryptor.cost_matches?(send(crypted_password_field)))
|
189
|
+
self.password = attempted_password
|
190
|
+
save(false)
|
191
|
+
end
|
168
192
|
|
169
|
-
|
193
|
+
after_password_verification
|
170
194
|
|
171
|
-
|
195
|
+
return true
|
196
|
+
end
|
172
197
|
end
|
173
|
-
end
|
174
198
|
|
175
|
-
|
176
|
-
|
199
|
+
false
|
200
|
+
end
|
177
201
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
202
|
+
# Resets the password to a random friendly token.
|
203
|
+
def reset_password
|
204
|
+
friendly_token = Authlogic::Random.friendly_token
|
205
|
+
self.password = friendly_token
|
206
|
+
self.password_confirmation = friendly_token
|
207
|
+
end
|
208
|
+
alias_method :randomize_password, :reset_password
|
185
209
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
210
|
+
# Resets the password to a random friendly token and then saves the record.
|
211
|
+
def reset_password!
|
212
|
+
reset_password
|
213
|
+
save_without_session_maintenance(false)
|
214
|
+
end
|
215
|
+
alias_method :randomize_password!, :reset_password!
|
192
216
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
217
|
+
private
|
218
|
+
def encrypt_arguments(raw_password, arguments_type = nil)
|
219
|
+
salt = password_salt_field ? send(password_salt_field) : nil
|
220
|
+
case arguments_type
|
221
|
+
when :restful_authentication
|
222
|
+
[REST_AUTH_SITE_KEY, salt, raw_password, REST_AUTH_SITE_KEY].compact
|
223
|
+
else
|
224
|
+
[raw_password, salt].compact
|
225
|
+
end
|
201
226
|
end
|
202
|
-
end
|
203
227
|
|
204
|
-
|
205
|
-
|
206
|
-
|
228
|
+
def require_password?
|
229
|
+
new_record? || password_changed? || send(crypted_password_field).blank?
|
230
|
+
end
|
207
231
|
|
208
|
-
|
209
|
-
|
210
|
-
|
232
|
+
def ignore_blank_passwords?
|
233
|
+
self.class.ignore_blank_passwords == true
|
234
|
+
end
|
211
235
|
|
212
|
-
|
213
|
-
|
214
|
-
|
236
|
+
def password_changed?
|
237
|
+
@password_changed == true
|
238
|
+
end
|
239
|
+
|
240
|
+
def reset_password_changed
|
241
|
+
@password_changed = false
|
242
|
+
end
|
215
243
|
|
216
|
-
|
217
|
-
|
218
|
-
|
244
|
+
def crypted_password_field
|
245
|
+
self.class.crypted_password_field
|
246
|
+
end
|
219
247
|
|
220
|
-
|
221
|
-
|
222
|
-
|
248
|
+
def password_salt_field
|
249
|
+
self.class.password_salt_field
|
250
|
+
end
|
223
251
|
|
224
|
-
|
225
|
-
|
226
|
-
|
252
|
+
def crypto_provider
|
253
|
+
self.class.crypto_provider
|
254
|
+
end
|
255
|
+
|
256
|
+
def transition_from_crypto_providers
|
257
|
+
self.class.transition_from_crypto_providers
|
258
|
+
end
|
259
|
+
end
|
227
260
|
end
|
228
261
|
end
|
229
262
|
end
|
@@ -29,7 +29,7 @@ module Authlogic
|
|
29
29
|
module Methods
|
30
30
|
def self.included(klass)
|
31
31
|
return if !klass.column_names.include?("single_access_token")
|
32
|
-
|
32
|
+
|
33
33
|
klass.class_eval do
|
34
34
|
include InstanceMethods
|
35
35
|
validates_uniqueness_of :single_access_token, :if => :single_access_token_changed?
|
@@ -4,7 +4,7 @@ module Authlogic
|
|
4
4
|
# provides. Similar to how ActiveRecord has an adapter for MySQL, PostgreSQL, SQLite, etc.
|
5
5
|
class RailsAdapter < AbstractAdapter
|
6
6
|
def authenticate_with_http_basic(&block)
|
7
|
-
|
7
|
+
controller.authenticate_with_http_basic(&block)
|
8
8
|
end
|
9
9
|
|
10
10
|
def cookies
|
@@ -13,7 +13,7 @@ module Authlogic
|
|
13
13
|
|
14
14
|
def cookie_domain
|
15
15
|
@cookie_domain_key ||= (Rails::VERSION::MAJOR >= 2 && Rails::VERSION::MINOR >= 3) ? :domain : :session_domain
|
16
|
-
|
16
|
+
ActionController::Base.session_options[@cookie_domain_key]
|
17
17
|
end
|
18
18
|
|
19
19
|
def request_content_type
|
@@ -5,7 +5,7 @@ module Authlogic
|
|
5
5
|
# This encryption method is reversible if you have the supplied key. So in order to use this encryption method you must supply it with a key first.
|
6
6
|
# In an initializer, or before your application initializes, you should do the following:
|
7
7
|
#
|
8
|
-
# Authlogic::CryptoProviders::AES256.key = "my really long and unique key,
|
8
|
+
# Authlogic::CryptoProviders::AES256.key = "my really long and unique key, preferrably a bunch of random characters"
|
9
9
|
#
|
10
10
|
# My final comment is that this is a strong encryption method, but its main weakness is that its reversible. If you do not need to reverse the hash
|
11
11
|
# then you should consider Sha512 or BCrypt instead.
|
@@ -34,7 +34,7 @@ module Authlogic
|
|
34
34
|
|
35
35
|
private
|
36
36
|
def aes
|
37
|
-
raise ArgumentError.new("You provide a key like #{name}.key = my_key before using the #{name}") if @key.blank?
|
37
|
+
raise ArgumentError.new("You must provide a key like #{name}.key = my_key before using the #{name}") if @key.blank?
|
38
38
|
@aes ||= OpenSSL::Cipher::Cipher.new("AES-256-ECB")
|
39
39
|
end
|
40
40
|
end
|
@@ -35,7 +35,9 @@ module Authlogic
|
|
35
35
|
#
|
36
36
|
# Tell acts_as_authentic to use it:
|
37
37
|
#
|
38
|
-
# acts_as_authentic
|
38
|
+
# acts_as_authentic do |c|
|
39
|
+
# c.crypto_provider = Authlogic::CryptoProviders::BCrypt
|
40
|
+
# end
|
39
41
|
#
|
40
42
|
# You are good to go!
|
41
43
|
class BCrypt
|
@@ -2,8 +2,8 @@ require "digest/sha1"
|
|
2
2
|
|
3
3
|
module Authlogic
|
4
4
|
module CryptoProviders
|
5
|
-
# This class was made for the users transitioning from restful_authentication. I highly discourage using this
|
6
|
-
# Please use any other provider offered by Authlogic.
|
5
|
+
# This class was made for the users transitioning from restful_authentication. I highly discourage using this
|
6
|
+
# crypto provider as it inferior to your other options. Please use any other provider offered by Authlogic.
|
7
7
|
class Sha1
|
8
8
|
class << self
|
9
9
|
def join_token
|
@@ -17,7 +17,7 @@ module Authlogic
|
|
17
17
|
# authlogic.attributes.user_session.login
|
18
18
|
def human_attribute_name(attribute_key_name, options = {})
|
19
19
|
options[:count] ||= 1
|
20
|
-
options[:default] ||= attribute_key_name.humanize
|
20
|
+
options[:default] ||= attribute_key_name.to_s.humanize
|
21
21
|
I18n.t("attributes.#{name.underscore}.#{attribute_key_name}", options)
|
22
22
|
end
|
23
23
|
|
@@ -98,13 +98,15 @@ module Authlogic
|
|
98
98
|
end
|
99
99
|
|
100
100
|
def cookie_credentials
|
101
|
-
controller.cookies[cookie_key]
|
101
|
+
controller.cookies[cookie_key] && controller.cookies[cookie_key].split("::")
|
102
102
|
end
|
103
103
|
|
104
104
|
# Tries to validate the session from information in the cookie
|
105
105
|
def persist_by_cookie
|
106
|
-
|
107
|
-
|
106
|
+
persistence_token, record_id = cookie_credentials
|
107
|
+
if !persistence_token.nil?
|
108
|
+
record = record_id.nil? ? search_for_record("find_by_persistence_token", persistence_token) : search_for_record("find_by_#{klass.primary_key}", record_id)
|
109
|
+
self.unauthorized_record = record if record && record.persistence_token == persistence_token
|
108
110
|
valid?
|
109
111
|
else
|
110
112
|
false
|
@@ -113,7 +115,7 @@ module Authlogic
|
|
113
115
|
|
114
116
|
def save_cookie
|
115
117
|
controller.cookies[cookie_key] = {
|
116
|
-
:value => record.persistence_token,
|
118
|
+
:value => "#{record.persistence_token}::#{record.send(record.class.primary_key)}",
|
117
119
|
:expires => remember_me_until,
|
118
120
|
:domain => controller.cookie_domain
|
119
121
|
}
|
@@ -29,10 +29,13 @@ module Authlogic
|
|
29
29
|
# end
|
30
30
|
# end
|
31
31
|
#
|
32
|
-
#
|
32
|
+
# Now just specifcy the name of this method for this configuration option and you are all set. You can do anything you want here. Maybe you allow users to have multiple logins
|
33
|
+
# and you want to search a has_many relationship, etc. The sky is the limit.
|
34
|
+
#
|
35
|
+
# * <tt>Default:</tt> "find_by_case_insensitive_#{login_field}"
|
33
36
|
# * <tt>Accepts:</tt> Symbol or String
|
34
37
|
def find_by_login_method(value = nil)
|
35
|
-
config(:find_by_login_method, value, "
|
38
|
+
config(:find_by_login_method, value, "find_with_#{login_field}")
|
36
39
|
end
|
37
40
|
alias_method :find_by_login_method=, :find_by_login_method
|
38
41
|
|
@@ -41,19 +44,19 @@ module Authlogic
|
|
41
44
|
# login with a field called "login" and then find users by email this is compeltely doable. See the find_by_login_method configuration
|
42
45
|
# option for more details.
|
43
46
|
#
|
44
|
-
# * <tt>Default:</tt>
|
47
|
+
# * <tt>Default:</tt> klass.login_field || klass.email_field
|
45
48
|
# * <tt>Accepts:</tt> Symbol or String
|
46
49
|
def login_field(value = nil)
|
47
50
|
config(:login_field, value, klass.login_field || klass.email_field)
|
48
51
|
end
|
49
52
|
alias_method :login_field=, :login_field
|
50
53
|
|
51
|
-
# Works exactly like login_field, but for the password instead.
|
54
|
+
# Works exactly like login_field, but for the password instead. Returns :password if a login_field exists.
|
52
55
|
#
|
53
56
|
# * <tt>Default:</tt> :password
|
54
57
|
# * <tt>Accepts:</tt> Symbol or String
|
55
58
|
def password_field(value = nil)
|
56
|
-
config(:password_field, value, :password)
|
59
|
+
config(:password_field, value, login_field && :password)
|
57
60
|
end
|
58
61
|
alias_method :password_field=, :password_field
|
59
62
|
|
@@ -71,18 +74,23 @@ module Authlogic
|
|
71
74
|
module InstanceMethods
|
72
75
|
def initialize(*args)
|
73
76
|
if !self.class.configured_password_methods
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
77
|
+
if login_field
|
78
|
+
self.class.send(:attr_writer, login_field) if !respond_to?("#{login_field}=")
|
79
|
+
self.class.send(:attr_reader, login_field) if !respond_to?(login_field)
|
80
|
+
end
|
81
|
+
|
82
|
+
if password_field
|
83
|
+
self.class.send(:attr_writer, password_field) if !respond_to?("#{password_field}=")
|
84
|
+
self.class.send(:define_method, password_field) {} if !respond_to?(password_field)
|
78
85
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
+
self.class.class_eval <<-"end_eval", __FILE__, __LINE__
|
87
|
+
private
|
88
|
+
# The password should not be accessible publicly. This way forms using form_for don't fill the password with the attempted password. The prevent this we just create this method that is private.
|
89
|
+
def protected_#{password_field}
|
90
|
+
@#{password_field}
|
91
|
+
end
|
92
|
+
end_eval
|
93
|
+
end
|
86
94
|
|
87
95
|
self.class.configured_password_methods = true
|
88
96
|
end
|
@@ -114,7 +122,7 @@ module Authlogic
|
|
114
122
|
|
115
123
|
private
|
116
124
|
def authenticating_with_password?
|
117
|
-
!send(login_field).nil? || !send("protected_#{password_field}").nil?
|
125
|
+
login_field && (!send(login_field).nil? || !send("protected_#{password_field}").nil?)
|
118
126
|
end
|
119
127
|
|
120
128
|
def validate_by_password
|
@@ -16,7 +16,7 @@ module Authlogic
|
|
16
16
|
def credentials=(value)
|
17
17
|
super
|
18
18
|
values = value.is_a?(Array) ? value : [value]
|
19
|
-
self.priority_record = values
|
19
|
+
self.priority_record = values[1] if values[1].class < ::ActiveRecord::Base
|
20
20
|
end
|
21
21
|
|
22
22
|
private
|
@@ -49,7 +49,7 @@ module Authlogic
|
|
49
49
|
def session_key
|
50
50
|
build_key(self.class.session_key)
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
def update_session
|
54
54
|
controller.session[session_key] = record && record.persistence_token
|
55
55
|
controller.session["#{session_key}_#{klass.primary_key}"] = record && record.send(record.class.primary_key)
|
@@ -4,11 +4,10 @@ module Authlogic
|
|
4
4
|
# a request is made, ultimately letting you log in users in functional tests.
|
5
5
|
class ControllerAdapter < ControllerAdapters::AbstractAdapter
|
6
6
|
def authenticate_with_http_basic(&block)
|
7
|
-
controller.authenticate_with_http_basic(&block)
|
8
7
|
end
|
9
8
|
|
10
9
|
def cookies
|
11
|
-
new_cookies =
|
10
|
+
new_cookies = MockCookieJar.new
|
12
11
|
super.each do |key, value|
|
13
12
|
new_cookies[key] = value[:value]
|
14
13
|
end
|
@@ -20,7 +19,7 @@ module Authlogic
|
|
20
19
|
end
|
21
20
|
|
22
21
|
def request
|
23
|
-
@request ||= MockRequest.new
|
22
|
+
@request ||= MockRequest.new(controller)
|
24
23
|
end
|
25
24
|
|
26
25
|
def request_content_type
|
@@ -2,7 +2,7 @@ module Authlogic
|
|
2
2
|
module TestCase
|
3
3
|
# Basically acts like a controller but doesn't do anything. Authlogic can interact with this, do it's thing and then you
|
4
4
|
# can look at the controller object to see if anything changed.
|
5
|
-
class MockController <
|
5
|
+
class MockController < ControllerAdapter
|
6
6
|
attr_accessor :http_user, :http_password
|
7
7
|
attr_writer :request_content_type
|
8
8
|
|
@@ -29,10 +29,6 @@ module Authlogic
|
|
29
29
|
@params ||= {}
|
30
30
|
end
|
31
31
|
|
32
|
-
def request
|
33
|
-
@request ||= MockRequest.new
|
34
|
-
end
|
35
|
-
|
36
32
|
def request_content_type
|
37
33
|
@request_content_type ||= "text/html"
|
38
34
|
end
|
@@ -1,12 +1,24 @@
|
|
1
1
|
module Authlogic
|
2
2
|
module TestCase
|
3
3
|
class MockRequest # :nodoc:
|
4
|
+
attr_accessor :controller
|
5
|
+
|
6
|
+
def initialize(controller)
|
7
|
+
self.controller = controller
|
8
|
+
end
|
9
|
+
|
4
10
|
def request_method
|
5
11
|
nil
|
6
12
|
end
|
7
13
|
|
14
|
+
def referer
|
15
|
+
end
|
16
|
+
|
8
17
|
def remote_ip
|
9
|
-
"1.1.1.1"
|
18
|
+
(controller && controller.respond_to?(:env) && controller.env.is_a?(Hahs) && controller.env['REMOTE_ADDR']) || "1.1.1.1"
|
19
|
+
end
|
20
|
+
|
21
|
+
def user_agent
|
10
22
|
end
|
11
23
|
end
|
12
24
|
end
|
data/lib/authlogic/version.rb
CHANGED
data/shoulda_macros/authlogic.rb
CHANGED
@@ -44,7 +44,7 @@ module ActsAsAuthenticTest
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def test_validates_uniqueness_of_email_field_options_config
|
47
|
-
default = {:scope => Employee.validations_scope, :if => "#{Employee.email_field}_changed?".to_sym}
|
47
|
+
default = {:case_sensitive => false, :scope => Employee.validations_scope, :if => "#{Employee.email_field}_changed?".to_sym}
|
48
48
|
assert_equal default, Employee.validates_uniqueness_of_email_field_options
|
49
49
|
|
50
50
|
Employee.validates_uniqueness_of_email_field_options = {:yes => "no"}
|
@@ -81,9 +81,20 @@ module ActsAsAuthenticTest
|
|
81
81
|
assert !u.valid?
|
82
82
|
assert u.errors.on(:email)
|
83
83
|
|
84
|
+
u.email = "BJOHNSON@binarylogic.com"
|
85
|
+
assert !u.valid?
|
86
|
+
assert u.errors.on(:email)
|
87
|
+
|
84
88
|
u.email = "a@a.com"
|
85
89
|
assert !u.valid?
|
86
90
|
assert !u.errors.on(:email)
|
87
91
|
end
|
92
|
+
|
93
|
+
def test_find_with_email
|
94
|
+
ben = users(:ben)
|
95
|
+
assert_equal ben, User.find_with_email("bjohnson@binarylogic.com")
|
96
|
+
assert_equal ben, User.find_with_email("bJohnson@binarylogic.com")
|
97
|
+
assert_equal ben, User.find_with_email("BJOHNSON@BINARYLOGIC.COM")
|
98
|
+
end
|
88
99
|
end
|
89
100
|
end
|
@@ -44,7 +44,7 @@ module ActsAsAuthenticTest
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def test_validates_uniqueness_of_login_field_options_config
|
47
|
-
default = {:scope => User.validations_scope, :if => "#{User.login_field}_changed?".to_sym}
|
47
|
+
default = {:case_sensitive => false, :scope => User.validations_scope, :if => "#{User.login_field}_changed?".to_sym}
|
48
48
|
assert_equal default, User.validates_uniqueness_of_login_field_options
|
49
49
|
|
50
50
|
User.validates_uniqueness_of_login_field_options = {:yes => "no"}
|
@@ -81,9 +81,20 @@ module ActsAsAuthenticTest
|
|
81
81
|
assert !u.valid?
|
82
82
|
assert u.errors.on(:login)
|
83
83
|
|
84
|
+
u.login = "BJOHNSON"
|
85
|
+
assert !u.valid?
|
86
|
+
assert u.errors.on(:login)
|
87
|
+
|
84
88
|
u.login = "fdsfdsf"
|
85
89
|
assert !u.valid?
|
86
90
|
assert !u.errors.on(:login)
|
87
91
|
end
|
92
|
+
|
93
|
+
def test_find_with_login
|
94
|
+
ben = users(:ben)
|
95
|
+
assert_equal ben, User.find_with_login("bjohnson")
|
96
|
+
assert_equal ben, User.find_with_login("BJOHNSON")
|
97
|
+
assert_equal ben, User.find_with_login("Bjohnson")
|
98
|
+
end
|
88
99
|
end
|
89
100
|
end
|
@@ -22,6 +22,16 @@ module ActsAsAuthenticTest
|
|
22
22
|
assert_equal :password_salt, User.password_salt_field
|
23
23
|
end
|
24
24
|
|
25
|
+
def test_ignore_blank_passwords_config
|
26
|
+
assert User.ignore_blank_passwords
|
27
|
+
assert Employee.ignore_blank_passwords
|
28
|
+
|
29
|
+
User.ignore_blank_passwords = false
|
30
|
+
assert !User.ignore_blank_passwords
|
31
|
+
User.ignore_blank_passwords true
|
32
|
+
assert User.ignore_blank_passwords
|
33
|
+
end
|
34
|
+
|
25
35
|
def test_validate_password_field_config
|
26
36
|
assert User.validate_password_field
|
27
37
|
assert Employee.validate_password_field
|
@@ -5,6 +5,7 @@ module SessionTest
|
|
5
5
|
class ClassMethodsTest < ActiveSupport::TestCase
|
6
6
|
def test_human_attribute_name
|
7
7
|
assert_equal "Some attribute", UserSession.human_attribute_name("some_attribute")
|
8
|
+
assert_equal "Some attribute", UserSession.human_attribute_name(:some_attribute)
|
8
9
|
end
|
9
10
|
|
10
11
|
def test_human_name
|
@@ -91,7 +91,7 @@ module SessionTest
|
|
91
91
|
ben = users(:ben)
|
92
92
|
session = UserSession.new(ben)
|
93
93
|
assert session.save
|
94
|
-
assert_equal ben.persistence_token, controller.cookies["user_credentials"]
|
94
|
+
assert_equal "#{ben.persistence_token}::#{ben.id}", controller.cookies["user_credentials"]
|
95
95
|
end
|
96
96
|
|
97
97
|
def test_after_destroy_destroy_cookie
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: authlogic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Johnson of Binary Logic
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-04-09 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -30,7 +30,7 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.
|
33
|
+
version: 1.12.1
|
34
34
|
version:
|
35
35
|
description: A clean, simple, and unobtrusive ruby authentication solution.
|
36
36
|
email: bjohnson@binarylogic.com
|