<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>Rakefile</filename>
    </added>
    <added>
      <filename>spec/spec.opts</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -11,12 +11,11 @@ Similarly, abstractions are provided for controllers to keep as much authenticat
 Installation
 ------------
 
-    # cd vendor/rails
-    # git clone git://github.com/spohlenz/acts_as_authenticated_user.git
+    # script/plugin install git://github.com/spohlenz/acts_as_authenticated_user.git
 
 
-Example (Model)
----------------
+Model Setup
+-----------
 
 The user model requires three fields: `login`, `hashed_password` and `salt` (all strings). This can be achieved with a migration such as:
 
@@ -47,14 +46,35 @@ Allowing the following behaviour:
     u = User.create(:login =&gt; 'sam', :password =&gt; 'foobar', :password_confirmation =&gt; 'foobar')
     User.authenticate('sam', 'foobar') #=&gt; u
     User.authenticate('invalid', 'user') #=&gt; nil
+    
+If you want to use another field for your main identifier (e.g. `email` instead of `login`), replace `login` in your database schema and call `acts_as_authenticated_user` with `:identifier =&gt; :email`.
+
+*acts\_as\_authenticated\_user* will validate the presence of login and password but any extra validations will need to be defined in the User model. If you want to disable validations altogether (for example to define your own validation messages), declare `acts_as_authenticated_user :validate =&gt; false` in your User model. If you do this, be sure to define at least the following validations:
+
+ - `validates_presence_of {identifier_column}`
+ - `validates_uniqueness_of {identifier_column}`
+ - `validates_presence_of :password, :if =&gt; :password_required?`
+ - `validates_presence_of :password_confirmation, :if =&gt; :password_required?`
+ - `validates_confirmation_of :password`
+
+`acts_as_authenticated_user` does not define any validations as to the length of the password. You will need to specify these yourself.
+
 
-*acts\_as\_authenticated\_user* will validate the presence of login and password but any extra validations will need to be defined in the User model.
 
+Controller Setup
+----------------
+
+In your `application_controller.rb`:
+
+    class ApplicationController &lt; ActionController::Base
+      authenticated_user
+    end
+
+Controllers and helpers have access to the `logged_in?` and `current_user` methods to determine the current login status.
 
-Example (Protecting a controller)
----------------------------------
 
-Controllers and helpers have access to the `logged_in?` and `current_user` methods to determine the status of the current login.
+Protecting a Controller
+-----------------------
 
 To protect a controller:
 
@@ -115,7 +135,6 @@ To Be Implemented
 
  - 'Remember me' functionality
  - OpenID authentication
- - Alternative login identifiers (i.e. use email rather than login)
 
 
 Copyright (c) 2008 Sam Pohlenz [&lt;sam@sampohlenz.com&gt;], released under the MIT license</diff>
      <filename>README.markdown</filename>
    </modified>
    <modified>
      <diff>@@ -5,12 +5,20 @@ module ActsAsAuthenticatedUser::ModelExtensions
         extend ClassMethods
         include InstanceMethods
         
-        setup_validation :validates_presence_of, :login, options[:messages]
-        setup_validation :validates_uniqueness_of, :login, options[:messages]
+        class_eval &lt;&lt;-EOF
+          def self.identifier_column
+            :#{options[:identifier] || :login}
+          end
+        EOF
         
-        setup_validation :validates_presence_of, :password, options[:messages], :if =&gt; :password_required?
-        setup_validation :validates_presence_of, :password_confirmation, options[:messages], :if =&gt; :password_required?
-        setup_validation :validates_confirmation_of, :password, options[:messages]
+        unless options[:validate] == false
+          validates_presence_of identifier_column
+          validates_uniqueness_of identifier_column
+        
+          validates_presence_of :password, :if =&gt; :password_required?
+          validates_presence_of :password_confirmation, :if =&gt; :password_required?
+          validates_confirmation_of :password
+        end
         
         attr_accessor :password
         attr_protected :hashed_password, :salt
@@ -25,21 +33,14 @@ module ActsAsAuthenticatedUser::ModelExtensions
   end
   
   module ClassMethods
-    def authenticate(login, password)
-      u = find_by_login(login)
+    def authenticate(identifier, password)
+      u = find(:first, :conditions =&gt; { identifier_column =&gt; identifier })
       u if u &amp;&amp; encrypt(password, u.salt) == u.hashed_password
     end
     
     def encrypt(password, salt)
       Digest::SHA1.hexdigest(&quot;--#{salt}--#{password}--&quot;)
     end
-    
-  private
-    def setup_validation(validation, attribute, messages, options={})
-      message_name = &quot;#{validation}_#{attribute}&quot;.to_sym
-      options[:message] = messages[message_name] if messages &amp;&amp; messages[message_name]
-      send(validation, attribute, options)
-    end
   end
   
   module InstanceMethods
@@ -49,7 +50,8 @@ module ActsAsAuthenticatedUser::ModelExtensions
     end
     
     def encrypt_password
-      self.salt = Digest::SHA1.hexdigest(&quot;--#{Time.now.to_s}--#{login}--&quot;) if salt.blank?
+      identifier = send(self.class.identifier_column)
+      self.salt = Digest::SHA1.hexdigest(&quot;--#{Time.now.to_s}--#{identifier}--&quot;) if salt.blank?
       self.hashed_password = self.class.encrypt(password, salt) unless password.blank?
     end
   end</diff>
      <filename>lib/model_extensions.rb</filename>
    </modified>
    <modified>
      <diff>@@ -11,29 +11,31 @@ module ActsAsAuthenticatedUser::ControllerExtensions
       
       if user
         @controller.instance_eval { self.current_user = user }
-        @controller.instance_eval(&amp;@success)
+        @controller.instance_eval(&amp;success)
         @controller.instance_eval do
           redirect_to session[:previous_location] || redirect_on_success
           session[:previous_location] = nil
         end
       else
-        @controller.instance_eval(&amp;@failure)
+        @controller.instance_eval(&amp;failure)
       end
     end
     
     def success(&amp;block)
-      @success = block
+      @success = block if block_given?
+      @success
     end
     
     def failure(&amp;block)
-      @failure = block
+      @failure = block if block_given?
+      @failure
     end
   end
   
   module InstanceMethods
-    def process_login(model, params, redirect_on_success='/', &amp;block)
+    def process_login(params, redirect_on_success='/', &amp;block)
       if request.post?
-        LoginHandler.new(self, model, &amp;block).process(params, redirect_on_success)
+        LoginHandler.new(self, user_model, &amp;block).process(params, redirect_on_success)
       end
     end
     </diff>
      <filename>lib/process_login.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,12 +1,13 @@
 require File.dirname(__FILE__) + '/spec_helper'
 
 class TestController &lt; ActionController::Base
-  #authenticated_user :model =&gt; User
+  authenticated_user
   
   def test_action
   end
 end
 
+Object.send(:remove_const, :User)
 class User; end
 
 describe &quot;Controller#current_user&quot; do
@@ -16,7 +17,6 @@ describe &quot;Controller#current_user&quot; do
     TestController.send(:public, :current_user, :current_user=)
     @user = mock('User instance')
     User.stub!(:find_by_id).and_return(@user)
-    controller.stub!(:user_model).and_return(User)
   end
   
   it &quot;should be settable&quot; do
@@ -109,7 +109,7 @@ describe &quot;Controller#require_login&quot; do
   end
   
   it &quot;should append the check_login before_filter&quot; do
-    TestController.find_filter(:check_login).should_not be_nil
+    TestController.before_filters.should include(:check_login)
   end
   
   ['user_conditions', 'check_login', 'login_action'].each do |method|
@@ -129,7 +129,7 @@ describe &quot;Controller#skip_login&quot; do
   end
   
   it &quot;should remove the check_login before_filter&quot; do
-    TestController.find_filter(:check_login).should be_nil
+    TestController.before_filter.should_not include(:check_login)
   end
 end
 
@@ -142,7 +142,7 @@ describe &quot;Controller#check_login&quot; do
   end
   
   def do_get
-    get :test_action
+    with_default_routing { get :test_action }
   end
   
   context 'no current user' do</diff>
      <filename>spec/controller_extensions_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,8 +1,10 @@
 require File.dirname(__FILE__) + '/spec_helper'
 
 class AccountController &lt; ActionController::Base
+  authenticated_user
+  
   def login
-    process_login(User, params[:user], '/foo/bar') do |login|
+    process_login(params[:user], '/foo/bar') do |login|
       login.success { login_succeeded! }
       login.failure { login_failed! }
     end
@@ -14,7 +16,7 @@ describe &quot;Controller#process_login&quot; do
   
   describe 'handling GET' do
     def do_get
-      get :login
+      with_default_routing { get :login }
     end
   
     it &quot;should be successful&quot; do
@@ -40,7 +42,9 @@ describe &quot;Controller#process_login&quot; do
       end
   
       def do_post
-        post :login, :user =&gt; { :login =&gt; 'login', :password =&gt; 'password' }
+        with_default_routing do
+          post :login, :user =&gt; { :login =&gt; 'login', :password =&gt; 'password' }
+        end
       end
   
       it &quot;should authenticate the user&quot; do
@@ -89,7 +93,9 @@ describe &quot;Controller#process_login&quot; do
       end
   
       def do_post
-        post :login, :user =&gt; { :login =&gt; 'login', :password =&gt; 'invalid' }
+        with_default_routing do
+          post :login, :user =&gt; { :login =&gt; 'login', :password =&gt; 'invalid' }
+        end
       end
   
       it &quot;should attempt to authenticate the user&quot; do</diff>
      <filename>spec/controller_process_login_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,8 @@
 require File.dirname(__FILE__) + '/spec_helper'
 
 class AccountController &lt; ActionController::Base
+  authenticated_user
+  
   def logout
     process_logout '/' do
       flash[:message] = 'Logged out'
@@ -13,7 +15,7 @@ describe &quot;Controller#process_logout&quot; do
   
   def do_get
     session[:user] = 1234
-    get :logout
+    with_default_routing { get :logout }
   end
   
   it &quot;should redirect to the provided path&quot; do</diff>
      <filename>spec/controller_process_logout_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,4 +4,16 @@ ActiveRecord::Schema.define(:version =&gt; 0) do
     t.column :hashed_password, :string
     t.column :salt, :string
   end
+  
+  create_table :email_users, :force =&gt; true do |t|
+    t.column :email, :string
+    t.column :hashed_password, :string
+    t.column :salt, :string
+  end
+  
+  create_table :no_validation_users, :force =&gt; true do |t|
+    t.column :login, :string
+    t.column :hashed_password, :string
+    t.column :salt, :string
+  end
 end</diff>
      <filename>spec/db/schema.rb</filename>
    </modified>
    <modified>
      <diff>@@ -5,26 +5,32 @@ class DefaultUser &lt; ActiveRecord::Base
 end
 
 describe 'A model which calls acts_as_authenticated_user' do
-  before(:each) do
-    @user = DefaultUser.new(:login =&gt; 'test')
+  def instance
+    @user
   end
   
-  it &quot;should have a password accessor&quot; do
-    @user.should respond_to(:password)
-    @user.should respond_to(:password=)
+  def valid_attributes
+    {
+      :login =&gt; 'test',
+      :password =&gt; 'password',
+      :password_confirmation =&gt; 'password'
+    }
   end
   
-  it &quot;should require a login&quot; do
-    @user.should validate_presence_of(:login)
+  before(:each) do
+    @user = DefaultUser.new
   end
   
-  it &quot;should require a unique login&quot; do
-    @user.should validate_uniqueness_of(:login)
-  end
+  it_should_have_attr_accessor :password
+  
+  it_should_validate_presence_of :login
+  it_should_validate_uniqueness_of :login
   
-  it &quot;should disallow mass-assignment of hashed_password and salt&quot; do
-    @user.should_not allow_mass_assignment_of(:hashed_password)
-    @user.should_not allow_mass_assignment_of(:salt)
+  it_should_not_mass_assign :hashed_password
+  it_should_not_mass_assign :salt
+  
+  it &quot;identifier_column should default to :login&quot; do
+    DefaultUser.identifier_column.should == :login
   end
   
   it &quot;should be able to encrypt password and salt using SHA1&quot; do
@@ -32,16 +38,22 @@ describe 'A model which calls acts_as_authenticated_user' do
     DefaultUser.encrypt('87654321def', 'hello').should == '0d46fe8292c2bfbe471384468c7506a948eb5282'
   end
   
-  it &quot;should validate presence of password and confirmation when password required&quot; do
-    @user.stub!(:password_required?).and_return(true)
-    @user.should validate_presence_of(:password)
-    @user.should validate_presence_of(:password_confirmation)
+  describe &quot;when password is required&quot; do
+    before(:each) do
+      @user.stub!(:password_required?).and_return(true)
+    end
+    
+    it_should_validate_presence_of :password
+    it_should_validate_presence_of :password_confirmation
   end
   
-  it &quot;should not validate presence of password and confirmation when password not required&quot; do
-    @user.stub!(:password_required?).and_return(false)
-    @user.should_not validate_presence_of(:password)
-    @user.should_not validate_presence_of(:password_confirmation)
+  describe &quot;when password not required&quot; do
+    before(:each) do
+      @user.stub!(:password_required?).and_return(false)
+    end
+    
+    it_should_not_validate_presence_of :password
+    it_should_not_validate_presence_of :password_confirmation
   end
   
   it &quot;should require a password if hashed_password is blank&quot; do
@@ -62,9 +74,9 @@ end
 
 
 describe &quot;A user encrypting their password&quot; do
-  setup do
+  before(:each) do
     @user = DefaultUser.new(:login =&gt; 'test', :password =&gt; 'mypassword')
-    Time.stub!(:now).and_return('Fri May 16 17:00:55 -0700 2008')
+    Time.stub!(:now).and_return(Time.parse('Fri May 16 17:00:55 -0700 2008'))
   end
   
   it &quot;should encrypt password when saving&quot; do
@@ -107,12 +119,48 @@ describe &quot;Authenticating user&quot; do
 end
 
 
-# describe &quot;A model which calls acts_as_authenticated_user with an alternate identifier&quot; do
-#   class EmailUser &lt; ActiveRecord::Base
-#     acts_as_authenticated_user :identifier =&gt; :email
-#   end
-#   
-#   setup do
-#     @user = EmailUser.new(:email =&gt; 'test@test.com')
-#   end
-# end
+describe &quot;A model which calls acts_as_authenticated_user with an alternate identifier&quot; do
+  class EmailUser &lt; ActiveRecord::Base
+    acts_as_authenticated_user :identifier =&gt; :email
+  end
+  
+  before(:each) do
+    @user = EmailUser.new
+  end
+  
+  def instance
+    @user
+  end
+  
+  def valid_attributes
+    {
+      :email =&gt; 'test@example.com',
+      :password =&gt; 'password',
+      :password_confirmation =&gt; 'password'
+    }
+  end
+  
+  it_should_validate_presence_of :email
+  it_should_validate_uniqueness_of :email
+  
+  it &quot;identifier_column should be :email&quot; do
+    EmailUser.identifier_column.should == :email
+  end
+  
+  it &quot;should authenticate with email and password&quot; do
+    @user = EmailUser.create(:email =&gt; 'foo@foo.com', :password =&gt; 'pass', :password_confirmation =&gt; 'pass')
+    EmailUser.authenticate('foo@foo.com', 'pass').should == @user
+  end
+end
+
+
+describe &quot;A model which calls acts_as_authenticated_user with validations disabled&quot; do
+  class NoValidationUser &lt; ActiveRecord::Base
+    acts_as_authenticated_user :validate =&gt; false
+  end
+  
+  it &quot;should be valid with no attributes&quot; do
+    @user = NoValidationUser.new
+    @user.should be_valid
+  end
+end</diff>
      <filename>spec/model_extensions_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,9 @@
-require File.dirname(__FILE__) + '/../../../../spec/spec_helper'
+begin
+  require File.dirname(__FILE__) + '/../../../../spec/spec_helper'
+rescue LoadError
+  puts &quot;You need to install rspec in your base app&quot;
+  exit
+end
 
 plugin_spec_dir = File.dirname(__FILE__)
 ActiveRecord::Base.logger = Logger.new(plugin_spec_dir + &quot;/debug.log&quot;)
@@ -21,4 +26,20 @@ Spec::Runner.configure do |config|
       end
     }
   end
+  
+  def it_should_have_attr_accessor(sym)
+    it &quot;should have accessor '#{sym}'&quot; do
+      instance.should respond_to(sym)
+      instance.should respond_to(&quot;#{sym}=&quot;)
+    end
+  end
+  
+  def with_default_routing
+    with_routing do |set|
+      set.draw do |map|
+        map.connect ':controller/:action/:id'
+        yield
+      end
+    end
+  end
 end</diff>
      <filename>spec/spec_helper.rb</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>install.rb</filename>
    </removed>
    <removed>
      <filename>tasks/acts_as_authenticated_user.rake</filename>
    </removed>
    <removed>
      <filename>uninstall.rb</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>6d9b8f7316578897f3cf2cdecda5477842533727</id>
    </parent>
  </parents>
  <author>
    <name>Sam Pohlenz</name>
    <email>sam@sampohlenz.com</email>
  </author>
  <url>http://github.com/spohlenz/acts_as_authenticated_user/commit/dc5bb7379f602911bec1a3f6c4bc25a18791fde0</url>
  <id>dc5bb7379f602911bec1a3f6c4bc25a18791fde0</id>
  <committed-date>2008-11-28T14:19:37-08:00</committed-date>
  <authored-date>2008-11-28T14:19:37-08:00</authored-date>
  <message>Specs and documentation cleanup</message>
  <tree>3783a7cd619f86d3f728d8ff3d723834c1824153</tree>
  <committer>
    <name>Sam Pohlenz</name>
    <email>sam@sampohlenz.com</email>
  </committer>
</commit>
