mirror of
https://github.com/heartcombo/devise.git
synced 2022-11-09 12:18:31 -05:00
Initial support for authorization using "authentication token" (a.k.a. "single access token") - new module. Corresponding changes to Devise core to hook events like "after_changed_password" (only one added now - only one that makes much sense for latest module) easily. Unit and integration tests included. NOTE: One failing test for hooking Warden::Manager.after_authentication - gets ignored for some reason.
Signed-off-by: José Valim <jose.valim@gmail.com>
This commit is contained in:
parent
c03b4ff339
commit
e1440fb430
16 changed files with 420 additions and 11 deletions
|
@ -18,7 +18,7 @@ class SessionsController < ApplicationController
|
|||
set_flash_message :notice, :signed_in
|
||||
sign_in_and_redirect(resource_name, resource, true)
|
||||
else
|
||||
set_now_flash_message :alert, warden.message || :invalid
|
||||
set_now_flash_message :alert, (warden.message || :invalid)
|
||||
build_resource
|
||||
render_with_scope :new
|
||||
end
|
||||
|
|
|
@ -27,21 +27,22 @@ module Devise
|
|||
end
|
||||
|
||||
ALL = [:authenticatable, :activatable, :confirmable, :recoverable,
|
||||
:rememberable, :validatable, :trackable, :timeoutable, :lockable]
|
||||
:rememberable, :validatable, :trackable, :timeoutable, :lockable, :token_authenticatable]
|
||||
|
||||
# Maps controller names to devise modules
|
||||
CONTROLLERS = {
|
||||
:sessions => [:authenticatable],
|
||||
:sessions => [:authenticatable, :token_authenticatable],
|
||||
:passwords => [:recoverable],
|
||||
:confirmations => [:confirmable],
|
||||
:unlocks => [:lockable]
|
||||
}
|
||||
|
||||
STRATEGIES = [:rememberable, :authenticatable]
|
||||
STRATEGIES = [:rememberable, :token_authenticatable, :authenticatable]
|
||||
|
||||
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE']
|
||||
|
||||
# Maps the messages types that are used in flash message.
|
||||
FLASH_MESSAGES = [ :unauthenticated, :unconfirmed, :invalid, :timeout, :inactive, :locked ]
|
||||
FLASH_MESSAGES = [ :unauthenticated, :unconfirmed, :invalid, :invalid_token, :timeout, :inactive, :locked ]
|
||||
|
||||
# Declare encryptors length which are used in migrations.
|
||||
ENCRYPTORS_LENGTH = {
|
||||
|
@ -131,6 +132,21 @@ module Devise
|
|||
mattr_accessor :mailer_sender
|
||||
@@mailer_sender
|
||||
|
||||
# Array of known events that should trigger a authentication token reset.
|
||||
#
|
||||
# == Valid events:
|
||||
#
|
||||
# Warden: :after_set_user, :before_logout
|
||||
# Authenticatable: :after_changed_password
|
||||
#
|
||||
# Note: If set to nil, authentication token will never be reset automatically.
|
||||
mattr_accessor :reset_authentication_token_on
|
||||
@@reset_authentication_token_on = nil
|
||||
|
||||
# Authentication token params key name of choice. E.g. /users/sign_in?some_key=...
|
||||
mattr_accessor :authentication_token_param_key
|
||||
@@authentication_token_param_key = :auth_token
|
||||
|
||||
class << self
|
||||
# Default way to setup Devise. Run script/generate devise_install to create
|
||||
# a fresh initializer with all configuration values.
|
||||
|
|
23
lib/devise/hooks/token_authenticatable.rb
Normal file
23
lib/devise/hooks/token_authenticatable.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
# After each Warden-sign-in: Ensure authentication token is set - if this is enabled.
|
||||
Warden::Manager.after_authentication do |record, warden, options|
|
||||
scope = options[:scope]
|
||||
puts "#"
|
||||
if Devise.mappings[scope].try(:token_authenticatable?) && warden.authenticated?(scope)
|
||||
Devise.reset_authentication_token_on ||= []
|
||||
|
||||
if Devise.reset_authentication_token_on.include?(:after_set_user)
|
||||
record.reset_authentication_token!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# After each Authenticatable-password-change: Ensure authentication token is re-set - if this is enabled.
|
||||
Devise.after_changed_password do |record, scope|
|
||||
if Devise.mappings[scope].try(:token_authenticatable?)
|
||||
Devise.reset_authentication_token_on ||= []
|
||||
|
||||
if Devise.reset_authentication_token_on.include?(:after_changed_password)
|
||||
record.reset_authentication_token!
|
||||
end
|
||||
end
|
||||
end if Devise.respond_to?(:after_changed_password)
|
|
@ -8,6 +8,7 @@ en:
|
|||
unconfirmed: 'You have to confirm your account before continuing.'
|
||||
locked: 'Your account is locked.'
|
||||
invalid: 'Invalid email or password.'
|
||||
invalid_token: 'Invalid authentication token.'
|
||||
timeout: 'Your session expired, please sign in again to continue.'
|
||||
inactive: 'Your account was not activated yet.'
|
||||
passwords:
|
||||
|
|
|
@ -46,6 +46,53 @@ module Devise
|
|||
end
|
||||
end
|
||||
|
||||
# Creates events/hooks for Devise and for the given module.
|
||||
#
|
||||
# Devise::Models.events(Devise::Authenticable, :after_changed_password, :after_timeout_hooks)
|
||||
#
|
||||
# The line above creates:
|
||||
#
|
||||
# 1) Accessor for each hook holding any callback hooks (see +Devise::Models::config+), or explicit:
|
||||
#
|
||||
# Devise::Models.config(Devise::Authenticable, :after_changed_password_hooks, :after_timeout_hooks)
|
||||
#
|
||||
# 1) Setup module accessor hook holding any callback hooks (default fallback config that is):
|
||||
#
|
||||
# Devise.after_changed_password_hooks = []
|
||||
# Devise.after_timeout_hooks = []
|
||||
#
|
||||
# 2) Callback hooks: +Devise::Authenticable.after_changed_password_hooks+ and +Devise::Authenticable.on_timeout+,
|
||||
# used in same manner as +Warden::Manager::after_set_user+, etc.
|
||||
#
|
||||
# To add the class methods you need to have a module ClassMethods defined
|
||||
# inside the given class.
|
||||
#
|
||||
def self.events(mod, *events)
|
||||
::Devise::Models.config(mod, *events.collect { |event| :"#{event}_hooks" })
|
||||
|
||||
events.each do |event|
|
||||
::Devise.class_eval <<-METHOD, __FILE__, __LINE__
|
||||
mattr_accessor :#{event}_hooks
|
||||
@@#{event}_hooks = []
|
||||
|
||||
# Hook for changed password event.
|
||||
def self.#{event}(options = {}, &block)
|
||||
raise BlockNotGiven unless block_given?
|
||||
self.#{event}_hooks << [block, options]
|
||||
end
|
||||
METHOD
|
||||
end
|
||||
end
|
||||
|
||||
# Triggers a named event for a Devise model instance, or more explicitly
|
||||
# triggers all callback hooks for this event.
|
||||
#
|
||||
def self.event!(object, event, *args)
|
||||
object.class.send(:"#{event}_hooks").each { |hook| hook.first.call(*args[0..hook.first.arity]) }
|
||||
rescue
|
||||
# raise "An invalid event was triggered: #{event}. See Devise::Models::events() for usage."
|
||||
end
|
||||
|
||||
# Include the chosen devise modules in your model:
|
||||
#
|
||||
# devise :authenticatable, :confirmable, :recoverable
|
||||
|
|
|
@ -36,7 +36,8 @@ module Devise
|
|||
end
|
||||
end
|
||||
|
||||
# Regenerates password salt and encrypted password each time password is set.
|
||||
# Regenerates password salt and encrypted password each time password is set,
|
||||
# and then trigger any "after_changed_password"-callbacks.
|
||||
def password=(new_password)
|
||||
@password = new_password
|
||||
|
||||
|
@ -44,11 +45,19 @@ module Devise
|
|||
self.password_salt = self.class.encryptor_class.salt
|
||||
self.encrypted_password = password_digest(@password)
|
||||
end
|
||||
|
||||
::Devise::Models.event!(self, :after_changed_password, self, self.class.name.underscore.to_sym)
|
||||
end
|
||||
|
||||
# Verifies whether an incoming_password (ie from sign in) is the user password.
|
||||
def valid_password?(incoming_password)
|
||||
password_digest(incoming_password) == encrypted_password
|
||||
password_digest(incoming_password) == self.encrypted_password
|
||||
end
|
||||
|
||||
# Verifies whether an +incoming_authentication_token+ (i.e. from single access URL)
|
||||
# is the user authentication token.
|
||||
def valid_authentication_token?(incoming_auth_token)
|
||||
incoming_auth_token == self.authentication_token
|
||||
end
|
||||
|
||||
# Checks if a resource is valid upon authentication.
|
||||
|
@ -74,7 +83,15 @@ module Devise
|
|||
self.class.encryptor_class.digest(password, self.class.stretches, self.password_salt, self.class.pepper)
|
||||
end
|
||||
|
||||
def password_changed?
|
||||
!valid_password?(params[:old_password])
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
|
||||
Devise::Models.config(self, :pepper, :stretches, :encryptor, :authentication_keys)
|
||||
Devise::Models.events(self, :after_changed_password)
|
||||
|
||||
# Authenticate a user based on configured attribute keys. Returns the
|
||||
# authenticated user if it's valid or nil. Attributes are by default
|
||||
# :email and :password, but the latter is always required.
|
||||
|
@ -106,7 +123,6 @@ module Devise
|
|||
find(:first, :conditions => conditions)
|
||||
end
|
||||
|
||||
Devise::Models.config(self, :pepper, :stretches, :encryptor, :authentication_keys)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
87
lib/devise/models/token_authenticatable.rb
Normal file
87
lib/devise/models/token_authenticatable.rb
Normal file
|
@ -0,0 +1,87 @@
|
|||
require 'devise/strategies/token_authenticatable'
|
||||
require 'devise/hooks/token_authenticatable'
|
||||
|
||||
module Devise
|
||||
module Models
|
||||
# Token Authenticatable Module, responsible for generate authentication token and validating
|
||||
# authenticity of a user while signing in using a authentication token (say follows an URL).
|
||||
#
|
||||
# == Configuration:
|
||||
#
|
||||
# You can overwrite configuration values by setting in globally in Devise (+Devise.setup+),
|
||||
# using devise method, or overwriting the respective instance method.
|
||||
#
|
||||
# +authentication_token_param_key+ - Defines name of the authentication token params key. E.g. /users/sign_in?some_key=...
|
||||
#
|
||||
# +reset_authentication_token_on+ - Defines which callback hooks that should trigger a authentication token reset.
|
||||
#
|
||||
# == 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
|
||||
def self.included(base)
|
||||
base.class_eval do
|
||||
extend ClassMethods
|
||||
|
||||
before_save :ensure_authentication_token!
|
||||
end
|
||||
end
|
||||
|
||||
# Generate authentication token unless already exists.
|
||||
#
|
||||
def ensure_authentication_token!
|
||||
self.reset_authentication_token!(false) if self.authentication_token.blank?
|
||||
end
|
||||
|
||||
# Generate new authentication token (a.k.a. "single access token").
|
||||
#
|
||||
def reset_authentication_token!(do_save = true)
|
||||
self.authentication_token = self.class.authentication_token
|
||||
self.save if do_save
|
||||
end
|
||||
|
||||
# Verifies whether an +incoming_authentication_token+ (i.e. from single access URL)
|
||||
# is the user authentication token.
|
||||
#
|
||||
def valid_authentication_token?(incoming_auth_token)
|
||||
incoming_auth_token.present? && incoming_auth_token == self.authentication_token
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
|
||||
::Devise::Models.config(self, :authentication_token_param_key, :reset_authentication_token_on)
|
||||
|
||||
# Authenticate a user based on authentication token.
|
||||
#
|
||||
def authenticate_with_token(attributes = {})
|
||||
token = attributes[::Devise.authentication_token_param_key]
|
||||
resource = self.find_for_token_authentication(token)
|
||||
resource if resource.try(:valid_authentication_token?, token)
|
||||
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}
|
||||
# self.find_by_authentication_token(token, :conditions => conditions)
|
||||
# end
|
||||
#
|
||||
def find_for_token_authentication(token, conditions = {})
|
||||
self.find_by_authentication_token(token, :conditions => conditions)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -17,6 +17,11 @@ module Devise
|
|||
apply_schema :password_salt, String, :null => null
|
||||
end
|
||||
|
||||
# Creates authentication_token.
|
||||
def token_authenticatable
|
||||
apply_schema :authentication_token, String, :limit => 20
|
||||
end
|
||||
|
||||
# Creates confirmation_token, confirmed_at and confirmation_sent_at.
|
||||
def confirmable
|
||||
apply_schema :confirmation_token, String, :limit => 20
|
||||
|
|
37
lib/devise/strategies/token_authenticatable.rb
Normal file
37
lib/devise/strategies/token_authenticatable.rb
Normal file
|
@ -0,0 +1,37 @@
|
|||
require 'devise/strategies/base'
|
||||
|
||||
module Devise
|
||||
module Strategies
|
||||
# Strategy for signing in a user, based on a authenticatable token.
|
||||
# Redirects to sign_in page if it's not authenticated.
|
||||
class TokenAuthenticatable < Base
|
||||
def valid?
|
||||
super && authentication_token(scope).present?
|
||||
end
|
||||
|
||||
# Authenticate a user based on authenticatable token params, returning to warden
|
||||
# success and the authenticated user if everything is okay. Otherwise redirect
|
||||
# to sign in page.
|
||||
def authenticate!
|
||||
if resource = mapping.to.authenticate_with_token(params[scope] || params)
|
||||
success!(resource)
|
||||
else
|
||||
fail!(:invalid_token)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def authentication_token(scope)
|
||||
if params[scope]
|
||||
params[scope][::Devise.authentication_token_param_key]
|
||||
else
|
||||
params[::Devise.authentication_token_param_key]
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Warden::Strategies.add(:token_authenticatable, Devise::Strategies::TokenAuthenticatable)
|
|
@ -25,7 +25,7 @@ class DeviseTest < ActiveSupport::TestCase
|
|||
Devise.configure_warden(config)
|
||||
|
||||
assert_equal Devise::FailureApp, config.failure_app
|
||||
assert_equal [:rememberable, :authenticatable], config.default_strategies
|
||||
assert_equal [:rememberable, :token_authenticatable, :authenticatable], config.default_strategies
|
||||
assert_equal :user, config.default_scope
|
||||
assert config.silence_missing_strategies?
|
||||
end
|
||||
|
|
126
test/integration/token_authenticatable_test.rb
Normal file
126
test/integration/token_authenticatable_test.rb
Normal file
|
@ -0,0 +1,126 @@
|
|||
require 'test/test_helper'
|
||||
|
||||
class TokenAuthenticationTest < ActionController::IntegrationTest
|
||||
|
||||
test 'sign in user should authenticate with valid authentication token and proper authentication token key' do
|
||||
swap Devise, :authentication_token_param_key => :secret_token do
|
||||
sign_in_as_new_user_with_token(:auth_token_key => :secret_token, :auth_token => VALID_AUTHENTICATION_TOKEN)
|
||||
|
||||
assert_response :success
|
||||
assert_template 'users/index'
|
||||
assert_contain 'Welcome'
|
||||
assert warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
|
||||
test 'user signing in with valid authentication token - but improper authentication token key - return to sign in form with error message' do
|
||||
# FIXME: For some reason I18n value is not respected. Always render defalt one. =S
|
||||
# store_translations :en, :devise => {:sessions => {:unauthenticated => 'Ouch!'}} do
|
||||
# assert 'Ouch!', I18n.t('devise.sessions.unauthenticated') # for paranoia
|
||||
|
||||
swap Devise, :authentication_token_param_key => :donald_duck_token do
|
||||
sign_in_as_new_user_with_token(:auth_token_key => :secret_token, :auth_token => VALID_AUTHENTICATION_TOKEN)
|
||||
|
||||
assert_redirected_to new_user_session_path(:unauthenticated => true)
|
||||
follow_redirect!
|
||||
|
||||
# assert_contain 'Ouch!'
|
||||
assert_contain 'Sign in'
|
||||
assert_not warden.authenticated?(:user)
|
||||
end
|
||||
# end
|
||||
end
|
||||
|
||||
test 'user signing in with invalid authentication token should return to sign in form with error message' do
|
||||
store_translations :en, :devise => {:sessions => {:invalid_token => 'LOL, that was not a single character correct.'}} do
|
||||
sign_in_as_new_user_with_token(:auth_token => '*** INVALID TOKEN ***')
|
||||
|
||||
assert_redirected_to new_user_session_path(:invalid_token => true)
|
||||
follow_redirect!
|
||||
assert_equal users_path(Devise.authentication_token_param_key => '*** INVALID TOKEN ***'), session[:"user.return_to"]
|
||||
|
||||
assert_response :success
|
||||
assert_contain 'LOL, that was not a single character correct.'
|
||||
assert_contain 'Sign in'
|
||||
assert_not warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
|
||||
test "authentication token should not be reset - if not set to do so if enabled" do
|
||||
swap Devise, :reset_authentication_token_on => [] do
|
||||
User.expects(:authentication_token).returns(VALID_AUTHENTICATION_TOKEN)
|
||||
user = create_user
|
||||
assert_equal VALID_AUTHENTICATION_TOKEN, user.authentication_token
|
||||
|
||||
# after_set_user-event
|
||||
user = sign_in_as_existing_user_with_token(:auth_token => VALID_AUTHENTICATION_TOKEN)
|
||||
assert_equal VALID_AUTHENTICATION_TOKEN, user.authentication_token
|
||||
|
||||
# after_changed_password-event
|
||||
user.password = "new_pass"
|
||||
user.save
|
||||
assert_equal VALID_AUTHENTICATION_TOKEN, user.authentication_token
|
||||
end
|
||||
end
|
||||
|
||||
test "authentication token should be reset after changed password if enabled" do
|
||||
swap Devise, :reset_authentication_token_on => [:after_changed_password] do
|
||||
User.expects(:authentication_token).returns(VALID_AUTHENTICATION_TOKEN)
|
||||
user = create_user
|
||||
assert_not_blank user.authentication_token
|
||||
assert_equal VALID_AUTHENTICATION_TOKEN, user.authentication_token
|
||||
|
||||
# after_set_user-event
|
||||
user = sign_in_as_existing_user_with_token(:auth_token => VALID_AUTHENTICATION_TOKEN)
|
||||
assert_equal VALID_AUTHENTICATION_TOKEN, user.authentication_token
|
||||
|
||||
# after_changed_password-event
|
||||
User.expects(:authentication_token).returns("*** NEW TOKEN / CHANGED PASSWORD ***")
|
||||
user.password = "new_pass"
|
||||
user.save
|
||||
assert_not_equal VALID_AUTHENTICATION_TOKEN, user.authentication_token
|
||||
end
|
||||
end
|
||||
|
||||
# Problem: Warden::Manager.after_authenticate and/or Warden::Manager.after_set_user ignores my hook. Why? =(
|
||||
# See: lib/devise/hooks/token_authenticatable.rb
|
||||
test "authentication token should be reset after logging in if enabled" do
|
||||
swap Devise, :reset_authentication_token_on => [:after_set_user] do
|
||||
User.expects(:authentication_token).returns(VALID_AUTHENTICATION_TOKEN)
|
||||
user = create_user
|
||||
assert_not_blank user.authentication_token
|
||||
assert_equal VALID_AUTHENTICATION_TOKEN, user.authentication_token
|
||||
|
||||
# after_changed_password-event
|
||||
user.password = "new_pass"
|
||||
user.save
|
||||
assert_equal VALID_AUTHENTICATION_TOKEN, user.authentication_token
|
||||
|
||||
# FIXME: after_set_user-event
|
||||
User.expects(:authentication_token).returns("*** NEW TOKEN / SIGN IN ***")
|
||||
user = sign_in_as_existing_user_with_token(:auth_token => VALID_AUTHENTICATION_TOKEN)
|
||||
assert_not_equal VALID_AUTHENTICATION_TOKEN, user.authentication_token
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def sign_in_as_new_user_with_token(options = {}, &block)
|
||||
options[:auth_token_key] ||= Devise.authentication_token_param_key
|
||||
user = create_user(options)
|
||||
user.authentication_token = VALID_AUTHENTICATION_TOKEN
|
||||
user.save
|
||||
visit users_path(options[:auth_token_key].to_sym => (options[:auth_token] || VALID_AUTHENTICATION_TOKEN))
|
||||
yield if block_given?
|
||||
user
|
||||
end
|
||||
|
||||
def sign_in_as_existing_user_with_token(options = {}, &block)
|
||||
options[:auth_token_key] ||= Devise.authentication_token_param_key
|
||||
options[:auth_token] ||= VALID_AUTHENTICATION_TOKEN
|
||||
user = User.authenticate_with_token(options[:auth_token_key].to_sym => options[:auth_token])
|
||||
yield if block_given?
|
||||
user
|
||||
end
|
||||
|
||||
end
|
45
test/models/token_authenticatable_test.rb
Normal file
45
test/models/token_authenticatable_test.rb
Normal file
|
@ -0,0 +1,45 @@
|
|||
require 'test/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!(false)
|
||||
previous_token = user.authentication_token
|
||||
|
||||
user.reset_authentication_token!(false)
|
||||
assert_not_equal previous_token, user.authentication_token
|
||||
end
|
||||
|
||||
test 'should test for a valid authentication token' do
|
||||
User.expects(:authentication_token).returns(VALID_AUTHENTICATION_TOKEN)
|
||||
user = create_user
|
||||
assert user.valid_authentication_token?(VALID_AUTHENTICATION_TOKEN)
|
||||
assert_not user.valid_authentication_token?(VALID_AUTHENTICATION_TOKEN.reverse)
|
||||
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.any_instance.stubs(:confirmed?).returns(true)
|
||||
authenticated_user = User.authenticate_with_token(: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.any_instance.stubs(:confirmed?).returns(true)
|
||||
authenticated_user = User.authenticate_with_token(:auth_token => user.authentication_token.reverse)
|
||||
assert_nil authenticated_user
|
||||
end
|
||||
|
||||
end
|
|
@ -17,6 +17,7 @@ ActiveRecord::Schema.define(:version => 1) do
|
|||
t.rememberable
|
||||
t.trackable
|
||||
t.lockable
|
||||
t.token_authenticatable
|
||||
end
|
||||
|
||||
t.timestamps
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
class User < ActiveRecord::Base
|
||||
devise :authenticatable, :confirmable, :recoverable, :rememberable, :trackable,
|
||||
:validatable, :timeoutable, :lockable
|
||||
:validatable, :timeoutable, :lockable, :token_authenticatable
|
||||
attr_accessible :username, :email, :password, :password_confirmation
|
||||
end
|
||||
|
|
|
@ -2,6 +2,6 @@ class User
|
|||
include MongoMapper::Document
|
||||
key :created_at, DateTime
|
||||
devise :authenticatable, :confirmable, :recoverable, :rememberable, :trackable,
|
||||
:validatable, :timeoutable, :lockable
|
||||
:validatable, :timeoutable, :lockable, :token_authenticatable
|
||||
# attr_accessible :username, :email, :password, :password_confirmation
|
||||
end
|
||||
|
|
5
test/support/tests_helper.rb
Normal file
5
test/support/tests_helper.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
class ActiveSupport::TestCase
|
||||
|
||||
VALID_AUTHENTICATION_TOKEN = 'AbCdEfGhIjKlMnOpQrSt'.freeze
|
||||
|
||||
end
|
Loading…
Reference in a new issue