graph_attack 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: a15c0b11d8e25c73943da6bf70907df378deb42c
4
- data.tar.gz: 25e5f9f166d1bb010eee56c7e595b126fe05b748
2
+ SHA256:
3
+ metadata.gz: dd5c8edf29d269a309957b279c0690cb46f897ca4e02c8909cd80816b9ce76fb
4
+ data.tar.gz: ccf872288c199a97d55a36565998e04ca94edc982f1318bd66a67b70140aac9a
5
5
  SHA512:
6
- metadata.gz: ef5a10ecbc9cbe51553bce3936cdbee0eb3ff67bfee7b8f423bd91f2d9a7a012d6b615d2c961f16f1e5366f537ec60ba13ad5264d4141bfaca7a5fc3b25db6c4
7
- data.tar.gz: 542014545b679ea08d44c59ec07df312f31be870d02edb88d3d6bb559948ced10ea9d566b09a7aa1e5ccd028642b230b2ebf6097b337d40108a4fbec1cb9c364
6
+ metadata.gz: 5d7f367fa3125069280b021f6404a19e6a5bcba197ea3c3408b066eadb593e295f2cabcb7d3d4cda5ef0b2a806ac2055dc3943559257aea208dd077a62ff468c
7
+ data.tar.gz: 52adf301f34c476a6b6f97013175bc0036c588788d158d971ad553d62c86c54ac27ad1be83be6c99a120a0b90bf7b2e4da58455bd2988e9fd523ffa92956c203
data/.circleci/config.yml CHANGED
@@ -6,7 +6,7 @@ version: 2
6
6
  jobs:
7
7
  build:
8
8
  docker:
9
- - image: circleci/ruby:2.4.1-node-browsers
9
+ - image: circleci/ruby:2.7.3
10
10
  - image: redis
11
11
 
12
12
  working_directory: ~/repo
@@ -17,19 +17,16 @@ jobs:
17
17
  # Download and cache dependencies
18
18
  - restore_cache:
19
19
  keys:
20
- - v1-dependencies-{{ checksum "graph_attack.gemspec" }}
21
- # fallback to using the latest cache if no exact match is found
22
- - v1-dependencies-
20
+ - v2-dependencies-{{ checksum "graph_attack.gemspec" }}
21
+ - v2-dependencies-
23
22
 
24
- - run:
25
- name: install dependencies
26
- command: |
27
- bundle install --jobs=4 --retry=3 --path vendor/bundle
23
+ - run: gem install bundler:2.0.2
24
+ - run: bundle install --jobs=4 --retry=3 --path vendor/bundle
28
25
 
29
26
  - save_cache:
30
27
  paths:
31
28
  - ./vendor/bundle
32
- key: v1-dependencies-{{ checksum "graph_attack.gemspec" }}
29
+ key: v2-dependencies-{{ checksum "graph_attack.gemspec" }}
33
30
 
34
31
  # Run tests!
35
32
  - run:
@@ -0,0 +1,9 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: bundler
4
+ directory: "/"
5
+ schedule:
6
+ interval: daily
7
+ time: "04:00"
8
+ open-pull-requests-limit: 3
9
+ rebase-strategy: disabled
data/.rubocop.yml CHANGED
@@ -1,5 +1,9 @@
1
+ require:
2
+ - rubocop-rspec
3
+ - rubocop-rake
4
+
1
5
  AllCops:
2
- TargetRubyVersion: 2.3
6
+ TargetRubyVersion: 2.7
3
7
  DisplayCopNames: true
4
8
 
5
9
  # Do not sort gems in Gemfile, since we are grouping them by functionality.
@@ -22,20 +26,19 @@ Style/TrailingCommaInHashLiteral:
22
26
  Layout/MultilineMethodCallIndentation:
23
27
  EnforcedStyle: indented
24
28
 
29
+ Gemspec/RequiredRubyVersion:
30
+ Enabled: false
31
+
25
32
  # Limit method length (default is 10).
26
33
  Metrics/MethodLength:
27
34
  Max: 15
28
35
 
29
- # Do not require `# frozen_string_literal: true` at the top of every file.
30
- FrozenStringLiteralComment:
31
- Enabled: false
32
-
33
36
  # Allow ASCII comments (e.g "…").
34
37
  Style/AsciiComments:
35
38
  Enabled: false
36
39
 
37
40
  # Do not comment the class we create, since the name should be self explanatory.
38
- Documentation:
41
+ Style/Documentation:
39
42
  Enabled: false
40
43
 
41
44
  # Do not verify the length of the blocks in specs.
@@ -43,15 +46,119 @@ Metrics/BlockLength:
43
46
  Exclude:
44
47
  - spec/**/*
45
48
 
46
- # Allow indenting multiline chained operations.
47
- Layout/MultilineMethodCallIndentation:
48
- EnforcedStyle: indented
49
-
50
49
  # Prefer `== 0`, `< 0`, `> 0` to `zero?`, `negative?` or `positive?`,
51
50
  # since they don't exist before Ruby 2.3 or Rails 5 and can be ambiguous.
52
51
  Style/NumericPredicate:
53
52
  EnforcedStyle: comparison
54
53
 
55
- # Allow shorter argument names like `ip`.
56
- Naming/UncommunicativeMethodParamName:
57
- MinNameLength: 2
54
+ # Allow more expectations per example (default 1).
55
+ RSpec/MultipleExpectations:
56
+ Max: 5
57
+
58
+ # Allow more group nesting (default 3)
59
+ RSpec/NestedGroups:
60
+ Max: 5
61
+
62
+ # Allow longer examples (default 5)
63
+ RSpec/ExampleLength:
64
+ Max: 8
65
+
66
+ Layout/EmptyLinesAroundAttributeAccessor:
67
+ Enabled: true
68
+
69
+ Layout/SpaceAroundMethodCallOperator:
70
+ Enabled: true
71
+
72
+ Lint/DeprecatedOpenSSLConstant:
73
+ Enabled: true
74
+
75
+ Lint/MixedRegexpCaptureTypes:
76
+ Enabled: true
77
+
78
+ Lint/RaiseException:
79
+ Enabled: true
80
+
81
+ Lint/StructNewOverride:
82
+ Enabled: true
83
+
84
+ Style/ExponentialNotation:
85
+ Enabled: true
86
+
87
+ Style/HashEachMethods:
88
+ Enabled: true
89
+
90
+ Style/HashTransformKeys:
91
+ Enabled: true
92
+
93
+ Style/HashTransformValues:
94
+ Enabled: true
95
+
96
+ Style/RedundantRegexpCharacterClass:
97
+ Enabled: true
98
+
99
+ Style/RedundantRegexpEscape:
100
+ Enabled: true
101
+
102
+ Style/SlicingWithRange:
103
+ Enabled: true
104
+
105
+ Gemspec/DateAssignment: # (new in 1.10)
106
+ Enabled: true
107
+ Layout/SpaceBeforeBrackets: # (new in 1.7)
108
+ Enabled: true
109
+ Lint/AmbiguousAssignment: # (new in 1.7)
110
+ Enabled: true
111
+ Lint/DeprecatedConstants: # (new in 1.8)
112
+ Enabled: true
113
+ Lint/DuplicateBranch: # (new in 1.3)
114
+ Enabled: true
115
+ Lint/DuplicateRegexpCharacterClassElement: # (new in 1.1)
116
+ Enabled: true
117
+ Lint/EmptyBlock: # (new in 1.1)
118
+ Enabled: true
119
+ Lint/EmptyClass: # (new in 1.3)
120
+ Enabled: true
121
+ Lint/LambdaWithoutLiteralBlock: # (new in 1.8)
122
+ Enabled: true
123
+ Lint/NoReturnInBeginEndBlocks: # (new in 1.2)
124
+ Enabled: true
125
+ Lint/NumberedParameterAssignment: # (new in 1.9)
126
+ Enabled: true
127
+ Lint/OrAssignmentToConstant: # (new in 1.9)
128
+ Enabled: true
129
+ Lint/RedundantDirGlobSort: # (new in 1.8)
130
+ Enabled: true
131
+ Lint/SymbolConversion: # (new in 1.9)
132
+ Enabled: true
133
+ Lint/ToEnumArguments: # (new in 1.1)
134
+ Enabled: true
135
+ Lint/TripleQuotes: # (new in 1.9)
136
+ Enabled: true
137
+ Lint/UnexpectedBlockArity: # (new in 1.5)
138
+ Enabled: true
139
+ Lint/UnmodifiedReduceAccumulator: # (new in 1.1)
140
+ Enabled: true
141
+ Style/ArgumentsForwarding: # (new in 1.1)
142
+ Enabled: true
143
+ Style/CollectionCompact: # (new in 1.2)
144
+ Enabled: true
145
+ Style/DocumentDynamicEvalDefinition: # (new in 1.1)
146
+ Enabled: true
147
+ Style/EndlessMethod: # (new in 1.8)
148
+ Enabled: true
149
+ Style/HashConversion: # (new in 1.10)
150
+ Enabled: true
151
+ Style/HashExcept: # (new in 1.7)
152
+ Enabled: true
153
+ Style/IfWithBooleanLiteralBranches: # (new in 1.9)
154
+ Enabled: true
155
+ Style/NegatedIfElseCondition: # (new in 1.2)
156
+ Enabled: true
157
+ Style/NilLambda: # (new in 1.3)
158
+ Enabled: true
159
+ Style/RedundantArgument: # (new in 1.4)
160
+ Enabled: true
161
+ Style/StringChars: # (new in 1.12)
162
+ Enabled: true
163
+ Style/SwapValues: # (new in 1.1)
164
+ Enabled: true
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.7.3
data/.travis.yml CHANGED
@@ -1,5 +1,6 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.4.1
5
- before_install: gem install bundler -v 1.16.1
4
+ - 2.7.3
5
+ services:
6
+ - redis-server
data/CHANGELOG.md CHANGED
@@ -1,6 +1,13 @@
1
1
  unreleased
2
2
  ----------
3
3
 
4
+ v1.2.0
5
+ ------
6
+
7
+ Feature:
8
+ - New GraphAttack::RateLimit extension to be used in GraphQL::Ruby's class-based
9
+ syntax.
10
+
4
11
  v1.1.0
5
12
  ------
6
13
 
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
data/README.md CHANGED
@@ -8,6 +8,19 @@ GraphQL analyser for blocking & throttling.
8
8
 
9
9
  This gem adds a method to limit access to your GraphQL fields by IP:
10
10
 
11
+ ```rb
12
+ class QueryType < GraphQL::Schema::Object
13
+ field :some_expensive_field, String, null: false do
14
+ extension(GraphAttack::RateLimit, threshold: 15, interval: 60)
15
+ end
16
+
17
+ # …
18
+ end
19
+ ```
20
+
21
+ <details>
22
+ <summary>If using GraphQL::Ruby's legacy schema definition</summary>
23
+
11
24
  ```rb
12
25
  QueryType = GraphQL::ObjectType.define do
13
26
  name 'Query'
@@ -20,6 +33,8 @@ QueryType = GraphQL::ObjectType.define do
20
33
  end
21
34
  ```
22
35
 
36
+ </details>
37
+
23
38
  This would allow only 15 calls per minute by the same IP.
24
39
 
25
40
  ## Requirements
@@ -42,6 +57,9 @@ And then execute:
42
57
  $ bundle
43
58
  ```
44
59
 
60
+ <details>
61
+ <summary>If using GraphQL::Ruby's legacy schema definition</summary>
62
+
45
63
  Add the query analyser to your schema:
46
64
 
47
65
  ```rb
@@ -52,8 +70,10 @@ ApplicationSchema = GraphQL::Schema.define do
52
70
  end
53
71
  ```
54
72
 
73
+ </details>
74
+
55
75
  Finally, make sure you add the current user's IP address as `ip:` to the
56
- GraphQL context:
76
+ GraphQL context. E.g.:
57
77
 
58
78
  ```rb
59
79
  class GraphqlController < ApplicationController
@@ -74,12 +94,28 @@ end
74
94
 
75
95
  Use a custom Redis client instead of the default:
76
96
 
97
+ ```rb
98
+ field :some_expensive_field, String, null: false do
99
+ extension(
100
+ GraphAttack::RateLimit,
101
+ threshold: 15,
102
+ interval: 60,
103
+ redis_client: Redis.new(url: "…"),
104
+ )
105
+ end
106
+ ```
107
+
108
+ <details>
109
+ <summary>If using GraphQL::Ruby's legacy schema definition</summary>
110
+
77
111
  ```rb
78
112
  query_analyzer GraphAttack::RateLimiter.new(
79
113
  redis_client: Redis.new(url: "…")
80
114
  )
81
115
  ```
82
116
 
117
+ </details>
118
+
83
119
  ## Development
84
120
 
85
121
  After checking out the repo, run `bin/setup` to install dependencies. Then, run
@@ -109,12 +145,12 @@ the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
109
145
 
110
146
  Everyone interacting in the GraphAttack project’s codebases, issue trackers,
111
147
  chat rooms and mailing lists is expected to follow the
112
- [code of conduct](https://github.com/sunny/graph_attack/blob/master/CODE_OF_CONDUCT.md).
148
+ [code of conduct](https://github.com/sunny/graph_attack/blob/main/CODE_OF_CONDUCT.md).
113
149
 
114
150
  ## License
115
151
 
116
152
  This project is licensed under the MIT License - see the
117
- [LICENSE.md](https://github.com/sunny/graph_attack/blob/master/LICENSE.md)
153
+ [LICENSE.md](https://github.com/sunny/graph_attack/blob/main/LICENSE.md)
118
154
  file for details.
119
155
 
120
156
  ## Authors
data/Rakefile CHANGED
@@ -1,12 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Bundler
2
4
  require 'bundler/gem_tasks'
3
- require 'rspec/core/rake_task'
4
5
 
5
- # Rspec
6
+ # RSpec
6
7
  require 'rspec/core/rake_task'
7
8
  RSpec::Core::RakeTask.new(:spec)
8
9
 
9
- task default: :spec
10
10
  # Rubocop
11
11
  require 'rubocop/rake_task'
12
12
  RuboCop::RakeTask.new(:rubocop)
data/bin/console CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'bundler/setup'
4
5
  require 'graph_attack'
data/bin/rake 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 'rake' 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', __dir__)
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('rake', 'rake')
data/bin/rubocop 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 'rubocop' 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', __dir__)
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('rubocop', 'rubocop')
data/graph_attack.gemspec CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  lib = File.expand_path('lib', __dir__)
2
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
5
  require 'graph_attack/version'
@@ -18,6 +20,7 @@ Gem::Specification.new do |spec|
18
20
  spec.bindir = 'exe'
19
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
22
  spec.require_paths = ['lib']
23
+ spec.required_ruby_version = ['>= 2.5.7', '< 2.8']
21
24
 
22
25
  # This gem is an analyser for the GraphQL ruby gem.
23
26
  spec.add_dependency 'graphql', '>= 1.7.9'
@@ -26,10 +29,10 @@ Gem::Specification.new do |spec|
26
29
  spec.add_dependency 'ratelimit', '>= 1.0.3'
27
30
 
28
31
  # Loads local dependencies.
29
- spec.add_development_dependency 'bundler', '~> 1.15'
32
+ spec.add_development_dependency 'bundler', '~> 2.0'
30
33
 
31
34
  # Development tasks runner.
32
- spec.add_development_dependency 'rake', '~> 10.0'
35
+ spec.add_development_dependency 'rake', '~> 13.0'
33
36
 
34
37
  # Testing framework.
35
38
  spec.add_development_dependency 'rspec', '~> 3.0'
@@ -38,5 +41,11 @@ Gem::Specification.new do |spec|
38
41
  spec.add_development_dependency 'rspec_junit_formatter', '~> 0.3'
39
42
 
40
43
  # Ruby code linter.
41
- spec.add_development_dependency 'rubocop', '~> 0.55'
44
+ spec.add_development_dependency 'rubocop', '~> 1.1'
45
+
46
+ # RSpec extension for RuboCop.
47
+ spec.add_development_dependency 'rubocop-rspec', '~> 2.2'
48
+
49
+ # Rake extension for RuboCop
50
+ spec.add_development_dependency 'rubocop-rake'
42
51
  end
data/lib/graph_attack.rb CHANGED
@@ -1,7 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'graphql'
2
4
  require 'ratelimit'
5
+
3
6
  require 'graphql/tracing'
4
7
 
5
8
  require 'graph_attack/version'
9
+
10
+ # Class-based schema
11
+ require 'graph_attack/rate_limit'
12
+ require 'graph_attack/error'
13
+ require 'graph_attack/rate_limited'
14
+
15
+ # Legacy schema
6
16
  require 'graph_attack/rate_limiter'
7
17
  require 'graph_attack/metadata'
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphAttack
4
+ class Error < StandardError; end
5
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Add custom field metadata
2
4
  GraphQL::Field.accepts_definitions(
3
5
  rate_limit: GraphQL::Define.assign_metadata_key(:rate_limit),
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphAttack
4
+ class RateLimit < GraphQL::Schema::FieldExtension
5
+ def resolve(object:, arguments:, **_rest)
6
+ ip = object.context[:ip]
7
+ raise GraphAttack::Error, 'Missing :ip value on the GraphQL context' unless ip
8
+
9
+ return RateLimited.new('Query rate limit exceeded') if calls_exceeded_on_query?(ip)
10
+
11
+ yield(object, arguments)
12
+ end
13
+
14
+ private
15
+
16
+ def key
17
+ "graphql-query-#{field.name}"
18
+ end
19
+
20
+ def calls_exceeded_on_query?(ip)
21
+ rate_limit = Ratelimit.new(ip, redis: redis_client)
22
+ rate_limit.add(key)
23
+ rate_limit.exceeded?(
24
+ key,
25
+ threshold: threshold,
26
+ interval: interval,
27
+ )
28
+ end
29
+
30
+ def threshold
31
+ options[:threshold] ||
32
+ raise(
33
+ GraphAttack::Error,
34
+ 'Missing "threshold:" option on the GraphAttack::RateLimit extension',
35
+ )
36
+ end
37
+
38
+ def interval
39
+ options[:interval] ||
40
+ raise(
41
+ GraphAttack::Error,
42
+ 'Missing "interval:" option on the GraphAttack::RateLimit extension',
43
+ )
44
+ end
45
+
46
+ def redis_client
47
+ options[:redis_client] || Redis.current
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphAttack
4
+ class RateLimited < GraphQL::AnalysisError; end
5
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module GraphAttack
2
4
  # Query analyser you can add to your GraphQL schema to limit calls by IP.
3
5
  #
@@ -7,6 +9,7 @@ module GraphAttack
7
9
  #
8
10
  class RateLimiter
9
11
  class Error < StandardError; end
12
+
10
13
  class RateLimited < GraphQL::AnalysisError; end
11
14
 
12
15
  def initialize(redis_client: Redis.new)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module GraphAttack
2
- VERSION = '1.1.0'.freeze
4
+ VERSION = '1.2.0'
3
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graph_attack
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fanny Cheung
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2019-02-18 00:00:00.000000000 Z
12
+ date: 2021-07-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: graphql
@@ -45,28 +45,28 @@ dependencies:
45
45
  requirements:
46
46
  - - "~>"
47
47
  - !ruby/object:Gem::Version
48
- version: '1.15'
48
+ version: '2.0'
49
49
  type: :development
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
53
  - - "~>"
54
54
  - !ruby/object:Gem::Version
55
- version: '1.15'
55
+ version: '2.0'
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: rake
58
58
  requirement: !ruby/object:Gem::Requirement
59
59
  requirements:
60
60
  - - "~>"
61
61
  - !ruby/object:Gem::Version
62
- version: '10.0'
62
+ version: '13.0'
63
63
  type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
67
  - - "~>"
68
68
  - !ruby/object:Gem::Version
69
- version: '10.0'
69
+ version: '13.0'
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: rspec
72
72
  requirement: !ruby/object:Gem::Requirement
@@ -101,14 +101,42 @@ dependencies:
101
101
  requirements:
102
102
  - - "~>"
103
103
  - !ruby/object:Gem::Version
104
- version: '0.55'
104
+ version: '1.1'
105
105
  type: :development
106
106
  prerelease: false
107
107
  version_requirements: !ruby/object:Gem::Requirement
108
108
  requirements:
109
109
  - - "~>"
110
110
  - !ruby/object:Gem::Version
111
- version: '0.55'
111
+ version: '1.1'
112
+ - !ruby/object:Gem::Dependency
113
+ name: rubocop-rspec
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - "~>"
117
+ - !ruby/object:Gem::Version
118
+ version: '2.2'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - "~>"
124
+ - !ruby/object:Gem::Version
125
+ version: '2.2'
126
+ - !ruby/object:Gem::Dependency
127
+ name: rubocop-rake
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
112
140
  description: GraphQL analyser for blocking & throttling
113
141
  email:
114
142
  - fanny@ynote.hk
@@ -118,9 +146,11 @@ extensions: []
118
146
  extra_rdoc_files: []
119
147
  files:
120
148
  - ".circleci/config.yml"
149
+ - ".github/dependabot.yml"
121
150
  - ".gitignore"
122
151
  - ".rspec"
123
152
  - ".rubocop.yml"
153
+ - ".ruby-version"
124
154
  - ".travis.yml"
125
155
  - CHANGELOG.md
126
156
  - CODE_OF_CONDUCT.md
@@ -129,10 +159,15 @@ files:
129
159
  - README.md
130
160
  - Rakefile
131
161
  - bin/console
162
+ - bin/rake
163
+ - bin/rubocop
132
164
  - bin/setup
133
165
  - graph_attack.gemspec
134
166
  - lib/graph_attack.rb
167
+ - lib/graph_attack/error.rb
135
168
  - lib/graph_attack/metadata.rb
169
+ - lib/graph_attack/rate_limit.rb
170
+ - lib/graph_attack/rate_limited.rb
136
171
  - lib/graph_attack/rate_limiter.rb
137
172
  - lib/graph_attack/version.rb
138
173
  homepage: https://github.com/sunny/graph_attack
@@ -146,15 +181,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
146
181
  requirements:
147
182
  - - ">="
148
183
  - !ruby/object:Gem::Version
149
- version: '0'
184
+ version: 2.5.7
185
+ - - "<"
186
+ - !ruby/object:Gem::Version
187
+ version: '2.8'
150
188
  required_rubygems_version: !ruby/object:Gem::Requirement
151
189
  requirements:
152
190
  - - ">="
153
191
  - !ruby/object:Gem::Version
154
192
  version: '0'
155
193
  requirements: []
156
- rubyforge_project:
157
- rubygems_version: 2.6.11
194
+ rubygems_version: 3.1.6
158
195
  signing_key:
159
196
  specification_version: 4
160
197
  summary: GraphQL analyser for blocking & throttling