diff --git a/lib/devise/models/database_authenticatable.rb b/lib/devise/models/database_authenticatable.rb index 3874d979..522c5717 100644 --- a/lib/devise/models/database_authenticatable.rb +++ b/lib/devise/models/database_authenticatable.rb @@ -75,6 +75,9 @@ module Devise result end + def after_database_authentication + end + protected # Digests the password using the configured encryptor. @@ -90,8 +93,8 @@ module Devise @encryptor_class ||= ::Devise::Encryptors.const_get(encryptor.to_s.classify) end - def find_for_database_authentication(*args) - find_for_authentication(*args) + def find_for_database_authentication(conditions) + find_for_authentication(conditions) end end end diff --git a/lib/devise/models/token_authenticatable.rb b/lib/devise/models/token_authenticatable.rb index f2ba8c05..c6e6824d 100644 --- a/lib/devise/models/token_authenticatable.rb +++ b/lib/devise/models/token_authenticatable.rb @@ -2,8 +2,11 @@ require 'devise/strategies/token_authenticatable' module Devise module Models - # Token Authenticatable Module, responsible for generate authentication token and validating - # authenticity of a user while signing in using an authentication token (say follows an URL). + # The TokenAuthenticatable module is responsible for generating an authentication token and + # validating the authenticity of the same while signing in. + # + # This module only provides a few helpers to help you manage the token. Creating and resetting + # the token is your responsibility. # # == Configuration: # @@ -12,19 +15,10 @@ module Devise # # +token_authentication_key+ - Defines name of the authentication token params key. E.g. /users/sign_in?some_key=... # - # == Examples: - # - # User.authenticate_with_token(:auth_token => '123456789') # returns authenticated user or nil - # User.find(1).valid_authentication_token?('rI1t6PKQ8yP7VetgwdybB') # returns true/false - # module TokenAuthenticatable extend ActiveSupport::Concern include Devise::Models::Authenticatable - included do - before_save :ensure_authentication_token - end - # Generate new authentication token (a.k.a. "single access token"). def reset_authentication_token self.authentication_token = self.class.authentication_token @@ -33,7 +27,7 @@ module Devise # Generate new authentication token and save the record. def reset_authentication_token! reset_authentication_token - self.save + self.save(:validate => false) end # Generate authentication token unless already exists. @@ -46,35 +40,21 @@ module Devise self.reset_authentication_token! if self.authentication_token.blank? end + # Hook called after token authentication. + def after_token_authentication + end + module ClassMethods ::Devise::Models.config(self, :token_authentication_key) - # Authenticate a user based on authentication token. - def authenticate_with_token(attributes) - token = attributes[self.token_authentication_key] - self.find_for_token_authentication(token) + def find_for_token_authentication(conditions) + conditions[:authentication_token] ||= conditions.delete(token_authentication_key) + find_for_authentication(conditions) end def authentication_token ::Devise.friendly_token end - - protected - - # Find first record based on conditions given (ie by the sign in form). - # Overwrite to add customized conditions, create a join, or maybe use a - # namedscope to filter records while authenticating. - # - # == Example: - # - # def self.find_for_token_authentication(token, conditions = {}) - # conditions = {:active => true} - # super - # end - # - def find_for_token_authentication(token) - self.find(:first, :conditions => { :authentication_token => token}) - end end end end diff --git a/lib/devise/strategies/database_authenticatable.rb b/lib/devise/strategies/database_authenticatable.rb index ce9619a5..f47e04ad 100644 --- a/lib/devise/strategies/database_authenticatable.rb +++ b/lib/devise/strategies/database_authenticatable.rb @@ -8,6 +8,7 @@ module Devise resource = mapping.to.find_for_database_authentication(authentication_hash) if validate(resource){ resource.valid_password?(password) } + resource.after_database_authentication success!(resource) else fail(:invalid) diff --git a/lib/devise/strategies/token_authenticatable.rb b/lib/devise/strategies/token_authenticatable.rb index e5dba730..197c460c 100644 --- a/lib/devise/strategies/token_authenticatable.rb +++ b/lib/devise/strategies/token_authenticatable.rb @@ -11,7 +11,8 @@ module Devise # you can pass anything and it will simply be ignored. class TokenAuthenticatable < Authenticatable def authenticate! - if resource = mapping.to.authenticate_with_token(authentication_hash) + if resource = mapping.to.find_for_token_authentication(authentication_hash) + resource.after_token_authentication success!(resource) else fail(:invalid_token) diff --git a/lib/generators/devise/templates/migration.rb b/lib/generators/devise/templates/migration.rb index 81c6b796..ccdace20 100644 --- a/lib/generators/devise/templates/migration.rb +++ b/lib/generators/devise/templates/migration.rb @@ -6,7 +6,9 @@ class DeviseCreate<%= table_name.camelize %> < ActiveRecord::Migration t.recoverable t.rememberable t.trackable + # t.lockable :lock_strategy => :<%= Devise.lock_strategy %>, :unlock_strategy => :<%= Devise.unlock_strategy %> + # t.token_authenticatable t.timestamps end diff --git a/test/models/token_authenticatable_test.rb b/test/models/token_authenticatable_test.rb index ebb1a52d..6ee6a22e 100644 --- a/test/models/token_authenticatable_test.rb +++ b/test/models/token_authenticatable_test.rb @@ -2,13 +2,6 @@ require 'test_helper' class TokenAuthenticatableTest < ActiveSupport::TestCase - test 'should generate friendly authentication token on create' do - User.expects(:authentication_token).returns(VALID_AUTHENTICATION_TOKEN) - user = create_user - assert_present user.authentication_token - assert_equal VALID_AUTHENTICATION_TOKEN, user.authentication_token - end - test 'should reset authentication token' do user = new_user user.reset_authentication_token @@ -26,18 +19,18 @@ class TokenAuthenticatableTest < ActiveSupport::TestCase end test 'should authenticate a valid user with authentication token and return it' do - User.expects(:authentication_token).returns(VALID_AUTHENTICATION_TOKEN) user = create_user + user.ensure_authentication_token! user.confirm! - authenticated_user = User.authenticate_with_token(:auth_token => user.authentication_token) + authenticated_user = User.find_for_token_authentication(:auth_token => user.authentication_token) assert_equal authenticated_user, user end test 'should return nil when authenticating an invalid user by authentication token' do - User.expects(:authentication_token).returns(VALID_AUTHENTICATION_TOKEN) user = create_user + user.ensure_authentication_token! user.confirm! - authenticated_user = User.authenticate_with_token(:auth_token => user.authentication_token.reverse) + authenticated_user = User.find_for_token_authentication(:auth_token => user.authentication_token.reverse) assert_nil authenticated_user end