authlogic 2.1.1 → 2.1.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of authlogic might be problematic. Click here for more details.

@@ -1,3 +1,8 @@
1
+ == 2.1.2
2
+
3
+ * Return the newly create object for the class level create method, instead of a boolean
4
+ * Add a model_name class method for Authlogic::Session for rails 3 compatibility. Will be using ActiveModel eventually, but this should be a quick fix.
5
+
1
6
  == 2.1.1 released 2009-7-04
2
7
 
3
8
  * Use mb_chars when downcasing the login string to support international characters.
@@ -55,12 +55,12 @@ Authlogic is very flexible, it has a strong public API and a plethora of hooks t
55
55
  * <b>Live example with OpenID "add on":</b> http://authlogicexample.binarylogic.com
56
56
  * <b>Live example repository with tutorial in README:</b> http://github.com/binarylogic/authlogic_example/tree/master
57
57
  * <b>Tutorial: Reset passwords with Authlogic the RESTful way:</b> http://www.binarylogic.com/2008/11/16/tutorial-reset-passwords-with-authlogic
58
- * <b>Bugs / feature suggestions:</b> http://binarylogic.lighthouseapp.com/projects/18752-authlogic
58
+ * <b>Issues:</b> http://github.com/binarylogic/authlogic/issues
59
59
  * <b>Google group:</b> http://groups.google.com/group/authlogic
60
60
 
61
61
  <b>Before contacting me directly, please read:</b>
62
62
 
63
- If you find a bug or a problem please post it on lighthouse. If you need help with something, please use google groups. I check both regularly and get emails when anything happens, so that is the best place to get help. This also benefits other people in the future with the same questions / problems. Thank you.
63
+ If you find a bug or a problem please post it in the issues section. If you need help with something, please use google groups. I check both regularly and get emails when anything happens, so that is the best place to get help. This also benefits other people in the future with the same questions / problems. Thank you.
64
64
 
65
65
  == Authlogic "add ons"
66
66
 
@@ -223,7 +223,7 @@ I think one of the best aspects of Authlogic is testing. For one, it cuts out <b
223
223
 
224
224
  For example, think about ActiveRecord. You don't test the internals of ActiveRecord, because the creators of ActiveRecord have already tested the internals for you. It wouldn't make sense for ActiveRecord to copy it's hundreds of tests into your applications. The same concept applies to Authlogic. You only need to test code you write that is specific to your application, just like everything else in your application.
225
225
 
226
- That being said, testing your code that uses Authlogic is easy. Since everyone uses different testing suites, I created a helpful module called Authlogic::TestCase, which is basically a set of tools for testing code using Authlogic. I explain testing Authlogic thoroughly in the {Authlogic::TestCase section of the documentation}[http://authlogic.rubyforge.org/classes/Authlogic/TestCase.html]. It should answer any questions you have in regards to testing Authlogic.
226
+ That being said, testing your code that uses Authlogic is easy. Since everyone uses different testing suites, I created a helpful module called Authlogic::TestCase, which is basically a set of tools for testing code using Authlogic. I explain testing Authlogic thoroughly in the {Authlogic::TestCase section of the documentation}[http://rdoc.info/rdoc/binarylogic/authlogic/blob/f2f6988d3b97e11770b00b72a7a9733df69ffa5b/Authlogic/TestCase.html]. It should answer any questions you have in regards to testing Authlogic.
227
227
 
228
228
  == Tell me quickly how Authlogic works
229
229
 
@@ -239,7 +239,7 @@ What inspired me to create Authlogic was the messiness of the current authentica
239
239
  4. <b>No redundant tests.</b> Because Authlogic doesn't use generators, #1 also applies to tests. Authlogic is *thoroughly* tested for you. You don't go and test the internals of ActiveRecord in each of your apps do you? So why do the same for Authlogic? Your application tests should be for application specific code. Get rid of the noise and make your tests focused and concise, no reason to copy tests from app to app.
240
240
  5. <b>Framework agnostic</b>. Authlogic can be used in *any* ruby framework you want: Rails, Merb, Sinatra, Mack, your own framework, whatever. It's not tied down to Rails. It does this by abstracting itself from these framework's controllers by using a controller adapter. Thanks to {Rack}[http://rack.rubyforge.org/], there is a defined standard for controller structure, and that's what Authlogic's abstract adapter follows. So if your controller follows the rack standards, you don't need to do anything. Any place it deviates from this is solved by a simple adapter for your framework that closes these gaps. For an example, checkout the Authlogic::ControllerAdapters::MerbAdapter.
241
241
  5. <b>You are not restricted to a single session.</b> Think about Apple's me.com, where they need you to authenticate a second time before changing your billing information. Why not just create a second session for this? It works just like your initial session. Then your billing controller can require an "ultra secure" session.
242
- 6. <b>Easily extendable.</b> One of the distinct advantages of using a library is the ability to use it's API, assuming it has one. Authlogic has an *excellent* public API, meaning it can easily be extended and grow beyond the core library. Checkout the "add ons" list above to see what I mean.
242
+ 6. <b>Easily extendable.</b> One of the distinct advantages of using a library is the ability to use its API, assuming it has one. Authlogic has an *excellent* public API, meaning it can easily be extended and grow beyond the core library. Checkout the "add ons" list above to see what I mean.
243
243
 
244
244
 
245
245
  Copyright (c) 2009 {Ben Johnson of Binary Logic}[http://www.binarylogic.com], released under the MIT license
data/Rakefile CHANGED
@@ -12,13 +12,14 @@ begin
12
12
  gem.rubyforge_project = "authlogic"
13
13
  gem.add_dependency "activesupport"
14
14
  end
15
+ Jeweler::RubyforgeTasks.new
15
16
  rescue LoadError
16
17
  puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
17
18
  end
18
19
 
19
20
  require 'rake/testtask'
20
21
  Rake::TestTask.new(:test) do |test|
21
- test.libs << 'lib' << 'test'
22
+ test.libs << 'test'
22
23
  test.pattern = 'test/**/*_test.rb'
23
24
  test.verbose = true
24
25
  end
@@ -36,14 +37,6 @@ rescue LoadError
36
37
  end
37
38
  end
38
39
 
39
- task :default => :test
40
+ task :test => :check_dependencies
40
41
 
41
- begin
42
- require 'rake/contrib/sshpublisher'
43
- namespace :rubyforge do
44
- desc "Release gem to RubyForge"
45
- task :release => ["rubyforge:release:gem"]
46
- end
47
- rescue LoadError
48
- puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
49
- end
42
+ task :default => :test
@@ -1,4 +1,4 @@
1
1
  ---
2
- :patch: 1
2
+ :patch: 2
3
3
  :major: 2
4
4
  :minor: 1
@@ -1,12 +1,15 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
1
4
  # -*- encoding: utf-8 -*-
2
5
 
3
6
  Gem::Specification.new do |s|
4
7
  s.name = %q{authlogic}
5
- s.version = "2.1.1"
8
+ s.version = "2.1.2"
6
9
 
7
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
11
  s.authors = ["Ben Johnson of Binary Logic"]
9
- s.date = %q{2009-07-04}
12
+ s.date = %q{2009-09-12}
10
13
  s.email = %q{bjohnson@binarylogic.com}
11
14
  s.extra_rdoc_files = [
12
15
  "LICENSE",
@@ -41,12 +44,14 @@ Gem::Specification.new do |s|
41
44
  "lib/authlogic/controller_adapters/abstract_adapter.rb",
42
45
  "lib/authlogic/controller_adapters/merb_adapter.rb",
43
46
  "lib/authlogic/controller_adapters/rails_adapter.rb",
47
+ "lib/authlogic/controller_adapters/sinatra_adapter.rb",
44
48
  "lib/authlogic/crypto_providers/aes256.rb",
45
49
  "lib/authlogic/crypto_providers/bcrypt.rb",
46
50
  "lib/authlogic/crypto_providers/md5.rb",
47
51
  "lib/authlogic/crypto_providers/sha1.rb",
48
52
  "lib/authlogic/crypto_providers/sha512.rb",
49
53
  "lib/authlogic/i18n.rb",
54
+ "lib/authlogic/i18n/translator.rb",
50
55
  "lib/authlogic/random.rb",
51
56
  "lib/authlogic/regex.rb",
52
57
  "lib/authlogic/session/activation.rb",
@@ -100,6 +105,7 @@ Gem::Specification.new do |s|
100
105
  "test/fixtures/employees.yml",
101
106
  "test/fixtures/projects.yml",
102
107
  "test/fixtures/users.yml",
108
+ "test/i18n_test.rb",
103
109
  "test/libs/affiliate.rb",
104
110
  "test/libs/company.rb",
105
111
  "test/libs/employee.rb",
@@ -137,7 +143,7 @@ Gem::Specification.new do |s|
137
143
  s.rdoc_options = ["--charset=UTF-8"]
138
144
  s.require_paths = ["lib"]
139
145
  s.rubyforge_project = %q{authlogic}
140
- s.rubygems_version = %q{1.3.4}
146
+ s.rubygems_version = %q{1.3.5}
141
147
  s.summary = %q{A clean, simple, and unobtrusive ruby authentication solution.}
142
148
  s.test_files = [
143
149
  "test/acts_as_authentic_test/base_test.rb",
@@ -156,6 +162,7 @@ Gem::Specification.new do |s|
156
162
  "test/crypto_provider_test/bcrypt_test.rb",
157
163
  "test/crypto_provider_test/sha1_test.rb",
158
164
  "test/crypto_provider_test/sha512_test.rb",
165
+ "test/i18n_test.rb",
159
166
  "test/libs/affiliate.rb",
160
167
  "test/libs/company.rb",
161
168
  "test/libs/employee.rb",
@@ -1,4 +1,4 @@
1
- require "active_support"
1
+ require "active_record"
2
2
 
3
3
  require File.dirname(__FILE__) + "/authlogic/i18n"
4
4
  require File.dirname(__FILE__) + "/authlogic/random"
@@ -7,6 +7,7 @@ require File.dirname(__FILE__) + "/authlogic/regex"
7
7
  require File.dirname(__FILE__) + "/authlogic/controller_adapters/abstract_adapter"
8
8
  require File.dirname(__FILE__) + "/authlogic/controller_adapters/rails_adapter" if defined?(Rails)
9
9
  require File.dirname(__FILE__) + "/authlogic/controller_adapters/merb_adapter" if defined?(Merb)
10
+ require File.dirname(__FILE__) + "/authlogic/controller_adapters/sinatra_adapter" if defined?(Sinatra)
10
11
 
11
12
  require File.dirname(__FILE__) + "/authlogic/crypto_providers/md5"
12
13
  require File.dirname(__FILE__) + "/authlogic/crypto_providers/sha1"
@@ -52,4 +53,4 @@ require File.dirname(__FILE__) + "/authlogic/session/session"
52
53
  require File.dirname(__FILE__) + "/authlogic/session/timeout"
53
54
  require File.dirname(__FILE__) + "/authlogic/session/unauthorized_record"
54
55
  require File.dirname(__FILE__) + "/authlogic/session/validation"
55
- require File.dirname(__FILE__) + "/authlogic/session/base"
56
+ require File.dirname(__FILE__) + "/authlogic/session/base"
@@ -92,21 +92,16 @@ module Authlogic
92
92
  end
93
93
  end
94
94
 
95
- if defined?(::ActiveRecord)
96
- module ::ActiveRecord
97
- class Base
98
- include Authlogic::ActsAsAuthentic::Base
99
- include Authlogic::ActsAsAuthentic::Email
100
- include Authlogic::ActsAsAuthentic::LoggedInStatus
101
- include Authlogic::ActsAsAuthentic::Login
102
- include Authlogic::ActsAsAuthentic::MagicColumns
103
- include Authlogic::ActsAsAuthentic::Password
104
- include Authlogic::ActsAsAuthentic::PerishableToken
105
- include Authlogic::ActsAsAuthentic::PersistenceToken
106
- include Authlogic::ActsAsAuthentic::RestfulAuthentication
107
- include Authlogic::ActsAsAuthentic::SessionMaintenance
108
- include Authlogic::ActsAsAuthentic::SingleAccessToken
109
- include Authlogic::ActsAsAuthentic::ValidationsScope
110
- end
111
- end
112
- end
95
+ ::ActiveRecord::Base.send :include, Authlogic::ActsAsAuthentic::Base
96
+ ::ActiveRecord::Base.send :include, Authlogic::ActsAsAuthentic::Email
97
+ ::ActiveRecord::Base.send :include, Authlogic::ActsAsAuthentic::LoggedInStatus
98
+ ::ActiveRecord::Base.send :include, Authlogic::ActsAsAuthentic::Login
99
+ ::ActiveRecord::Base.send :include, Authlogic::ActsAsAuthentic::MagicColumns
100
+ ::ActiveRecord::Base.send :include, Authlogic::ActsAsAuthentic::Password
101
+ ::ActiveRecord::Base.send :include, Authlogic::ActsAsAuthentic::PerishableToken
102
+ ::ActiveRecord::Base.send :include, Authlogic::ActsAsAuthentic::PersistenceToken
103
+ ::ActiveRecord::Base.send :include, Authlogic::ActsAsAuthentic::RestfulAuthentication
104
+ ::ActiveRecord::Base.send :include, Authlogic::ActsAsAuthentic::SessionMaintenance
105
+ ::ActiveRecord::Base.send :include, Authlogic::ActsAsAuthentic::SingleAccessToken
106
+ ::ActiveRecord::Base.send :include, Authlogic::ActsAsAuthentic::ValidationsScope
107
+
@@ -0,0 +1,61 @@
1
+ # Authlogic bridge for Sinatra
2
+ module Authlogic
3
+ module ControllerAdapters
4
+ module SinatraAdapter
5
+ class Cookies
6
+ attr_reader :request, :response
7
+
8
+ def initialize(request, response)
9
+ @request = request
10
+ @response = response
11
+ end
12
+
13
+ def delete(key, options = {})
14
+ @request.cookies.delete(key)
15
+ end
16
+
17
+ def []=(key, options)
18
+ @response.set_cookie(key, options)
19
+ end
20
+
21
+ def method_missing(meth, *args, &block)
22
+ @request.cookies.send(meth, *args, &block)
23
+ end
24
+ end
25
+
26
+ class Controller
27
+ attr_reader :request, :response, :cookies
28
+
29
+ def initialize(request, response)
30
+ @request = request
31
+ @cookies = Cookies.new(request, response)
32
+ end
33
+
34
+ def session
35
+ env['rack.session']
36
+ end
37
+
38
+ def method_missing(meth, *args, &block)
39
+ @request.send meth, *args, &block
40
+ end
41
+ end
42
+
43
+ class Adapter < AbstractAdapter
44
+ def cookie_domain
45
+ env['SERVER_NAME']
46
+ end
47
+
48
+ module Implementation
49
+ def self.included(klass)
50
+ klass.send :before do
51
+ controller = Controller.new(request, response)
52
+ Authlogic::Session::Base.controller = Adapter.new(controller)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ Sinatra::Request.send(:include, Authlogic::ControllerAdapters::SinatraAdapter::Adapter::Implementation)
@@ -1,3 +1,5 @@
1
+ require "authlogic/i18n/translator"
2
+
1
3
  module Authlogic
2
4
  # This class allows any message in Authlogic to use internationalization. In earlier versions of Authlogic each message was translated via configuration.
3
5
  # This cluttered up the configuration and cluttered up Authlogic. So all translation has been extracted out into this class. Now all messages pass through
@@ -11,18 +13,17 @@ module Authlogic
11
13
  #
12
14
  # Authlogic::I18n.t('error_messages.password_invalid', :default => "is invalid")
13
15
  #
14
- # If you use a different I18n library or plugin just redefine the t method in the Authlogic::I18n class to do whatever you want with those options. For example:
16
+ # If you use a different I18n library just replace the build-in I18n::Translator class with your own. For example:
15
17
  #
16
- # # config/initializers/authlogic.rb
17
- # module MyAuthlogicI18nAdapter
18
- # def t(key, options = {})
18
+ # class MyAuthlogicI18nTranslator
19
+ # def translate(key, options = {})
19
20
  # # you will have key which will be something like: "error_messages.password_invalid"
20
21
  # # you will also have options[:default], which will be the default english version of the message
21
22
  # # do whatever you want here with the arguments passed to you.
22
23
  # end
23
24
  # end
24
25
  #
25
- # Authlogic::I18n.extend MyAuthlogicI18nAdapter
26
+ # Authlogic::I18n.translator = MyAuthlogicI18nTranslator.new
26
27
  #
27
28
  # That it's! Here is a complete list of the keys that are passed. Just define these however you wish:
28
29
  #
@@ -47,17 +48,36 @@ module Authlogic
47
48
  # email: email
48
49
  # password: password
49
50
  # remember_me: remember me
50
- class I18n
51
+ module I18n
52
+ @@scope = :authlogic
53
+ @@translator = nil
54
+
51
55
  class << self
56
+ # Returns the current scope. Defaults to :authlogic
57
+ def scope
58
+ @@scope
59
+ end
60
+
61
+ # Sets the current scope. Used to set a custom scope.
62
+ def scope=(scope)
63
+ @@scope = scope
64
+ end
65
+
66
+ # Returns the current translator. Defaults to +Translator+.
67
+ def translator
68
+ @@translator ||= Translator.new
69
+ end
70
+
71
+ # Sets the current translator. Used to set a custom translator.
72
+ def translator=(translator)
73
+ @@translator = translator
74
+ end
75
+
52
76
  # All message translation is passed to this method. The first argument is the key for the message. The second is options, see the rails I18n library for a list of options used.
53
- def t(key, options = {})
54
- if defined?(::I18n)
55
- ::I18n.t(key, options.merge(:scope => :authlogic))
56
- else
57
- options[:default]
58
- end
77
+ def translate(key, options = {})
78
+ translator.translate key, { :scope => I18n.scope }.merge(options)
59
79
  end
60
- alias_method :translate, :t
80
+ alias :t :translate
61
81
  end
62
82
  end
63
- end
83
+ end
@@ -0,0 +1,15 @@
1
+ module Authlogic
2
+ module I18n
3
+ class Translator
4
+ # If the I18n gem is present, calls +I18n.translate+ passing all
5
+ # arguments, else returns +options[:default]+.
6
+ def translate(key, options = {})
7
+ if defined?(::I18n)
8
+ ::I18n.translate key, options
9
+ else
10
+ options[:default]
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -33,10 +33,16 @@ module Authlogic
33
33
  [self]
34
34
  end
35
35
 
36
- # For Rails >2.3, fix mispelling
36
+ # For rails >= 2.3, mispelling fixed
37
37
  def self_and_descendants_from_active_record
38
38
  [self]
39
39
  end
40
+
41
+ # For rails >= 3.0
42
+ def model_name
43
+ clazz = defined?(::ActiveModel) ? ::ActiveModel::Name : ::ActiveSupport::ModelName
44
+ clazz.new(self.to_s)
45
+ end
40
46
  end
41
47
 
42
48
  module InstanceMethods
@@ -44,7 +50,12 @@ module Authlogic
44
50
  def new_record?
45
51
  new_session?
46
52
  end
53
+
54
+ # For rails >= 3.0
55
+ def to_model
56
+ self
57
+ end
47
58
  end
48
59
  end
49
60
  end
50
- end
61
+ end
@@ -57,7 +57,8 @@ module Authlogic
57
57
  # Notice the word temporary, the user will not be permanently banned unless you choose to do so with configuration.
58
58
  # By default they will be banned for 2 hours. During that 2 hour period this method will return true.
59
59
  def being_brute_force_protected?
60
- exceeded_failed_logins_limit? && (failed_login_ban_for <= 0 || (attempted_record.respond_to?(:updated_at) && attempted_record.updated_at >= failed_login_ban_for.seconds.ago))
60
+ exceeded_failed_logins_limit? && (failed_login_ban_for <= 0 ||
61
+ (attempted_record.respond_to?(:updated_at) && attempted_record.updated_at >= failed_login_ban_for.seconds.ago))
61
62
  end
62
63
 
63
64
  private
@@ -76,7 +77,10 @@ module Authlogic
76
77
 
77
78
  def validate_failed_logins
78
79
  errors.clear # Clear all other error messages, as they are irrelevant at this point and can only provide additional information that is not needed
79
- errors.add(:base, I18n.t('error_messages.consecutive_failed_logins_limit_exceeded', :default => "Consecutive failed logins limit exceeded, account is disabled."))
80
+ errors.add(:base, I18n.t(
81
+ 'error_messages.consecutive_failed_logins_limit_exceeded',
82
+ :default => "Consecutive failed logins limit exceeded, account has been" + (failed_login_ban_for == 0 ? "" : " temporarily") + " disabled."
83
+ ))
80
84
  end
81
85
 
82
86
  def consecutive_failed_logins_limit
@@ -55,7 +55,8 @@ module Authlogic
55
55
  module Callbacks
56
56
  METHODS = [
57
57
  "before_persisting", "persist", "after_persisting",
58
- "before_validation", "before_validation_on_create", "before_validation_on_update", "validate", "after_validation_on_update", "after_validation_on_create", "after_validation",
58
+ "before_validation", "before_validation_on_create", "before_validation_on_update", "validate",
59
+ "after_validation_on_update", "after_validation_on_create", "after_validation",
59
60
  "before_save", "before_create", "before_update", "after_update", "after_create", "after_save",
60
61
  "before_destroy", "after_destroy"
61
62
  ]
@@ -69,12 +69,12 @@ module Authlogic
69
69
  return @remember_me if defined?(@remember_me)
70
70
  @remember_me = self.class.remember_me
71
71
  end
72
-
72
+
73
73
  # Accepts a boolean as a flag to remember the session or not. Basically to expire the cookie at the end of the session or keep it for "remember_me_until".
74
74
  def remember_me=(value)
75
75
  @remember_me = value
76
76
  end
77
-
77
+
78
78
  # See remember_me
79
79
  def remember_me?
80
80
  remember_me == true || remember_me == "true" || remember_me == "1"
@@ -85,7 +85,7 @@ module Authlogic
85
85
  return unless remember_me?
86
86
  self.class.remember_me_for
87
87
  end
88
-
88
+
89
89
  # When to expire the cookie. See remember_me_for configuration option to change this.
90
90
  def remember_me_until
91
91
  return unless remember_me?
@@ -112,7 +112,7 @@ module Authlogic
112
112
  false
113
113
  end
114
114
  end
115
-
115
+
116
116
  def save_cookie
117
117
  controller.cookies[cookie_key] = {
118
118
  :value => "#{record.persistence_token}::#{record.send(record.class.primary_key)}",
@@ -120,7 +120,7 @@ module Authlogic
120
120
  :domain => controller.cookie_domain
121
121
  }
122
122
  end
123
-
123
+
124
124
  def destroy_cookie
125
125
  controller.cookies.delete cookie_key, :domain => controller.cookie_domain
126
126
  end
@@ -28,12 +28,14 @@ module Authlogic
28
28
  def create(*args, &block)
29
29
  session = new(*args)
30
30
  session.save(&block)
31
+ session
31
32
  end
32
33
 
33
34
  # Same as create but calls create!, which raises an exception when validation fails.
34
35
  def create!(*args)
35
36
  session = new(*args)
36
37
  session.save!
38
+ session
37
39
  end
38
40
  end
39
41
 
@@ -24,9 +24,10 @@ module Authlogic
24
24
 
25
25
  # Configuration for the magic columns feature.
26
26
  module Config
27
- # Every time a session is found the last_request_at field for that record is updatd with the current time, if that field exists. If you want to limit how frequent that field is updated specify the threshold
28
- # here. For example, if your user is making a request every 5 seconds, and you feel this is too frequent, and feel a minute is a good threashold. Set this to 1.minute. Once a minute has passed in between
29
- # requests the field will be updated.
27
+ # Every time a session is found the last_request_at field for that record is updatd with the current time, if that field exists.
28
+ # If you want to limit how frequent that field is updated specify the threshold here. For example, if your user is making a
29
+ # request every 5 seconds, and you feel this is too frequent, and feel a minute is a good threashold. Set this to 1.minute.
30
+ # Once a minute has passed in between requests the field will be updated.
30
31
  #
31
32
  # * <tt>Default:</tt> 0
32
33
  # * <tt>Accepts:</tt> integer representing time in seconds
@@ -9,7 +9,8 @@ module Authlogic
9
9
  #
10
10
  # Authlogic does nothing to define these methods for you, its up to you to define what they mean. If your object responds to these methods Authlogic will use them, otherwise they are ignored.
11
11
  #
12
- # What's neat about this is that these are checked upon any type of login. When logging in explicitly, by cookie, session, or basic http auth. So if you mark a user inactive in the middle of their session they wont be logged back in next time they refresh the page. Giving you complete control.
12
+ # What's neat about this is that these are checked upon any type of login. When logging in explicitly, by cookie, session, or basic http auth.
13
+ # So if you mark a user inactive in the middle of their session they wont be logged back in next time they refresh the page. Giving you complete control.
13
14
  #
14
15
  # Need Authlogic to check your own "state"? No problem, check out the hooks section below. Add in a before_validation to do your own checking. The sky is the limit.
15
16
  module MagicStates
@@ -47,8 +47,9 @@ module Authlogic
47
47
  end
48
48
  alias_method :params_key=, :params_key
49
49
 
50
- # Authentication is allowed via a single access token, but maybe this is something you don't want for your application as a whole. Maybe this is something you only want for specific request types.
51
- # Specify a list of allowed request types and single access authentication will only be allowed for the ones you specify.
50
+ # Authentication is allowed via a single access token, but maybe this is something you don't want for your application as a whole. Maybe this is
51
+ # something you only want for specific request types. Specify a list of allowed request types and single access authentication will only be
52
+ # allowed for the ones you specify.
52
53
  #
53
54
  # * <tt>Default:</tt> ["application/rss+xml", "application/atom+xml"]
54
55
  # * <tt>Accepts:</tt> String of a request type, or :all or :any to allow single access authentication for any and all request types
@@ -16,12 +16,15 @@ module Authlogic
16
16
 
17
17
  # Password configuration
18
18
  module Config
19
- # Authlogic tries to validate the credentials passed to it. One part of validation is actually finding the user and making sure it exists. What method it uses the do this is up to you.
19
+ # Authlogic tries to validate the credentials passed to it. One part of validation is actually finding the user and
20
+ # making sure it exists. What method it uses the do this is up to you.
20
21
  #
21
- # Let's say you have a UserSession that is authenticating a User. By default UserSession will call User.find_by_login(login). You can change what method UserSession calls by specifying it here. Then
22
- # in your User model you can make that method do anything you want, giving you complete control of how users are found by the UserSession.
22
+ # Let's say you have a UserSession that is authenticating a User. By default UserSession will call User.find_by_login(login).
23
+ # You can change what method UserSession calls by specifying it here. Then in your User model you can make that method do
24
+ # anything you want, giving you complete control of how users are found by the UserSession.
23
25
  #
24
- # Let's take an example: You want to allow users to login by username or email. Set this to the name of the class method that does this in the User model. Let's call it "find_by_username_or_email"
26
+ # Let's take an example: You want to allow users to login by username or email. Set this to the name of the class method
27
+ # that does this in the User model. Let's call it "find_by_username_or_email"
25
28
  #
26
29
  # class User < ActiveRecord::Base
27
30
  # def self.find_by_username_or_email(login)
@@ -29,8 +32,8 @@ module Authlogic
29
32
  # end
30
33
  # end
31
34
  #
32
- # Now just specify the name of this method for this configuration option and you are all set. You can do anything you want here. Maybe you allow users to have multiple logins
33
- # and you want to search a has_many relationship, etc. The sky is the limit.
35
+ # Now just specify the name of this method for this configuration option and you are all set. You can do anything you
36
+ # want here. Maybe you allow users to have multiple logins and you want to search a has_many relationship, etc. The sky is the limit.
34
37
  #
35
38
  # * <tt>Default:</tt> "find_by_smart_case_login_field"
36
39
  # * <tt>Accepts:</tt> Symbol or String
@@ -50,9 +53,17 @@ module Authlogic
50
53
  # generalize_credentials_error_messages true
51
54
  # end
52
55
  #
53
- # This would make the error message for bad logins and bad passwords look identical:
56
+ # This would make the error message for bad logins and bad passwords look identical:
54
57
  #
55
58
  # Login/Password combination is not valid
59
+ #
60
+ # Alternatively you may use a custom message:
61
+ #
62
+ # class UserSession < AuthLogic::Session::Base
63
+ # generalize_credentials_error_messages "Your login information is invalid"
64
+ # end
65
+ #
66
+ # This will instead show your custom error message when the UserSession is invalid.
56
67
  #
57
68
  # The downside to enabling this is that is can be too vague for a user that has a hard time remembering
58
69
  # their username and password combinations. It also disables the ability to to highlight the field
@@ -89,7 +100,8 @@ module Authlogic
89
100
  end
90
101
  alias_method :password_field=, :password_field
91
102
 
92
- # The name of the method in your model used to verify the password. This should be an instance method. It should also be prepared to accept a raw password and a crytped password.
103
+ # The name of the method in your model used to verify the password. This should be an instance method. It should also
104
+ # be prepared to accept a raw password and a crytped password.
93
105
  #
94
106
  # * <tt>Default:</tt> "valid_password?"
95
107
  # * <tt>Accepts:</tt> Symbol or String
@@ -114,7 +126,8 @@ module Authlogic
114
126
 
115
127
  self.class.class_eval <<-"end_eval", __FILE__, __LINE__
116
128
  private
117
- # The password should not be accessible publicly. This way forms using form_for don't fill the password with the attempted password. To prevent this we just create this method that is private.
129
+ # The password should not be accessible publicly. This way forms using form_for don't fill the password with the
130
+ # attempted password. To prevent this we just create this method that is private.
118
131
  def protected_#{password_field}
119
132
  @#{password_field}
120
133
  end
@@ -168,15 +181,18 @@ module Authlogic
168
181
  return if errors.count > 0
169
182
 
170
183
  self.attempted_record = search_for_record(find_by_login_method, send(login_field))
171
-
172
184
  if attempted_record.blank?
173
- generalize_credentials_error_messages? ? add_general_credentials_error : errors.add(login_field, I18n.t('error_messages.login_not_found', :default => "is not valid"))
185
+ generalize_credentials_error_messages? ?
186
+ add_general_credentials_error :
187
+ errors.add(login_field, I18n.t('error_messages.login_not_found', :default => "is not valid"))
174
188
  return
175
189
  end
176
190
 
177
191
  if !attempted_record.send(verify_password_method, send("protected_#{password_field}"))
178
192
  self.invalid_password = true
179
- generalize_credentials_error_messages? ? add_general_credentials_error : errors.add(password_field, I18n.t('error_messages.password_invalid', :default => "is not valid"))
193
+ generalize_credentials_error_messages? ?
194
+ add_general_credentials_error :
195
+ errors.add(password_field, I18n.t('error_messages.password_invalid', :default => "is not valid"))
180
196
  return
181
197
  end
182
198
  end
@@ -198,11 +214,17 @@ module Authlogic
198
214
  end
199
215
 
200
216
  def add_general_credentials_error
201
- errors.add(:base, I18n.t('error_messages.general_credentials_error', :default => "#{login_field.to_s.humanize}/Password combination is not valid"))
217
+ error_message =
218
+ if self.class.generalize_credentials_error_messages.is_a? String
219
+ self.class.generalize_credentials_error_messages
220
+ else
221
+ "#{login_field.to_s.humanize}/Password combination is not valid"
222
+ end
223
+ errors.add(:base, I18n.t('error_messages.general_credentials_error', :default => error_message))
202
224
  end
203
225
 
204
226
  def generalize_credentials_error_messages?
205
- self.class.generalize_credentials_error_messages == true
227
+ self.class.generalize_credentials_error_messages
206
228
  end
207
229
 
208
230
  def password_field
@@ -215,4 +237,4 @@ module Authlogic
215
237
  end
216
238
  end
217
239
  end
218
- end
240
+ end
@@ -34,7 +34,9 @@ module Authlogic
34
34
  if !persistence_token.nil?
35
35
  # Allow finding by persistence token, because when records are created the session is maintained in a before_save, when there is no id.
36
36
  # This is done for performance reasons and to save on queries.
37
- record = record_id.nil? ? search_for_record("find_by_persistence_token", persistence_token) : search_for_record("find_by_#{klass.primary_key}", record_id)
37
+ record = record_id.nil? ?
38
+ search_for_record("find_by_persistence_token", persistence_token) :
39
+ search_for_record("find_by_#{klass.primary_key}", record_id)
38
40
  self.unauthorized_record = record if record && record.persistence_token == persistence_token
39
41
  valid?
40
42
  else
@@ -13,10 +13,12 @@ module Authlogic
13
13
  # errors.add(:base, "You must be awesome to log in") unless attempted_record.awesome?
14
14
  # end
15
15
  # end
16
- class Errors < ::ActiveRecord::Errors
17
- def [](key)
18
- value = super
19
- value.is_a?(Array) ? value : [value].compact
16
+ class Errors < (defined?(::ActiveModel) ? ::ActiveModel::Errors : ::ActiveRecord::Errors)
17
+ unless defined?(::ActiveModel)
18
+ def [](key)
19
+ value = super
20
+ value.is_a?(Array) ? value : [value].compact
21
+ end
20
22
  end
21
23
  end
22
24
 
@@ -77,4 +79,4 @@ module Authlogic
77
79
  end
78
80
  end
79
81
  end
80
- end
82
+ end
@@ -2,7 +2,7 @@ module Authlogic
2
2
  module ShouldaMacros
3
3
  class Test::Unit::TestCase
4
4
  def self.should_be_authentic
5
- klass = model_class
5
+ klass = described_type rescue model_class
6
6
  should "acts as authentic" do
7
7
  assert klass.new.respond_to?(:password=)
8
8
  assert klass.new.respond_to?(:valid_password?)
@@ -0,0 +1,33 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class I18nTest < ActiveSupport::TestCase
4
+ def test_uses_authlogic_as_scope_by_default
5
+ assert_equal :authlogic, Authlogic::I18n.scope
6
+ end
7
+
8
+ def test_can_set_scope
9
+ assert_nothing_raised { Authlogic::I18n.scope = [:a, :b] }
10
+ assert_equal [:a, :b], Authlogic::I18n.scope
11
+ Authlogic::I18n.scope = :authlogic
12
+ end
13
+
14
+ def test_uses_built_in_translator_by_default
15
+ assert_equal Authlogic::I18n::Translator, Authlogic::I18n.translator.class
16
+ end
17
+
18
+ def test_can_set_custom_translator
19
+ old_translator = Authlogic::I18n.translator
20
+
21
+ assert_nothing_raised do
22
+ Authlogic::I18n.translator = Class.new do
23
+ def translate(key, options = {})
24
+ "Translated: #{key}"
25
+ end
26
+ end.new
27
+ end
28
+
29
+ assert_equal "Translated: x", Authlogic::I18n.translate(:x)
30
+
31
+ Authlogic::I18n.translator = old_translator
32
+ end
33
+ end
@@ -15,6 +15,10 @@ module SessionTest
15
15
  def test_self_and_descendents_from_active_record
16
16
  assert_equal [UserSession], UserSession.self_and_descendents_from_active_record
17
17
  end
18
+
19
+ def test_self_and_descendants_from_active_record
20
+ assert_equal [UserSession], UserSession.self_and_descendants_from_active_record
21
+ end
18
22
  end
19
23
 
20
24
  class InstanceMethodsTest < ActiveSupport::TestCase
@@ -22,6 +26,11 @@ module SessionTest
22
26
  session = UserSession.new
23
27
  assert session.new_record?
24
28
  end
29
+
30
+ def test_to_model
31
+ session = UserSession.new
32
+ assert session, session.to_model
33
+ end
25
34
  end
26
35
  end
27
- end
36
+ end
@@ -32,10 +32,10 @@ module SessionTest
32
32
  ben = users(:ben)
33
33
  ben.failed_login_count = UserSession.consecutive_failed_logins_limit
34
34
  assert ben.save
35
- assert !UserSession.create(:login => ben.login, :password => "benrocks")
36
- assert !UserSession.create(ben)
35
+ assert UserSession.create(:login => ben.login, :password => "benrocks").new_session?
36
+ assert UserSession.create(ben).new_session?
37
37
  ben.updated_at = (UserSession.failed_login_ban_for + 2.hours.to_i).seconds.ago
38
- assert UserSession.create(ben)
38
+ assert !UserSession.create(ben).new_session?
39
39
  end
40
40
 
41
41
  def test_exceeding_failed_logins_limit
@@ -5,10 +5,10 @@ module SessionTest
5
5
  class ClassMethodsTest < ActiveSupport::TestCase
6
6
  def test_create
7
7
  ben = users(:ben)
8
- assert !UserSession.create(:login => "somelogin", :password => "badpw2")
9
- assert UserSession.create(:login => ben.login, :password => "benrocks")
8
+ assert UserSession.create(:login => "somelogin", :password => "badpw2").new_session?
9
+ assert !UserSession.create(:login => ben.login, :password => "benrocks").new_session?
10
10
  assert_raise(Authlogic::Session::Existence::SessionInvalidError) { UserSession.create!(:login => ben.login, :password => "badpw") }
11
- assert UserSession.create!(:login => ben.login, :password => "benrocks")
11
+ assert !UserSession.create!(:login => ben.login, :password => "benrocks").new_session?
12
12
  end
13
13
  end
14
14
 
@@ -15,7 +15,7 @@ module SessionTest
15
15
  class InstanceMethodsTest < ActiveSupport::TestCase
16
16
  def test_after_persisting_set_last_request_at
17
17
  ben = users(:ben)
18
- assert UserSession.create(ben)
18
+ assert !UserSession.create(ben).new_session?
19
19
 
20
20
  set_cookie_for(ben)
21
21
  old_last_request_at = ben.last_request_at
@@ -27,7 +27,7 @@ module SessionTest
27
27
  def test_valid_increase_failed_login_count
28
28
  ben = users(:ben)
29
29
  old_failed_login_count = ben.failed_login_count
30
- assert !UserSession.create(:login => ben.login, :password => "wrong")
30
+ assert UserSession.create(:login => ben.login, :password => "wrong").new_session?
31
31
  ben.reload
32
32
  assert_equal old_failed_login_count + 1, ben.failed_login_count
33
33
  end
@@ -36,7 +36,7 @@ module SessionTest
36
36
  ben = users(:ben)
37
37
 
38
38
  # increase failed login count
39
- assert !UserSession.create(:login => ben.login, :password => "wrong")
39
+ assert UserSession.create(:login => ben.login, :password => "wrong").new_session?
40
40
  ben.reload
41
41
 
42
42
  # grab old values
@@ -47,7 +47,7 @@ module SessionTest
47
47
  old_last_login_ip = ben.last_login_ip
48
48
  old_current_login_ip = ben.current_login_ip
49
49
 
50
- assert UserSession.create(:login => ben.login, :password => "benrocks")
50
+ assert !UserSession.create(:login => ben.login, :password => "benrocks").new_session?
51
51
 
52
52
  ben.reload
53
53
  assert_equal old_login_count + 1, ben.login_count
@@ -19,13 +19,27 @@ module SessionTest
19
19
  assert_equal "valid_password?", UserSession.verify_password_method
20
20
  end
21
21
 
22
- def test_generalize_credentials_error_messages
23
- UserSession.generalize_credentials_error_messages = true
24
- assert UserSession.generalize_credentials_error_messages
25
-
22
+ def test_generalize_credentials_error_mesages_set_to_false
26
23
  UserSession.generalize_credentials_error_messages false
27
24
  assert !UserSession.generalize_credentials_error_messages
25
+ session = UserSession.create(:login => users(:ben).login, :password => "invalud-password")
26
+ assert_equal ["Password is not valid"], session.errors.full_messages
27
+ end
28
+
29
+ def test_generalize_credentials_error_messages_set_to_true
30
+ UserSession.generalize_credentials_error_messages true
31
+ assert UserSession.generalize_credentials_error_messages
32
+ session = UserSession.create(:login => users(:ben).login, :password => "invalud-password")
33
+ assert_equal ["Login/Password combination is not valid"], session.errors.full_messages
28
34
  end
35
+
36
+ def test_generalize_credentials_error_messages_set_to_string
37
+ UserSession.generalize_credentials_error_messages= "Custom Error Message"
38
+ assert UserSession.generalize_credentials_error_messages
39
+ session = UserSession.create(:login => users(:ben).login, :password => "invalud-password")
40
+ assert_equal ["Custom Error Message"], session.errors.full_messages
41
+ end
42
+
29
43
 
30
44
  def test_login_field
31
45
  UserSession.configured_password_methods = false
@@ -89,4 +103,4 @@ module SessionTest
89
103
  end
90
104
  end
91
105
  end
92
- end
106
+ end
@@ -6,16 +6,24 @@ require "active_record/fixtures"
6
6
 
7
7
  # A temporary fix to bring active record errors up to speed with rails edge.
8
8
  # I need to remove this once the new gem is released. This is only here so my tests pass.
9
- class ActiveRecord::Errors
10
- def [](key)
11
- value = on(key)
12
- value.is_a?(Array) ? value : [value].compact
9
+ unless defined?(::ActiveModel)
10
+ class ActiveRecord::Errors
11
+ def [](key)
12
+ value = on(key)
13
+ value.is_a?(Array) ? value : [value].compact
14
+ end
13
15
  end
14
16
  end
15
17
 
16
18
 
17
19
  ActiveRecord::Schema.verbose = false
18
- ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :dbfile => ":memory:")
20
+
21
+ begin
22
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
23
+ rescue ArgumentError
24
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :dbfile => ":memory:")
25
+ end
26
+
19
27
  ActiveRecord::Base.configurations = true
20
28
  ActiveRecord::Schema.define(:version => 1) do
21
29
  create_table :companies do |t|
@@ -171,4 +179,4 @@ class ActiveSupport::TestCase
171
179
  def unset_session
172
180
  controller.session["user_credentials"] = controller.session["user_credentials_id"] = nil
173
181
  end
174
- end
182
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: authlogic
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 2.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Johnson of Binary Logic
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-07-04 00:00:00 -05:00
12
+ date: 2009-09-12 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -60,12 +60,14 @@ files:
60
60
  - lib/authlogic/controller_adapters/abstract_adapter.rb
61
61
  - lib/authlogic/controller_adapters/merb_adapter.rb
62
62
  - lib/authlogic/controller_adapters/rails_adapter.rb
63
+ - lib/authlogic/controller_adapters/sinatra_adapter.rb
63
64
  - lib/authlogic/crypto_providers/aes256.rb
64
65
  - lib/authlogic/crypto_providers/bcrypt.rb
65
66
  - lib/authlogic/crypto_providers/md5.rb
66
67
  - lib/authlogic/crypto_providers/sha1.rb
67
68
  - lib/authlogic/crypto_providers/sha512.rb
68
69
  - lib/authlogic/i18n.rb
70
+ - lib/authlogic/i18n/translator.rb
69
71
  - lib/authlogic/random.rb
70
72
  - lib/authlogic/regex.rb
71
73
  - lib/authlogic/session/activation.rb
@@ -119,6 +121,7 @@ files:
119
121
  - test/fixtures/employees.yml
120
122
  - test/fixtures/projects.yml
121
123
  - test/fixtures/users.yml
124
+ - test/i18n_test.rb
122
125
  - test/libs/affiliate.rb
123
126
  - test/libs/company.rb
124
127
  - test/libs/employee.rb
@@ -175,7 +178,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
175
178
  requirements: []
176
179
 
177
180
  rubyforge_project: authlogic
178
- rubygems_version: 1.3.4
181
+ rubygems_version: 1.3.5
179
182
  signing_key:
180
183
  specification_version: 3
181
184
  summary: A clean, simple, and unobtrusive ruby authentication solution.
@@ -196,6 +199,7 @@ test_files:
196
199
  - test/crypto_provider_test/bcrypt_test.rb
197
200
  - test/crypto_provider_test/sha1_test.rb
198
201
  - test/crypto_provider_test/sha512_test.rb
202
+ - test/i18n_test.rb
199
203
  - test/libs/affiliate.rb
200
204
  - test/libs/company.rb
201
205
  - test/libs/employee.rb