Added a couple of helpers to help sign up and delete account tasks.

This commit is contained in:
José Valim 2009-11-15 12:19:16 -02:00
parent 4f6dfefe0e
commit 05fc5712e3
5 changed files with 102 additions and 26 deletions

View File

@ -1,3 +1,7 @@
* enhancements
* [#28] Improved sign_in and sign_out helpers to accepts resources
* [#28] Added stored_location_for as a helper
== 0.5.1
* enhancements

View File

@ -49,17 +49,45 @@ module Devise
warden.authenticated?(scope)
end
# Set the warden user with the scope, signing in the resource automatically,
# without running hooks.
def sign_in(scope, resource)
# Sign in an user that already was authenticated. This helper is useful for logging
# users in after sign up.
#
# Examples:
#
# sign_in :user, @user # sign_in(scope, resource)
# sign_in @user # sign_in(resource)
#
def sign_in(resource_or_scope, resource=nil)
scope ||= find_devise_scope(resource_or_scope)
resource ||= resource_or_scope
warden.set_user(resource, :scope => scope)
end
# Sign out based on scope.
def sign_out(scope, *args)
# Sign out a given user or scope. This helper is useful for signing out an user
# after deleting accounts.
#
# Examples:
#
# sign_out :user # sign_out(scope)
# sign_out @user # sign_out(resource)
#
def sign_out(resource_or_scope)
scope = find_devise_scope(resource_or_scope)
warden.user(scope) # Without loading user here, before_logout hook is not called
warden.raw_session.inspect # Without this inspect here. The session does not clear.
warden.logout(scope, *args)
warden.logout(scope)
end
# Returns and delete the url stored in the session for the given scope. Useful
# for giving redirect backs after sign up:
#
# Example:
#
# redirect_to stored_location_for(:user) || root_path
#
def stored_location_for(resource_or_scope)
scope = find_devise_scope(resource_or_scope)
session.delete(:"#{scope}.return_to")
end
# Define authentication filters and accessor helpers based on mappings.
@ -106,6 +134,16 @@ module Devise
METHODS
end
protected
def find_devise_scope(resource_or_scope)
if resource_or_scope.is_a?(Symbol)
resource_or_scope
else
Devise::Mapping.find_by_class!(resource_or_scope.class).name
end
end
end
end
end

View File

@ -45,18 +45,7 @@ module Devise
# Redirects to stored uri before signing in or the default path and clear
# return to.
def redirect_back_or_to(default)
redirect_to(return_to || default)
clear_return_to
end
# Access to scoped stored uri
def return_to
session[:"#{resource_name}.return_to"]
end
# Clear scoped stored uri
def clear_return_to
session[:"#{resource_name}.return_to"] = nil
redirect_to(stored_location_for(resource_name) || default)
end
# Checks for the existence of the resource root path. If it exists,

View File

@ -34,6 +34,18 @@ module Devise
nil
end
# Find a mapping by a given class. It takes into account single table inheritance as well.
def self.find_by_class(klass)
Devise.mappings.values.find { |m| return m if klass <= m.to }
end
# Find by class but raising an error in case it can't be found.
def self.find_by_class!(klass)
mapping = find_by_class(klass)
raise "Could not find a valid mapping for #{klass}" unless mapping
mapping
end
# Default url options which can be used as prefix.
def self.default_url_options
{}

View File

@ -14,11 +14,13 @@ class MockController < ApplicationController
end
class ControllerAuthenticableTest < ActionController::TestCase
tests MockController
def setup
@controller = MockController.new
@mock_warden = OpenStruct.new
@controller.env = { 'warden' => @mock_warden }
@controller.session = {}
end
test 'setup warden' do
@ -47,12 +49,6 @@ class ControllerAuthenticableTest < ActionController::TestCase
@controller.current_user
end
test 'proxy logout to warden' do
@mock_warden.expects(:user).with(:user).returns(true)
@mock_warden.expects(:logout).with(:user).returns(true)
@controller.sign_out(:user)
end
test 'proxy user_authenticate! to authenticate with user scope' do
@mock_warden.expects(:authenticate!).with(:scope => :user)
@controller.authenticate_user!
@ -83,11 +79,48 @@ class ControllerAuthenticableTest < ActionController::TestCase
@controller.admin_session
end
test 'sign in automatically proxy to set user on warden' do
@mock_warden.expects(:set_user).with(user = mock, :scope => :user).returns(true)
test 'sign in proxy to set_user on warden' do
user = User.new
@mock_warden.expects(:set_user).with(user, :scope => :user).returns(true)
@controller.sign_in(:user, user)
end
test 'sign in accepts a resource as argument' do
user = User.new
@mock_warden.expects(:set_user).with(user, :scope => :user).returns(true)
@controller.sign_in(user)
end
test 'sign out proxy to logout on warden' do
@mock_warden.expects(:user).with(:user).returns(true)
@mock_warden.expects(:logout).with(:user).returns(true)
@controller.sign_out(:user)
end
test 'sign out accepts a resource as argument' do
@mock_warden.expects(:user).with(:user).returns(true)
@mock_warden.expects(:logout).with(:user).returns(true)
@controller.sign_out(User.new)
end
test 'stored location for returns the location for a given scope' do
assert_nil @controller.stored_location_for(:user)
@controller.session[:"user.return_to"] = "/foo.bar"
assert_equal "/foo.bar", @controller.stored_location_for(:user)
end
test 'stored location for accepts a resource as argument' do
assert_nil @controller.stored_location_for(:user)
@controller.session[:"user.return_to"] = "/foo.bar"
assert_equal "/foo.bar", @controller.stored_location_for(User.new)
end
test 'stored location cleans information after reading' do
@controller.session[:"user.return_to"] = "/foo.bar"
assert_equal "/foo.bar", @controller.stored_location_for(:user)
assert_nil @controller.session[:"user.return_to"]
end
test 'is not a devise controller' do
assert_not @controller.devise_controller?
end