From edaa6c6a918f596a19af333f48a0746a65f095e7 Mon Sep 17 00:00:00 2001 From: fatkodima Date: Thu, 24 Oct 2019 02:48:32 +0300 Subject: [PATCH] Make store proxies lookup dynamic --- lib/rack/attack.rb | 13 +++++---- lib/rack/attack/base_proxy.rb | 27 +++++++++++++++++++ lib/rack/attack/cache.rb | 7 ++++- lib/rack/attack/store_proxy.rb | 21 --------------- .../active_support_redis_store_proxy.rb | 4 +-- lib/rack/attack/store_proxy/dalli_proxy.rb | 4 +-- .../store_proxy/mem_cache_store_proxy.rb | 4 +-- .../store_proxy/redis_cache_store_proxy.rb | 4 +-- lib/rack/attack/store_proxy/redis_proxy.rb | 6 ++--- .../attack/store_proxy/redis_store_proxy.rb | 2 +- 10 files changed, 51 insertions(+), 41 deletions(-) create mode 100644 lib/rack/attack/base_proxy.rb delete mode 100644 lib/rack/attack/store_proxy.rb diff --git a/lib/rack/attack.rb b/lib/rack/attack.rb index 740df4f6..ad668756 100644 --- a/lib/rack/attack.rb +++ b/lib/rack/attack.rb @@ -6,6 +6,12 @@ require 'rack/attack/configuration' require 'rack/attack/path_normalizer' require 'rack/attack/request' +require 'rack/attack/store_proxy/dalli_proxy' +require 'rack/attack/store_proxy/mem_cache_store_proxy' +require 'rack/attack/store_proxy/redis_proxy' +require 'rack/attack/store_proxy/redis_store_proxy' +require 'rack/attack/store_proxy/redis_cache_store_proxy' +require 'rack/attack/store_proxy/active_support_redis_store_proxy' require 'rack/attack/railtie' if defined?(::Rails) @@ -21,13 +27,6 @@ class IncompatibleStoreError < Error; end autoload :Safelist, 'rack/attack/safelist' autoload :Blocklist, 'rack/attack/blocklist' autoload :Track, 'rack/attack/track' - autoload :StoreProxy, 'rack/attack/store_proxy' - autoload :DalliProxy, 'rack/attack/store_proxy/dalli_proxy' - autoload :MemCacheStoreProxy, 'rack/attack/store_proxy/mem_cache_store_proxy' - autoload :RedisProxy, 'rack/attack/store_proxy/redis_proxy' - autoload :RedisStoreProxy, 'rack/attack/store_proxy/redis_store_proxy' - autoload :RedisCacheStoreProxy, 'rack/attack/store_proxy/redis_cache_store_proxy' - autoload :ActiveSupportRedisStoreProxy, 'rack/attack/store_proxy/active_support_redis_store_proxy' autoload :Fail2Ban, 'rack/attack/fail2ban' autoload :Allow2Ban, 'rack/attack/allow2ban' diff --git a/lib/rack/attack/base_proxy.rb b/lib/rack/attack/base_proxy.rb new file mode 100644 index 00000000..3e3c28af --- /dev/null +++ b/lib/rack/attack/base_proxy.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require 'delegate' + +module Rack + class Attack + class BaseProxy < SimpleDelegator + class << self + def proxies + @@proxies ||= [] + end + + def inherited(klass) + proxies << klass + end + + def lookup(store) + proxies.find { |proxy| proxy.handle?(store) } + end + + def handle?(_store) + raise NotImplementedError + end + end + end + end +end diff --git a/lib/rack/attack/cache.rb b/lib/rack/attack/cache.rb index 0defa646..f27259e1 100644 --- a/lib/rack/attack/cache.rb +++ b/lib/rack/attack/cache.rb @@ -13,7 +13,12 @@ def initialize attr_reader :store def store=(store) - @store = StoreProxy.build(store) + @store = + if (proxy = BaseProxy.lookup(store)) + proxy.new(store) + else + store + end end def count(unprefixed_key, period) diff --git a/lib/rack/attack/store_proxy.rb b/lib/rack/attack/store_proxy.rb deleted file mode 100644 index 55c63e21..00000000 --- a/lib/rack/attack/store_proxy.rb +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -module Rack - class Attack - module StoreProxy - PROXIES = [ - DalliProxy, - MemCacheStoreProxy, - RedisStoreProxy, - RedisProxy, - RedisCacheStoreProxy, - ActiveSupportRedisStoreProxy - ].freeze - - def self.build(store) - klass = PROXIES.find { |proxy| proxy.handle?(store) } - klass ? klass.new(store) : store - end - end - end -end diff --git a/lib/rack/attack/store_proxy/active_support_redis_store_proxy.rb b/lib/rack/attack/store_proxy/active_support_redis_store_proxy.rb index 68f0326f..d2c0e3b2 100644 --- a/lib/rack/attack/store_proxy/active_support_redis_store_proxy.rb +++ b/lib/rack/attack/store_proxy/active_support_redis_store_proxy.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true -require 'delegate' +require 'rack/attack/base_proxy' module Rack class Attack module StoreProxy - class ActiveSupportRedisStoreProxy < SimpleDelegator + class ActiveSupportRedisStoreProxy < BaseProxy def self.handle?(store) defined?(::Redis) && defined?(::ActiveSupport::Cache::RedisStore) && diff --git a/lib/rack/attack/store_proxy/dalli_proxy.rb b/lib/rack/attack/store_proxy/dalli_proxy.rb index 360e2198..48198bb2 100644 --- a/lib/rack/attack/store_proxy/dalli_proxy.rb +++ b/lib/rack/attack/store_proxy/dalli_proxy.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true -require 'delegate' +require 'rack/attack/base_proxy' module Rack class Attack module StoreProxy - class DalliProxy < SimpleDelegator + class DalliProxy < BaseProxy def self.handle?(store) return false unless defined?(::Dalli) diff --git a/lib/rack/attack/store_proxy/mem_cache_store_proxy.rb b/lib/rack/attack/store_proxy/mem_cache_store_proxy.rb index f8c036c9..122037f0 100644 --- a/lib/rack/attack/store_proxy/mem_cache_store_proxy.rb +++ b/lib/rack/attack/store_proxy/mem_cache_store_proxy.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true -require 'delegate' +require 'rack/attack/base_proxy' module Rack class Attack module StoreProxy - class MemCacheStoreProxy < SimpleDelegator + class MemCacheStoreProxy < BaseProxy def self.handle?(store) defined?(::Dalli) && defined?(::ActiveSupport::Cache::MemCacheStore) && diff --git a/lib/rack/attack/store_proxy/redis_cache_store_proxy.rb b/lib/rack/attack/store_proxy/redis_cache_store_proxy.rb index 78807f86..380215f7 100644 --- a/lib/rack/attack/store_proxy/redis_cache_store_proxy.rb +++ b/lib/rack/attack/store_proxy/redis_cache_store_proxy.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true -require 'delegate' +require 'rack/attack/base_proxy' module Rack class Attack module StoreProxy - class RedisCacheStoreProxy < SimpleDelegator + class RedisCacheStoreProxy < BaseProxy def self.handle?(store) store.class.name == "ActiveSupport::Cache::RedisCacheStore" end diff --git a/lib/rack/attack/store_proxy/redis_proxy.rb b/lib/rack/attack/store_proxy/redis_proxy.rb index e51b3e92..3127de63 100644 --- a/lib/rack/attack/store_proxy/redis_proxy.rb +++ b/lib/rack/attack/store_proxy/redis_proxy.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true -require 'delegate' +require 'rack/attack/base_proxy' module Rack class Attack module StoreProxy - class RedisProxy < SimpleDelegator + class RedisProxy < BaseProxy def initialize(*args) if Gem::Version.new(Redis::VERSION) < Gem::Version.new("3") warn 'RackAttack requires Redis gem >= 3.0.0.' @@ -15,7 +15,7 @@ def initialize(*args) end def self.handle?(store) - defined?(::Redis) && store.is_a?(::Redis) + defined?(::Redis) && store.class == ::Redis end def read(key) diff --git a/lib/rack/attack/store_proxy/redis_store_proxy.rb b/lib/rack/attack/store_proxy/redis_store_proxy.rb index 6be54128..28557bcb 100644 --- a/lib/rack/attack/store_proxy/redis_store_proxy.rb +++ b/lib/rack/attack/store_proxy/redis_store_proxy.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'delegate' +require 'rack/attack/store_proxy/redis_proxy' module Rack class Attack