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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b4eee6371389b2dc2b666235993adb716b2edaddb327e6f6a7676bbfbde909d8
4
- data.tar.gz: 1e2d08f7882d72926842d76335f165621a3685b93a541e27c85bda12be5c4c8c
3
+ metadata.gz: d2877f7a77b6c2c63a91fe28cf21b64e99ebd92d6ec8e68c13acf3ed18911edb
4
+ data.tar.gz: 97781e7d915f98154c4f3252a7b244afbffd2d5a7920ff4c77d54b6e4409976f
5
5
  SHA512:
6
- metadata.gz: 51c32bc6d94598f571f5b679efeab6d67ba1a3656f41c4c669c615ee414bae2d780bb2de80a92a11ceda730af49297a1418da4d448b843b17daf540ce9f89f2b
7
- data.tar.gz: 9b42478cf51ad1e48f84604526caec0d1fc7d993f32f3e7f09fefd8299a911ca77a136fd4b1d11f52fed722afe61510f44c72c3d99e8f3d6fc246ecc0c9732d7
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
- :auto_load_attributes,
22
- :auto_load_associations
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)
@@ -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
@@ -1,4 +1,33 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
- # typed: strict
4
- require "hq/graphql/field/association_loader"
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
@@ -7,10 +7,14 @@ module HQ
7
7
  include Scalars
8
8
  include ::HQ::GraphQL::ActiveRecordExtensions
9
9
 
10
- field_class ::HQ::GraphQL::Field::AssociationLoader
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, loader_klass: model_name
54
+ field name, [type], null: false, klass: model_name
46
55
  else
47
- field name, type, null: !auto_nil || !association_required?(association), loader_klass: model_name
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
@@ -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
@@ -3,6 +3,6 @@
3
3
 
4
4
  module HQ
5
5
  module GraphQL
6
- VERSION = "2.0.3"
6
+ VERSION = "2.0.4"
7
7
  end
8
8
  end
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.3
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-12 00:00:00.000000000 Z
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