diff --git a/lib/devise/failure.rb b/lib/devise/failure.rb new file mode 100644 index 00000000..cc023f8d --- /dev/null +++ b/lib/devise/failure.rb @@ -0,0 +1,25 @@ +module Devise + module Failure + + # 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. + def self.call(env) + options = env['warden.options'] + params = options[:params] || {} + scope = options[:scope] + mapping = Devise.mappings[scope] + + redirect_path = "/#{mapping.as}/#{mapping.path_names[:sign_in]}" + + headers = {} + headers["Location"] = redirect_path + headers["Location"] << "?" << Rack::Utils.build_query(params) unless params.empty? + headers["Content-Type"] = 'text/plain' + + message = options[:message] || "You are being redirected to #{redirect_path}" + + [302, headers, message] + end + end +end diff --git a/test/failure_test.rb b/test/failure_test.rb new file mode 100644 index 00000000..2f94b764 --- /dev/null +++ b/test/failure_test.rb @@ -0,0 +1,34 @@ +require 'test/test_helper' + +class FailureTest < ActiveSupport::TestCase + + def call_failure(env_params={}) + env = {'warden.options' => {:scope => :user}.update(env_params)} + Devise::Failure.call(env) + end + + test 'return 302 status' do + assert_equal 302, call_failure.first + end + + test 'return redirect location based on mapping with params' do + assert_equal '/users/sign_in', call_failure.second['Location'] + end + + test 'add params to redirect location' do + location = call_failure(:params => {:test => true}).second['Location'] + assert_equal '/users/sign_in?test=true', location + end + + test 'set content type to default text/plain' do + assert_equal 'text/plain', call_failure.second['Content-Type'] + end + + test 'setup a default message' do + assert_equal 'You are being redirected to /users/sign_in', call_failure.last + end + + test 'pass in a different message' do + assert_equal 'Hello world', call_failure(:message => 'Hello world').last + end +end