graphql-relay-walker 0.0.2 → 0.0.3
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/README.md +55 -3
- data/graphql-relay-walker.gemspec +6 -2
- data/lib/graphql/relay/walker.rb +4 -1
- data/lib/graphql/relay/walker/client_ext.rb +12 -4
- data/lib/graphql/relay/walker/frame.rb +51 -0
- data/lib/graphql/relay/walker/queue.rb +9 -56
- metadata +48 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a59fafdca23458e2d2d7c5a057904ef2a2382878
|
4
|
+
data.tar.gz: 8091a0d978843a5e39acf8337a4e6cb30d83491c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eb354a762a31dc48448c18a05a6af5830fb4c6e3c5c20cafbfb5bd3aa2918ffe34c1fb58f9ff5f49f49b667066764c91e12b86566a23cf5f931d180f0b2ab406
|
7
|
+
data.tar.gz: 45ad5fb722b107c74f9825417bb25790c2137ef972871cdae6ba76401ee67ae562e0645da4beefaee78eb0d5c28cea328f81a4ded9438b9dedbe9b6aaf8e70fb
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# GraphQL Relay Walker
|
1
|
+
# GraphQL Relay Walker [](https://travis-ci.org/github/graphql-relay-walker) [](http://badge.fury.io/rb/graphql-relay-walker)
|
2
2
|
|
3
3
|

|
4
4
|
|
@@ -8,8 +8,8 @@
|
|
8
8
|
|
9
9
|
You can install this library as a Ruby Gem:
|
10
10
|
|
11
|
-
```
|
12
|
-
gem install graphql-relay-walker
|
11
|
+
```
|
12
|
+
$ gem install graphql-relay-walker
|
13
13
|
```
|
14
14
|
|
15
15
|
## Usage
|
@@ -60,3 +60,55 @@ SWAPI::Client.walk(from_id: skywalker_gid) do |frame|
|
|
60
60
|
frame.result
|
61
61
|
end
|
62
62
|
```
|
63
|
+
|
64
|
+
## Development
|
65
|
+
|
66
|
+
1. Clone repository and install dependencies
|
67
|
+
|
68
|
+
```
|
69
|
+
$ git clone https://github.com/github/graphql-relay-walker
|
70
|
+
$ cd graphql-relay-walker
|
71
|
+
$ bundle install
|
72
|
+
```
|
73
|
+
|
74
|
+
2. Run tests
|
75
|
+
|
76
|
+
```
|
77
|
+
$ bundle exec rake
|
78
|
+
```
|
79
|
+
|
80
|
+
## Compatibility & Versioning
|
81
|
+
|
82
|
+
This project is designed to work with MRI Ruby 2.2.2 or greater. It may work on other versions of Ruby.
|
83
|
+
|
84
|
+
All releases adhere to strict [semantic versioning](http://semver.org). For Example, major.minor.patch-pre (aka. stick.carrot.oops-peek).
|
85
|
+
|
86
|
+
## Contributions & Feedback
|
87
|
+
|
88
|
+
We love community contributions! If you're planning to send us a pull request, please make sure read our [Contributing Guidelines](https://github.com/github/graphql-relay-walker/blob/master/CONTRIBUTING.md) first.
|
89
|
+
|
90
|
+
Found a bug or have a question? Open up [an issue](https://github.com/github/graphql-relay-walker/issues/new).
|
91
|
+
|
92
|
+
## License
|
93
|
+
|
94
|
+
The MIT License (MIT)
|
95
|
+
|
96
|
+
Copyright (C) 2016 GitHub, Inc.
|
97
|
+
|
98
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
99
|
+
of this software and associated documentation files (the "Software"), to deal
|
100
|
+
in the Software without restriction, including without limitation the rights
|
101
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
102
|
+
copies of the Software, and to permit persons to whom the Software is
|
103
|
+
furnished to do so, subject to the following conditions:
|
104
|
+
|
105
|
+
The above copyright notice and this permission notice shall be included in all
|
106
|
+
copies or substantial portions of the Software.
|
107
|
+
|
108
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
109
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
110
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
111
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
112
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
113
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
114
|
+
SOFTWARE.
|
@@ -1,8 +1,8 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "graphql-relay-walker"
|
3
|
-
s.version = "0.0.
|
3
|
+
s.version = "0.0.3"
|
4
4
|
s.licenses = ["MIT"]
|
5
|
-
s.summary = "
|
5
|
+
s.summary = "A tool for traversing your GraphQL schema to proactively detect potential data access vulnerabilities."
|
6
6
|
s.authors = ["Ben Toews"]
|
7
7
|
s.email = "opensource+graphql-relay-walker@github.com"
|
8
8
|
s.files = %w(LICENSE.md README.md CONTRIBUTING.md CODE_OF_CONDUCT.md graphql-relay-walker.gemspec)
|
@@ -10,4 +10,8 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.homepage = "https://github.com/github/graphql-relay-walker"
|
11
11
|
|
12
12
|
s.add_dependency "graphql", "~> 0.19"
|
13
|
+
|
14
|
+
s.add_development_dependency "rake", "~> 11.3"
|
15
|
+
s.add_development_dependency "rspec", "~> 3.5"
|
16
|
+
s.add_development_dependency "graphql-client", "~> 0.2"
|
13
17
|
end
|
data/lib/graphql/relay/walker.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require "graphql"
|
2
|
+
|
1
3
|
module GraphQL::Relay
|
2
4
|
module Walker
|
3
5
|
# Build a query that starts with a relay node and grabs the IDs of all its
|
@@ -13,7 +15,7 @@ module GraphQL::Relay
|
|
13
15
|
# Start traversing a graph, starting from the given relay node ID.
|
14
16
|
#
|
15
17
|
# from_id: - The `ID!` id to start walking from.
|
16
|
-
# &blk - A block to call with each Walker::
|
18
|
+
# &blk - A block to call with each Walker::Frame that is visited.
|
17
19
|
# This block is responsible for executing a query for the frame's
|
18
20
|
# GID, storing the results in the frame, and enqueuing further
|
19
21
|
# node IDs to visit.
|
@@ -29,4 +31,5 @@ module GraphQL::Relay
|
|
29
31
|
end
|
30
32
|
|
31
33
|
require "graphql/relay/walker/queue"
|
34
|
+
require "graphql/relay/walker/frame"
|
32
35
|
require "graphql/relay/walker/query_builder"
|
@@ -3,18 +3,26 @@ module GraphQL::Relay::Walker
|
|
3
3
|
# Walk this client's graph from the given GID.
|
4
4
|
#
|
5
5
|
# from_id: - The String GID to start walking from.
|
6
|
-
#
|
6
|
+
# variables: - A Hash of variables to be passed to GraphQL::Client.
|
7
|
+
# context: - A Hash containing context to be passed to GraphQL::Client.
|
8
|
+
# &blk - A block to call with each Walker::Frame that is visited.
|
7
9
|
#
|
8
10
|
# Returns nothing.
|
9
|
-
def walk(from_id:)
|
11
|
+
def walk(from_id:, variables: {}, context: {})
|
10
12
|
query_string = GraphQL::Relay::Walker.query_string(schema)
|
11
13
|
walker_query = parse(query_string)
|
12
14
|
|
13
15
|
GraphQL::Relay::Walker.walk(from_id: from_id) do |frame|
|
14
|
-
response = query(
|
16
|
+
response = query(
|
17
|
+
walker_query,
|
18
|
+
variables: variables.merge({"id" => frame.gid}),
|
19
|
+
context: context
|
20
|
+
)
|
21
|
+
|
15
22
|
frame.context[:response] = response
|
16
|
-
frame.result = response.data.to_h
|
23
|
+
frame.result = (response.respond_to?(:data) && response.data) ? response.data.to_h : {}
|
17
24
|
frame.enqueue_found_gids
|
25
|
+
|
18
26
|
yield(frame) if block_given?
|
19
27
|
end
|
20
28
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module GraphQL::Relay::Walker
|
2
|
+
class Frame
|
3
|
+
attr_reader :queue, :gid, :parent, :context
|
4
|
+
attr_accessor :result
|
5
|
+
|
6
|
+
# Initialize a new Frame.
|
7
|
+
#
|
8
|
+
# queue - The Queue that this frame belongs to.
|
9
|
+
# gid - The String GID.
|
10
|
+
# parent - The Frame where this GID was discovered.
|
11
|
+
#
|
12
|
+
# Returns nothing.
|
13
|
+
def initialize(queue, gid, parent)
|
14
|
+
@queue = queue
|
15
|
+
@gid = gid
|
16
|
+
@parent = parent
|
17
|
+
@context = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
# Add each found GID to the queue.
|
21
|
+
#
|
22
|
+
# Returns nothing.
|
23
|
+
def enqueue_found_gids
|
24
|
+
found_gids.each { |gid| queue.add(child(gid)) }
|
25
|
+
end
|
26
|
+
|
27
|
+
# Make a new frame with the given GID and this frame as its parent.
|
28
|
+
#
|
29
|
+
# gid - The String GID to create the frame with.
|
30
|
+
#
|
31
|
+
# Returns a Frame instance.
|
32
|
+
def child(gid)
|
33
|
+
Frame.new(queue, gid, self)
|
34
|
+
end
|
35
|
+
|
36
|
+
# The GIDs from this frame's results.
|
37
|
+
#
|
38
|
+
# Returns an Array of GID Strings.
|
39
|
+
def found_gids(data=result)
|
40
|
+
[].tap do |ids|
|
41
|
+
case data
|
42
|
+
when Hash
|
43
|
+
ids.concat(Array(data["id"]))
|
44
|
+
ids.concat(found_gids(data.values))
|
45
|
+
when Array
|
46
|
+
data.each { |datum| ids.concat(found_gids(datum)) }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module GraphQL::Relay::Walker
|
2
2
|
class Queue
|
3
3
|
attr_accessor :max_size, :random_idx
|
4
|
+
attr_reader :queue, :seen
|
4
5
|
|
5
6
|
# Initialize a new Queue.
|
6
7
|
#
|
@@ -21,16 +22,16 @@ module GraphQL::Relay::Walker
|
|
21
22
|
# Add a frame to the queue if its GID hasn't been seen already and the queue
|
22
23
|
# hasn't exceeded its max size.
|
23
24
|
#
|
24
|
-
# frame - The
|
25
|
+
# frame - The Frame to add to the queue.
|
25
26
|
#
|
26
27
|
# Returns true if the frame was added, false otherwise.
|
27
28
|
def add(frame)
|
28
29
|
return false if max_size && queue.length >= max_size
|
29
|
-
return false if
|
30
|
+
return false if seen.include?(frame.gid)
|
30
31
|
|
31
|
-
|
32
|
-
idx = random_idx ? rand(
|
33
|
-
|
32
|
+
seen.add(frame.gid)
|
33
|
+
idx = random_idx ? rand(queue.length + 1) : queue.length
|
34
|
+
queue.insert(idx, frame)
|
34
35
|
|
35
36
|
true
|
36
37
|
end
|
@@ -50,58 +51,10 @@ module GraphQL::Relay::Walker
|
|
50
51
|
#
|
51
52
|
# Returns nothing.
|
52
53
|
def each_frame
|
53
|
-
|
54
|
-
yield(frame)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
class Frame
|
60
|
-
attr_reader :queue, :gid, :parent, :context
|
61
|
-
attr_accessor :result
|
62
|
-
|
63
|
-
# Initialize a new Frame.
|
64
|
-
#
|
65
|
-
# queue - The Queue that this frame belongs to.
|
66
|
-
# gid - The String GID.
|
67
|
-
# parent - The Frame where this GID was discovered.
|
68
|
-
#
|
69
|
-
# Returns nothing.
|
70
|
-
def initialize(queue, gid, parent)
|
71
|
-
@queue = queue
|
72
|
-
@gid = gid
|
73
|
-
@parent = parent
|
74
|
-
@context = {}
|
75
|
-
end
|
54
|
+
return enum_for(:each_frame) unless block_given?
|
76
55
|
|
77
|
-
|
78
|
-
|
79
|
-
# Returns nothing.
|
80
|
-
def enqueue_found_gids
|
81
|
-
found_gids.each { |gid| queue.add(child(gid)) }
|
82
|
-
end
|
83
|
-
|
84
|
-
# Make a new frame with the given GID and this frame as its parent.
|
85
|
-
#
|
86
|
-
# gid - The String GID to create the frame with.
|
87
|
-
#
|
88
|
-
# Returns a Queue::Frame instance.
|
89
|
-
def child(gid)
|
90
|
-
Frame.new(queue, gid, self)
|
91
|
-
end
|
92
|
-
|
93
|
-
# The GIDs from this frame's results.
|
94
|
-
#
|
95
|
-
# Returns an Array of GID Strings.
|
96
|
-
def found_gids(data=result)
|
97
|
-
[].tap do |ids|
|
98
|
-
case data
|
99
|
-
when Hash
|
100
|
-
ids.concat(Array(data["id"]))
|
101
|
-
ids.concat(found_gids(data.values))
|
102
|
-
when Array
|
103
|
-
data.each { |datum| ids.concat(found_gids(datum)) }
|
104
|
-
end
|
56
|
+
while frame = queue.shift
|
57
|
+
yield(frame)
|
105
58
|
end
|
106
59
|
end
|
107
60
|
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.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Toews
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-11-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: graphql
|
@@ -24,6 +24,48 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0.19'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '11.3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '11.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.5'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: graphql-client
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.2'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.2'
|
27
69
|
description:
|
28
70
|
email: opensource+graphql-relay-walker@github.com
|
29
71
|
executables: []
|
@@ -37,6 +79,7 @@ files:
|
|
37
79
|
- graphql-relay-walker.gemspec
|
38
80
|
- lib/graphql/relay/walker.rb
|
39
81
|
- lib/graphql/relay/walker/client_ext.rb
|
82
|
+
- lib/graphql/relay/walker/frame.rb
|
40
83
|
- lib/graphql/relay/walker/query_builder.rb
|
41
84
|
- lib/graphql/relay/walker/queue.rb
|
42
85
|
homepage: https://github.com/github/graphql-relay-walker
|
@@ -59,9 +102,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
59
102
|
version: '0'
|
60
103
|
requirements: []
|
61
104
|
rubyforge_project:
|
62
|
-
rubygems_version: 2.
|
105
|
+
rubygems_version: 2.5.1
|
63
106
|
signing_key:
|
64
107
|
specification_version: 4
|
65
|
-
summary:
|
108
|
+
summary: A tool for traversing your GraphQL schema to proactively detect potential
|
109
|
+
data access vulnerabilities.
|
66
110
|
test_files: []
|
67
|
-
has_rdoc:
|