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 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