graph_attack 2.2.0 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +39 -0
- data/.rubocop.yml +5 -4
- data/.ruby-version +1 -1
- data/CHANGELOG.md +21 -0
- data/README.md +15 -1
- data/bin/rspec +29 -0
- data/graph_attack.gemspec +2 -2
- data/lib/graph_attack/configuration.rb +37 -0
- data/lib/graph_attack/rate_limit.rb +10 -9
- data/lib/graph_attack/version.rb +1 -1
- data/lib/graph_attack.rb +1 -1
- metadata +11 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bba106f336288a7576af88787f681758899e77b5a35297fa66b855d58bff3678
|
4
|
+
data.tar.gz: c67dd2128bb5779c694de180c8518fc67c91cdd1e048448c420d00c910a2cc97
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 73f2a6a48f8196c0c46a71aefb5d28c89a1a3aa3a024d9e65913388771dfd4cadcadcddcdce79d3022e82607cacd60f0f0533086cff2b69bd53bc212e2a26779
|
7
|
+
data.tar.gz: 170bec4bf21761a476598de2166dbbfcb11cad9b403cc556a3e4d43f9411b0e2b694385f54ce3d9ac022c270d6c517b6b3ce0d7248c3ccb9c307e3986f1dfbf1
|
@@ -0,0 +1,39 @@
|
|
1
|
+
name: Test
|
2
|
+
|
3
|
+
on: [push, pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
test:
|
7
|
+
name: on ruby ${{matrix.ruby}}
|
8
|
+
runs-on: ubuntu-latest
|
9
|
+
|
10
|
+
strategy:
|
11
|
+
fail-fast: false
|
12
|
+
matrix:
|
13
|
+
ruby: ['2.7', '3.0', '3.1', '3.2', head]
|
14
|
+
|
15
|
+
services:
|
16
|
+
redis:
|
17
|
+
image: redis
|
18
|
+
options: >-
|
19
|
+
--health-cmd "redis-cli ping"
|
20
|
+
--health-interval 10s
|
21
|
+
--health-timeout 5s
|
22
|
+
--health-retries 5
|
23
|
+
ports:
|
24
|
+
- 6379:6379
|
25
|
+
|
26
|
+
steps:
|
27
|
+
- name: Checkout repository
|
28
|
+
uses: actions/checkout@v3
|
29
|
+
|
30
|
+
- name: Set up Ruby
|
31
|
+
uses: ruby/setup-ruby@v1
|
32
|
+
with:
|
33
|
+
ruby-version: ${{matrix.ruby}}
|
34
|
+
|
35
|
+
- name: Install dependencies
|
36
|
+
run: bundle install --jobs 4 --retry 3
|
37
|
+
|
38
|
+
- name: RSpec
|
39
|
+
run: bin/rspec
|
data/.rubocop.yml
CHANGED
@@ -6,6 +6,10 @@ AllCops:
|
|
6
6
|
TargetRubyVersion: 2.7
|
7
7
|
DisplayCopNames: true
|
8
8
|
NewCops: enable
|
9
|
+
Exclude:
|
10
|
+
- bin/rake
|
11
|
+
- bin/rspec
|
12
|
+
- bin/rubocop
|
9
13
|
|
10
14
|
# Do not sort gems in Gemfile, since we are grouping them by functionality.
|
11
15
|
Bundler/OrderedGems:
|
@@ -37,9 +41,6 @@ Metrics/MethodLength:
|
|
37
41
|
# Limit line length.
|
38
42
|
Layout/LineLength:
|
39
43
|
Max: 80
|
40
|
-
Exclude:
|
41
|
-
- bin/rake
|
42
|
-
- bin/rubocop
|
43
44
|
|
44
45
|
# Allow ASCII comments (e.g "…").
|
45
46
|
Style/AsciiComments:
|
@@ -69,7 +70,7 @@ RSpec/NestedGroups:
|
|
69
70
|
|
70
71
|
# Allow longer examples (default 5)
|
71
72
|
RSpec/ExampleLength:
|
72
|
-
Max:
|
73
|
+
Max: 15
|
73
74
|
|
74
75
|
Layout/EmptyLinesAroundAttributeAccessor:
|
75
76
|
Enabled: true
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
3.1.3
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,27 @@
|
|
1
1
|
unreleased
|
2
2
|
----------
|
3
3
|
|
4
|
+
v2.3.1
|
5
|
+
------
|
6
|
+
|
7
|
+
Fix:
|
8
|
+
- Relax Ruby version constraint to allow Ruby 3.2.
|
9
|
+
|
10
|
+
v2.3.0
|
11
|
+
------
|
12
|
+
|
13
|
+
Feature:
|
14
|
+
- Add configuration for setting defaults. E.g.:
|
15
|
+
|
16
|
+
```rb
|
17
|
+
GraphAttack.configure do |config|
|
18
|
+
# config.threshold = 15
|
19
|
+
# config.interval = 60
|
20
|
+
# config.on = :ip
|
21
|
+
# config.redis_client = Redis.new
|
22
|
+
end
|
23
|
+
```
|
24
|
+
|
4
25
|
v2.2.0
|
5
26
|
------
|
6
27
|
|
data/README.md
CHANGED
@@ -85,6 +85,20 @@ extension GraphAttack::RateLimit,
|
|
85
85
|
redis_client: Redis.new(url: "…")
|
86
86
|
```
|
87
87
|
|
88
|
+
### Common configuration
|
89
|
+
|
90
|
+
To have a default configuration for all rate-limited fields, you can create an
|
91
|
+
initializer:
|
92
|
+
|
93
|
+
```rb
|
94
|
+
GraphAttack.configure do |config|
|
95
|
+
# config.threshold = 15
|
96
|
+
# config.interval = 60
|
97
|
+
# config.on = :ip
|
98
|
+
# config.redis_client = Redis.new
|
99
|
+
end
|
100
|
+
```
|
101
|
+
|
88
102
|
## Development
|
89
103
|
|
90
104
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
@@ -104,7 +118,7 @@ tests and linting are pristine by calling `bundle && bin/rake`, then create a
|
|
104
118
|
commit for this version, for example with:
|
105
119
|
|
106
120
|
```sh
|
107
|
-
git add
|
121
|
+
git add --patch
|
108
122
|
git commit -m v`ruby -rbundler/setup -rgraph_attack/version -e "puts GraphAttack::VERSION"`
|
109
123
|
```
|
110
124
|
|
data/bin/rspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rspec' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("rspec-core", "rspec")
|
data/graph_attack.gemspec
CHANGED
@@ -23,13 +23,13 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
24
24
|
spec.require_paths = ['lib']
|
25
25
|
|
26
|
-
spec.required_ruby_version =
|
26
|
+
spec.required_ruby_version = '>= 2.5.7'
|
27
27
|
|
28
28
|
# This gem is an analyser for the GraphQL ruby gem.
|
29
29
|
spec.add_dependency 'graphql', '>= 1.7.9'
|
30
30
|
|
31
31
|
# A Redis-backed rate limiter.
|
32
|
-
spec.add_dependency 'ratelimit', '>= 1.0.
|
32
|
+
spec.add_dependency 'ratelimit', '>= 1.0.4'
|
33
33
|
|
34
34
|
# Loads local dependencies.
|
35
35
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphAttack
|
4
|
+
# Store the config
|
5
|
+
class Configuration
|
6
|
+
# Number of calls allowed.
|
7
|
+
attr_accessor :threshold
|
8
|
+
|
9
|
+
# Time interval in seconds.
|
10
|
+
attr_accessor :interval
|
11
|
+
|
12
|
+
# Key on the context on which to differentiate users.
|
13
|
+
attr_accessor :on
|
14
|
+
|
15
|
+
# Use a custom Redis client.
|
16
|
+
attr_accessor :redis_client
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@threshold = nil
|
20
|
+
@interval = nil
|
21
|
+
@on = :ip
|
22
|
+
@redis_client = Redis.new
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class << self
|
27
|
+
attr_writer :configuration
|
28
|
+
|
29
|
+
def configuration
|
30
|
+
@configuration ||= Configuration.new
|
31
|
+
end
|
32
|
+
|
33
|
+
def configure
|
34
|
+
yield(configuration)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -3,11 +3,10 @@
|
|
3
3
|
module GraphAttack
|
4
4
|
class RateLimit < GraphQL::Schema::FieldExtension
|
5
5
|
def resolve(object:, arguments:, **_rest)
|
6
|
-
rate_limited_field = object.context[
|
6
|
+
rate_limited_field = object.context[on]
|
7
7
|
|
8
|
-
unless object.context.key?(
|
9
|
-
raise GraphAttack::Error,
|
10
|
-
"Missing :#{rate_limited_key} key on the GraphQL context"
|
8
|
+
unless object.context.key?(on)
|
9
|
+
raise GraphAttack::Error, "Missing :#{on} key on the GraphQL context"
|
11
10
|
end
|
12
11
|
|
13
12
|
if rate_limited_field && calls_exceeded_on_query?(rate_limited_field)
|
@@ -20,9 +19,9 @@ module GraphAttack
|
|
20
19
|
private
|
21
20
|
|
22
21
|
def key
|
23
|
-
|
22
|
+
suffix = "-#{on}" if on != :ip
|
24
23
|
|
25
|
-
"graphql-query-#{field.name}#{
|
24
|
+
"graphql-query-#{field.name}#{suffix}"
|
26
25
|
end
|
27
26
|
|
28
27
|
def calls_exceeded_on_query?(rate_limited_field)
|
@@ -34,6 +33,7 @@ module GraphAttack
|
|
34
33
|
|
35
34
|
def threshold
|
36
35
|
options[:threshold] ||
|
36
|
+
GraphAttack.configuration.threshold ||
|
37
37
|
raise(
|
38
38
|
GraphAttack::Error,
|
39
39
|
'Missing "threshold:" option on the GraphAttack::RateLimit extension',
|
@@ -42,6 +42,7 @@ module GraphAttack
|
|
42
42
|
|
43
43
|
def interval
|
44
44
|
options[:interval] ||
|
45
|
+
GraphAttack.configuration.interval ||
|
45
46
|
raise(
|
46
47
|
GraphAttack::Error,
|
47
48
|
'Missing "interval:" option on the GraphAttack::RateLimit extension',
|
@@ -49,11 +50,11 @@ module GraphAttack
|
|
49
50
|
end
|
50
51
|
|
51
52
|
def redis_client
|
52
|
-
options[:redis_client] ||
|
53
|
+
options[:redis_client] || GraphAttack.configuration.redis_client
|
53
54
|
end
|
54
55
|
|
55
|
-
def
|
56
|
-
options[:on] ||
|
56
|
+
def on
|
57
|
+
options[:on] || GraphAttack.configuration.on
|
57
58
|
end
|
58
59
|
end
|
59
60
|
end
|
data/lib/graph_attack/version.rb
CHANGED
data/lib/graph_attack.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graph_attack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fanny Cheung
|
8
8
|
- Sunny Ripert
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2023-03-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: graphql
|
@@ -31,14 +31,14 @@ dependencies:
|
|
31
31
|
requirements:
|
32
32
|
- - ">="
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: 1.0.
|
34
|
+
version: 1.0.4
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - ">="
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: 1.0.
|
41
|
+
version: 1.0.4
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: bundler
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -147,6 +147,7 @@ extra_rdoc_files: []
|
|
147
147
|
files:
|
148
148
|
- ".circleci/config.yml"
|
149
149
|
- ".github/dependabot.yml"
|
150
|
+
- ".github/workflows/test.yml"
|
150
151
|
- ".gitignore"
|
151
152
|
- ".rspec"
|
152
153
|
- ".rubocop.yml"
|
@@ -160,10 +161,12 @@ files:
|
|
160
161
|
- Rakefile
|
161
162
|
- bin/console
|
162
163
|
- bin/rake
|
164
|
+
- bin/rspec
|
163
165
|
- bin/rubocop
|
164
166
|
- bin/setup
|
165
167
|
- graph_attack.gemspec
|
166
168
|
- lib/graph_attack.rb
|
169
|
+
- lib/graph_attack/configuration.rb
|
167
170
|
- lib/graph_attack/error.rb
|
168
171
|
- lib/graph_attack/rate_limit.rb
|
169
172
|
- lib/graph_attack/rate_limited.rb
|
@@ -172,7 +175,7 @@ homepage: https://github.com/sunny/graph_attack
|
|
172
175
|
licenses: []
|
173
176
|
metadata:
|
174
177
|
rubygems_mfa_required: 'true'
|
175
|
-
post_install_message:
|
178
|
+
post_install_message:
|
176
179
|
rdoc_options: []
|
177
180
|
require_paths:
|
178
181
|
- lib
|
@@ -181,17 +184,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
181
184
|
- - ">="
|
182
185
|
- !ruby/object:Gem::Version
|
183
186
|
version: 2.5.7
|
184
|
-
- - "<"
|
185
|
-
- !ruby/object:Gem::Version
|
186
|
-
version: '3.2'
|
187
187
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
188
188
|
requirements:
|
189
189
|
- - ">="
|
190
190
|
- !ruby/object:Gem::Version
|
191
191
|
version: '0'
|
192
192
|
requirements: []
|
193
|
-
rubygems_version: 3.
|
194
|
-
signing_key:
|
193
|
+
rubygems_version: 3.3.26
|
194
|
+
signing_key:
|
195
195
|
specification_version: 4
|
196
196
|
summary: GraphQL analyser for blocking & throttling
|
197
197
|
test_files: []
|