diff --git a/CHANGELOG.md b/CHANGELOG.md index 8300c69..97a9256 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ unreleased ---------- +Feature: +- Add `redis_prefix` configuration to provide a custom prefix to Redis ratelimit + keys. + v2.4.1 ------ @@ -30,10 +34,7 @@ Feature: ```rb GraphAttack.configure do |config| - # config.threshold = 15 - # config.interval = 60 - # config.on = :ip - # config.redis_client = Redis.new + … end ``` diff --git a/README.md b/README.md index 753ea73..22e7dda 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,8 @@ class QueryType < GraphQL::Schema::Object end ``` -This would allow 15 requests per minute by the same IP address, blocking the 16th and subsequent requests within that 60-second window. +This would allow 15 requests per minute by the same IP address, blocking the +16th and subsequent requests within that 60-second window. ## Requirements @@ -85,6 +86,17 @@ extension GraphAttack::RateLimit, redis_client: Redis.new(url: "…") ``` +### Custom Redis ratelimit key prefix + +Use a custom prefix in front of the Redis ratelimit key: + +```rb +extension GraphAttack::RateLimit, + threshold: 15, + interval: 60, + redis_prefix: "my-app/production/" +``` + ### Common configuration To have a default configuration for all rate-limited fields, you can create an @@ -96,6 +108,7 @@ GraphAttack.configure do |config| # config.interval = 60 # config.on = :ip # config.redis_client = Redis.new + # config.redis_prefix = "" end ``` diff --git a/lib/graph_attack/configuration.rb b/lib/graph_attack/configuration.rb index 7933098..75e5c99 100644 --- a/lib/graph_attack/configuration.rb +++ b/lib/graph_attack/configuration.rb @@ -15,11 +15,15 @@ class Configuration # Use a custom Redis client. attr_accessor :redis_client + # Prefix for all rate limit Redis keys. + attr_accessor :redis_prefix + def initialize @threshold = nil @interval = nil @on = :ip @redis_client = Redis.new + @redis_prefix = "" end end diff --git a/lib/graph_attack/rate_limit.rb b/lib/graph_attack/rate_limit.rb index 6510493..7d9fd0b 100644 --- a/lib/graph_attack/rate_limit.rb +++ b/lib/graph_attack/rate_limit.rb @@ -18,24 +18,28 @@ def resolve(object:, arguments:, **_rest) private - def key - suffix = "-#{on}" if on != :ip - - "graphql-query-#{field.name}#{suffix}" - end - - def calls_exceeded_on_query?(rate_limited_field) + def calls_exceeded_on_query?(field) with_redis_client do |redis_client| - rate_limit = Ratelimit.new(rate_limited_field, redis: redis_client) - if rate_limit.exceeded?(key, threshold: threshold, interval: interval) + limit = Ratelimit.new(rate_limit_key_name(field), redis: redis_client) + if limit.exceeded?(key, threshold: threshold, interval: interval) true else - rate_limit.add(key) + limit.add(key) false end end end + def key + suffix = "-#{on}" if on != :ip + + "graphql-query-#{field.name}#{suffix}" + end + + def rate_limit_key_name(field) + "#{redis_prefix}#{field}" + end + def threshold options[:threshold] || GraphAttack.configuration.threshold || @@ -66,5 +70,9 @@ def with_redis_client(&block) def on options[:on] || GraphAttack.configuration.on end + + def redis_prefix + options[:redis_prefix] || GraphAttack.configuration.redis_prefix + end end end