authlogic 3.4.6 → 3.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +33 -0
- data/.rubocop_todo.yml +427 -0
- data/.travis.yml +24 -3
- data/CHANGELOG.md +9 -2
- data/CONTRIBUTING.md +40 -1
- data/Gemfile +1 -1
- data/README.md +295 -0
- data/Rakefile +10 -2
- data/authlogic.gemspec +6 -5
- data/lib/authlogic.rb +2 -2
- data/lib/authlogic/acts_as_authentic/base.rb +2 -2
- data/lib/authlogic/acts_as_authentic/email.rb +59 -14
- data/lib/authlogic/acts_as_authentic/logged_in_status.rb +4 -3
- data/lib/authlogic/acts_as_authentic/login.rb +62 -12
- data/lib/authlogic/acts_as_authentic/magic_columns.rb +17 -6
- data/lib/authlogic/acts_as_authentic/password.rb +107 -53
- data/lib/authlogic/acts_as_authentic/persistence_token.rb +10 -9
- data/lib/authlogic/acts_as_authentic/restful_authentication.rb +2 -0
- data/lib/authlogic/acts_as_authentic/session_maintenance.rb +48 -35
- data/lib/authlogic/acts_as_authentic/single_access_token.rb +19 -15
- data/lib/authlogic/acts_as_authentic/validations_scope.rb +2 -2
- data/lib/authlogic/authenticates_many/association.rb +6 -5
- data/lib/authlogic/authenticates_many/base.rb +22 -12
- data/lib/authlogic/config.rb +2 -1
- data/lib/authlogic/controller_adapters/abstract_adapter.rb +2 -1
- data/lib/authlogic/controller_adapters/rack_adapter.rb +3 -4
- data/lib/authlogic/controller_adapters/rails_adapter.rb +26 -14
- data/lib/authlogic/controller_adapters/sinatra_adapter.rb +1 -1
- data/lib/authlogic/crypto_providers/aes256.rb +16 -12
- data/lib/authlogic/crypto_providers/bcrypt.rb +10 -4
- data/lib/authlogic/crypto_providers/md5.rb +7 -7
- data/lib/authlogic/crypto_providers/scrypt.rb +10 -2
- data/lib/authlogic/crypto_providers/sha1.rb +3 -3
- data/lib/authlogic/crypto_providers/sha256.rb +3 -3
- data/lib/authlogic/crypto_providers/sha512.rb +4 -4
- data/lib/authlogic/crypto_providers/wordpress.rb +13 -13
- data/lib/authlogic/i18n.rb +22 -16
- data/lib/authlogic/i18n/translator.rb +1 -1
- data/lib/authlogic/random.rb +13 -12
- data/lib/authlogic/regex.rb +3 -3
- data/lib/authlogic/session/activation.rb +7 -6
- data/lib/authlogic/session/active_record_trickery.rb +1 -2
- data/lib/authlogic/session/base.rb +7 -6
- data/lib/authlogic/session/brute_force_protection.rb +58 -34
- data/lib/authlogic/session/callbacks.rb +16 -12
- data/lib/authlogic/session/cookies.rb +29 -14
- data/lib/authlogic/session/existence.rb +10 -10
- data/lib/authlogic/session/foundation.rb +11 -7
- data/lib/authlogic/session/http_auth.rb +6 -5
- data/lib/authlogic/session/id.rb +5 -4
- data/lib/authlogic/session/klass.rb +2 -1
- data/lib/authlogic/session/magic_columns.rb +21 -14
- data/lib/authlogic/session/magic_states.rb +25 -14
- data/lib/authlogic/session/params.rb +41 -26
- data/lib/authlogic/session/password.rb +62 -40
- data/lib/authlogic/session/perishable_token.rb +3 -2
- data/lib/authlogic/session/persistence.rb +3 -3
- data/lib/authlogic/session/priority_record.rb +5 -4
- data/lib/authlogic/session/scopes.rb +20 -9
- data/lib/authlogic/session/session.rb +9 -4
- data/lib/authlogic/session/timeout.rb +40 -23
- data/lib/authlogic/session/unauthorized_record.rb +6 -5
- data/lib/authlogic/session/validation.rb +18 -9
- data/lib/authlogic/test_case.rb +2 -2
- data/lib/authlogic/test_case/mock_controller.rb +9 -9
- data/lib/authlogic/test_case/mock_cookie_jar.rb +2 -2
- data/lib/authlogic/test_case/mock_logger.rb +1 -1
- data/lib/authlogic/test_case/mock_request.rb +2 -1
- data/lib/authlogic/test_case/rails_request_adapter.rb +5 -5
- data/test/acts_as_authentic_test/email_test.rb +29 -17
- data/test/acts_as_authentic_test/logged_in_status_test.rb +9 -3
- data/test/acts_as_authentic_test/login_test.rb +47 -13
- data/test/acts_as_authentic_test/magic_columns_test.rb +4 -4
- data/test/acts_as_authentic_test/password_test.rb +31 -21
- data/test/acts_as_authentic_test/perishable_token_test.rb +15 -15
- data/test/acts_as_authentic_test/session_maintenance_test.rb +20 -13
- data/test/acts_as_authentic_test/single_access_test.rb +8 -8
- data/test/authenticates_many_test.rb +4 -4
- data/test/crypto_provider_test/aes256_test.rb +2 -2
- data/test/crypto_provider_test/scrypt_test.rb +1 -1
- data/test/crypto_provider_test/sha1_test.rb +3 -3
- data/test/crypto_provider_test/sha256_test.rb +1 -1
- data/test/crypto_provider_test/sha512_test.rb +2 -2
- data/test/gemfiles/Gemfile.rails-3.2.x +2 -2
- data/test/gemfiles/Gemfile.rails-5.0.x +6 -0
- data/test/i18n_test.rb +5 -5
- data/test/libs/affiliate.rb +2 -2
- data/test/libs/company.rb +1 -1
- data/test/libs/employee.rb +2 -2
- data/test/libs/employee_session.rb +1 -1
- data/test/libs/ldaper.rb +1 -1
- data/test/libs/project.rb +1 -1
- data/test/random_test.rb +5 -4
- data/test/session_test/activation_test.rb +5 -5
- data/test/session_test/active_record_trickery_test.rb +7 -5
- data/test/session_test/cookies_test.rb +8 -6
- data/test/session_test/existence_test.rb +19 -13
- data/test/session_test/http_auth_test.rb +0 -3
- data/test/session_test/id_test.rb +2 -2
- data/test/session_test/klass_test.rb +1 -1
- data/test/session_test/magic_columns_test.rb +0 -3
- data/test/session_test/magic_states_test.rb +11 -11
- data/test/session_test/params_test.rb +10 -10
- data/test/session_test/password_test.rb +4 -5
- data/test/session_test/perishability_test.rb +3 -3
- data/test/session_test/scopes_test.rb +8 -8
- data/test/session_test/session_test.rb +5 -4
- data/test/session_test/timeout_test.rb +8 -8
- data/test/session_test/unauthorized_record_test.rb +2 -2
- data/test/session_test/validation_test.rb +3 -3
- data/test/test_helper.rb +9 -5
- metadata +54 -24
- data/README.rdoc +0 -232
data/lib/authlogic.rb
CHANGED
@@ -55,5 +55,5 @@ path = File.dirname(__FILE__) + "/authlogic/"
|
|
55
55
|
require path + library
|
56
56
|
end
|
57
57
|
|
58
|
-
require path + "controller_adapters/rails_adapter" if defined?(
|
59
|
-
require path + "controller_adapters/sinatra_adapter" if defined?(
|
58
|
+
require path + "controller_adapters/rails_adapter" if defined?(Rails)
|
59
|
+
require path + "controller_adapters/sinatra_adapter" if defined?(Sinatra)
|
@@ -67,11 +67,12 @@ module Authlogic
|
|
67
67
|
end
|
68
68
|
|
69
69
|
private
|
70
|
+
|
70
71
|
def db_setup?
|
71
72
|
begin
|
72
73
|
column_names
|
73
74
|
true
|
74
|
-
rescue
|
75
|
+
rescue StandardError
|
75
76
|
false
|
76
77
|
end
|
77
78
|
end
|
@@ -99,4 +100,3 @@ end
|
|
99
100
|
::ActiveRecord::Base.send :include, Authlogic::ActsAsAuthentic::SessionMaintenance
|
100
101
|
::ActiveRecord::Base.send :include, Authlogic::ActsAsAuthentic::SingleAccessToken
|
101
102
|
::ActiveRecord::Base.send :include, Authlogic::ActsAsAuthentic::ValidationsScope
|
102
|
-
|
@@ -41,11 +41,11 @@ module Authlogic
|
|
41
41
|
# * <tt>Default:</tt> {:maximum => 100}
|
42
42
|
# * <tt>Accepts:</tt> Hash of options accepted by validates_length_of
|
43
43
|
def validates_length_of_email_field_options(value = nil)
|
44
|
-
rw_config(:validates_length_of_email_field_options, value, {:maximum => 100})
|
44
|
+
rw_config(:validates_length_of_email_field_options, value, { :maximum => 100 })
|
45
45
|
end
|
46
46
|
alias_method :validates_length_of_email_field_options=, :validates_length_of_email_field_options
|
47
47
|
|
48
|
-
# A convenience function to merge options into the validates_length_of_email_field_options. So
|
48
|
+
# A convenience function to merge options into the validates_length_of_email_field_options. So instead of:
|
49
49
|
#
|
50
50
|
# self.validates_length_of_email_field_options = validates_length_of_email_field_options.merge(:my_option => my_value)
|
51
51
|
#
|
@@ -56,19 +56,46 @@ module Authlogic
|
|
56
56
|
self.validates_length_of_email_field_options = validates_length_of_email_field_options.merge(options)
|
57
57
|
end
|
58
58
|
|
59
|
-
# A hash of options for the validates_format_of call for the email
|
59
|
+
# A hash of options for the validates_format_of call for the email
|
60
|
+
# field. Allows you to change this however you want.
|
60
61
|
#
|
61
|
-
# <b>Keep in mind this is ruby. I wanted to keep this as flexible as
|
62
|
-
#
|
63
|
-
#
|
62
|
+
# <b>Keep in mind this is ruby. I wanted to keep this as flexible as
|
63
|
+
# possible, so you can completely replace the hash or merge options into
|
64
|
+
# it. Checkout the convenience function
|
65
|
+
# merge_validates_format_of_email_field_options to merge options.</b>
|
66
|
+
#
|
67
|
+
# To validate international email addresses, enable the provided
|
68
|
+
# alternate regex:
|
64
69
|
#
|
65
|
-
# To validate international email addresses, enable the provided alternate regex:
|
66
70
|
# * <tt>validates_format_of_email_field_options({:with => Authlogic::Regex.email_nonascii})</tt>
|
67
71
|
#
|
68
|
-
# * <tt>Default:</tt>
|
72
|
+
# * <tt>Default:</tt>
|
73
|
+
#
|
74
|
+
# {
|
75
|
+
# :with => Authlogic::Regex.email,
|
76
|
+
# :message => Proc.new {
|
77
|
+
# I18n.t(
|
78
|
+
# 'error_messages.email_invalid',
|
79
|
+
# :default => "should look like an email address."
|
80
|
+
# )
|
81
|
+
# }
|
82
|
+
# }
|
83
|
+
#
|
69
84
|
# * <tt>Accepts:</tt> Hash of options accepted by validates_format_of
|
70
85
|
def validates_format_of_email_field_options(value = nil)
|
71
|
-
rw_config(
|
86
|
+
rw_config(
|
87
|
+
:validates_format_of_email_field_options,
|
88
|
+
value,
|
89
|
+
{
|
90
|
+
:with => Authlogic::Regex.email,
|
91
|
+
:message => Proc.new do
|
92
|
+
I18n.t(
|
93
|
+
'error_messages.email_invalid',
|
94
|
+
:default => "should look like an email address."
|
95
|
+
)
|
96
|
+
end
|
97
|
+
}
|
98
|
+
)
|
72
99
|
end
|
73
100
|
alias_method :validates_format_of_email_field_options=, :validates_format_of_email_field_options
|
74
101
|
|
@@ -77,16 +104,34 @@ module Authlogic
|
|
77
104
|
self.validates_format_of_email_field_options = validates_format_of_email_field_options.merge(options)
|
78
105
|
end
|
79
106
|
|
80
|
-
# A hash of options for the validates_uniqueness_of call for the email
|
107
|
+
# A hash of options for the validates_uniqueness_of call for the email
|
108
|
+
# field. Allows you to change this however you want.
|
81
109
|
#
|
82
|
-
# <b>Keep in mind this is ruby. I wanted to keep this as flexible as
|
83
|
-
#
|
110
|
+
# <b>Keep in mind this is ruby. I wanted to keep this as flexible as
|
111
|
+
# possible, so you can completely replace the hash or merge options into
|
112
|
+
# it. Checkout the convenience function
|
113
|
+
# merge_validates_uniqueness_of_email_field_options to merge
|
84
114
|
# options.</b>
|
85
115
|
#
|
86
|
-
# * <tt>Default:</tt>
|
116
|
+
# * <tt>Default:</tt>
|
117
|
+
#
|
118
|
+
# {
|
119
|
+
# :case_sensitive => false,
|
120
|
+
# :scope => validations_scope,
|
121
|
+
# :if => "#{email_field}_changed?".to_sym
|
122
|
+
# }
|
123
|
+
#
|
87
124
|
# * <tt>Accepts:</tt> Hash of options accepted by validates_uniqueness_of
|
88
125
|
def validates_uniqueness_of_email_field_options(value = nil)
|
89
|
-
rw_config(
|
126
|
+
rw_config(
|
127
|
+
:validates_uniqueness_of_email_field_options,
|
128
|
+
value,
|
129
|
+
{
|
130
|
+
:case_sensitive => false,
|
131
|
+
:scope => validations_scope,
|
132
|
+
:if => "#{email_field}_changed?".to_sym
|
133
|
+
}
|
134
|
+
)
|
90
135
|
end
|
91
136
|
alias_method :validates_uniqueness_of_email_field_options=, :validates_uniqueness_of_email_field_options
|
92
137
|
|
@@ -31,8 +31,8 @@ module Authlogic
|
|
31
31
|
|
32
32
|
klass.class_eval do
|
33
33
|
include InstanceMethods
|
34
|
-
scope :logged_in, lambda{ where("last_request_at > ? and current_login_at IS NOT NULL", logged_in_timeout.seconds.ago) }
|
35
|
-
scope :logged_out, lambda{ where("last_request_at is NULL or last_request_at <= ?", logged_in_timeout.seconds.ago) }
|
34
|
+
scope :logged_in, lambda { where("last_request_at > ? and current_login_at IS NOT NULL", logged_in_timeout.seconds.ago) }
|
35
|
+
scope :logged_out, lambda { where("last_request_at is NULL or last_request_at <= ?", logged_in_timeout.seconds.ago) }
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
@@ -49,6 +49,7 @@ module Authlogic
|
|
49
49
|
end
|
50
50
|
|
51
51
|
private
|
52
|
+
|
52
53
|
def logged_in_timeout
|
53
54
|
self.class.logged_in_timeout
|
54
55
|
end
|
@@ -56,4 +57,4 @@ module Authlogic
|
|
56
57
|
end
|
57
58
|
end
|
58
59
|
end
|
59
|
-
end
|
60
|
+
end
|
@@ -38,7 +38,7 @@ module Authlogic
|
|
38
38
|
# * <tt>Default:</tt> {:within => 3..100}
|
39
39
|
# * <tt>Accepts:</tt> Hash of options accepted by validates_length_of
|
40
40
|
def validates_length_of_login_field_options(value = nil)
|
41
|
-
rw_config(:validates_length_of_login_field_options, value, {:within => 3..100})
|
41
|
+
rw_config(:validates_length_of_login_field_options, value, { :within => 3..100 })
|
42
42
|
end
|
43
43
|
alias_method :validates_length_of_login_field_options=, :validates_length_of_login_field_options
|
44
44
|
|
@@ -59,10 +59,31 @@ module Authlogic
|
|
59
59
|
# merge options into it. Checkout the convenience function merge_validates_format_of_login_field_options to merge
|
60
60
|
# options.</b>
|
61
61
|
#
|
62
|
-
# * <tt>Default:</tt>
|
62
|
+
# * <tt>Default:</tt>
|
63
|
+
#
|
64
|
+
# {
|
65
|
+
# :with => Authlogic::Regex.login,
|
66
|
+
# :message => lambda {
|
67
|
+
# I18n.t(
|
68
|
+
# 'error_messages.login_invalid',
|
69
|
+
# :default => "should use only letters, numbers, spaces, and .-_@+ please."
|
70
|
+
# )
|
71
|
+
# }
|
72
|
+
# }
|
73
|
+
#
|
63
74
|
# * <tt>Accepts:</tt> Hash of options accepted by validates_format_of
|
64
75
|
def validates_format_of_login_field_options(value = nil)
|
65
|
-
rw_config(
|
76
|
+
rw_config(
|
77
|
+
:validates_format_of_login_field_options,
|
78
|
+
value,
|
79
|
+
{
|
80
|
+
:with => Authlogic::Regex.login,
|
81
|
+
:message => I18n.t(
|
82
|
+
'error_messages.login_invalid',
|
83
|
+
:default => "should use only letters, numbers, spaces, and .-_@+ please."
|
84
|
+
)
|
85
|
+
}
|
86
|
+
)
|
66
87
|
end
|
67
88
|
alias_method :validates_format_of_login_field_options=, :validates_format_of_login_field_options
|
68
89
|
|
@@ -71,16 +92,33 @@ module Authlogic
|
|
71
92
|
self.validates_format_of_login_field_options = validates_format_of_login_field_options.merge(options)
|
72
93
|
end
|
73
94
|
|
74
|
-
# A hash of options for the validates_uniqueness_of call for the login
|
95
|
+
# A hash of options for the validates_uniqueness_of call for the login
|
96
|
+
# field. Allows you to change this however you want.
|
75
97
|
#
|
76
|
-
# <b>Keep in mind this is ruby. I wanted to keep this as flexible as
|
77
|
-
#
|
78
|
-
#
|
98
|
+
# <b>Keep in mind this is ruby. I wanted to keep this as flexible as
|
99
|
+
# possible, so you can completely replace the hash or merge options into
|
100
|
+
# it. Checkout the convenience function
|
101
|
+
# merge_validates_format_of_login_field_options to merge options.</b>
|
102
|
+
#
|
103
|
+
# * <tt>Default:</tt>
|
104
|
+
#
|
105
|
+
# {
|
106
|
+
# :case_sensitive => false,
|
107
|
+
# :scope => validations_scope,
|
108
|
+
# :if => "#{login_field}_changed?".to_sym
|
109
|
+
# }
|
79
110
|
#
|
80
|
-
# * <tt>Default:</tt> {:case_sensitive => false, :scope => validations_scope, :if => "#{login_field}_changed?".to_sym}
|
81
111
|
# * <tt>Accepts:</tt> Hash of options accepted by validates_uniqueness_of
|
82
112
|
def validates_uniqueness_of_login_field_options(value = nil)
|
83
|
-
rw_config(
|
113
|
+
rw_config(
|
114
|
+
:validates_uniqueness_of_login_field_options,
|
115
|
+
value,
|
116
|
+
{
|
117
|
+
:case_sensitive => false,
|
118
|
+
:scope => validations_scope,
|
119
|
+
:if => "#{login_field}_changed?".to_sym
|
120
|
+
}
|
121
|
+
)
|
84
122
|
end
|
85
123
|
alias_method :validates_uniqueness_of_login_field_options=, :validates_uniqueness_of_login_field_options
|
86
124
|
|
@@ -112,18 +150,30 @@ module Authlogic
|
|
112
150
|
end
|
113
151
|
|
114
152
|
private
|
153
|
+
|
115
154
|
def find_with_case(field, value, sensitivity = true)
|
155
|
+
ar_gem_version = Gem::Version.new(ActiveRecord::VERSION::STRING)
|
156
|
+
|
116
157
|
relation = if not sensitivity
|
117
158
|
connection.case_insensitive_comparison(arel_table, field.to_s, columns_hash[field.to_s], value)
|
159
|
+
elsif ar_gem_version >= Gem::Version.new('5.0')
|
160
|
+
connection.case_sensitive_comparison(arel_table, field.to_s, columns_hash[field.to_s], value)
|
118
161
|
else
|
119
|
-
if
|
162
|
+
if ar_gem_version < Gem::Version.new('4.2')
|
120
163
|
value = connection.case_sensitive_modifier(value)
|
121
164
|
else
|
122
165
|
value = connection.case_sensitive_modifier(value, field.to_s)
|
123
166
|
end
|
124
|
-
|
167
|
+
arel_table[field.to_s].eq(value)
|
168
|
+
end
|
169
|
+
|
170
|
+
# bind value in rails 5
|
171
|
+
if ar_gem_version >= Gem::Version.new('5')
|
172
|
+
bind = ActiveRecord::Relation::QueryAttribute.new(field.to_s, value, ActiveRecord::Type::Value.new)
|
173
|
+
where(relation, bind).first
|
174
|
+
else
|
175
|
+
where(relation).first
|
125
176
|
end
|
126
|
-
where(relation).first
|
127
177
|
end
|
128
178
|
end
|
129
179
|
|
@@ -1,21 +1,32 @@
|
|
1
1
|
module Authlogic
|
2
2
|
module ActsAsAuthentic
|
3
|
-
# Magic columns are like ActiveRecord's created_at and updated_at columns. They are
|
4
|
-
# you. Authlogic has the same thing, but these are
|
5
|
-
#
|
3
|
+
# Magic columns are like ActiveRecord's created_at and updated_at columns. They are
|
4
|
+
# "magically" maintained for you. Authlogic has the same thing, but these are
|
5
|
+
# maintained on the session side. Please see Authlogic::Session::MagicColumns for more
|
6
|
+
# details. This module merely adds validations for the magic columns if they exist.
|
6
7
|
module MagicColumns
|
7
8
|
def self.included(klass)
|
8
9
|
klass.class_eval do
|
9
10
|
add_acts_as_authentic_module(Methods)
|
10
11
|
end
|
11
12
|
end
|
12
|
-
|
13
|
+
|
13
14
|
# Methods relating to the magic columns
|
14
15
|
module Methods
|
15
16
|
def self.included(klass)
|
16
17
|
klass.class_eval do
|
17
|
-
|
18
|
-
|
18
|
+
if column_names.include?("login_count")
|
19
|
+
validates_numericality_of :login_count,
|
20
|
+
:only_integer => true,
|
21
|
+
:greater_than_or_equal_to => 0,
|
22
|
+
:allow_nil => true
|
23
|
+
end
|
24
|
+
if column_names.include?("failed_login_count")
|
25
|
+
validates_numericality_of :failed_login_count,
|
26
|
+
:only_integer => true,
|
27
|
+
:greater_than_or_equal_to => 0,
|
28
|
+
:allow_nil => true
|
29
|
+
end
|
19
30
|
end
|
20
31
|
end
|
21
32
|
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
module Authlogic
|
2
2
|
module ActsAsAuthentic
|
3
|
-
# This module has a lot of neat functionality. It is responsible for encrypting your
|
4
|
-
# It can also help you transition to a new
|
3
|
+
# This module has a lot of neat functionality. It is responsible for encrypting your
|
4
|
+
# password, salting it, and verifying it. It can also help you transition to a new
|
5
|
+
# encryption algorithm. See the Config sub module for configuration options.
|
5
6
|
module Password
|
6
7
|
def self.included(klass)
|
7
8
|
klass.class_eval do
|
@@ -18,7 +19,11 @@ module Authlogic
|
|
18
19
|
# * <tt>Default:</tt> :crypted_password, :encrypted_password, :password_hash, or :pw_hash
|
19
20
|
# * <tt>Accepts:</tt> Symbol
|
20
21
|
def crypted_password_field(value = nil)
|
21
|
-
rw_config(
|
22
|
+
rw_config(
|
23
|
+
:crypted_password_field,
|
24
|
+
value,
|
25
|
+
first_column_to_exist(nil, :crypted_password, :encrypted_password, :password_hash, :pw_hash)
|
26
|
+
)
|
22
27
|
end
|
23
28
|
alias_method :crypted_password_field=, :crypted_password_field
|
24
29
|
|
@@ -27,12 +32,16 @@ module Authlogic
|
|
27
32
|
# * <tt>Default:</tt> :password_salt, :pw_salt, :salt, nil if none exist
|
28
33
|
# * <tt>Accepts:</tt> Symbol
|
29
34
|
def password_salt_field(value = nil)
|
30
|
-
rw_config(
|
35
|
+
rw_config(
|
36
|
+
:password_salt_field,
|
37
|
+
value,
|
38
|
+
first_column_to_exist(nil, :password_salt, :pw_salt, :salt)
|
39
|
+
)
|
31
40
|
end
|
32
41
|
alias_method :password_salt_field=, :password_salt_field
|
33
42
|
|
34
|
-
# Whether or not to require a password confirmation. If you don't want your users
|
35
|
-
# just set this to false.
|
43
|
+
# Whether or not to require a password confirmation. If you don't want your users
|
44
|
+
# to confirm their password just set this to false.
|
36
45
|
#
|
37
46
|
# * <tt>Default:</tt> true
|
38
47
|
# * <tt>Accepts:</tt> Boolean
|
@@ -41,14 +50,17 @@ module Authlogic
|
|
41
50
|
end
|
42
51
|
alias_method :require_password_confirmation=, :require_password_confirmation
|
43
52
|
|
44
|
-
# By default passwords are required when a record is new or the crypted_password
|
45
|
-
# are met a password is not required. In
|
53
|
+
# By default passwords are required when a record is new or the crypted_password
|
54
|
+
# is blank, but if both of these things are met a password is not required. In
|
55
|
+
# this case, blank passwords are ignored.
|
46
56
|
#
|
47
|
-
# Think about a profile page, where the user can edit all of their information,
|
48
|
-
# If they do not want to change their password
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
57
|
+
# Think about a profile page, where the user can edit all of their information,
|
58
|
+
# including changing their password. If they do not want to change their password
|
59
|
+
# they just leave the fields blank. This will try to set the password to a blank
|
60
|
+
# value, in which case is incorrect behavior. As such, Authlogic ignores this. But
|
61
|
+
# let's say you have a completely separate page for resetting passwords, you might
|
62
|
+
# not want to ignore blank passwords. If this is the case for you, then just set
|
63
|
+
# this value to false.
|
52
64
|
#
|
53
65
|
# * <tt>Default:</tt> true
|
54
66
|
# * <tt>Accepts:</tt> Boolean
|
@@ -57,15 +69,16 @@ module Authlogic
|
|
57
69
|
end
|
58
70
|
alias_method :ignore_blank_passwords=, :ignore_blank_passwords
|
59
71
|
|
60
|
-
# When calling valid_password?("some pass") do you want to check that password
|
61
|
-
# the database. Take this example:
|
72
|
+
# When calling valid_password?("some pass") do you want to check that password
|
73
|
+
# against what's in that object or whats in the database. Take this example:
|
62
74
|
#
|
63
75
|
# u = User.first
|
64
76
|
# u.password = "new pass"
|
65
77
|
# u.valid_password?("old pass")
|
66
78
|
#
|
67
|
-
# Should the last line above return true or false? The record hasn't been saved
|
68
|
-
# Other would assume false. So I let you decide by
|
79
|
+
# Should the last line above return true or false? The record hasn't been saved
|
80
|
+
# yet, so most would assume true. Other would assume false. So I let you decide by
|
81
|
+
# giving you this option.
|
69
82
|
#
|
70
83
|
# * <tt>Default:</tt> true
|
71
84
|
# * <tt>Accepts:</tt> Boolean
|
@@ -83,22 +96,26 @@ module Authlogic
|
|
83
96
|
end
|
84
97
|
alias_method :validate_password_field=, :validate_password_field
|
85
98
|
|
86
|
-
# A hash of options for the validates_length_of call for the password field.
|
99
|
+
# A hash of options for the validates_length_of call for the password field.
|
100
|
+
# Allows you to change this however you want.
|
87
101
|
#
|
88
|
-
# <b>Keep in mind this is ruby. I wanted to keep this as flexible as possible, so
|
89
|
-
# merge options into it. Checkout the
|
102
|
+
# <b>Keep in mind this is ruby. I wanted to keep this as flexible as possible, so
|
103
|
+
# you can completely replace the hash or merge options into it. Checkout the
|
104
|
+
# convenience function merge_validates_length_of_password_field_options to merge
|
90
105
|
# options.</b>
|
91
106
|
#
|
92
|
-
# * <tt>Default:</tt> {:minimum =>
|
107
|
+
# * <tt>Default:</tt> {:minimum => 8, :if => :require_password?}
|
93
108
|
# * <tt>Accepts:</tt> Hash of options accepted by validates_length_of
|
94
109
|
def validates_length_of_password_field_options(value = nil)
|
95
|
-
rw_config(:validates_length_of_password_field_options, value, {:minimum =>
|
110
|
+
rw_config(:validates_length_of_password_field_options, value, { :minimum => 8, :if => :require_password? })
|
96
111
|
end
|
97
112
|
alias_method :validates_length_of_password_field_options=, :validates_length_of_password_field_options
|
98
113
|
|
99
|
-
# A convenience function to merge options into the
|
114
|
+
# A convenience function to merge options into the
|
115
|
+
# validates_length_of_login_field_options. So instead of:
|
100
116
|
#
|
101
|
-
# self.validates_length_of_password_field_options =
|
117
|
+
# self.validates_length_of_password_field_options =
|
118
|
+
# validates_length_of_password_field_options.merge(:my_option => my_value)
|
102
119
|
#
|
103
120
|
# You can do this:
|
104
121
|
#
|
@@ -107,44 +124,56 @@ module Authlogic
|
|
107
124
|
self.validates_length_of_password_field_options = validates_length_of_password_field_options.merge(options)
|
108
125
|
end
|
109
126
|
|
110
|
-
# A hash of options for the validates_confirmation_of call for the password field.
|
127
|
+
# A hash of options for the validates_confirmation_of call for the password field.
|
128
|
+
# Allows you to change this however you want.
|
111
129
|
#
|
112
|
-
# <b>Keep in mind this is ruby. I wanted to keep this as flexible as possible, so
|
113
|
-
# merge options into it. Checkout the
|
130
|
+
# <b>Keep in mind this is ruby. I wanted to keep this as flexible as possible, so
|
131
|
+
# you can completely replace the hash or merge options into it. Checkout the
|
132
|
+
# convenience function merge_validates_length_of_password_field_options to merge
|
114
133
|
# options.</b>
|
115
134
|
#
|
116
135
|
# * <tt>Default:</tt> {:if => :require_password?}
|
117
136
|
# * <tt>Accepts:</tt> Hash of options accepted by validates_confirmation_of
|
118
137
|
def validates_confirmation_of_password_field_options(value = nil)
|
119
|
-
rw_config(:validates_confirmation_of_password_field_options, value, {:if => :require_password?})
|
138
|
+
rw_config(:validates_confirmation_of_password_field_options, value, { :if => :require_password? })
|
120
139
|
end
|
121
140
|
alias_method :validates_confirmation_of_password_field_options=, :validates_confirmation_of_password_field_options
|
122
141
|
|
123
|
-
# See merge_validates_length_of_password_field_options. The same thing, except for
|
142
|
+
# See merge_validates_length_of_password_field_options. The same thing, except for
|
143
|
+
# validates_confirmation_of_password_field_options
|
124
144
|
def merge_validates_confirmation_of_password_field_options(options = {})
|
125
145
|
self.validates_confirmation_of_password_field_options = validates_confirmation_of_password_field_options.merge(options)
|
126
146
|
end
|
127
147
|
|
128
|
-
# A hash of options for the validates_length_of call for the password_confirmation
|
148
|
+
# A hash of options for the validates_length_of call for the password_confirmation
|
149
|
+
# field. Allows you to change this however you want.
|
129
150
|
#
|
130
|
-
# <b>Keep in mind this is ruby. I wanted to keep this as flexible as possible, so
|
131
|
-
# merge options into it. Checkout the
|
151
|
+
# <b>Keep in mind this is ruby. I wanted to keep this as flexible as possible, so
|
152
|
+
# you can completely replace the hash or merge options into it. Checkout the
|
153
|
+
# convenience function merge_validates_length_of_password_field_options to merge
|
132
154
|
# options.</b>
|
133
155
|
#
|
134
156
|
# * <tt>Default:</tt> validates_length_of_password_field_options
|
135
157
|
# * <tt>Accepts:</tt> Hash of options accepted by validates_length_of
|
136
158
|
def validates_length_of_password_confirmation_field_options(value = nil)
|
137
|
-
rw_config(
|
159
|
+
rw_config(
|
160
|
+
:validates_length_of_password_confirmation_field_options,
|
161
|
+
value,
|
162
|
+
validates_length_of_password_field_options
|
163
|
+
)
|
138
164
|
end
|
139
165
|
alias_method :validates_length_of_password_confirmation_field_options=, :validates_length_of_password_confirmation_field_options
|
140
166
|
|
141
|
-
# See merge_validates_length_of_password_field_options. The same thing, except for
|
167
|
+
# See merge_validates_length_of_password_field_options. The same thing, except for
|
168
|
+
# validates_length_of_password_confirmation_field_options
|
142
169
|
def merge_validates_length_of_password_confirmation_field_options(options = {})
|
143
|
-
self.validates_length_of_password_confirmation_field_options =
|
170
|
+
self.validates_length_of_password_confirmation_field_options =
|
171
|
+
validates_length_of_password_confirmation_field_options.merge(options)
|
144
172
|
end
|
145
173
|
|
146
|
-
# The class you want to use to encrypt and verify your encrypted passwords. See
|
147
|
-
# on the available methods and
|
174
|
+
# The class you want to use to encrypt and verify your encrypted passwords. See
|
175
|
+
# the Authlogic::CryptoProviders module for more info on the available methods and
|
176
|
+
# how to create your own.
|
148
177
|
#
|
149
178
|
# * <tt>Default:</tt> CryptoProviders::SCrypt
|
150
179
|
# * <tt>Accepts:</tt> Class
|
@@ -153,14 +182,17 @@ module Authlogic
|
|
153
182
|
end
|
154
183
|
alias_method :crypto_provider=, :crypto_provider
|
155
184
|
|
156
|
-
# Let's say you originally encrypted your passwords with Sha1. Sha1 is starting to
|
157
|
-
#
|
158
|
-
#
|
159
|
-
#
|
160
|
-
#
|
185
|
+
# Let's say you originally encrypted your passwords with Sha1. Sha1 is starting to
|
186
|
+
# join the party with MD5 and you want to switch to something stronger. No
|
187
|
+
# problem, just specify your new and improved algorithm with the crypt_provider
|
188
|
+
# option and then let Authlogic know you are transitioning from Sha1 using this
|
189
|
+
# option. Authlogic will take care of everything, including transitioning your
|
190
|
+
# users to the new algorithm. The next time a user logs in, they will be granted
|
191
|
+
# access using the old algorithm and their password will be resaved with the new
|
192
|
+
# algorithm. All new users will obviously use the new algorithm as well.
|
161
193
|
#
|
162
|
-
# Lastly, if you want to transition again, you can pass an array of crypto
|
163
|
-
# as you want.
|
194
|
+
# Lastly, if you want to transition again, you can pass an array of crypto
|
195
|
+
# providers. So you can transition from as many algorithms as you want.
|
164
196
|
#
|
165
197
|
# * <tt>Default:</tt> nil
|
166
198
|
# * <tt>Accepts:</tt> Class or Array
|
@@ -194,6 +226,7 @@ module Authlogic
|
|
194
226
|
end
|
195
227
|
|
196
228
|
private
|
229
|
+
|
197
230
|
METHODS.each do |method|
|
198
231
|
class_eval <<-"end_eval", __FILE__, __LINE__
|
199
232
|
def #{method}
|
@@ -230,23 +263,36 @@ module Authlogic
|
|
230
263
|
@password
|
231
264
|
end
|
232
265
|
|
233
|
-
# This is a virtual method. Once a password is passed to it, it will
|
234
|
-
# the password.
|
266
|
+
# This is a virtual method. Once a password is passed to it, it will
|
267
|
+
# create new password salt as well as encrypt the password.
|
235
268
|
def password=(pass)
|
236
269
|
return if ignore_blank_passwords? && pass.blank?
|
237
270
|
before_password_set
|
238
271
|
@password = pass
|
239
272
|
send("#{password_salt_field}=", Authlogic::Random.friendly_token) if password_salt_field
|
240
|
-
send(
|
273
|
+
send(
|
274
|
+
"#{crypted_password_field}=",
|
275
|
+
crypto_provider.encrypt(
|
276
|
+
*encrypt_arguments(@password, false, act_like_restful_authentication? ? :restful_authentication : nil)
|
277
|
+
)
|
278
|
+
)
|
241
279
|
@password_changed = true
|
242
280
|
after_password_set
|
243
281
|
end
|
244
282
|
|
245
|
-
# Accepts a raw password to determine if it is the correct password or not.
|
246
|
-
#
|
247
|
-
#
|
283
|
+
# Accepts a raw password to determine if it is the correct password or not.
|
284
|
+
# Notice the second argument. That defaults to the value of
|
285
|
+
# check_passwords_against_database. See that method for more information, but
|
286
|
+
# basically it just tells Authlogic to check the password against the value in
|
287
|
+
# the database or the value in the object.
|
248
288
|
def valid_password?(attempted_password, check_against_database = check_passwords_against_database?)
|
249
|
-
crypted =
|
289
|
+
crypted =
|
290
|
+
if check_against_database && send("#{crypted_password_field}_changed?")
|
291
|
+
send("#{crypted_password_field}_was")
|
292
|
+
else
|
293
|
+
send(crypted_password_field)
|
294
|
+
end
|
295
|
+
|
250
296
|
return false if attempted_password.blank? || crypted.blank?
|
251
297
|
before_password_verification
|
252
298
|
|
@@ -282,6 +328,7 @@ module Authlogic
|
|
282
328
|
alias_method :randomize_password!, :reset_password!
|
283
329
|
|
284
330
|
private
|
331
|
+
|
285
332
|
def check_passwords_against_database?
|
286
333
|
self.class.check_passwords_against_database == true
|
287
334
|
end
|
@@ -292,7 +339,14 @@ module Authlogic
|
|
292
339
|
|
293
340
|
def encrypt_arguments(raw_password, check_against_database, arguments_type = nil)
|
294
341
|
salt = nil
|
295
|
-
|
342
|
+
if password_salt_field
|
343
|
+
salt =
|
344
|
+
if check_against_database && send("#{password_salt_field}_changed?")
|
345
|
+
send("#{password_salt_field}_was")
|
346
|
+
else
|
347
|
+
send(password_salt_field)
|
348
|
+
end
|
349
|
+
end
|
296
350
|
|
297
351
|
case arguments_type
|
298
352
|
when :restful_authentication
|
@@ -302,7 +356,7 @@ module Authlogic
|
|
302
356
|
end
|
303
357
|
end
|
304
358
|
|
305
|
-
# Determines if we need to
|
359
|
+
# Determines if we need to transition the password.
|
306
360
|
# If the index > 0 then we are using an "transition from" crypto provider.
|
307
361
|
# If the encryptor has a cost and the cost it outdated.
|
308
362
|
# If we aren't using database values
|