authlogic 4.0.1 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +43 -1
  3. data/.rubocop_todo.yml +23 -132
  4. data/CHANGELOG.md +12 -0
  5. data/CONTRIBUTING.md +10 -3
  6. data/Gemfile +2 -2
  7. data/Rakefile +6 -6
  8. data/authlogic.gemspec +13 -12
  9. data/lib/authlogic/acts_as_authentic/base.rb +12 -7
  10. data/lib/authlogic/acts_as_authentic/email.rb +16 -6
  11. data/lib/authlogic/acts_as_authentic/logged_in_status.rb +10 -5
  12. data/lib/authlogic/acts_as_authentic/login.rb +11 -5
  13. data/lib/authlogic/acts_as_authentic/password.rb +111 -57
  14. data/lib/authlogic/acts_as_authentic/perishable_token.rb +6 -2
  15. data/lib/authlogic/acts_as_authentic/persistence_token.rb +1 -1
  16. data/lib/authlogic/acts_as_authentic/queries/find_with_case.rb +2 -2
  17. data/lib/authlogic/acts_as_authentic/restful_authentication.rb +31 -3
  18. data/lib/authlogic/acts_as_authentic/session_maintenance.rb +11 -3
  19. data/lib/authlogic/acts_as_authentic/single_access_token.rb +14 -2
  20. data/lib/authlogic/acts_as_authentic/validations_scope.rb +6 -6
  21. data/lib/authlogic/authenticates_many/association.rb +2 -2
  22. data/lib/authlogic/authenticates_many/base.rb +27 -19
  23. data/lib/authlogic/controller_adapters/rack_adapter.rb +1 -1
  24. data/lib/authlogic/controller_adapters/rails_adapter.rb +6 -3
  25. data/lib/authlogic/controller_adapters/sinatra_adapter.rb +2 -2
  26. data/lib/authlogic/crypto_providers.rb +2 -0
  27. data/lib/authlogic/crypto_providers/bcrypt.rb +15 -9
  28. data/lib/authlogic/crypto_providers/md5.rb +2 -1
  29. data/lib/authlogic/crypto_providers/scrypt.rb +12 -7
  30. data/lib/authlogic/crypto_providers/sha256.rb +2 -1
  31. data/lib/authlogic/crypto_providers/wordpress.rb +31 -2
  32. data/lib/authlogic/i18n.rb +22 -17
  33. data/lib/authlogic/regex.rb +57 -29
  34. data/lib/authlogic/session/activation.rb +1 -1
  35. data/lib/authlogic/session/brute_force_protection.rb +2 -2
  36. data/lib/authlogic/session/callbacks.rb +43 -36
  37. data/lib/authlogic/session/cookies.rb +4 -2
  38. data/lib/authlogic/session/existence.rb +1 -1
  39. data/lib/authlogic/session/foundation.rb +5 -1
  40. data/lib/authlogic/session/http_auth.rb +2 -2
  41. data/lib/authlogic/session/klass.rb +2 -1
  42. data/lib/authlogic/session/magic_columns.rb +4 -2
  43. data/lib/authlogic/session/magic_states.rb +9 -10
  44. data/lib/authlogic/session/params.rb +11 -4
  45. data/lib/authlogic/session/password.rb +72 -38
  46. data/lib/authlogic/session/perishable_token.rb +2 -1
  47. data/lib/authlogic/session/persistence.rb +2 -1
  48. data/lib/authlogic/session/scopes.rb +26 -16
  49. data/lib/authlogic/session/unauthorized_record.rb +12 -7
  50. data/lib/authlogic/session/validation.rb +1 -1
  51. data/lib/authlogic/test_case/mock_controller.rb +1 -1
  52. data/lib/authlogic/test_case/mock_cookie_jar.rb +1 -1
  53. data/lib/authlogic/test_case/mock_request.rb +1 -1
  54. data/lib/authlogic/version.rb +1 -1
  55. data/test/acts_as_authentic_test/base_test.rb +1 -1
  56. data/test/acts_as_authentic_test/email_test.rb +11 -11
  57. data/test/acts_as_authentic_test/logged_in_status_test.rb +4 -4
  58. data/test/acts_as_authentic_test/login_test.rb +2 -2
  59. data/test/acts_as_authentic_test/magic_columns_test.rb +1 -1
  60. data/test/acts_as_authentic_test/password_test.rb +1 -1
  61. data/test/acts_as_authentic_test/perishable_token_test.rb +2 -2
  62. data/test/acts_as_authentic_test/persistence_token_test.rb +1 -1
  63. data/test/acts_as_authentic_test/restful_authentication_test.rb +12 -3
  64. data/test/acts_as_authentic_test/session_maintenance_test.rb +1 -1
  65. data/test/acts_as_authentic_test/single_access_test.rb +1 -1
  66. data/test/adapter_test.rb +3 -3
  67. data/test/authenticates_many_test.rb +1 -1
  68. data/test/config_test.rb +9 -9
  69. data/test/crypto_provider_test/aes256_test.rb +1 -1
  70. data/test/crypto_provider_test/bcrypt_test.rb +1 -1
  71. data/test/crypto_provider_test/scrypt_test.rb +1 -1
  72. data/test/crypto_provider_test/sha1_test.rb +1 -1
  73. data/test/crypto_provider_test/sha256_test.rb +1 -1
  74. data/test/crypto_provider_test/sha512_test.rb +1 -1
  75. data/test/crypto_provider_test/wordpress_test.rb +24 -0
  76. data/test/i18n_test.rb +3 -3
  77. data/test/libs/user_session.rb +2 -2
  78. data/test/random_test.rb +1 -1
  79. data/test/session_test/activation_test.rb +1 -1
  80. data/test/session_test/active_record_trickery_test.rb +3 -3
  81. data/test/session_test/brute_force_protection_test.rb +1 -1
  82. data/test/session_test/callbacks_test.rb +9 -3
  83. data/test/session_test/cookies_test.rb +11 -11
  84. data/test/session_test/existence_test.rb +1 -1
  85. data/test/session_test/foundation_test.rb +1 -1
  86. data/test/session_test/http_auth_test.rb +6 -6
  87. data/test/session_test/id_test.rb +1 -1
  88. data/test/session_test/klass_test.rb +1 -1
  89. data/test/session_test/magic_columns_test.rb +1 -1
  90. data/test/session_test/magic_states_test.rb +1 -1
  91. data/test/session_test/params_test.rb +7 -4
  92. data/test/session_test/password_test.rb +1 -1
  93. data/test/session_test/perishability_test.rb +1 -1
  94. data/test/session_test/persistence_test.rb +1 -1
  95. data/test/session_test/scopes_test.rb +9 -3
  96. data/test/session_test/session_test.rb +2 -2
  97. data/test/session_test/timeout_test.rb +1 -1
  98. data/test/session_test/unauthorized_record_test.rb +1 -1
  99. data/test/session_test/validation_test.rb +1 -1
  100. data/test/test_helper.rb +34 -14
  101. metadata +6 -4
@@ -1,28 +1,29 @@
1
1
  module Authlogic
2
- # This is a module the contains regular expressions used throughout Authlogic. The point
3
- # of extracting them out into their own module is to make them easily available to you
4
- # for other uses. Ex:
2
+ # This is a module the contains regular expressions used throughout Authlogic.
3
+ # The point of extracting them out into their own module is to make them
4
+ # easily available to you for other uses. Ex:
5
5
  #
6
6
  # validates_format_of :my_email_field, :with => Authlogic::Regex.email
7
7
  module Regex
8
- # A general email regular expression. It allows top level domains (TLD) to be from 2 -
9
- # 24 in length. The decisions behind this regular expression were made by analyzing
10
- # the list of top-level domains maintained by IANA and by reading this website:
11
- # http://www.regular-expressions.info/email.html, which is an excellent resource for
12
- # regular expressions.
13
- def self.email
14
- @email_regex ||= begin
15
- email_name_regex = '[A-Z0-9_\.&%\+\-\']+'
16
- domain_head_regex = '(?:[A-Z0-9\-]+\.)+'
17
- domain_tld_regex = '(?:[A-Z]{2,25})'
18
- /\A#{email_name_regex}@#{domain_head_regex}#{domain_tld_regex}\z/i
19
- end
20
- end
8
+ # A general email regular expression. It allows top level domains (TLD) to
9
+ # be from 2 - 24 in length. The decisions behind this regular expression
10
+ # were made by analyzing the list of top-level domains maintained by IANA
11
+ # and by reading this website:
12
+ # http://www.regular-expressions.info/email.html, which is an excellent
13
+ # resource for regular expressions.
14
+ EMAIL = /
15
+ \A
16
+ [A-Z0-9_.&%+\-']+ # mailbox
17
+ @
18
+ (?:[A-Z0-9\-]+\.)+ # subdomains
19
+ (?:[A-Z]{2,25}) # TLD
20
+ \z
21
+ /ix
21
22
 
22
- # A draft regular expression for internationalized email addresses. Given that the
23
- # standard may be in flux, this simply emulates @email_regex but rather than allowing
24
- # specific characters for each part, it instead disallows the complement set of
25
- # characters:
23
+ # A draft regular expression for internationalized email addresses. Given
24
+ # that the standard may be in flux, this simply emulates @email_regex but
25
+ # rather than allowing specific characters for each part, it instead
26
+ # disallows the complement set of characters:
26
27
  #
27
28
  # - email_name_regex disallows: @[]^ !"#$()*,/:;<=>?`{|}~\ and control characters
28
29
  # - domain_head_regex disallows: _%+ and all characters in email_name_regex
@@ -33,19 +34,46 @@ module Authlogic
33
34
  # http://www.unicode.org/faq/idn.html
34
35
  # http://ruby-doc.org/core-2.1.5/Regexp.html#class-Regexp-label-Character+Classes
35
36
  # http://en.wikipedia.org/wiki/Unicode_character_property#General_Category
36
- def self.email_nonascii
37
- @email_nonascii_regex ||= begin
38
- email_name_regex = '[^[:cntrl:][@\[\]\^ \!\"#$\(\)*,/:;<=>\?`{|}~\\\]]+'
39
- domain_head_regex = '(?:[^[:cntrl:][@\[\]\^ \!\"#$&\(\)*,/:;<=>\?`{|}~\\\_\.%\+\']]+\.)+'
40
- domain_tld_regex = '(?:[^[:cntrl:][@\[\]\^ \!\"#$&\(\)*,/:;<=>\?`{|}~\\\_\.%\+\-\'0-9]]{2,25})'
41
- /\A#{email_name_regex}@#{domain_head_regex}#{domain_tld_regex}\z/
42
- end
43
- end
37
+ EMAIL_NONASCII = /
38
+ \A
39
+ [^[:cntrl:][@\[\]\^ \!"\#$\(\)*,\/:;<=>?`{|}~\\]]+ # mailbox
40
+ @
41
+ (?:[^[:cntrl:][@\[\]\^ \!\"\#$&\(\)*,\/:;<=>\?`{|}~\\_.%+']]+\.)+ # subdomains
42
+ (?:[^[:cntrl:][@\[\]\^ \!\"\#$&\(\)*,\/:;<=>\?`{|}~\\_.%+\-'0-9]]{2,25}) # TLD
43
+ \z
44
+ /x
44
45
 
45
46
  # A simple regular expression that only allows for letters, numbers, spaces, and
46
47
  # .-_@+. Just a standard login / username regular expression.
48
+ LOGIN = /\A[a-zA-Z0-9_][a-zA-Z0-9\.+\-_@ ]+\z/
49
+
50
+ # Accessing the above constants using the following methods is deprecated.
51
+
52
+ # @deprecated
53
+ def self.email
54
+ ::ActiveSupport::Deprecation.warn(
55
+ "Authlogic::Regex.email is deprecated, use Authlogic::Regex::EMAIL",
56
+ caller(1)
57
+ )
58
+ EMAIL
59
+ end
60
+
61
+ # @deprecated
62
+ def self.email_nonascii
63
+ ::ActiveSupport::Deprecation.warn(
64
+ "Authlogic::Regex.email_nonascii is deprecated, use Authlogic::Regex::EMAIL_NONASCII",
65
+ caller(1)
66
+ )
67
+ EMAIL_NONASCII
68
+ end
69
+
70
+ # @deprecated
47
71
  def self.login
48
- /\A[a-zA-Z0-9_][a-zA-Z0-9\.+\-_@ ]+\z/
72
+ ::ActiveSupport::Deprecation.warn(
73
+ "Authlogic::Regex.login is deprecated, use Authlogic::Regex::LOGIN",
74
+ caller(1)
75
+ )
76
+ LOGIN
49
77
  end
50
78
  end
51
79
  end
@@ -1,4 +1,4 @@
1
- require 'request_store'
1
+ require "request_store"
2
2
 
3
3
  module Authlogic
4
4
  module Session
@@ -106,9 +106,9 @@ module Authlogic
106
106
  errors.add(
107
107
  :base,
108
108
  I18n.t(
109
- 'error_messages.consecutive_failed_logins_limit_exceeded',
109
+ "error_messages.consecutive_failed_logins_limit_exceeded",
110
110
  default: "Consecutive failed logins limit exceeded, account has been" +
111
- (failed_login_ban_for == 0 ? "" : " temporarily") +
111
+ (failed_login_ban_for.zero? ? "" : " temporarily") +
112
112
  " disabled."
113
113
  )
114
114
  )
@@ -58,61 +58,68 @@ module Authlogic
58
58
  # allow Authlogic to extend properly with multiple extensions. Please ONLY use the
59
59
  # method above.
60
60
  module Callbacks
61
- METHODS = [
62
- "before_persisting",
63
- "persist",
64
- "after_persisting",
65
- "before_validation",
66
- "before_validation_on_create",
67
- "before_validation_on_update",
68
- "validate",
69
- "after_validation_on_update",
70
- "after_validation_on_create",
71
- "after_validation",
72
- "before_save",
73
- "before_create",
74
- "before_update",
75
- "after_update",
76
- "after_create",
77
- "after_save",
78
- "before_destroy",
79
- "after_destroy"
61
+ METHODS = %w[
62
+ before_persisting
63
+ persist
64
+ after_persisting
65
+ before_validation
66
+ before_validation_on_create
67
+ before_validation_on_update
68
+ validate
69
+ after_validation_on_update
70
+ after_validation_on_create
71
+ after_validation
72
+ before_save
73
+ before_create
74
+ before_update
75
+ after_update
76
+ after_create
77
+ after_save
78
+ before_destroy
79
+ after_destroy
80
80
  ].freeze
81
81
 
82
82
  def self.included(base) #:nodoc:
83
83
  base.send :include, ActiveSupport::Callbacks
84
- if Gem::Version.new(ActiveSupport::VERSION::STRING) >= Gem::Version.new('5')
84
+
85
+ if Gem::Version.new(ActiveSupport::VERSION::STRING) >= Gem::Version.new("5")
85
86
  base.define_callbacks(
86
87
  *METHODS + [{ terminator: ->(_target, result_lambda) { result_lambda.call == false } }]
87
88
  )
88
89
  base.define_callbacks(
89
- 'persist',
90
+ "persist",
90
91
  terminator: ->(_target, result_lambda) { result_lambda.call == true }
91
92
  )
92
- elsif Gem::Version.new(ActiveSupport::VERSION::STRING) >= Gem::Version.new('4.1')
93
- base.define_callbacks(*METHODS + [{ terminator: ->(_target, result) { result == false } }])
94
- base.define_callbacks('persist', terminator: ->(_target, result) { result == true })
95
93
  else
96
- base.define_callbacks(*METHODS + [{ terminator: 'result == false' }])
97
- base.define_callbacks('persist', terminator: 'result == true')
94
+ base.define_callbacks(
95
+ *METHODS + [{ terminator: ->(_target, result) { result == false } }]
96
+ )
97
+ base.define_callbacks("persist", terminator: ->(_target, result) { result == true })
98
98
  end
99
99
 
100
- # If Rails 3, support the new callback syntax
101
- if base.singleton_class.method_defined?(:set_callback)
102
- METHODS.each do |method|
103
- base.class_eval <<-EOS, __FILE__, __LINE__
104
- def self.#{method}(*methods, &block)
105
- set_callback :#{method}, *methods, &block
106
- end
107
- EOS
108
- end
100
+ # Now we define the "callback installation methods". These class methods
101
+ # will be used by other modules to install their callbacks. Examples:
102
+ #
103
+ # ```
104
+ # # Timeout.included
105
+ # before_persisting :reset_stale_state
106
+ #
107
+ # # Session::Password.included
108
+ # validate :validate_by_password, if: :authenticating_with_password?
109
+ # ```
110
+ METHODS.each do |method|
111
+ base.class_eval <<-EOS, __FILE__, __LINE__ + 1
112
+ def self.#{method}(*methods, &block)
113
+ set_callback :#{method}, *methods, &block
114
+ end
115
+ EOS
109
116
  end
110
117
  end
111
118
 
112
119
  private
113
120
 
114
121
  METHODS.each do |method|
115
- class_eval <<-EOS, __FILE__, __LINE__
122
+ class_eval <<-EOS, __FILE__, __LINE__ + 1
116
123
  def #{method}
117
124
  run_callbacks(:#{method})
118
125
  end
@@ -3,7 +3,7 @@ module Authlogic
3
3
  # Handles all authentication that deals with cookies, such as persisting,
4
4
  # saving, and destroying.
5
5
  module Cookies
6
- VALID_SAME_SITE_VALUES = [nil, 'Lax', 'Strict'].freeze
6
+ VALID_SAME_SITE_VALUES = [nil, "Lax", "Strict"].freeze
7
7
 
8
8
  def self.included(klass)
9
9
  klass.class_eval do
@@ -244,7 +244,9 @@ module Authlogic
244
244
  persistence_token, record_id = cookie_credentials
245
245
  if persistence_token.present?
246
246
  record = search_for_record("find_by_#{klass.primary_key}", record_id)
247
- self.unauthorized_record = record if record && record.persistence_token == persistence_token
247
+ if record && record.persistence_token == persistence_token
248
+ self.unauthorized_record = record
249
+ end
248
250
  valid?
249
251
  else
250
252
  false
@@ -6,7 +6,7 @@ module Authlogic
6
6
  class SessionInvalidError < ::StandardError # :nodoc:
7
7
  def initialize(session)
8
8
  message = I18n.t(
9
- 'error_messages.session_invalid',
9
+ "error_messages.session_invalid",
10
10
  default: "Your session is invalid and has the following errors:"
11
11
  )
12
12
  message += " #{session.errors.full_messages.to_sentence}"
@@ -87,7 +87,11 @@ module Authlogic
87
87
  end
88
88
 
89
89
  def inspect
90
- "#<#{self.class.name}: #{credentials.blank? ? "no credentials provided" : credentials.inspect}>"
90
+ format(
91
+ "#<%s: %s>",
92
+ self.class.name,
93
+ credentials.blank? ? "no credentials provided" : credentials.inspect
94
+ )
91
95
  end
92
96
 
93
97
  private
@@ -64,7 +64,7 @@ module Authlogic
64
64
  # * <tt>Default:</tt> 'Application'
65
65
  # * <tt>Accepts:</tt> String
66
66
  def http_basic_auth_realm(value = nil)
67
- rw_config(:http_basic_auth_realm, value, 'Application')
67
+ rw_config(:http_basic_auth_realm, value, "Application")
68
68
  end
69
69
  alias_method :http_basic_auth_realm=, :http_basic_auth_realm
70
70
  end
@@ -78,7 +78,7 @@ module Authlogic
78
78
  end
79
79
 
80
80
  def persist_by_http_auth
81
- login_proc = Proc.new do |login, password|
81
+ login_proc = proc do |login, password|
82
82
  if !login.blank? && !password.blank?
83
83
  send("#{login_field}=", login)
84
84
  send("#{password_field}=", password)
@@ -42,7 +42,8 @@ module Authlogic
42
42
  end
43
43
 
44
44
  module InstanceMethods
45
- # Creating an alias method for the "record" method based on the klass name, so that we can do:
45
+ # Creating an alias method for the "record" method based on the klass
46
+ # name, so that we can do:
46
47
  #
47
48
  # session.user
48
49
  #
@@ -43,7 +43,8 @@ module Authlogic
43
43
  alias_method :last_request_at_threshold=, :last_request_at_threshold
44
44
  end
45
45
 
46
- # The methods available for an Authlogic::Session::Base object that make up the magic columns feature.
46
+ # The methods available for an Authlogic::Session::Base object that make
47
+ # up the magic columns feature.
47
48
  module InstanceMethods
48
49
  private
49
50
 
@@ -109,7 +110,8 @@ module Authlogic
109
110
  if !record || !klass.column_names.include?("last_request_at")
110
111
  return false
111
112
  end
112
- if controller.responds_to_last_request_update_allowed? && !controller.last_request_update_allowed?
113
+ if controller.responds_to_last_request_update_allowed? &&
114
+ !controller.last_request_update_allowed?
113
115
  return false
114
116
  end
115
117
  record.last_request_at.blank? ||
@@ -56,7 +56,7 @@ module Authlogic
56
56
 
57
57
  # @api private
58
58
  def required_magic_states_for(record)
59
- [:active, :approved, :confirmed].select { |state|
59
+ %i[active approved confirmed].select { |state|
60
60
  record.respond_to?("#{state}?")
61
61
  }
62
62
  end
@@ -64,16 +64,15 @@ module Authlogic
64
64
  def validate_magic_states
65
65
  return true if attempted_record.nil?
66
66
  required_magic_states_for(attempted_record).each do |required_status|
67
- unless attempted_record.send("#{required_status}?")
68
- errors.add(
69
- :base,
70
- I18n.t(
71
- "error_messages.not_#{required_status}",
72
- default: "Your account is not #{required_status}"
73
- )
67
+ next if attempted_record.send("#{required_status}?")
68
+ errors.add(
69
+ :base,
70
+ I18n.t(
71
+ "error_messages.not_#{required_status}",
72
+ default: "Your account is not #{required_status}"
74
73
  )
75
- return false
76
- end
74
+ )
75
+ return false
77
76
  end
78
77
  true
79
78
  end
@@ -82,20 +82,27 @@ module Authlogic
82
82
 
83
83
  def persist_by_params
84
84
  return false unless params_enabled?
85
- self.unauthorized_record = search_for_record("find_by_single_access_token", params_credentials)
85
+ self.unauthorized_record = search_for_record(
86
+ "find_by_single_access_token",
87
+ params_credentials
88
+ )
86
89
  self.single_access = valid?
87
90
  end
88
91
 
89
92
  def params_enabled?
90
- return false if !params_credentials || !klass.column_names.include?("single_access_token")
91
- return controller.single_access_allowed? if controller.responds_to_single_access_allowed?
93
+ if !params_credentials || !klass.column_names.include?("single_access_token")
94
+ return false
95
+ end
96
+ if controller.responds_to_single_access_allowed?
97
+ return controller.single_access_allowed?
98
+ end
92
99
 
93
100
  case single_access_allowed_request_types
94
101
  when Array
95
102
  single_access_allowed_request_types.include?(controller.request_content_type) ||
96
103
  single_access_allowed_request_types.include?(:all)
97
104
  else
98
- [:all, :any].include?(single_access_allowed_request_types)
105
+ %i[all any].include?(single_access_allowed_request_types)
99
106
  end
100
107
  end
101
108
 
@@ -119,7 +119,7 @@ module Authlogic
119
119
  # should be an instance method. It should also be prepared to accept a
120
120
  # raw password and a crytped password.
121
121
  #
122
- # * <tt>Default:</tt> "valid_password?"
122
+ # * <tt>Default:</tt> "valid_password?" defined in acts_as_authentic/password.rb
123
123
  # * <tt>Accepts:</tt> Symbol or String
124
124
  def verify_password_method(value = nil)
125
125
  rw_config(:verify_password_method, value, "valid_password?")
@@ -162,7 +162,11 @@ module Authlogic
162
162
  super
163
163
  values = Array.wrap(value)
164
164
  if values.first.is_a?(Hash)
165
- values.first.with_indifferent_access.slice(login_field, password_field).each do |field, val|
165
+ sliced = values
166
+ .first
167
+ .with_indifferent_access
168
+ .slice(login_field, password_field)
169
+ sliced.each do |field, val|
166
170
  next if val.blank?
167
171
  send("#{field}=", val)
168
172
  end
@@ -179,7 +183,10 @@ module Authlogic
179
183
  if generalize_credentials_error_messages?
180
184
  add_general_credentials_error
181
185
  else
182
- errors.add(password_field, I18n.t('error_messages.password_invalid', default: "is not valid"))
186
+ errors.add(
187
+ password_field,
188
+ I18n.t("error_messages.password_invalid", default: "is not valid")
189
+ )
183
190
  end
184
191
  end
185
192
 
@@ -187,60 +194,84 @@ module Authlogic
187
194
  if generalize_credentials_error_messages?
188
195
  add_general_credentials_error
189
196
  else
190
- errors.add(login_field, I18n.t('error_messages.login_not_found', default: "is not valid"))
197
+ errors.add(
198
+ login_field,
199
+ I18n.t("error_messages.login_not_found", default: "is not valid")
200
+ )
191
201
  end
192
202
  end
193
203
 
194
- def configure_password_methods
195
- if login_field
196
- self.class.send(:attr_writer, login_field) unless respond_to?("#{login_field}=")
197
- self.class.send(:attr_reader, login_field) unless respond_to?(login_field)
198
- end
204
+ def authenticating_with_password?
205
+ login_field && (!send(login_field).nil? || !send("protected_#{password_field}").nil?)
206
+ end
199
207
 
200
- if password_field
201
- self.class.send(:attr_writer, password_field) unless respond_to?("#{password_field}=")
202
- self.class.send(:define_method, password_field) {} unless respond_to?(password_field)
208
+ def configure_password_methods
209
+ define_login_field_methods
210
+ define_password_field_methods
211
+ end
203
212
 
204
- # The password should not be accessible publicly. This way forms
205
- # using form_for don't fill the password with the attempted
206
- # password. To prevent this we just create this method that is
207
- # private.
208
- self.class.class_eval <<-EOS, __FILE__, __LINE__
209
- private
210
- def protected_#{password_field}
211
- @#{password_field}
212
- end
213
- EOS
214
- end
213
+ def define_login_field_methods
214
+ return unless login_field
215
+ self.class.send(:attr_writer, login_field) unless respond_to?("#{login_field}=")
216
+ self.class.send(:attr_reader, login_field) unless respond_to?(login_field)
215
217
  end
216
218
 
217
- def authenticating_with_password?
218
- login_field && (!send(login_field).nil? || !send("protected_#{password_field}").nil?)
219
+ def define_password_field_methods
220
+ return unless password_field
221
+ self.class.send(:attr_writer, password_field) unless respond_to?("#{password_field}=")
222
+ self.class.send(:define_method, password_field) {} unless respond_to?(password_field)
223
+
224
+ # The password should not be accessible publicly. This way forms
225
+ # using form_for don't fill the password with the attempted
226
+ # password. To prevent this we just create this method that is
227
+ # private.
228
+ self.class.class_eval <<-EOS, __FILE__, __LINE__ + 1
229
+ private
230
+ def protected_#{password_field}
231
+ @#{password_field}
232
+ end
233
+ EOS
219
234
  end
220
235
 
236
+ # In keeping with the metaphor of ActiveRecord, verification of the
237
+ # password is referred to as a "validation".
221
238
  def validate_by_password
222
239
  self.invalid_password = false
223
-
224
- # check for blank fields
225
- if send(login_field).blank?
226
- errors.add(login_field, I18n.t('error_messages.login_blank', default: "cannot be blank"))
227
- end
228
- if send("protected_#{password_field}").blank?
229
- errors.add(password_field, I18n.t('error_messages.password_blank', default: "cannot be blank"))
230
- end
240
+ validate_by_password__blank_fields
231
241
  return if errors.count > 0
232
-
233
242
  self.attempted_record = search_for_record(find_by_login_method, send(login_field))
234
243
  if attempted_record.blank?
235
244
  add_login_not_found_error
236
245
  return
237
246
  end
247
+ validate_by_password__invalid_password
248
+ end
249
+
250
+ def validate_by_password__blank_fields
251
+ if send(login_field).blank?
252
+ errors.add(
253
+ login_field,
254
+ I18n.t("error_messages.login_blank", default: "cannot be blank")
255
+ )
256
+ end
257
+ if send("protected_#{password_field}").blank?
258
+ errors.add(
259
+ password_field,
260
+ I18n.t("error_messages.password_blank", default: "cannot be blank")
261
+ )
262
+ end
263
+ end
238
264
 
239
- # check for invalid password
240
- unless attempted_record.send(verify_password_method, send("protected_#{password_field}"))
265
+ # Verify the password, usually using `valid_password?` in
266
+ # `acts_as_authentic/password.rb`. If it cannot be verified, we
267
+ # refer to it as "invalid".
268
+ def validate_by_password__invalid_password
269
+ unless attempted_record.send(
270
+ verify_password_method,
271
+ send("protected_#{password_field}")
272
+ )
241
273
  self.invalid_password = true
242
274
  add_invalid_password_error
243
- return
244
275
  end
245
276
  end
246
277
 
@@ -261,7 +292,10 @@ module Authlogic
261
292
  else
262
293
  "#{login_field.to_s.humanize}/Password combination is not valid"
263
294
  end
264
- errors.add(:base, I18n.t('error_messages.general_credentials_error', default: error_message))
295
+ errors.add(
296
+ :base,
297
+ I18n.t("error_messages.general_credentials_error", default: error_message)
298
+ )
265
299
  end
266
300
 
267
301
  def generalize_credentials_error_messages?