graphql-relay-walker 0.0.9 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- 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
|