authlogic 2.0.1 → 2.1.1

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 (82) hide show
  1. data/.gitignore +9 -0
  2. data/CHANGELOG.rdoc +105 -1
  3. data/{MIT-LICENSE → LICENSE} +1 -1
  4. data/README.rdoc +137 -160
  5. data/Rakefile +47 -19
  6. data/VERSION.yml +4 -0
  7. data/authlogic.gemspec +205 -0
  8. data/init.rb +1 -1
  9. data/lib/authlogic/acts_as_authentic/base.rb +31 -17
  10. data/lib/authlogic/acts_as_authentic/email.rb +47 -14
  11. data/lib/authlogic/acts_as_authentic/logged_in_status.rb +20 -14
  12. data/lib/authlogic/acts_as_authentic/login.rb +84 -8
  13. data/lib/authlogic/acts_as_authentic/password.rb +207 -88
  14. data/lib/authlogic/acts_as_authentic/perishable_token.rb +9 -4
  15. data/lib/authlogic/acts_as_authentic/persistence_token.rb +4 -2
  16. data/lib/authlogic/acts_as_authentic/restful_authentication.rb +5 -4
  17. data/lib/authlogic/acts_as_authentic/session_maintenance.rb +16 -4
  18. data/lib/authlogic/acts_as_authentic/single_access_token.rb +10 -3
  19. data/lib/authlogic/acts_as_authentic/validations_scope.rb +1 -1
  20. data/lib/authlogic/controller_adapters/abstract_adapter.rb +13 -1
  21. data/lib/authlogic/controller_adapters/rails_adapter.rb +14 -4
  22. data/lib/authlogic/crypto_providers/aes256.rb +2 -2
  23. data/lib/authlogic/crypto_providers/bcrypt.rb +3 -1
  24. data/lib/authlogic/crypto_providers/sha1.rb +2 -2
  25. data/lib/authlogic/i18n.rb +10 -1
  26. data/lib/authlogic/regex.rb +25 -0
  27. data/lib/authlogic/session/activation.rb +2 -0
  28. data/lib/authlogic/session/active_record_trickery.rb +13 -3
  29. data/lib/authlogic/session/brute_force_protection.rb +26 -11
  30. data/lib/authlogic/session/callbacks.rb +16 -6
  31. data/lib/authlogic/session/cookies.rb +16 -12
  32. data/lib/authlogic/session/existence.rb +4 -2
  33. data/lib/authlogic/session/foundation.rb +1 -1
  34. data/lib/authlogic/session/http_auth.rb +46 -11
  35. data/lib/authlogic/session/magic_columns.rb +25 -6
  36. data/lib/authlogic/session/magic_states.rb +4 -4
  37. data/lib/authlogic/session/params.rb +14 -9
  38. data/lib/authlogic/session/password.rb +86 -24
  39. data/lib/authlogic/session/priority_record.rb +1 -1
  40. data/lib/authlogic/session/session.rb +2 -2
  41. data/lib/authlogic/session/timeout.rb +1 -1
  42. data/lib/authlogic/session/validation.rb +9 -5
  43. data/lib/authlogic/test_case/mock_controller.rb +45 -0
  44. data/lib/authlogic/test_case/mock_cookie_jar.rb +14 -0
  45. data/lib/authlogic/test_case/mock_logger.rb +10 -0
  46. data/lib/authlogic/test_case/mock_request.rb +19 -0
  47. data/lib/authlogic/test_case/rails_request_adapter.rb +30 -0
  48. data/lib/authlogic/test_case.rb +114 -0
  49. data/lib/authlogic.rb +1 -1
  50. data/rails/init.rb +1 -0
  51. data/shoulda_macros/authlogic.rb +2 -1
  52. data/test/acts_as_authentic_test/base_test.rb +6 -0
  53. data/test/acts_as_authentic_test/email_test.rb +25 -7
  54. data/test/acts_as_authentic_test/login_test.rb +37 -7
  55. data/test/acts_as_authentic_test/magic_columns_test.rb +4 -4
  56. data/test/acts_as_authentic_test/password_test.rb +46 -44
  57. data/test/acts_as_authentic_test/perishable_token_test.rb +36 -2
  58. data/test/acts_as_authentic_test/restful_authentication_test.rb +40 -0
  59. data/test/acts_as_authentic_test/session_maintenance_test.rb +26 -18
  60. data/test/acts_as_authentic_test/single_access_test.rb +6 -1
  61. data/test/libs/affiliate.rb +7 -0
  62. data/test/libs/ldaper.rb +3 -0
  63. data/test/random_test.rb +2 -2
  64. data/test/session_test/activation_test.rb +1 -1
  65. data/test/session_test/active_record_trickery_test.rb +2 -1
  66. data/test/session_test/brute_force_protection_test.rb +34 -9
  67. data/test/session_test/cookies_test.rb +3 -3
  68. data/test/session_test/http_auth_test.rb +20 -8
  69. data/test/session_test/magic_columns_test.rb +7 -4
  70. data/test/session_test/magic_states_test.rb +3 -3
  71. data/test/session_test/params_test.rb +4 -4
  72. data/test/session_test/password_test.rb +8 -0
  73. data/test/session_test/session_test.rb +9 -9
  74. data/test/session_test/timeout_test.rb +10 -1
  75. data/test/test_helper.rb +43 -21
  76. metadata +38 -27
  77. data/Manifest.txt +0 -111
  78. data/lib/authlogic/testing/test_unit_helpers.rb +0 -39
  79. data/lib/authlogic/version.rb +0 -56
  80. data/test/libs/mock_controller.rb +0 -35
  81. data/test/libs/mock_cookie_jar.rb +0 -10
  82. data/test/libs/mock_request.rb +0 -5
data/authlogic.gemspec ADDED
@@ -0,0 +1,205 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{authlogic}
5
+ s.version = "2.1.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Ben Johnson of Binary Logic"]
9
+ s.date = %q{2009-07-04}
10
+ s.email = %q{bjohnson@binarylogic.com}
11
+ s.extra_rdoc_files = [
12
+ "LICENSE",
13
+ "README.rdoc"
14
+ ]
15
+ s.files = [
16
+ ".gitignore",
17
+ "CHANGELOG.rdoc",
18
+ "LICENSE",
19
+ "README.rdoc",
20
+ "Rakefile",
21
+ "VERSION.yml",
22
+ "authlogic.gemspec",
23
+ "generators/session/session_generator.rb",
24
+ "generators/session/templates/session.rb",
25
+ "init.rb",
26
+ "lib/authlogic.rb",
27
+ "lib/authlogic/acts_as_authentic/base.rb",
28
+ "lib/authlogic/acts_as_authentic/email.rb",
29
+ "lib/authlogic/acts_as_authentic/logged_in_status.rb",
30
+ "lib/authlogic/acts_as_authentic/login.rb",
31
+ "lib/authlogic/acts_as_authentic/magic_columns.rb",
32
+ "lib/authlogic/acts_as_authentic/password.rb",
33
+ "lib/authlogic/acts_as_authentic/perishable_token.rb",
34
+ "lib/authlogic/acts_as_authentic/persistence_token.rb",
35
+ "lib/authlogic/acts_as_authentic/restful_authentication.rb",
36
+ "lib/authlogic/acts_as_authentic/session_maintenance.rb",
37
+ "lib/authlogic/acts_as_authentic/single_access_token.rb",
38
+ "lib/authlogic/acts_as_authentic/validations_scope.rb",
39
+ "lib/authlogic/authenticates_many/association.rb",
40
+ "lib/authlogic/authenticates_many/base.rb",
41
+ "lib/authlogic/controller_adapters/abstract_adapter.rb",
42
+ "lib/authlogic/controller_adapters/merb_adapter.rb",
43
+ "lib/authlogic/controller_adapters/rails_adapter.rb",
44
+ "lib/authlogic/crypto_providers/aes256.rb",
45
+ "lib/authlogic/crypto_providers/bcrypt.rb",
46
+ "lib/authlogic/crypto_providers/md5.rb",
47
+ "lib/authlogic/crypto_providers/sha1.rb",
48
+ "lib/authlogic/crypto_providers/sha512.rb",
49
+ "lib/authlogic/i18n.rb",
50
+ "lib/authlogic/random.rb",
51
+ "lib/authlogic/regex.rb",
52
+ "lib/authlogic/session/activation.rb",
53
+ "lib/authlogic/session/active_record_trickery.rb",
54
+ "lib/authlogic/session/base.rb",
55
+ "lib/authlogic/session/brute_force_protection.rb",
56
+ "lib/authlogic/session/callbacks.rb",
57
+ "lib/authlogic/session/cookies.rb",
58
+ "lib/authlogic/session/existence.rb",
59
+ "lib/authlogic/session/foundation.rb",
60
+ "lib/authlogic/session/http_auth.rb",
61
+ "lib/authlogic/session/id.rb",
62
+ "lib/authlogic/session/klass.rb",
63
+ "lib/authlogic/session/magic_columns.rb",
64
+ "lib/authlogic/session/magic_states.rb",
65
+ "lib/authlogic/session/params.rb",
66
+ "lib/authlogic/session/password.rb",
67
+ "lib/authlogic/session/perishable_token.rb",
68
+ "lib/authlogic/session/persistence.rb",
69
+ "lib/authlogic/session/priority_record.rb",
70
+ "lib/authlogic/session/scopes.rb",
71
+ "lib/authlogic/session/session.rb",
72
+ "lib/authlogic/session/timeout.rb",
73
+ "lib/authlogic/session/unauthorized_record.rb",
74
+ "lib/authlogic/session/validation.rb",
75
+ "lib/authlogic/test_case.rb",
76
+ "lib/authlogic/test_case/mock_controller.rb",
77
+ "lib/authlogic/test_case/mock_cookie_jar.rb",
78
+ "lib/authlogic/test_case/mock_logger.rb",
79
+ "lib/authlogic/test_case/mock_request.rb",
80
+ "lib/authlogic/test_case/rails_request_adapter.rb",
81
+ "rails/init.rb",
82
+ "shoulda_macros/authlogic.rb",
83
+ "test/acts_as_authentic_test/base_test.rb",
84
+ "test/acts_as_authentic_test/email_test.rb",
85
+ "test/acts_as_authentic_test/logged_in_status_test.rb",
86
+ "test/acts_as_authentic_test/login_test.rb",
87
+ "test/acts_as_authentic_test/magic_columns_test.rb",
88
+ "test/acts_as_authentic_test/password_test.rb",
89
+ "test/acts_as_authentic_test/perishable_token_test.rb",
90
+ "test/acts_as_authentic_test/persistence_token_test.rb",
91
+ "test/acts_as_authentic_test/restful_authentication_test.rb",
92
+ "test/acts_as_authentic_test/session_maintenance_test.rb",
93
+ "test/acts_as_authentic_test/single_access_test.rb",
94
+ "test/authenticates_many_test.rb",
95
+ "test/crypto_provider_test/aes256_test.rb",
96
+ "test/crypto_provider_test/bcrypt_test.rb",
97
+ "test/crypto_provider_test/sha1_test.rb",
98
+ "test/crypto_provider_test/sha512_test.rb",
99
+ "test/fixtures/companies.yml",
100
+ "test/fixtures/employees.yml",
101
+ "test/fixtures/projects.yml",
102
+ "test/fixtures/users.yml",
103
+ "test/libs/affiliate.rb",
104
+ "test/libs/company.rb",
105
+ "test/libs/employee.rb",
106
+ "test/libs/employee_session.rb",
107
+ "test/libs/ldaper.rb",
108
+ "test/libs/ordered_hash.rb",
109
+ "test/libs/project.rb",
110
+ "test/libs/user.rb",
111
+ "test/libs/user_session.rb",
112
+ "test/random_test.rb",
113
+ "test/session_test/activation_test.rb",
114
+ "test/session_test/active_record_trickery_test.rb",
115
+ "test/session_test/brute_force_protection_test.rb",
116
+ "test/session_test/callbacks_test.rb",
117
+ "test/session_test/cookies_test.rb",
118
+ "test/session_test/credentials_test.rb",
119
+ "test/session_test/existence_test.rb",
120
+ "test/session_test/http_auth_test.rb",
121
+ "test/session_test/id_test.rb",
122
+ "test/session_test/klass_test.rb",
123
+ "test/session_test/magic_columns_test.rb",
124
+ "test/session_test/magic_states_test.rb",
125
+ "test/session_test/params_test.rb",
126
+ "test/session_test/password_test.rb",
127
+ "test/session_test/perishability_test.rb",
128
+ "test/session_test/persistence_test.rb",
129
+ "test/session_test/scopes_test.rb",
130
+ "test/session_test/session_test.rb",
131
+ "test/session_test/timeout_test.rb",
132
+ "test/session_test/unauthorized_record_test.rb",
133
+ "test/session_test/validation_test.rb",
134
+ "test/test_helper.rb"
135
+ ]
136
+ s.homepage = %q{http://github.com/binarylogic/authlogic}
137
+ s.rdoc_options = ["--charset=UTF-8"]
138
+ s.require_paths = ["lib"]
139
+ s.rubyforge_project = %q{authlogic}
140
+ s.rubygems_version = %q{1.3.4}
141
+ s.summary = %q{A clean, simple, and unobtrusive ruby authentication solution.}
142
+ s.test_files = [
143
+ "test/acts_as_authentic_test/base_test.rb",
144
+ "test/acts_as_authentic_test/email_test.rb",
145
+ "test/acts_as_authentic_test/logged_in_status_test.rb",
146
+ "test/acts_as_authentic_test/login_test.rb",
147
+ "test/acts_as_authentic_test/magic_columns_test.rb",
148
+ "test/acts_as_authentic_test/password_test.rb",
149
+ "test/acts_as_authentic_test/perishable_token_test.rb",
150
+ "test/acts_as_authentic_test/persistence_token_test.rb",
151
+ "test/acts_as_authentic_test/restful_authentication_test.rb",
152
+ "test/acts_as_authentic_test/session_maintenance_test.rb",
153
+ "test/acts_as_authentic_test/single_access_test.rb",
154
+ "test/authenticates_many_test.rb",
155
+ "test/crypto_provider_test/aes256_test.rb",
156
+ "test/crypto_provider_test/bcrypt_test.rb",
157
+ "test/crypto_provider_test/sha1_test.rb",
158
+ "test/crypto_provider_test/sha512_test.rb",
159
+ "test/libs/affiliate.rb",
160
+ "test/libs/company.rb",
161
+ "test/libs/employee.rb",
162
+ "test/libs/employee_session.rb",
163
+ "test/libs/ldaper.rb",
164
+ "test/libs/ordered_hash.rb",
165
+ "test/libs/project.rb",
166
+ "test/libs/user.rb",
167
+ "test/libs/user_session.rb",
168
+ "test/random_test.rb",
169
+ "test/session_test/activation_test.rb",
170
+ "test/session_test/active_record_trickery_test.rb",
171
+ "test/session_test/brute_force_protection_test.rb",
172
+ "test/session_test/callbacks_test.rb",
173
+ "test/session_test/cookies_test.rb",
174
+ "test/session_test/credentials_test.rb",
175
+ "test/session_test/existence_test.rb",
176
+ "test/session_test/http_auth_test.rb",
177
+ "test/session_test/id_test.rb",
178
+ "test/session_test/klass_test.rb",
179
+ "test/session_test/magic_columns_test.rb",
180
+ "test/session_test/magic_states_test.rb",
181
+ "test/session_test/params_test.rb",
182
+ "test/session_test/password_test.rb",
183
+ "test/session_test/perishability_test.rb",
184
+ "test/session_test/persistence_test.rb",
185
+ "test/session_test/scopes_test.rb",
186
+ "test/session_test/session_test.rb",
187
+ "test/session_test/timeout_test.rb",
188
+ "test/session_test/unauthorized_record_test.rb",
189
+ "test/session_test/validation_test.rb",
190
+ "test/test_helper.rb"
191
+ ]
192
+
193
+ if s.respond_to? :specification_version then
194
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
195
+ s.specification_version = 3
196
+
197
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
198
+ s.add_runtime_dependency(%q<activesupport>, [">= 0"])
199
+ else
200
+ s.add_dependency(%q<activesupport>, [">= 0"])
201
+ end
202
+ else
203
+ s.add_dependency(%q<activesupport>, [">= 0"])
204
+ end
205
+ end
data/init.rb CHANGED
@@ -1 +1 @@
1
- require "authlogic"
1
+ require File.dirname(__FILE__) + "/rails/init.rb"
@@ -23,13 +23,12 @@ 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
- begin
29
- column_names
30
- rescue Exception
31
- return
32
- end
28
+ return if !db_setup?
29
+
30
+ raise ArgumentError.new("You are using the old v1.X.X configuration method for Authlogic. Instead of " +
31
+ "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?
33
32
 
34
33
  yield self if block_given?
35
34
  acts_as_authentic_modules.each { |mod| include mod }
@@ -41,9 +40,14 @@ module Authlogic
41
40
  # nothing to do with Authlogic.
42
41
  #
43
42
  # That being said, this is your tool for extending Authlogic and "hooking" into the acts_as_authentic call.
44
- def add_acts_as_authentic_module(mod)
43
+ def add_acts_as_authentic_module(mod, action = :append)
45
44
  modules = acts_as_authentic_modules
46
- modules << mod
45
+ case action
46
+ when :append
47
+ modules << mod
48
+ when :prepend
49
+ modules = [mod] + modules
50
+ end
47
51
  modules.uniq!
48
52
  write_inheritable_attribute(:acts_as_authentic_modules, modules)
49
53
  end
@@ -53,25 +57,35 @@ module Authlogic
53
57
  acts_as_authentic_modules.delete(mod)
54
58
  acts_as_authentic_modules
55
59
  end
56
-
60
+
57
61
  private
58
62
  def acts_as_authentic_modules
59
63
  key = :acts_as_authentic_modules
60
64
  inheritable_attributes.include?(key) ? read_inheritable_attribute(key) : []
61
65
  end
62
-
63
- def config(key, value, default_value = nil, read_value = nil)
66
+
67
+ def db_setup?
68
+ begin
69
+ column_names
70
+ true
71
+ rescue Exception
72
+ false
73
+ end
74
+ end
75
+
76
+ def rw_config(key, value, default_value = nil, read_value = nil)
64
77
  if value == read_value
65
- return read_inheritable_attribute(key) if inheritable_attributes.include?(key)
66
- write_inheritable_attribute(key, default_value)
78
+ inheritable_attributes.include?(key) ? read_inheritable_attribute(key) : default_value
67
79
  else
68
80
  write_inheritable_attribute(key, value)
69
81
  end
70
82
  end
71
-
72
- def first_column_to_exist(*columns_to_check) # :nodoc:
73
- columns_to_check.each { |column_name| return column_name.to_sym if column_names.include?(column_name.to_s) }
74
- columns_to_check.first ? columns_to_check.first.to_sym : nil
83
+
84
+ def first_column_to_exist(*columns_to_check)
85
+ if db_setup?
86
+ columns_to_check.each { |column_name| return column_name.to_sym if column_names.include?(column_name.to_s) }
87
+ end
88
+ columns_to_check.first && columns_to_check.first.to_sym
75
89
  end
76
90
  end
77
91
  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
+ rw_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
 
@@ -28,36 +28,69 @@ module Authlogic
28
28
  # * <tt>Default:</tt> true
29
29
  # * <tt>Accepts:</tt> Boolean
30
30
  def validate_email_field(value = nil)
31
- config(:validate_email_field, value, true)
31
+ rw_config(:validate_email_field, value, true)
32
32
  end
33
33
  alias_method :validate_email_field=, :validate_email_field
34
34
 
35
35
  # A hash of options for the validates_length_of call for the email field. Allows you to change this however you want.
36
36
  #
37
+ # <b>Keep in mind this is ruby. I wanted to keep this as flexible as possible, so you can completely replace the hash or
38
+ # merge options into it. Checkout the convenience function merge_validates_length_of_email_field_options to merge
39
+ # options.</b>
40
+ #
37
41
  # * <tt>Default:</tt> {:within => 6..100}
38
42
  # * <tt>Accepts:</tt> Hash of options accepted by validates_length_of
39
43
  def validates_length_of_email_field_options(value = nil)
40
- config(:validates_length_of_email_field_options, value, {:within => 6..100})
44
+ rw_config(:validates_length_of_email_field_options, value, {:within => 6..100})
41
45
  end
42
46
  alias_method :validates_length_of_email_field_options=, :validates_length_of_email_field_options
43
47
 
48
+ # A convenience function to merge options into the validates_length_of_email_field_options. So intead of:
49
+ #
50
+ # self.validates_length_of_email_field_options = validates_length_of_email_field_options.merge(:my_option => my_value)
51
+ #
52
+ # You can do this:
53
+ #
54
+ # merge_validates_length_of_email_field_options :my_option => my_value
55
+ def merge_validates_length_of_email_field_options(options = {})
56
+ self.validates_length_of_email_field_options = validates_length_of_email_field_options.merge(options)
57
+ end
58
+
44
59
  # A hash of options for the validates_format_of call for the email field. Allows you to change this however you want.
45
60
  #
46
- # * <tt>Default:</tt> {:with => email_regex, :message => I18n.t('error_messages.email_invalid', :default => "should look like an email address.")}
61
+ # <b>Keep in mind this is ruby. I wanted to keep this as flexible as possible, so you can completely replace the hash or
62
+ # merge options into it. Checkout the convenience function merge_validates_format_of_email_field_options to merge
63
+ # options.</b>
64
+ #
65
+ # * <tt>Default:</tt> {:with => Authlogic::Regex.email, :message => I18n.t('error_messages.email_invalid', :default => "should look like an email address.")}
47
66
  # * <tt>Accepts:</tt> Hash of options accepted by validates_format_of
48
67
  def validates_format_of_email_field_options(value = nil)
49
- config(:validates_format_of_email_field_options, value, {:with => email_regex, :message => I18n.t('error_messages.email_invalid', :default => "should look like an email address.")})
68
+ rw_config(:validates_format_of_email_field_options, value, {:with => Authlogic::Regex.email, :message => I18n.t('error_messages.email_invalid', :default => "should look like an email address.")})
50
69
  end
51
70
  alias_method :validates_format_of_email_field_options=, :validates_format_of_email_field_options
52
71
 
53
- private
54
- def email_regex
55
- return @email_regex if @email_regex
56
- email_name_regex = '[\w\.%\+\-]+'
57
- domain_head_regex = '(?:[A-Z0-9\-]+\.)+'
58
- domain_tld_regex = '(?:[A-Z]{2}|aero|ag|asia|at|be|biz|ca|cc|cn|com|de|edu|eu|fm|gov|gs|jobs|jp|in|info|me|mil|mobi|museum|ms|name|net|nu|nz|org|tc|tw|tv|uk|us|vg|ws)'
59
- @email_regex = /\A#{email_name_regex}@#{domain_head_regex}#{domain_tld_regex}\z/i
60
- end
72
+ # See merge_validates_length_of_email_field_options. The same thing except for validates_format_of_email_field_options.
73
+ def merge_validates_format_of_email_field_options(options = {})
74
+ self.validates_format_of_email_field_options = validates_format_of_email_field_options.merge(options)
75
+ end
76
+
77
+ # A hash of options for the validates_uniqueness_of call for the email field. Allows you to change this however you want.
78
+ #
79
+ # <b>Keep in mind this is ruby. I wanted to keep this as flexible as possible, so you can completely replace the hash or
80
+ # merge options into it. Checkout the convenience function merge_validates_uniqueness_of_email_field_options to merge
81
+ # options.</b>
82
+ #
83
+ # * <tt>Default:</tt> {:case_sensitive => false, :scope => validations_scope, :if => "#{email_field}_changed?".to_sym}
84
+ # * <tt>Accepts:</tt> Hash of options accepted by validates_uniqueness_of
85
+ def validates_uniqueness_of_email_field_options(value = nil)
86
+ rw_config(:validates_uniqueness_of_email_field_options, value, {:case_sensitive => false, :scope => validations_scope, :if => "#{email_field}_changed?".to_sym})
87
+ end
88
+ alias_method :validates_uniqueness_of_email_field_options=, :validates_uniqueness_of_email_field_options
89
+
90
+ # See merge_validates_length_of_email_field_options. The same thing except for validates_uniqueness_of_email_field_options.
91
+ def merge_validates_uniqueness_of_email_field_options(options = {})
92
+ self.validates_uniqueness_of_email_field_options = validates_uniqueness_of_email_field_options.merge(options)
93
+ end
61
94
  end
62
95
 
63
96
  # All methods relating to the email field
@@ -67,7 +100,7 @@ module Authlogic
67
100
  if validate_email_field && email_field
68
101
  validates_length_of email_field, validates_length_of_email_field_options
69
102
  validates_format_of email_field, validates_format_of_email_field_options
70
- validates_uniqueness_of email_field, :scope => validations_scope, :if => "#{email_field}_changed?".to_sym
103
+ validates_uniqueness_of email_field, validates_uniqueness_of_email_field_options
71
104
  end
72
105
  end
73
106
  end
@@ -19,7 +19,7 @@ module Authlogic
19
19
  # * <tt>Default:</tt> 10.minutes
20
20
  # * <tt>Accepts:</tt> Fixnum
21
21
  def logged_in_timeout(value = nil)
22
- config(:logged_in_timeout, (!value.nil? && value.to_i) || value, 10.minutes.to_i)
22
+ rw_config(:logged_in_timeout, (!value.nil? && value.to_i) || value, 10.minutes.to_i)
23
23
  end
24
24
  alias_method :logged_in_timeout=, :logged_in_timeout
25
25
  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
- # Returns true if the last_request_at > logged_in_timeout.
37
- def logged_in?
38
- raise "Can not determine the records login state because there is no last_request_at column" if !respond_to?(:last_request_at)
39
- !last_request_at.nil? && last_request_at > logged_in_timeout.seconds.ago
40
- end
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
- private
48
- def logged_in_timeout
49
- self.class.logged_in_timeout
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
@@ -16,7 +16,7 @@ module Authlogic
16
16
  # * <tt>Default:</tt> :login or :username, if they exist
17
17
  # * <tt>Accepts:</tt> Symbol
18
18
  def login_field(value = nil)
19
- config(:login_field, value, first_column_to_exist(nil, :login, :username))
19
+ rw_config(:login_field, value, first_column_to_exist(nil, :login, :username))
20
20
  end
21
21
  alias_method :login_field=, :login_field
22
22
 
@@ -25,37 +25,113 @@ module Authlogic
25
25
  # * <tt>Default:</tt> true
26
26
  # * <tt>Accepts:</tt> Boolean
27
27
  def validate_login_field(value = nil)
28
- config(:validate_login_field, value, true)
28
+ rw_config(:validate_login_field, value, true)
29
29
  end
30
30
  alias_method :validate_login_field=, :validate_login_field
31
31
 
32
32
  # A hash of options for the validates_length_of call for the login field. Allows you to change this however you want.
33
33
  #
34
- # * <tt>Default:</tt> {:within => 6..100}
34
+ # <b>Keep in mind this is ruby. I wanted to keep this as flexible as possible, so you can completely replace the hash or
35
+ # merge options into it. Checkout the convenience function merge_validates_length_of_login_field_options to merge
36
+ # options.</b>
37
+ #
38
+ # * <tt>Default:</tt> {:within => 3..100}
35
39
  # * <tt>Accepts:</tt> Hash of options accepted by validates_length_of
36
40
  def validates_length_of_login_field_options(value = nil)
37
- config(:validates_length_of_login_field_options, value, {:within => 3..100})
41
+ rw_config(:validates_length_of_login_field_options, value, {:within => 3..100})
38
42
  end
39
43
  alias_method :validates_length_of_login_field_options=, :validates_length_of_login_field_options
40
44
 
41
- # A hash of options for the validates_format_of call for the email field. Allows you to change this however you want.
45
+ # A convenience function to merge options into the validates_length_of_login_field_options. So intead of:
46
+ #
47
+ # self.validates_length_of_login_field_options = validates_length_of_login_field_options.merge(:my_option => my_value)
48
+ #
49
+ # You can do this:
50
+ #
51
+ # merge_validates_length_of_login_field_options :my_option => my_value
52
+ def merge_validates_length_of_login_field_options(options = {})
53
+ self.validates_length_of_login_field_options = validates_length_of_login_field_options.merge(options)
54
+ end
55
+
56
+ # A hash of options for the validates_format_of call for the login field. Allows you to change this however you want.
57
+ #
58
+ # <b>Keep in mind this is ruby. I wanted to keep this as flexible as possible, so you can completely replace the hash or
59
+ # merge options into it. Checkout the convenience function merge_validates_format_of_login_field_options to merge
60
+ # options.</b>
42
61
  #
43
- # * <tt>Default:</tt> {:with => /\A\w[\w\.\-_@ ]+\z/, :message => I18n.t('error_messages.login_invalid', :default => "should use only letters, numbers, spaces, and .-_@ please.")}
62
+ # * <tt>Default:</tt> {:with => Authlogic::Regex.login, :message => I18n.t('error_messages.login_invalid', :default => "should use only letters, numbers, spaces, and .-_@ please.")}
44
63
  # * <tt>Accepts:</tt> Hash of options accepted by validates_format_of
45
64
  def validates_format_of_login_field_options(value = nil)
46
- config(:validates_format_of_login_field_options, value, {:with => /\A\w[\w\.\-_@ ]+\z/, :message => I18n.t('error_messages.login_invalid', :default => "should use only letters, numbers, spaces, and .-_@ please.")})
65
+ rw_config(:validates_format_of_login_field_options, value, {:with => Authlogic::Regex.login, :message => I18n.t('error_messages.login_invalid', :default => "should use only letters, numbers, spaces, and .-_@ please.")})
47
66
  end
48
67
  alias_method :validates_format_of_login_field_options=, :validates_format_of_login_field_options
68
+
69
+ # See merge_validates_length_of_login_field_options. The same thing, except for validates_format_of_login_field_options
70
+ def merge_validates_format_of_login_field_options(options = {})
71
+ self.validates_format_of_login_field_options = validates_format_of_login_field_options.merge(options)
72
+ end
73
+
74
+ # A hash of options for the validates_uniqueness_of call for the login field. Allows you to change this however you want.
75
+ #
76
+ # <b>Keep in mind this is ruby. I wanted to keep this as flexible as possible, so you can completely replace the hash or
77
+ # merge options into it. Checkout the convenience function merge_validates_format_of_login_field_options to merge
78
+ # options.</b>
79
+ #
80
+ # * <tt>Default:</tt> {:case_sensitive => false, :scope => validations_scope, :if => "#{login_field}_changed?".to_sym}
81
+ # * <tt>Accepts:</tt> Hash of options accepted by validates_uniqueness_of
82
+ def validates_uniqueness_of_login_field_options(value = nil)
83
+ rw_config(:validates_uniqueness_of_login_field_options, value, {:case_sensitive => false, :scope => validations_scope, :if => "#{login_field}_changed?".to_sym})
84
+ end
85
+ alias_method :validates_uniqueness_of_login_field_options=, :validates_uniqueness_of_login_field_options
86
+
87
+ # See merge_validates_length_of_login_field_options. The same thing, except for validates_uniqueness_of_login_field_options
88
+ def merge_validates_uniqueness_of_login_field_options(options = {})
89
+ self.validates_uniqueness_of_login_field_options = validates_uniqueness_of_login_field_options.merge(options)
90
+ end
91
+
92
+ # This method allows you to find a record with the given login. If you notice, with ActiveRecord you have the
93
+ # validates_uniqueness_of validation function. They give you a :case_sensitive option. I handle this in the same
94
+ # manner that they handle that. If you are using the login field and set false for the :case_sensitive option in
95
+ # validates_uniqueness_of_login_field_options this method will modify the query to look something like:
96
+ #
97
+ # first(:conditions => ["LOWER(#{quoted_table_name}.#{login_field}) = ?", login.downcase])
98
+ #
99
+ # If you don't specify this it calls the good old find_by_* method:
100
+ #
101
+ # find_by_login(login)
102
+ #
103
+ # The above also applies for using email as your login, except that you need to set the :case_sensitive in
104
+ # validates_uniqueness_of_email_field_options to false.
105
+ #
106
+ # The only reason I need to do the above is for Postgres and SQLite since they perform case sensitive searches with the
107
+ # find_by_* methods.
108
+ def find_by_smart_case_login_field(login)
109
+ if login_field
110
+ find_with_case(login_field, login, validates_uniqueness_of_login_field_options[:case_sensitive] != false)
111
+ else
112
+ find_with_case(email_field, login, validates_uniqueness_of_email_field_options[:case_sensitive] != false)
113
+ end
114
+ end
115
+
116
+ private
117
+ def find_with_case(field, value, sensitivity = true)
118
+ if sensitivity
119
+ send("find_by_#{field}", value)
120
+ else
121
+ first(:conditions => ["LOWER(#{quoted_table_name}.#{field}) = ?", value.mb_chars.downcase])
122
+ end
123
+ end
49
124
  end
50
125
 
51
126
  # All methods relating to the login field
52
127
  module Methods
128
+ # Adds in various validations, modules, etc.
53
129
  def self.included(klass)
54
130
  klass.class_eval do
55
131
  if validate_login_field && login_field
56
132
  validates_length_of login_field, validates_length_of_login_field_options
57
133
  validates_format_of login_field, validates_format_of_login_field_options
58
- validates_uniqueness_of login_field, :scope => validations_scope, :if => "#{login_field}_changed?".to_sym
134
+ validates_uniqueness_of login_field, validates_uniqueness_of_login_field_options
59
135
  end
60
136
  end
61
137
  end