activeadmin-graphql 0.3.2 → 0.3.3

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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -0
  3. data/app/controllers/active_admin/graphql_controller.rb +19 -4
  4. data/docs/changelogs/20261010091415_graphql-resource-enabled-default.md +34 -0
  5. data/docs/changelogs/20261012050051_graphql-surface-toggles.md +40 -0
  6. data/docs/changelogs/20261012064500_graphql-capabilities.md +35 -0
  7. data/docs/changelogs/20261012113500_release-0-3-3.md +45 -0
  8. data/docs/graphql-api.md +124 -8
  9. data/lib/active_admin/graphql/capability.rb +35 -0
  10. data/lib/active_admin/graphql/capability_definition_dsl.rb +64 -0
  11. data/lib/active_admin/graphql/integration.rb +19 -1
  12. data/lib/active_admin/graphql/policy_adapter.rb +94 -0
  13. data/lib/active_admin/graphql/policy_set_cache.rb +10 -6
  14. data/lib/active_admin/graphql/resource_capability_dsl.rb +31 -0
  15. data/lib/active_admin/graphql/resource_capability_maps.rb +59 -0
  16. data/lib/active_admin/graphql/resource_config.rb +19 -2
  17. data/lib/active_admin/graphql/resource_definition_dsl.rb +5 -4
  18. data/lib/active_admin/graphql/resource_methods.rb +7 -1
  19. data/lib/active_admin/graphql/resource_surface_dsl.rb +48 -0
  20. data/lib/active_admin/graphql/schema_builder/build.rb +52 -3
  21. data/lib/active_admin/graphql/schema_builder/mutation_batch.rb +7 -0
  22. data/lib/active_admin/graphql/schema_builder/mutation_collection.rb +8 -0
  23. data/lib/active_admin/graphql/schema_builder/mutation_create.rb +1 -0
  24. data/lib/active_admin/graphql/schema_builder/mutation_member.rb +8 -0
  25. data/lib/active_admin/graphql/schema_builder/mutation_type_builder.rb +15 -10
  26. data/lib/active_admin/graphql/schema_builder/mutation_update_destroy.rb +2 -0
  27. data/lib/active_admin/graphql/schema_builder/query_type.rb +2 -1
  28. data/lib/active_admin/graphql/schema_builder/query_type_collection.rb +3 -0
  29. data/lib/active_admin/graphql/schema_builder/query_type_member.rb +1 -0
  30. data/lib/active_admin/graphql/schema_builder/query_type_policies.rb +9 -63
  31. data/lib/active_admin/graphql/schema_builder/resources.rb +34 -0
  32. data/lib/active_admin/graphql/schema_builder/types_object.rb +18 -8
  33. data/lib/active_admin/graphql/schema_builder/visibility.rb +22 -7
  34. data/lib/active_admin/graphql/schema_builder/wire.rb +3 -1
  35. data/lib/active_admin/graphql/schema_field.rb +18 -2
  36. data/lib/active_admin/graphql/version.rb +1 -1
  37. data/lib/active_admin/graphql.rb +2 -0
  38. metadata +11 -1
@@ -113,18 +113,28 @@ module ActiveAdmin
113
113
  next unless col
114
114
 
115
115
  gql_t = graphql_scalar_for_column(aa_res, model, col)
116
- type_class.field(name.to_sym, gql_t, null: true, camelize: false, authorize: false)
116
+ type_class.field(
117
+ name.to_sym,
118
+ gql_t,
119
+ null: true,
120
+ camelize: false,
121
+ authorize: false,
122
+ capability: aa_res.graphql_config.capability_for_field(name)
123
+ )
117
124
 
118
125
  type_class.define_method(name.to_sym) { object.public_send(name) }
119
126
  end
120
127
 
121
- type_class.field :activeadmin_policies, policy_set_type, null: false, camelize: false, authorize: false
122
- type_class.define_method(:activeadmin_policies) do
123
- ActiveAdmin::GraphQL::PolicySetCache.fetch(
124
- context,
125
- subject_owner: aa_res,
126
- subject: object
127
- )
128
+ adapter = policy_adapter
129
+ if adapter&.include_resource?(aa_res)
130
+ type_class.field :activeadmin_policies, policy_set_type, null: false, camelize: false, authorize: false
131
+ type_class.define_method(:activeadmin_policies) do
132
+ ActiveAdmin::GraphQL::PolicySetCache.fetch(
133
+ context,
134
+ subject_owner: aa_res,
135
+ subject: object
136
+ )
137
+ end
128
138
  end
129
139
 
130
140
  if (ext = aa_res.graphql_config.extension_block)
@@ -10,14 +10,29 @@ module ActiveAdmin
10
10
  vis = @namespace.graphql_visibility
11
11
  return if vis.nil?
12
12
 
13
- if vis == true
14
- schema.use(::GraphQL::Schema::Visibility)
15
- elsif vis.is_a?(Hash)
16
- schema.use(::GraphQL::Schema::Visibility, **vis.symbolize_keys)
17
- else
18
- raise ActiveAdmin::DependencyError,
19
- "namespace graphql_visibility must be nil, true, or a Hash of GraphQL::Schema::Visibility options"
13
+ options =
14
+ case vis
15
+ when true
16
+ {}
17
+ when Hash
18
+ vis.symbolize_keys
19
+ else
20
+ raise ActiveAdmin::DependencyError,
21
+ "namespace graphql_visibility must be nil, true, or a Hash of GraphQL::Schema::Visibility options"
22
+ end
23
+
24
+ if @namespace.graphql_capabilities.respond_to?(:call)
25
+ profiles = options[:profiles]
26
+ if profiles.respond_to?(:any?) && profiles.any?
27
+ raise ActiveAdmin::DependencyError,
28
+ "graphql_capabilities cannot be combined with named GraphQL visibility profiles " \
29
+ "(named profiles cache a fixed context and ignore per-request capabilities). " \
30
+ "Omit profiles: and use dynamic visibility, or drop graphql_capabilities."
31
+ end
32
+ options = options.merge(dynamic: true)
20
33
  end
34
+
35
+ schema.use(::GraphQL::Schema::Visibility, **options)
21
36
  end
22
37
 
23
38
  def attach_registered_resource_union_visibility!(union_class)
@@ -20,7 +20,9 @@ module ActiveAdmin
20
20
  field_name = ref.name.to_sym
21
21
  fk = ref.foreign_key.to_s
22
22
 
23
- type_class.field field_name, @object_types[target], null: true, camelize: false
23
+ type_class.field field_name, @object_types[target], null: true, camelize: false,
24
+ authorize: false,
25
+ capability: aa_res.graphql_config.capability_for_field(field_name)
24
26
 
25
27
  type_class.define_method(field_name) do
26
28
  fk_val = object.public_send(fk)
@@ -8,9 +8,17 @@ module ActiveAdmin
8
8
  # +graphql_schema_visible+ (second argument) when {GraphQL::Schema::Visibility} is enabled.
9
9
  # That hook runs from {#visible?}; it does not replace graphql-ruby's visibility system—it
10
10
  # composes with +super+ like any custom +Field+ class.
11
+ #
12
+ # +capability:+ (RFC 0008) gates +visible?+ and +authorized?+ via +context[:capabilities]+.
11
13
  class SchemaField < ::GraphQL::Schema::Field
12
- def initialize(visibility: nil, authorize: nil, authorize_action: nil, **kwargs, &block)
13
- @visibility = visibility
14
+ def initialize(visibility: nil, authorize: nil, authorize_action: nil, capability: nil, **kwargs, &block)
15
+ @capability = capability&.to_sym
16
+ @visibility =
17
+ if @capability && visibility.is_a?(Hash) && !visibility.key?(:capability)
18
+ visibility.merge(capability: @capability)
19
+ else
20
+ visibility
21
+ end
14
22
  @authorize = authorize
15
23
  @authorize_action = authorize_action
16
24
  super(**kwargs, &block)
@@ -19,6 +27,13 @@ module ActiveAdmin
19
27
  def visible?(ctx)
20
28
  return false unless super
21
29
 
30
+ # Gate introspection only when Schema::Visibility is enabled; otherwise
31
+ # capability is enforced in +authorized?+ so hosts without the plugin
32
+ # do not trip graphql-ruby's legacy Warden +visible?+ path.
33
+ if ctx[:namespace]&.graphql_visibility && !Capability.granted?(ctx, @capability)
34
+ return false
35
+ end
36
+
22
37
  return true unless @visibility
23
38
 
24
39
  hook = ctx[:namespace]&.graphql_schema_visible
@@ -29,6 +44,7 @@ module ActiveAdmin
29
44
 
30
45
  def authorized?(object, args, ctx)
31
46
  return false unless super
47
+ return false unless Capability.granted?(ctx, @capability)
32
48
 
33
49
  owner = self.owner
34
50
  aa_resource = owner.respond_to?(:activeadmin_graphql_resource) ? owner.activeadmin_graphql_resource : nil
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ActiveAdmin
4
4
  module GraphQL
5
- VERSION = "0.3.2"
5
+ VERSION = "0.3.3"
6
6
  end
7
7
  end
@@ -68,6 +68,7 @@ module ActiveAdmin
68
68
  def require_active_admin_graphql_components!
69
69
  %w[
70
70
  graphql/resource_interface
71
+ graphql/capability
71
72
  graphql/schema_field
72
73
  graphql/auth_context
73
74
  graphql/record_source
@@ -77,6 +78,7 @@ module ActiveAdmin
77
78
  graphql/run_action_mutation_config
78
79
  graphql/run_action_mutation_dsl
79
80
  graphql/key_value_pair_input
81
+ graphql/policy_adapter
80
82
  graphql/policy_set_cache
81
83
  graphql/mutation_execution_error
82
84
  graphql/schema_builder
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activeadmin-graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrei Makarov
@@ -374,10 +374,14 @@ files:
374
374
  - docs/changelogs/20260921111000_release-0-3-0.md
375
375
  - docs/changelogs/20260921112800_drop-standard-rubocop-direct.md
376
376
  - docs/changelogs/20260921120000_graphql-floor-and-activeadmin-4.md
377
+ - docs/changelogs/20261010091415_graphql-resource-enabled-default.md
377
378
  - docs/changelogs/20261010101500_nonconventional-id-fields.md
378
379
  - docs/changelogs/20261010103800_release-0-3-1.md
379
380
  - docs/changelogs/20261010110600_graphql-identity-dsl.md
380
381
  - docs/changelogs/20261010111800_release-0-3-2.md
382
+ - docs/changelogs/20261012050051_graphql-surface-toggles.md
383
+ - docs/changelogs/20261012064500_graphql-capabilities.md
384
+ - docs/changelogs/20261012113500_release-0-3-3.md
381
385
  - docs/dependencies/20260907141000_json-cve-2026-71847.md
382
386
  - docs/dependencies/20260907141000_sqlite3-ghsa-mwm8-39rw-8826.md
383
387
  - docs/dependencies/20260921114000_rails-json-parse-kwargs.md
@@ -396,15 +400,20 @@ files:
396
400
  - docs/plan/20260817201500_rfc-starter.md
397
401
  - lib/active_admin/graphql.rb
398
402
  - lib/active_admin/graphql/auth_context.rb
403
+ - lib/active_admin/graphql/capability.rb
404
+ - lib/active_admin/graphql/capability_definition_dsl.rb
399
405
  - lib/active_admin/graphql/engine.rb
400
406
  - lib/active_admin/graphql/integration.rb
401
407
  - lib/active_admin/graphql/key_value_pair_input.rb
402
408
  - lib/active_admin/graphql/mutation_execution_error.rb
403
409
  - lib/active_admin/graphql/mutation_input_config.rb
404
410
  - lib/active_admin/graphql/mutation_input_definition_dsl.rb
411
+ - lib/active_admin/graphql/policy_adapter.rb
405
412
  - lib/active_admin/graphql/policy_set_cache.rb
406
413
  - lib/active_admin/graphql/railtie.rb
407
414
  - lib/active_admin/graphql/record_source.rb
415
+ - lib/active_admin/graphql/resource_capability_dsl.rb
416
+ - lib/active_admin/graphql/resource_capability_maps.rb
408
417
  - lib/active_admin/graphql/resource_config.rb
409
418
  - lib/active_admin/graphql/resource_definition_dsl.rb
410
419
  - lib/active_admin/graphql/resource_identity.rb
@@ -413,6 +422,7 @@ files:
413
422
  - lib/active_admin/graphql/resource_query_proxy.rb
414
423
  - lib/active_admin/graphql/resource_query_proxy/controller.rb
415
424
  - lib/active_admin/graphql/resource_query_proxy/identity.rb
425
+ - lib/active_admin/graphql/resource_surface_dsl.rb
416
426
  - lib/active_admin/graphql/run_action_mutation_config.rb
417
427
  - lib/active_admin/graphql/run_action_mutation_dsl.rb
418
428
  - lib/active_admin/graphql/run_action_payload.rb