hq-graphql 2.0.3 → 2.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/hq/graphql/active_record_extensions.rb +3 -2
- data/lib/hq/graphql/config.rb +6 -3
- data/lib/hq/graphql/field.rb +31 -2
- data/lib/hq/graphql/object.rb +13 -4
- data/lib/hq/graphql/resource/mutation.rb +5 -1
- data/lib/hq/graphql/resource.rb +5 -2
- data/lib/hq/graphql/root_query.rb +2 -2
- data/lib/hq/graphql/version.rb +1 -1
- data/lib/hq/graphql.rb +9 -4
- metadata +2 -3
- data/lib/hq/graphql/field/association_loader.rb +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d2877f7a77b6c2c63a91fe28cf21b64e99ebd92d6ec8e68c13acf3ed18911edb
|
4
|
+
data.tar.gz: 97781e7d915f98154c4f3252a7b244afbffd2d5a7920ff4c77d54b6e4409976f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92120bf166668fd9e76cc0c42f0fc350ac7be0eacc9653f14f22b4a6c792910f9d3fbaf15ae0cfdbb596b6732c1dddbdaba24188e53d9a41cbae6cd2250b3659
|
7
|
+
data.tar.gz: 2ec3a9597f0059ec4c988534c355171489c958a43a1287f617d5056e33847bc9af67ea2572a93d3dd3d6b531443770218e543e3e2acc9131305d07217010f562
|
@@ -18,8 +18,9 @@ module HQ
|
|
18
18
|
include Kernel
|
19
19
|
|
20
20
|
attr_accessor :model_name,
|
21
|
-
|
22
|
-
|
21
|
+
:authorize_action,
|
22
|
+
:auto_load_attributes,
|
23
|
+
:auto_load_associations
|
23
24
|
|
24
25
|
sig { params(block: T.nilable(T.proc.void)).returns(T::Array[T.proc.void]) }
|
25
26
|
def lazy_load(&block)
|
data/lib/hq/graphql/config.rb
CHANGED
@@ -5,11 +5,14 @@
|
|
5
5
|
module HQ
|
6
6
|
module GraphQL
|
7
7
|
class Config < T::Struct
|
8
|
+
AuthorizeProc = T.type_alias { T.nilable(T.proc.params(action: T.untyped, object: T.untyped, context: ::GraphQL::Query::Context).returns(T::Boolean)) }
|
9
|
+
prop :authorize, AuthorizeProc, default: nil
|
10
|
+
|
11
|
+
AuthorizeFieldProc = T.type_alias { T.nilable(T.proc.params(action: T.untyped, field: ::HQ::GraphQL::Field, object: T.untyped, context: ::GraphQL::Query::Context).returns(T::Boolean)) }
|
12
|
+
prop :authorize_field, AuthorizeFieldProc, default: nil
|
13
|
+
|
8
14
|
DefaultScopeProc = T.type_alias { T.proc.params(arg0: T.untyped, arg1: ::GraphQL::Query::Context).returns(T.untyped) }
|
9
15
|
prop :default_scope, DefaultScopeProc, default: ->(scope, _context) { scope }
|
10
|
-
|
11
|
-
AuthorizeProc = T.type_alias { T.proc.params(arg0: T.untyped, arg1: ::GraphQL::Query::Context).returns(T::Boolean) }
|
12
|
-
prop :authorize, AuthorizeProc, default: ->(_object, _context) { true }
|
13
16
|
end
|
14
17
|
end
|
15
18
|
end
|
data/lib/hq/graphql/field.rb
CHANGED
@@ -1,4 +1,33 @@
|
|
1
|
+
# typed: false
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
|
-
|
4
|
-
|
4
|
+
module HQ
|
5
|
+
module GraphQL
|
6
|
+
class Field < ::GraphQL::Schema::Field
|
7
|
+
attr_reader :authorize_action, :authorize, :klass
|
8
|
+
|
9
|
+
def initialize(*args, authorize_action: :read, authorize: nil, klass: nil, **options, &block)
|
10
|
+
super(*args, **options, &block)
|
11
|
+
@authorize_action = authorize_action
|
12
|
+
@authorize = authorize
|
13
|
+
@klass = klass
|
14
|
+
end
|
15
|
+
|
16
|
+
def authorized?(object, ctx)
|
17
|
+
super &&
|
18
|
+
(!authorize || authorize.call(object, ctx)) &&
|
19
|
+
::HQ::GraphQL.authorize_field(authorize_action, self, object, ctx)
|
20
|
+
end
|
21
|
+
|
22
|
+
def resolve_field(object, args, ctx)
|
23
|
+
if klass.present? && !!::GraphQL::Batch::Executor.current && object.object
|
24
|
+
Loaders::Association.for(klass.constantize, original_name).load(object.object).then do
|
25
|
+
super
|
26
|
+
end
|
27
|
+
else
|
28
|
+
super
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/hq/graphql/object.rb
CHANGED
@@ -7,10 +7,14 @@ module HQ
|
|
7
7
|
include Scalars
|
8
8
|
include ::HQ::GraphQL::ActiveRecordExtensions
|
9
9
|
|
10
|
-
field_class ::HQ::GraphQL::Field
|
10
|
+
field_class ::HQ::GraphQL::Field
|
11
|
+
|
12
|
+
def self.authorize_action(action)
|
13
|
+
self.authorized_action = action
|
14
|
+
end
|
11
15
|
|
12
16
|
def self.authorized?(object, context)
|
13
|
-
super && ::HQ::GraphQL.authorized?(object, context)
|
17
|
+
super && ::HQ::GraphQL.authorized?(authorized_action, object, context)
|
14
18
|
end
|
15
19
|
|
16
20
|
def self.with_model(model_name, attributes: true, associations: true, auto_nil: true)
|
@@ -36,15 +40,20 @@ module HQ
|
|
36
40
|
|
37
41
|
class << self
|
38
42
|
private
|
43
|
+
attr_writer :authorized_action
|
44
|
+
|
45
|
+
def authorized_action
|
46
|
+
@authorized_action ||= :read
|
47
|
+
end
|
39
48
|
|
40
49
|
def field_from_association(association, auto_nil:)
|
41
50
|
type = ::HQ::GraphQL::Types[association.klass]
|
42
51
|
name = association.name
|
43
52
|
case association.macro
|
44
53
|
when :has_many
|
45
|
-
field name, [type], null: false,
|
54
|
+
field name, [type], null: false, klass: model_name
|
46
55
|
else
|
47
|
-
field name, type, null: !auto_nil || !association_required?(association),
|
56
|
+
field name, type, null: !auto_nil || !association_required?(association), klass: model_name
|
48
57
|
end
|
49
58
|
rescue ::HQ::GraphQL::Types::Error
|
50
59
|
nil
|
@@ -5,10 +5,14 @@ module HQ
|
|
5
5
|
module GraphQL
|
6
6
|
module Resource
|
7
7
|
module Mutation
|
8
|
-
def self.build(model_name, graphql_name:, require_primary_key: false, nil_klass: false, &block)
|
8
|
+
def self.build(model_name, action:, graphql_name:, require_primary_key: false, nil_klass: false, &block)
|
9
9
|
Class.new(::HQ::GraphQL::Mutation) do
|
10
10
|
graphql_name graphql_name
|
11
11
|
|
12
|
+
define_method(:ready?) do |*args|
|
13
|
+
super(*args) && ::HQ::GraphQL.authorized?(action, model_name, context)
|
14
|
+
end
|
15
|
+
|
12
16
|
lazy_load do
|
13
17
|
field :errors, ::HQ::GraphQL::Types::Object, null: false
|
14
18
|
field :resource, ::HQ::GraphQL::Types[model_name, nil_klass], null: true
|
data/lib/hq/graphql/resource.rb
CHANGED
@@ -78,7 +78,7 @@ module HQ
|
|
78
78
|
scoped_self = self
|
79
79
|
|
80
80
|
if create
|
81
|
-
create_mutation = ::HQ::GraphQL::Resource::Mutation.build(model_name, graphql_name: "#{scoped_graphql_name}Create") do
|
81
|
+
create_mutation = ::HQ::GraphQL::Resource::Mutation.build(model_name, action: :create, graphql_name: "#{scoped_graphql_name}Create") do
|
82
82
|
define_method(:resolve) do |**args|
|
83
83
|
resource = scoped_self.new_record(context)
|
84
84
|
resource.assign_attributes(args[:attributes].format_nested_attributes)
|
@@ -106,6 +106,7 @@ module HQ
|
|
106
106
|
if copy
|
107
107
|
copy_mutation = ::HQ::GraphQL::Resource::Mutation.build(
|
108
108
|
model_name,
|
109
|
+
action: :copy,
|
109
110
|
graphql_name: "#{scoped_graphql_name}Copy",
|
110
111
|
require_primary_key: true,
|
111
112
|
nil_klass: true
|
@@ -141,6 +142,7 @@ module HQ
|
|
141
142
|
if update
|
142
143
|
update_mutation = ::HQ::GraphQL::Resource::Mutation.build(
|
143
144
|
model_name,
|
145
|
+
action: :update,
|
144
146
|
graphql_name: "#{scoped_graphql_name}Update",
|
145
147
|
require_primary_key: true
|
146
148
|
) do
|
@@ -179,6 +181,7 @@ module HQ
|
|
179
181
|
if destroy
|
180
182
|
destroy_mutation = ::HQ::GraphQL::Resource::Mutation.build(
|
181
183
|
model_name,
|
184
|
+
action: :destroy,
|
182
185
|
graphql_name: "#{scoped_graphql_name}Destroy",
|
183
186
|
require_primary_key: true
|
184
187
|
) do
|
@@ -224,7 +227,7 @@ module HQ
|
|
224
227
|
end
|
225
228
|
}
|
226
229
|
::HQ::GraphQL.root_queries << {
|
227
|
-
field_name: field_name, resolver: resolver
|
230
|
+
field_name: field_name, resolver: resolver, model_name: model_name
|
228
231
|
}
|
229
232
|
end
|
230
233
|
|
@@ -8,8 +8,8 @@ module HQ
|
|
8
8
|
super
|
9
9
|
base.class_eval do
|
10
10
|
lazy_load do
|
11
|
-
::HQ::GraphQL.root_queries.each do |field_name:, resolver:|
|
12
|
-
field field_name, resolver: resolver.call
|
11
|
+
::HQ::GraphQL.root_queries.each do |field_name:, resolver:, model_name:|
|
12
|
+
field field_name, resolver: resolver.call, klass: model_name
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
data/lib/hq/graphql/version.rb
CHANGED
data/lib/hq/graphql.rb
CHANGED
@@ -5,6 +5,7 @@ require "rails"
|
|
5
5
|
require "graphql"
|
6
6
|
require "graphql/batch"
|
7
7
|
require "sorbet-runtime"
|
8
|
+
require "hq/graphql/field"
|
8
9
|
require "hq/graphql/config"
|
9
10
|
|
10
11
|
module HQ
|
@@ -23,9 +24,14 @@ module HQ
|
|
23
24
|
config.instance_eval(&block)
|
24
25
|
end
|
25
26
|
|
26
|
-
sig { params(object: T.untyped, context: ::GraphQL::Query::Context).returns(T::Boolean) }
|
27
|
-
def self.authorized?(object, context)
|
28
|
-
config.authorize.call(object, context)
|
27
|
+
sig { params(action: T.untyped, object: T.untyped, context: ::GraphQL::Query::Context).returns(T::Boolean) }
|
28
|
+
def self.authorized?(action, object, context)
|
29
|
+
!config.authorize || T.must(config.authorize).call(action, object, context)
|
30
|
+
end
|
31
|
+
|
32
|
+
sig { params(action: T.untyped, field: ::HQ::GraphQL::Field, object: T.untyped, context: ::GraphQL::Query::Context).returns(T::Boolean) }
|
33
|
+
def self.authorize_field(action, field, object, context)
|
34
|
+
!config.authorize_field || T.must(config.authorize_field).call(action, field, object, context)
|
29
35
|
end
|
30
36
|
|
31
37
|
sig { params(scope: T.untyped, context: ::GraphQL::Query::Context).returns(T.untyped) }
|
@@ -55,7 +61,6 @@ end
|
|
55
61
|
require "hq/graphql/active_record_extensions"
|
56
62
|
require "hq/graphql/scalars"
|
57
63
|
|
58
|
-
require "hq/graphql/field"
|
59
64
|
require "hq/graphql/inputs"
|
60
65
|
require "hq/graphql/input_object"
|
61
66
|
require "hq/graphql/loaders"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hq-graphql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Danny Jones
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-11-
|
11
|
+
date: 2019-11-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -270,7 +270,6 @@ files:
|
|
270
270
|
- lib/hq/graphql/config.rb
|
271
271
|
- lib/hq/graphql/engine.rb
|
272
272
|
- lib/hq/graphql/field.rb
|
273
|
-
- lib/hq/graphql/field/association_loader.rb
|
274
273
|
- lib/hq/graphql/input_object.rb
|
275
274
|
- lib/hq/graphql/inputs.rb
|
276
275
|
- lib/hq/graphql/loaders.rb
|
@@ -1,27 +0,0 @@
|
|
1
|
-
# typed: false
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
module HQ
|
5
|
-
module GraphQL
|
6
|
-
module Field
|
7
|
-
class AssociationLoader < ::GraphQL::Schema::Field
|
8
|
-
attr_reader :loader_klass
|
9
|
-
|
10
|
-
def initialize(*args, loader_klass: nil, **options, &block)
|
11
|
-
super(*args, **options, &block)
|
12
|
-
@loader_klass = loader_klass
|
13
|
-
end
|
14
|
-
|
15
|
-
def resolve_field(object, args, ctx)
|
16
|
-
if loader_klass.present? && !!::GraphQL::Batch::Executor.current && object.object
|
17
|
-
Loaders::Association.for(loader_klass.constantize, original_name).load(object.object).then do
|
18
|
-
super
|
19
|
-
end
|
20
|
-
else
|
21
|
-
super
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|