Use metal for Devise::FailureApp. \m/

This commit is contained in:
José Valim 2010-02-19 09:52:04 +01:00
parent f0eb4348f3
commit 4a0b9c663a
3 changed files with 42 additions and 48 deletions

View File

@ -1,57 +1,54 @@
require "action_controller/metal"
module Devise
# Failure application that will be called every time :warden is thrown from
# any strategy or hook. Responsible for redirect the user to the sign in
# page based on current scope and mapping. If no scope is given, redirect
# to the default_url.
class FailureApp
attr_reader :env
include Warden::Mixins::Common
class FailureApp < ActionController::Metal
include ActionController::RackDelegation
include ActionController::UrlFor
include ActionController::Redirecting
cattr_accessor :default_url, :default_message, :instance_writer => false
@@default_message = :unauthenticated
mattr_accessor :default_message
self.default_message = :unauthenticated
def self.call(env)
new(env).respond!
action(:respond).call(env)
end
def initialize(env)
@env = env
def self.default_url_options(*args)
ApplicationController.default_url_options(*args)
end
def respond!
options = @env['warden.options']
scope = options[:scope]
redirect_path = if mapping = Devise.mappings[scope]
"#{mapping.parsed_path}/#{mapping.path_names[:sign_in]}"
else
"/#{default_url}"
end
query_string = query_string_for(options)
def respond
scope = env['warden.options'][:scope]
store_location!(scope)
headers = {}
headers["Location"] = redirect_path
headers["Location"] << "?" << query_string unless query_string.empty?
headers["Content-Type"] = 'text/plain'
[302, headers, ["You are being redirected to #{redirect_path}"]]
redirect_to send(:"new_#{scope}_session_path", query_string_params)
end
protected
# Build the proper query string based on the given message.
def query_string_for(options)
message = @env['warden'].try(:message) || options[:message] || default_message
def query_string_params
message = warden.try(:message) || warden_options[:message] || self.class.default_message
params = case message
when Symbol
{ message => true }
when String
{ :message => message }
else
{}
case message
when Symbol
{ message => true }
when String
{ :message => message }
else
{}
end
end
Rack::Utils.build_query(params)
def warden
env['warden']
end
def warden_options
env['warden.options']
end
# Stores requested uri to redirect the user after signing in. We cannot use

View File

@ -7,6 +7,7 @@ class FailureTest < ActiveSupport::TestCase
env = {
'warden.options' => { :scope => :user },
'REQUEST_URI' => 'http://test.host/',
'HTTP_HOST' => 'test.host',
'REQUEST_METHOD' => 'GET',
'rack.session' => {}
}.merge!(env_params)
@ -18,32 +19,28 @@ class FailureTest < ActiveSupport::TestCase
end
test 'return to the default redirect location' do
assert_equal '/users/sign_in?unauthenticated=true', call_failure.second['Location']
assert_equal 'http://test.host/users/sign_in?unauthenticated=true', call_failure.second['Location']
end
test 'uses the proxy failure message' do
warden = OpenStruct.new(:message => :test)
location = call_failure('warden' => warden).second['Location']
assert_equal '/users/sign_in?test=true', location
assert_equal 'http://test.host/users/sign_in?test=true', location
end
test 'uses the given message' do
warden = OpenStruct.new(:message => 'Hello world')
location = call_failure('warden' => warden).second['Location']
assert_equal '/users/sign_in?message=Hello+world', location
assert_equal 'http://test.host/users/sign_in?message=Hello+world', location
end
test 'setup default url' do
Devise::FailureApp.default_url = 'test/sign_in'
location = call_failure('warden.options' => { :scope => nil }).second['Location']
assert_equal '/test/sign_in?unauthenticated=true', location
end
test 'set content type to default text/plain' do
assert_equal 'text/plain', call_failure.second['Content-Type']
test 'set content type to default text/html' do
assert_equal 'text/html; charset=utf-8', call_failure.second['Content-Type']
end
test 'setup a default message' do
assert_equal ['You are being redirected to /users/sign_in?unauthenticated=true'], call_failure.last
assert_match /You are being/, call_failure.last.body
assert_match /redirected/, call_failure.last.body
assert_match /\?unauthenticated=true/, call_failure.last.body
end
end

View File

@ -50,7 +50,7 @@ class ActionController::IntegrationTest
end
def assert_current_path(path)
assert_equal path, current_url
assert_equal(prepend_host(path), prepend_host(current_url))
end
# Fix assert_redirect_to in integration sessions because they don't take into