graphql-relay-walker 0.0.9 → 0.0.10
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/graphql-relay-walker.gemspec +13 -13
- data/lib/graphql/relay/walker.rb +6 -7
- data/lib/graphql/relay/walker/client_ext.rb +6 -6
- data/lib/graphql/relay/walker/frame.rb +2 -2
- data/lib/graphql/relay/walker/query_builder.rb +37 -22
- data/lib/graphql/relay/walker/queue.rb +1 -1
- metadata +12 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f313210bb570cb222d880fe8366826dac2a67dfa
|
4
|
+
data.tar.gz: 526a75f19efffb79fa3daba6cf232bc4ce198e17
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d22c84ebd382d999c204f193350899d8c41c96f20c5f001e21470710c098c0183dc7b2113629de97d06eb3d27c603ded7b00aa615a756ec095025e56bd55346e
|
7
|
+
data.tar.gz: 8e3f30ceeb5280e995eb6dc618148dada50b0a17d5a0d73220e6b220df805fb5258d3f710d650325f584d14bf1fdd6678b224f18f8e74162f1341db9695e54f4
|
@@ -1,17 +1,17 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
|
-
s.name =
|
3
|
-
s.version =
|
4
|
-
s.licenses = [
|
5
|
-
s.summary =
|
6
|
-
s.authors = [
|
7
|
-
s.email =
|
8
|
-
s.files = %w
|
9
|
-
s.files
|
10
|
-
s.homepage
|
2
|
+
s.name = 'graphql-relay-walker'
|
3
|
+
s.version = '0.0.10'
|
4
|
+
s.licenses = ['MIT']
|
5
|
+
s.summary = 'A tool for traversing your GraphQL schema to proactively detect potential data access vulnerabilities.'
|
6
|
+
s.authors = ['Ben Toews']
|
7
|
+
s.email = 'opensource+graphql-relay-walker@github.com'
|
8
|
+
s.files = %w[LICENSE.md README.md CONTRIBUTING.md CODE_OF_CONDUCT.md graphql-relay-walker.gemspec]
|
9
|
+
s.files += Dir.glob('lib/**/*.rb')
|
10
|
+
s.homepage = 'https://github.com/github/graphql-relay-walker'
|
11
11
|
|
12
|
-
s.add_dependency
|
12
|
+
s.add_dependency 'graphql', '>= 0.19'
|
13
13
|
|
14
|
-
s.add_development_dependency
|
15
|
-
s.add_development_dependency
|
16
|
-
s.add_development_dependency
|
14
|
+
s.add_development_dependency 'graphql-client', '~> 0.2'
|
15
|
+
s.add_development_dependency 'rake', '~> 11.3'
|
16
|
+
s.add_development_dependency 'rspec', '~> 3.5'
|
17
17
|
end
|
data/lib/graphql/relay/walker.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'graphql'
|
2
2
|
|
3
3
|
module GraphQL::Relay
|
4
4
|
module Walker
|
@@ -8,8 +8,8 @@ module GraphQL::Relay
|
|
8
8
|
# schema - The GraphQL::Schema to build a query for.
|
9
9
|
#
|
10
10
|
# Returns a String query.
|
11
|
-
def self.query_string(schema)
|
12
|
-
QueryBuilder.new(schema).query_string
|
11
|
+
def self.query_string(schema, except: nil, only: nil)
|
12
|
+
QueryBuilder.new(schema, except: except, only: only).query_string
|
13
13
|
end
|
14
14
|
|
15
15
|
# Start traversing a graph, starting from the given relay node ID.
|
@@ -26,10 +26,9 @@ module GraphQL::Relay
|
|
26
26
|
queue.add_gid(from_id)
|
27
27
|
queue.each_frame(&blk)
|
28
28
|
end
|
29
|
-
|
30
29
|
end
|
31
30
|
end
|
32
31
|
|
33
|
-
require
|
34
|
-
require
|
35
|
-
require
|
32
|
+
require 'graphql/relay/walker/queue'
|
33
|
+
require 'graphql/relay/walker/frame'
|
34
|
+
require 'graphql/relay/walker/query_builder'
|
@@ -8,19 +8,19 @@ module GraphQL::Relay::Walker
|
|
8
8
|
# &blk - A block to call with each Walker::Frame that is visited.
|
9
9
|
#
|
10
10
|
# Returns nothing.
|
11
|
-
def walk(from_id:, variables: {}, context: {})
|
12
|
-
query_string = GraphQL::Relay::Walker.query_string(schema)
|
11
|
+
def walk(from_id:, except: nil, only: nil, variables: {}, context: {})
|
12
|
+
query_string = GraphQL::Relay::Walker.query_string(schema, except: except, only: only)
|
13
13
|
walker_query = parse(query_string)
|
14
14
|
|
15
15
|
GraphQL::Relay::Walker.walk(from_id: from_id) do |frame|
|
16
16
|
response = query(
|
17
17
|
walker_query,
|
18
|
-
variables: variables.merge(
|
18
|
+
variables: variables.merge('id' => frame.gid),
|
19
19
|
context: context
|
20
20
|
)
|
21
21
|
|
22
22
|
frame.context[:response] = response
|
23
|
-
frame.result =
|
23
|
+
frame.result = response.respond_to?(:data) && response.data ? response.data.to_h : {}
|
24
24
|
frame.enqueue_found_gids
|
25
25
|
|
26
26
|
yield(frame) if block_given?
|
@@ -30,8 +30,8 @@ module GraphQL::Relay::Walker
|
|
30
30
|
end
|
31
31
|
|
32
32
|
begin
|
33
|
-
require
|
34
|
-
require
|
33
|
+
require 'graphql/relay/walker'
|
34
|
+
require 'graphql/client'
|
35
35
|
GraphQL::Client.send(:include, GraphQL::Relay::Walker::ClientExt)
|
36
36
|
rescue LoadError
|
37
37
|
end
|
@@ -36,11 +36,11 @@ module GraphQL::Relay::Walker
|
|
36
36
|
# The GIDs from this frame's results.
|
37
37
|
#
|
38
38
|
# Returns an Array of GID Strings.
|
39
|
-
def found_gids(data=result)
|
39
|
+
def found_gids(data = result)
|
40
40
|
[].tap do |ids|
|
41
41
|
case data
|
42
42
|
when Hash
|
43
|
-
ids.concat(Array(data[
|
43
|
+
ids.concat(Array(data['id']))
|
44
44
|
ids.concat(found_gids(data.values))
|
45
45
|
when Array
|
46
46
|
data.each { |datum| ids.concat(found_gids(datum)) }
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module GraphQL::Relay::Walker
|
2
2
|
class QueryBuilder
|
3
|
-
DEFAULT_ARGUMENTS = {
|
4
|
-
BASE_QUERY =
|
3
|
+
DEFAULT_ARGUMENTS = { 'first' => 5 }.freeze
|
4
|
+
BASE_QUERY = 'query($id: ID!) { node(id: $id) { id } }'.freeze
|
5
5
|
|
6
|
-
attr_reader :schema, :connection_arguments, :ast
|
6
|
+
attr_reader :schema, :connection_arguments, :ast, :except, :only
|
7
7
|
|
8
8
|
# Initialize a new QueryBuilder.
|
9
9
|
#
|
@@ -12,8 +12,10 @@ module GraphQL::Relay::Walker
|
|
12
12
|
# (optional).
|
13
13
|
#
|
14
14
|
# Returns nothing.
|
15
|
-
def initialize(schema, connection_arguments: DEFAULT_ARGUMENTS)
|
15
|
+
def initialize(schema, except: nil, only: nil, connection_arguments: DEFAULT_ARGUMENTS)
|
16
16
|
@schema = schema
|
17
|
+
@except = except
|
18
|
+
@only = only
|
17
19
|
@connection_arguments = connection_arguments
|
18
20
|
@ast = build_query
|
19
21
|
end
|
@@ -37,13 +39,25 @@ module GraphQL::Relay::Walker
|
|
37
39
|
selections = d_ast.definitions.first.selections.first.selections
|
38
40
|
|
39
41
|
node_types.each do |type|
|
40
|
-
selections << inline_fragment_ast(type)
|
42
|
+
selections << inline_fragment_ast(type) if include?(type)
|
41
43
|
end
|
42
44
|
|
43
45
|
selections.compact!
|
44
46
|
end
|
45
47
|
end
|
46
48
|
|
49
|
+
# Private: Depending on the `except` or `include` filters,
|
50
|
+
# should this item be included a AST of the given type.
|
51
|
+
#
|
52
|
+
# type - The GraphQL item to identify to make the fragment
|
53
|
+
#
|
54
|
+
# Returns a Boolean.
|
55
|
+
def include?(type)
|
56
|
+
return !@except.call(type, {}) if @except
|
57
|
+
return @only.call(type, {}) if @only
|
58
|
+
true
|
59
|
+
end
|
60
|
+
|
47
61
|
# Private: Make a AST of the given type.
|
48
62
|
#
|
49
63
|
# klass - The GraphQL::Language::Nodes::AbstractNode subclass
|
@@ -80,13 +94,14 @@ module GraphQL::Relay::Walker
|
|
80
94
|
|
81
95
|
if with_children
|
82
96
|
type.all_fields.each do |field|
|
83
|
-
|
97
|
+
field_type = field.type.unwrap
|
98
|
+
if node_field?(field) && include?(field_type)
|
84
99
|
if_ast.selections << node_field_ast(field)
|
85
|
-
elsif connection_field?(field)
|
100
|
+
elsif connection_field?(field) && include?(field_type)
|
86
101
|
if_ast.selections << connection_field_ast(field)
|
87
102
|
end
|
88
103
|
end
|
89
|
-
elsif id = type.get_field(
|
104
|
+
elsif id = type.get_field('id')
|
90
105
|
if_ast.selections << field_ast(id)
|
91
106
|
end
|
92
107
|
end
|
@@ -101,7 +116,7 @@ module GraphQL::Relay::Walker
|
|
101
116
|
#
|
102
117
|
# Returns a GraphQL::Language::Nodes::Field instance or nil if the created
|
103
118
|
# AST was invalid for having no selections or missing required arguments.
|
104
|
-
def field_ast(field, arguments={}, &blk)
|
119
|
+
def field_ast(field, arguments = {}, &blk)
|
105
120
|
type = field.type.unwrap
|
106
121
|
|
107
122
|
# Bail unless we have the required arguments.
|
@@ -113,12 +128,12 @@ module GraphQL::Relay::Walker
|
|
113
128
|
|
114
129
|
make(GraphQL::Language::Nodes::Field, needs_selections: !type.kind.scalar?) do |f_ast|
|
115
130
|
f_ast.name = field.name
|
116
|
-
f_ast.alias = random_alias unless field.name ==
|
131
|
+
f_ast.alias = random_alias unless field.name == 'id'
|
117
132
|
f_ast.arguments = arguments.map do |name, value|
|
118
133
|
GraphQL::Language::Nodes::Argument.new(name: name, value: value)
|
119
134
|
end
|
120
135
|
|
121
|
-
|
136
|
+
yield(f_ast, type) if blk
|
122
137
|
end
|
123
138
|
end
|
124
139
|
|
@@ -132,10 +147,10 @@ module GraphQL::Relay::Walker
|
|
132
147
|
selections = f_ast.selections
|
133
148
|
|
134
149
|
if type.kind.object?
|
135
|
-
|
150
|
+
selections << field_ast(type.get_field('id'))
|
136
151
|
else
|
137
152
|
possible_node_types(type).each do |if_type|
|
138
|
-
|
153
|
+
selections << inline_fragment_ast(if_type, with_children: false)
|
139
154
|
end
|
140
155
|
end
|
141
156
|
end
|
@@ -148,7 +163,7 @@ module GraphQL::Relay::Walker
|
|
148
163
|
# Returns a GraphQL::Language::Nodes::Field instance.
|
149
164
|
def edges_field_ast(field)
|
150
165
|
field_ast(field) do |f_ast, type|
|
151
|
-
f_ast.selections << node_field_ast(type.get_field(
|
166
|
+
f_ast.selections << node_field_ast(type.get_field('node'))
|
152
167
|
end
|
153
168
|
end
|
154
169
|
|
@@ -160,7 +175,7 @@ module GraphQL::Relay::Walker
|
|
160
175
|
# AST was invalid for missing required arguments.
|
161
176
|
def connection_field_ast(field)
|
162
177
|
field_ast(field, connection_arguments) do |f_ast, type|
|
163
|
-
f_ast.selections << edges_field_ast(type.get_field(
|
178
|
+
f_ast.selections << edges_field_ast(type.get_field('edges'))
|
164
179
|
end
|
165
180
|
end
|
166
181
|
|
@@ -191,9 +206,9 @@ module GraphQL::Relay::Walker
|
|
191
206
|
def connection_field?(field)
|
192
207
|
type = field.type.unwrap
|
193
208
|
|
194
|
-
if edges_field = type.get_field(
|
209
|
+
if edges_field = type.get_field('edges')
|
195
210
|
edges = edges_field.type.unwrap
|
196
|
-
if node_field = edges.get_field(
|
211
|
+
if node_field = edges.get_field('node')
|
197
212
|
return node_field?(node_field)
|
198
213
|
end
|
199
214
|
end
|
@@ -234,7 +249,7 @@ module GraphQL::Relay::Walker
|
|
234
249
|
#
|
235
250
|
# Returns a GraphQL::InterfaceType instance.
|
236
251
|
def node_interface
|
237
|
-
schema.types[
|
252
|
+
schema.types['Node']
|
238
253
|
end
|
239
254
|
|
240
255
|
# Make a random alias for a field.
|
@@ -244,16 +259,16 @@ module GraphQL::Relay::Walker
|
|
244
259
|
12.times.map { (SecureRandom.random_number(26) + 97).chr }.join
|
245
260
|
end
|
246
261
|
|
247
|
-
if GraphQL::VERSION >=
|
262
|
+
if GraphQL::VERSION >= '1.5.6'
|
248
263
|
def valid_input?(type, input)
|
249
264
|
type.valid_isolated_input?(input)
|
250
265
|
end
|
251
|
-
elsif GraphQL::VERSION >=
|
266
|
+
elsif GraphQL::VERSION >= '1.4.0'
|
252
267
|
def valid_input?(type, input)
|
253
268
|
allow_all = GraphQL::Schema::Warden.new(->(_) { false }, schema: schema, context: nil)
|
254
269
|
type.valid_input?(input, allow_all)
|
255
270
|
end
|
256
|
-
elsif GraphQL::VERSION >=
|
271
|
+
elsif GraphQL::VERSION >= '1.1.0'
|
257
272
|
def valid_input?(type, input)
|
258
273
|
allow_all = GraphQL::Schema::Warden.new(schema, ->(_) { false })
|
259
274
|
type.valid_input?(input, allow_all)
|
@@ -264,7 +279,7 @@ module GraphQL::Relay::Walker
|
|
264
279
|
end
|
265
280
|
end
|
266
281
|
|
267
|
-
if GraphQL::VERSION >=
|
282
|
+
if GraphQL::VERSION >= '1.0.0'
|
268
283
|
def make_type_name_node(type_name)
|
269
284
|
GraphQL::Language::Nodes::TypeName.new(name: type_name)
|
270
285
|
end
|
@@ -42,7 +42,7 @@ module GraphQL::Relay::Walker
|
|
42
42
|
# parent - The frame where this GID was discovered (optional).
|
43
43
|
#
|
44
44
|
# Returns true if a frame was added, false otherwise.
|
45
|
-
def add_gid(gid, parent=nil)
|
45
|
+
def add_gid(gid, parent = nil)
|
46
46
|
frame = Frame.new(self, gid, parent)
|
47
47
|
add(frame)
|
48
48
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphql-relay-walker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Toews
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-03-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: graphql
|
@@ -25,47 +25,47 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0.19'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: graphql-client
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '0.2'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '0.2'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '3
|
47
|
+
version: '11.3'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '3
|
54
|
+
version: '11.3'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '3.5'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '3.5'
|
69
69
|
description:
|
70
70
|
email: opensource+graphql-relay-walker@github.com
|
71
71
|
executables: []
|
@@ -102,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
102
102
|
version: '0'
|
103
103
|
requirements: []
|
104
104
|
rubyforge_project:
|
105
|
-
rubygems_version: 2.6.
|
105
|
+
rubygems_version: 2.6.12
|
106
106
|
signing_key:
|
107
107
|
specification_version: 4
|
108
108
|
summary: A tool for traversing your GraphQL schema to proactively detect potential
|