hq-graphql 2.0.3 → 2.0.4
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/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
|