Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions lib/warden/manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -134,16 +134,32 @@ def process_unauthenticated(env, options={})
# The before_failure hooks are run on each failure
# :api: private
def call_failure_app(env, options = {})
if config.failure_app
options.merge!(:attempted_path => ::Rack::Request.new(env).fullpath)
env["PATH_INFO"] = "/#{options[:action]}"
env["warden.options"] = options
raise "No Failure App provided" unless config.failure_app

_run_callbacks(:before_failure, env, options)
config.failure_app.call(env).to_a
options.merge!(:attempted_path => ::Rack::Request.new(env).fullpath)
env["PATH_INFO"] = "/#{options[:action]}"
env["warden.options"] = options

_run_callbacks(:before_failure, env, options)

failure_app_config = config.failure_app
case failure_app_config
when Array
call_multiple_failure_apps(failure_app_config, env, options)
when Hash
call_multiple_failure_apps([failure_app_config], env, options)
else
raise "No Failure App provided"
call_multiple_failure_apps([{ app: failure_app_config, scope: options[:scope] }], env, options)
end
end # call_failure_app

# :api: private
def call_multiple_failure_apps(failure_app_config, env, options)
failure_app_config.each do |c|
return c[:app].call(env).to_a if options[:scope] == c[:scope]
end

raise "No Failure App provided for scope"
end # call_multiple_failure_apps
end
end # Warden
40 changes: 40 additions & 0 deletions spec/warden/manager_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,46 @@
expect(result.last).to eq(["Failure App"])
end

it "should raise an error when no matching failure app by scope is found" do
app = lambda { |e| throw(:warden, :scope => :default) }
fail_app = lambda { |e| [401, {"Content-Type" => "text/plain"}, ["Failure App"]] }

expect {
setup_rack(
app,
:failure_app => { app: fail_app, scope: :foo }
).call(env_with_params)
}.to raise_error(RuntimeError, 'No Failure App provided for scope')
end

it "should render the matching failure app by scope" do
app = lambda { |e| throw(:warden, :scope => :default) }
fail_app = lambda { |e| [401, {"Content-Type" => "text/plain"}, ["Failure App"]] }

result = setup_rack(
app,
:failure_app => { app: fail_app, scope: :default }
).call(env_with_params)

expect(result.last).to eq(["Failure App"])
end

it "should render the right configured matching failure app by scope" do
app = lambda { |e| throw(:warden, :scope => :default) }
fail_app1 = lambda { |e| [401, {"Content-Type" => "text/plain"}, ["Failure App #1"]] }
fail_app2 = lambda { |e| [401, {"Content-Type" => "text/plain"}, ["Failure App #2"]] }

result = setup_rack(
app,
:failure_app => [
{ app: fail_app1, scope: :foo },
{ app: fail_app2, scope: :default }
]
).call(env_with_params)

expect(result.last).to eq(["Failure App #2"])
end

it "should call failure app if warden is thrown even after successful authentication" do
env = env_with_params("/", {})
app = lambda do |_env|
Expand Down