Skip to content

Commit

Permalink
Merge pull request #394 from grzuy/improve_misconfigured_store_except…
Browse files Browse the repository at this point in the history
…ion_message

feat: improve MisconfiguredStoreError exception message to aid debugging
  • Loading branch information
grzuy committed Oct 30, 2018
1 parent cde1e7f commit ef5b0c8
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 45 deletions.
2 changes: 1 addition & 1 deletion lib/rack/attack/cache.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def enforce_store_presence!

def enforce_store_method_presence!(method_name)
if !store.respond_to?(method_name)
raise Rack::Attack::MisconfiguredStoreError, "Store needs to respond to ##{method_name}"
raise Rack::Attack::MisconfiguredStoreError, "Configured store #{store.class.name} doesn't respond to ##{method_name} method"
end
end
end
Expand Down
69 changes: 42 additions & 27 deletions spec/acceptance/cache_store_config_for_allow2ban_spec.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require_relative "../spec_helper"
require "minitest/stub_const"

describe "Cache store config when using allow2ban" do
before do
Expand All @@ -16,61 +17,73 @@
end

it "gives semantic error if store is missing #read method" do
basic_store_class = Class.new do
raised_exception = nil

fake_store_class = Class.new do
def write(key, value)
end

def increment(key, count, options = {})
end
end

Rack::Attack.cache.store = basic_store_class.new
Object.stub_const(:FakeStore, fake_store_class) do
Rack::Attack.cache.store = FakeStore.new

raised_exception = assert_raises(Rack::Attack::MisconfiguredStoreError) do
get "/scarce-resource"
raised_exception = assert_raises(Rack::Attack::MisconfiguredStoreError) do
get "/scarce-resource"
end
end

assert_equal "Store needs to respond to #read", raised_exception.message
assert_equal "Configured store FakeStore doesn't respond to #read method", raised_exception.message
end

it "gives semantic error if store is missing #write method" do
basic_store_class = Class.new do
raised_exception = nil

fake_store_class = Class.new do
def read(key)
end

def increment(key, count, options = {})
end
end

Rack::Attack.cache.store = basic_store_class.new
Object.stub_const(:FakeStore, fake_store_class) do
Rack::Attack.cache.store = FakeStore.new

raised_exception = assert_raises(Rack::Attack::MisconfiguredStoreError) do
get "/scarce-resource"
raised_exception = assert_raises(Rack::Attack::MisconfiguredStoreError) do
get "/scarce-resource"
end
end

assert_equal "Store needs to respond to #write", raised_exception.message
assert_equal "Configured store FakeStore doesn't respond to #write method", raised_exception.message
end

it "gives semantic error if store is missing #increment method" do
basic_store_class = Class.new do
raised_exception = nil

fake_store_class = Class.new do
def read(key)
end

def write(key, value)
end
end

Rack::Attack.cache.store = basic_store_class.new
Object.stub_const(:FakeStore, fake_store_class) do
Rack::Attack.cache.store = FakeStore.new

raised_exception = assert_raises(Rack::Attack::MisconfiguredStoreError) do
get "/scarce-resource"
raised_exception = assert_raises(Rack::Attack::MisconfiguredStoreError) do
get "/scarce-resource"
end
end

assert_equal "Store needs to respond to #increment", raised_exception.message
assert_equal "Configured store FakeStore doesn't respond to #increment method", raised_exception.message
end

it "works with any object that responds to #read, #write and #increment" do
basic_store_class = Class.new do
fake_store_class = Class.new do
attr_accessor :backend

def initialize
Expand All @@ -91,21 +104,23 @@ def increment(key, _count, _options = {})
end
end

Rack::Attack.cache.store = basic_store_class.new
Object.stub_const(:FakeStore, fake_store_class) do
Rack::Attack.cache.store = FakeStore.new

get "/"
assert_equal 200, last_response.status
get "/"
assert_equal 200, last_response.status

get "/scarce-resource"
assert_equal 200, last_response.status
get "/scarce-resource"
assert_equal 200, last_response.status

get "/scarce-resource"
assert_equal 200, last_response.status
get "/scarce-resource"
assert_equal 200, last_response.status

get "/scarce-resource"
assert_equal 403, last_response.status
get "/scarce-resource"
assert_equal 403, last_response.status

get "/"
assert_equal 403, last_response.status
get "/"
assert_equal 403, last_response.status
end
end
end
47 changes: 30 additions & 17 deletions spec/acceptance/cache_store_config_for_fail2ban_spec.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require_relative "../spec_helper"
require "minitest/stub_const"

describe "Cache store config when using fail2ban" do
before do
Expand All @@ -16,61 +17,73 @@
end

it "gives semantic error if store is missing #read method" do
basic_store_class = Class.new do
raised_exception = nil

fake_store_class = Class.new do
def write(key, value)
end

def increment(key, count, options = {})
end
end

Rack::Attack.cache.store = basic_store_class.new
Object.stub_const(:FakeStore, fake_store_class) do
Rack::Attack.cache.store = FakeStore.new

raised_exception = assert_raises(Rack::Attack::MisconfiguredStoreError) do
get "/private-place"
raised_exception = assert_raises(Rack::Attack::MisconfiguredStoreError) do
get "/private-place"
end
end

assert_equal "Store needs to respond to #read", raised_exception.message
assert_equal "Configured store FakeStore doesn't respond to #read method", raised_exception.message
end

it "gives semantic error if store is missing #write method" do
basic_store_class = Class.new do
raised_exception = nil

fake_store_class = Class.new do
def read(key)
end

def increment(key, count, options = {})
end
end

Rack::Attack.cache.store = basic_store_class.new
Object.stub_const(:FakeStore, fake_store_class) do
Rack::Attack.cache.store = FakeStore.new

raised_exception = assert_raises(Rack::Attack::MisconfiguredStoreError) do
get "/private-place"
raised_exception = assert_raises(Rack::Attack::MisconfiguredStoreError) do
get "/private-place"
end
end

assert_equal "Store needs to respond to #write", raised_exception.message
assert_equal "Configured store FakeStore doesn't respond to #write method", raised_exception.message
end

it "gives semantic error if store is missing #increment method" do
basic_store_class = Class.new do
raised_exception = nil

fake_store_class = Class.new do
def read(key)
end

def write(key, value)
end
end

Rack::Attack.cache.store = basic_store_class.new
Object.stub_const(:FakeStore, fake_store_class) do
Rack::Attack.cache.store = FakeStore.new

raised_exception = assert_raises(Rack::Attack::MisconfiguredStoreError) do
get "/private-place"
raised_exception = assert_raises(Rack::Attack::MisconfiguredStoreError) do
get "/private-place"
end
end

assert_equal "Store needs to respond to #increment", raised_exception.message
assert_equal "Configured store FakeStore doesn't respond to #increment method", raised_exception.message
end

it "works with any object that responds to #read, #write and #increment" do
basic_store_class = Class.new do
FakeStore = Class.new do
attr_accessor :backend

def initialize
Expand All @@ -91,7 +104,7 @@ def increment(key, _count, _options = {})
end
end

Rack::Attack.cache.store = basic_store_class.new
Rack::Attack.cache.store = FakeStore.new

get "/"
assert_equal 200, last_response.status
Expand Down

0 comments on commit ef5b0c8

Please sign in to comment.