mirror of
https://github.com/samsonjs/rack-attack.git
synced 2026-03-25 09:25:49 +00:00
Fix reset! when using namespaced cache store (#673)
This commit is contained in:
parent
8d5b210fcd
commit
86650c4f7e
5 changed files with 97 additions and 24 deletions
|
|
@ -55,7 +55,7 @@ module Rack
|
||||||
|
|
||||||
def reset!
|
def reset!
|
||||||
if store.respond_to?(:delete_matched)
|
if store.respond_to?(:delete_matched)
|
||||||
store.delete_matched("#{prefix}*")
|
store.delete_matched(/#{prefix}*/)
|
||||||
else
|
else
|
||||||
raise(
|
raise(
|
||||||
Rack::Attack::IncompatibleStoreError,
|
Rack::Attack::IncompatibleStoreError,
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,10 @@ module Rack
|
||||||
def write(name, value, options = {})
|
def write(name, value, options = {})
|
||||||
super(name, value, options.merge!(raw: true))
|
super(name, value, options.merge!(raw: true))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def delete_matched(matcher, options = nil)
|
||||||
|
super(matcher.source, options)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -45,11 +45,12 @@ module Rack
|
||||||
|
|
||||||
def delete_matched(matcher, _options = nil)
|
def delete_matched(matcher, _options = nil)
|
||||||
cursor = "0"
|
cursor = "0"
|
||||||
|
source = matcher.source
|
||||||
|
|
||||||
rescuing do
|
rescuing do
|
||||||
# Fetch keys in batches using SCAN to avoid blocking the Redis server.
|
# Fetch keys in batches using SCAN to avoid blocking the Redis server.
|
||||||
loop do
|
loop do
|
||||||
cursor, keys = scan(cursor, match: matcher, count: 1000)
|
cursor, keys = scan(cursor, match: source, count: 1000)
|
||||||
del(*keys) unless keys.empty?
|
del(*keys) unless keys.empty?
|
||||||
break if cursor == "0"
|
break if cursor == "0"
|
||||||
end
|
end
|
||||||
|
|
|
||||||
90
spec/rack_attack_reset_spec.rb
Normal file
90
spec/rack_attack_reset_spec.rb
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative "spec_helper"
|
||||||
|
|
||||||
|
describe "Rack::Attack.reset!" do
|
||||||
|
it "raises an error when is not supported by cache store" do
|
||||||
|
Rack::Attack.cache.store = Class.new
|
||||||
|
assert_raises(Rack::Attack::IncompatibleStoreError) do
|
||||||
|
Rack::Attack.reset!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if defined?(Redis)
|
||||||
|
it "should delete rack attack keys" do
|
||||||
|
redis = Redis.new
|
||||||
|
redis.set("key", "value")
|
||||||
|
redis.set("#{Rack::Attack.cache.prefix}::key", "value")
|
||||||
|
Rack::Attack.cache.store = redis
|
||||||
|
Rack::Attack.reset!
|
||||||
|
|
||||||
|
_(redis.get("key")).must_equal "value"
|
||||||
|
_(redis.get("#{Rack::Attack.cache.prefix}::key")).must_be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if defined?(Redis::Store)
|
||||||
|
it "should delete rack attack keys" do
|
||||||
|
redis_store = Redis::Store.new
|
||||||
|
redis_store.set("key", "value")
|
||||||
|
redis_store.set("#{Rack::Attack.cache.prefix}::key", "value")
|
||||||
|
Rack::Attack.cache.store = redis_store
|
||||||
|
Rack::Attack.reset!
|
||||||
|
|
||||||
|
_(redis_store.get("key")).must_equal "value"
|
||||||
|
_(redis_store.get("#{Rack::Attack.cache.prefix}::key")).must_be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if defined?(Redis) && defined?(ActiveSupport::Cache::RedisCacheStore)
|
||||||
|
it "should delete rack attack keys" do
|
||||||
|
redis_cache_store = ActiveSupport::Cache::RedisCacheStore.new
|
||||||
|
redis_cache_store.write("key", "value")
|
||||||
|
redis_cache_store.write("#{Rack::Attack.cache.prefix}::key", "value")
|
||||||
|
Rack::Attack.cache.store = redis_cache_store
|
||||||
|
Rack::Attack.reset!
|
||||||
|
|
||||||
|
_(redis_cache_store.read("key")).must_equal "value"
|
||||||
|
_(redis_cache_store.read("#{Rack::Attack.cache.prefix}::key")).must_be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "with a namespaced cache" do
|
||||||
|
it "should delete rack attack keys" do
|
||||||
|
redis_cache_store = ActiveSupport::Cache::RedisCacheStore.new(namespace: "ns")
|
||||||
|
redis_cache_store.write("key", "value")
|
||||||
|
redis_cache_store.write("#{Rack::Attack.cache.prefix}::key", "value")
|
||||||
|
Rack::Attack.cache.store = redis_cache_store
|
||||||
|
Rack::Attack.reset!
|
||||||
|
|
||||||
|
_(redis_cache_store.read("key")).must_equal "value"
|
||||||
|
_(redis_cache_store.read("#{Rack::Attack.cache.prefix}::key")).must_be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if defined?(ActiveSupport::Cache::MemoryStore)
|
||||||
|
it "should delete rack attack keys" do
|
||||||
|
memory_store = ActiveSupport::Cache::MemoryStore.new
|
||||||
|
memory_store.write("key", "value")
|
||||||
|
memory_store.write("#{Rack::Attack.cache.prefix}::key", "value")
|
||||||
|
Rack::Attack.cache.store = memory_store
|
||||||
|
Rack::Attack.reset!
|
||||||
|
|
||||||
|
_(memory_store.read("key")).must_equal "value"
|
||||||
|
_(memory_store.read("#{Rack::Attack.cache.prefix}::key")).must_be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "with a namespaced cache" do
|
||||||
|
it "should delete rack attack keys" do
|
||||||
|
memory_store = ActiveSupport::Cache::MemoryStore.new(namespace: "ns")
|
||||||
|
memory_store.write("key", "value")
|
||||||
|
memory_store.write("#{Rack::Attack.cache.prefix}::key", "value")
|
||||||
|
Rack::Attack.cache.store = memory_store
|
||||||
|
Rack::Attack.reset!
|
||||||
|
|
||||||
|
_(memory_store.read("key")).must_equal "value"
|
||||||
|
_(memory_store.read("#{Rack::Attack.cache.prefix}::key")).must_be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -103,26 +103,4 @@ describe 'Rack::Attack' do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'reset!' do
|
|
||||||
it 'raises an error when is not supported by cache store' do
|
|
||||||
Rack::Attack.cache.store = Class.new
|
|
||||||
assert_raises(Rack::Attack::IncompatibleStoreError) do
|
|
||||||
Rack::Attack.reset!
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if defined?(Redis)
|
|
||||||
it 'should delete rack attack keys' do
|
|
||||||
redis = Redis.new
|
|
||||||
redis.set('key', 'value')
|
|
||||||
redis.set("#{Rack::Attack.cache.prefix}::key", 'value')
|
|
||||||
Rack::Attack.cache.store = redis
|
|
||||||
Rack::Attack.reset!
|
|
||||||
|
|
||||||
_(redis.get('key')).must_equal 'value'
|
|
||||||
_(redis.get("#{Rack::Attack.cache.prefix}::key")).must_be_nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue