authlogic 4.0.1 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
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?