Use metal for Devise::FailureApp. \m/
This commit is contained in:
parent
f0eb4348f3
commit
4a0b9c663a
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue