graphql-guard 0.4.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +40 -1
- data/README.md +13 -15
- data/lib/graphql/guard/testing.rb +9 -8
- data/lib/graphql/guard/version.rb +1 -1
- data/lib/graphql/guard.rb +8 -15
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2fee7151ba4f1b935f9bb185bc1ecef61920d0bc
|
4
|
+
data.tar.gz: d5286b90482d2e5a99827f05a3587d9f596a0669
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36f519bf2ed0879655eced44f1a8062e13fcfc01d08565c7c92d33ee50cef08278e430054cc42ed9834a629dc16d3512b19cf14ef2c395a19f37929c615488c0
|
7
|
+
data.tar.gz: c9873f1af3b37a07398e853871f661bb45d232d79cc833aa6f0bc2aca1104e961b8e2ecf2bda3a38950de7ad91181918dbe62447cb2267ac88966b88df9c3c26
|
data/CHANGELOG.md
CHANGED
@@ -8,10 +8,49 @@ one of the following labels: `Added`, `Changed`, `Deprecated`,
|
|
8
8
|
to manage the versions of this gem so
|
9
9
|
that you can set version constraints properly.
|
10
10
|
|
11
|
-
#### [Unreleased](https://github.com/exAspArk/graphql-guard/compare/
|
11
|
+
#### [Unreleased](https://github.com/exAspArk/graphql-guard/compare/v1.0.0...HEAD)
|
12
12
|
|
13
13
|
* WIP
|
14
14
|
|
15
|
+
#### [v1.0.0](https://github.com/exAspArk/graphql-guard/compare/v0.4.0...v1.0.0) – 2017-07-31
|
16
|
+
|
17
|
+
* `Changed`: guards for every `*` field also accepts arguments: `->(object, arguments, context) { ... }`:
|
18
|
+
|
19
|
+
* Before:
|
20
|
+
|
21
|
+
<pre>
|
22
|
+
GraphQL::ObjectType.define do
|
23
|
+
name "Post"
|
24
|
+
guard ->(obj, ctx) { ... }
|
25
|
+
...
|
26
|
+
end
|
27
|
+
</pre>
|
28
|
+
|
29
|
+
* After:
|
30
|
+
|
31
|
+
<pre>
|
32
|
+
GraphQL::ObjectType.define do
|
33
|
+
name "Post"
|
34
|
+
guard ->(obj, <b>args</b>, ctx) { ... }
|
35
|
+
...
|
36
|
+
end
|
37
|
+
</pre>
|
38
|
+
|
39
|
+
* `Changed`: `.field_with_guard` from `graphql/guard/testing` module accepts policy object as a second argument:
|
40
|
+
|
41
|
+
* Before:
|
42
|
+
|
43
|
+
<pre>
|
44
|
+
guard_object = GraphQL::Guard.new(policy_object: GraphqlPolicy)
|
45
|
+
posts_field = QueryType.field_with_guard('posts', <b>guard_object</b>)
|
46
|
+
</pre>
|
47
|
+
|
48
|
+
* After:
|
49
|
+
|
50
|
+
<pre>
|
51
|
+
posts_field = QueryType.field_with_guard('posts', <b>GraphqlPolicy</b>)
|
52
|
+
</pre>
|
53
|
+
|
15
54
|
#### [v0.4.0](https://github.com/exAspArk/graphql-guard/compare/v0.3.0...v0.4.0) – 2017-07-25
|
16
55
|
|
17
56
|
* `Added`: ability to test `guard` lambdas via field.
|
data/README.md
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
[![Downloads](https://img.shields.io/gem/dt/graphql-guard.svg)](https://rubygems.org/gems/graphql-guard)
|
7
7
|
[![Latest Version](https://img.shields.io/gem/v/graphql-guard.svg)](https://rubygems.org/gems/graphql-guard)
|
8
8
|
|
9
|
-
This
|
9
|
+
This gem provides a field-level authorization for [graphql-ruby](https://github.com/rmosolgo/graphql-ruby).
|
10
10
|
|
11
11
|
## Contents
|
12
12
|
|
@@ -44,7 +44,7 @@ QueryType = GraphQL::ObjectType.define do
|
|
44
44
|
|
45
45
|
field :posts, !types[PostType] do
|
46
46
|
argument :user_id, !types.ID
|
47
|
-
resolve ->(
|
47
|
+
resolve ->(obj, args, ctx) { Post.where(user_id: args[:user_id]) }
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -82,12 +82,12 @@ QueryType = GraphQL::ObjectType.define do
|
|
82
82
|
end
|
83
83
|
</pre>
|
84
84
|
|
85
|
-
You can also define `guard`, which will be executed for every
|
85
|
+
You can also define `guard`, which will be executed for every `*` field in the type:
|
86
86
|
|
87
87
|
<pre>
|
88
88
|
PostType = GraphQL::ObjectType.define do
|
89
89
|
name "Post"
|
90
|
-
<b>guard ->(obj, ctx) {</b> ctx[:current_user].admin? <b>}</b>
|
90
|
+
<b>guard ->(obj, args, ctx) {</b> ctx[:current_user].admin? <b>}</b>
|
91
91
|
...
|
92
92
|
end
|
93
93
|
</pre>
|
@@ -105,7 +105,7 @@ class <b>GraphqlPolicy</b>
|
|
105
105
|
<b>posts: ->(obj, args, ctx) {</b> args[:user_id] == ctx[:current_user].id <b>}</b>
|
106
106
|
},
|
107
107
|
PostType => {
|
108
|
-
<b>'*': ->(obj, ctx) {</b> ctx[:current_user].admin? <b>}</b>
|
108
|
+
<b>'*': ->(obj, args, ctx) {</b> ctx[:current_user].admin? <b>}</b>
|
109
109
|
}
|
110
110
|
}
|
111
111
|
|
@@ -137,8 +137,8 @@ end
|
|
137
137
|
class <b>GraphqlPolicy</b>
|
138
138
|
RULES = {
|
139
139
|
PostType => {
|
140
|
-
<b>'*': ->(
|
141
|
-
<b>title: ->(
|
140
|
+
<b>'*': ->(obj, args, ctx) {</b> ctx[:current_user].admin? <b>}</b>, # <=== <b>4</b>
|
141
|
+
<b>title: ->(obj, args, ctx) {</b> ctx[:current_user].admin? <b>}</b> # <=== <b>2</b>
|
142
142
|
}
|
143
143
|
}
|
144
144
|
|
@@ -149,8 +149,8 @@ end
|
|
149
149
|
|
150
150
|
PostType = GraphQL::ObjectType.define do
|
151
151
|
name "Post"
|
152
|
-
<b>guard ->(
|
153
|
-
<b>field :title</b>, !types.String, <b>guard: ->(
|
152
|
+
<b>guard ->(obj, args, ctx) {</b> ctx[:current_user].admin? <b>}</b> # <=== <b>3</b>
|
153
|
+
<b>field :title</b>, !types.String, <b>guard: ->(obj, args, ctx) {</b> ctx[:current_user].admin? <b>}</b> # <=== <b>1</b>
|
154
154
|
end
|
155
155
|
|
156
156
|
Schema = GraphQL::Schema.define do
|
@@ -211,7 +211,7 @@ end
|
|
211
211
|
# Use the ability in your guard
|
212
212
|
PostType = GraphQL::ObjectType.define do
|
213
213
|
name "Post"
|
214
|
-
<b>guard ->(post, ctx) { ctx[:current_ability].can?(:read, post) }</b>
|
214
|
+
<b>guard ->(post, args, ctx) { ctx[:current_ability].can?(:read, post) }</b>
|
215
215
|
...
|
216
216
|
end
|
217
217
|
|
@@ -232,7 +232,7 @@ end
|
|
232
232
|
# Use the ability in your guard
|
233
233
|
PostType = GraphQL::ObjectType.define do
|
234
234
|
name "Post"
|
235
|
-
<b>guard ->(post, ctx) { PostPolicy.new(ctx[:current_user], post).show? }</b>
|
235
|
+
<b>guard ->(post, args, ctx) { PostPolicy.new(ctx[:current_user], post).show? }</b>
|
236
236
|
...
|
237
237
|
end
|
238
238
|
|
@@ -288,16 +288,14 @@ end
|
|
288
288
|
# Your policy object
|
289
289
|
class <b>GraphqlPolicy</b>
|
290
290
|
def self.<b>guard</b>(type, field)
|
291
|
-
<b>->(
|
291
|
+
<b>->(obj, args, ctx) {</b> ... <b>}</b>
|
292
292
|
end
|
293
293
|
end
|
294
294
|
|
295
295
|
# Your test
|
296
296
|
<b>require "graphql/guard/testing"</b>
|
297
297
|
|
298
|
-
|
299
|
-
|
300
|
-
posts = QueryType.<b>field_with_guard('posts', guard_object)</b>
|
298
|
+
posts = QueryType.<b>field_with_guard('posts', GraphqlPolicy)</b>
|
301
299
|
result = posts.<b>guard(obj, args, ctx)</b>
|
302
300
|
expect(result).to eq(true)
|
303
301
|
</pre>
|
@@ -5,29 +5,30 @@ module GraphQL
|
|
5
5
|
NoGuardError = Class.new(StandardError)
|
6
6
|
|
7
7
|
def guard(*args)
|
8
|
-
raise NoGuardError.new("Get your field by calling: Type.field_with_guard('#{name}')") unless @
|
9
|
-
guard_proc = @
|
10
|
-
raise NoGuardError.new("Guard lambda does not exist for #{@
|
8
|
+
raise NoGuardError.new("Get your field by calling: Type.field_with_guard('#{name}')") unless @__guard_type
|
9
|
+
guard_proc = @__guard_object.guard_proc(@__guard_type, self)
|
10
|
+
raise NoGuardError.new("Guard lambda does not exist for #{@__guard_type}.#{name}") unless guard_proc
|
11
11
|
|
12
12
|
guard_proc.call(*args)
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
16
|
-
@
|
15
|
+
def __policy_object=(policy_object)
|
16
|
+
@__policy_object = policy_object
|
17
|
+
@__guard_object = GraphQL::Guard.new(policy_object: policy_object)
|
17
18
|
end
|
18
19
|
|
19
20
|
def __guard_type=(guard_type)
|
20
|
-
@
|
21
|
+
@__guard_type = guard_type
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
24
25
|
class ObjectType
|
25
|
-
def field_with_guard(field_name,
|
26
|
+
def field_with_guard(field_name, policy_object = nil)
|
26
27
|
field = get_field(field_name)
|
27
28
|
return unless field
|
28
29
|
|
29
30
|
field.clone.tap do |f|
|
30
|
-
f.
|
31
|
+
f.__policy_object = policy_object
|
31
32
|
f.__guard_type = self
|
32
33
|
end
|
33
34
|
end
|
data/lib/graphql/guard.rb
CHANGED
@@ -25,18 +25,12 @@ module GraphQL
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def instrument(type, field)
|
28
|
-
|
29
|
-
|
30
|
-
return field if !field_guard_proc && !type_guard_proc
|
28
|
+
guard_proc = guard_proc(type, field)
|
29
|
+
return field unless guard_proc
|
31
30
|
|
32
31
|
old_resolve_proc = field.resolve_proc
|
33
32
|
new_resolve_proc = ->(object, arguments, context) do
|
34
|
-
authorized =
|
35
|
-
if field_guard_proc
|
36
|
-
field_guard_proc.call(object, arguments, context)
|
37
|
-
elsif type_guard_proc
|
38
|
-
type_guard_proc.call(object, context)
|
39
|
-
end
|
33
|
+
authorized = guard_proc.call(object, arguments, context)
|
40
34
|
|
41
35
|
if authorized
|
42
36
|
old_resolve_proc.call(object, arguments, context)
|
@@ -48,12 +42,11 @@ module GraphQL
|
|
48
42
|
field.redefine { resolve(new_resolve_proc) }
|
49
43
|
end
|
50
44
|
|
51
|
-
def
|
52
|
-
inline_field_guard(field) ||
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
inline_type_guard(type) || policy_object_guard(type, ANY_FIELD_NAME)
|
45
|
+
def guard_proc(type, field)
|
46
|
+
inline_field_guard(field) ||
|
47
|
+
policy_object_guard(type, field.name.to_sym) ||
|
48
|
+
inline_type_guard(type) ||
|
49
|
+
policy_object_guard(type, ANY_FIELD_NAME)
|
57
50
|
end
|
58
51
|
|
59
52
|
private
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphql-guard
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- exAspArk
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-07-
|
11
|
+
date: 2017-07-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: graphql
|