activeadmin-graphql 0.3.2 → 0.4.0
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/CHANGELOG.md +27 -1
- data/app/controllers/active_admin/graphql_controller.rb +19 -4
- data/docs/changelogs/20261010091415_graphql-resource-enabled-default.md +34 -0
- data/docs/changelogs/20261012050051_graphql-surface-toggles.md +40 -0
- data/docs/changelogs/20261012064500_graphql-capabilities.md +35 -0
- data/docs/changelogs/20261012113500_release-0-3-3.md +45 -0
- data/docs/changelogs/20261012200000_host-customization-hooks.md +27 -0
- data/docs/changelogs/20261013080000_release-0-4-0.md +48 -0
- data/docs/graphql-api.md +173 -10
- data/docs/issues/20261012200000_host-customization-gaps.md +26 -0
- data/lib/active_admin/graphql/capability.rb +35 -0
- data/lib/active_admin/graphql/capability_definition_dsl.rb +69 -0
- data/lib/active_admin/graphql/collection_query_policy.rb +103 -0
- data/lib/active_admin/graphql/integration.rb +43 -1
- data/lib/active_admin/graphql/member_action_capability.rb +14 -0
- data/lib/active_admin/graphql/member_action_dry_run.rb +121 -0
- data/lib/active_admin/graphql/policy_adapter.rb +94 -0
- data/lib/active_admin/graphql/policy_set_cache.rb +10 -6
- data/lib/active_admin/graphql/resource_capability_dsl.rb +32 -0
- data/lib/active_admin/graphql/resource_capability_maps.rb +77 -0
- data/lib/active_admin/graphql/resource_config.rb +19 -2
- data/lib/active_admin/graphql/resource_definition_dsl.rb +22 -10
- data/lib/active_admin/graphql/resource_methods.rb +7 -1
- data/lib/active_admin/graphql/resource_surface_dsl.rb +48 -0
- data/lib/active_admin/graphql/run_action_capability.rb +62 -0
- data/lib/active_admin/graphql/run_action_control_extension.rb +72 -0
- data/lib/active_admin/graphql/run_action_field.rb +103 -0
- data/lib/active_admin/graphql/run_action_mutation_config.rb +8 -0
- data/lib/active_admin/graphql/run_action_mutation_dsl.rb +18 -0
- data/lib/active_admin/graphql/run_action_preview.rb +20 -0
- data/lib/active_admin/graphql/schema_builder/build.rb +52 -3
- data/lib/active_admin/graphql/schema_builder/mutation_batch.rb +7 -0
- data/lib/active_admin/graphql/schema_builder/mutation_collection.rb +9 -0
- data/lib/active_admin/graphql/schema_builder/mutation_create.rb +1 -0
- data/lib/active_admin/graphql/schema_builder/mutation_member.rb +13 -0
- data/lib/active_admin/graphql/schema_builder/mutation_type_builder.rb +15 -10
- data/lib/active_admin/graphql/schema_builder/mutation_update_destroy.rb +2 -0
- data/lib/active_admin/graphql/schema_builder/query_type.rb +2 -1
- data/lib/active_admin/graphql/schema_builder/query_type_collection.rb +3 -0
- data/lib/active_admin/graphql/schema_builder/query_type_member.rb +1 -0
- data/lib/active_admin/graphql/schema_builder/query_type_policies.rb +9 -63
- data/lib/active_admin/graphql/schema_builder/resolvers.rb +46 -7
- data/lib/active_admin/graphql/schema_builder/resources.rb +34 -0
- data/lib/active_admin/graphql/schema_builder/types_object.rb +19 -8
- data/lib/active_admin/graphql/schema_builder/visibility.rb +22 -7
- data/lib/active_admin/graphql/schema_builder/wire.rb +4 -1
- data/lib/active_admin/graphql/schema_field.rb +97 -6
- data/lib/active_admin/graphql/version.rb +1 -1
- data/lib/active_admin/graphql.rb +9 -0
- metadata +21 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c03a6abe474dea238c1dec40f75bb03b2f3203e4874d4639e2327a0562c9a9ce
|
|
4
|
+
data.tar.gz: 3bb9bd9cf8b55e796cf87cf8f51dca817b41b5ae9a515132ff0e56a218afe6db
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9e0a6930217123a83432a072410be640d618371c062eb83e27c86786461218f4d48d524edd9a7c00749914ac3c216d015d565fbc60a7f5fcdf7fc0d2f57d48b7
|
|
7
|
+
data.tar.gz: 639363956ab8b19349df04e7a5c5f9f6610705206b3d7d8f82838cde74b4dc10ab5e7b53f993def3c2de016885d1a1ecd267698252b877f655c87b49ef1a8f9f
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 0.4.0 (2026-10-13)
|
|
4
|
+
|
|
5
|
+
- Add field `capability_mode` (`:omit` / `:null`) and namespace hooks
|
|
6
|
+
`graphql_field_capability_mode_default` and `graphql_field_visible` (RFC 0009).
|
|
7
|
+
- Add `member_action_mutation … dry_run: true` with `preview`, `extra_params`,
|
|
8
|
+
`ok` / `refuse`, and optional `graphql_run_action_audit` (RFC 0010).
|
|
9
|
+
- Add `graphql_collection_query_policy` and
|
|
10
|
+
`CollectionQueryPolicy.require_visible_fields!`, inferring filter grants from
|
|
11
|
+
resource field capabilities by default (RFC 0011).
|
|
12
|
+
- Add `graphql_member_action_capability_default`,
|
|
13
|
+
`graphql_batch_action_capability_default`,
|
|
14
|
+
`graphql_collection_action_capability_default`, and `capability:` on
|
|
15
|
+
`batch_action_mutation` / `member_action_mutation` /
|
|
16
|
+
`collection_action_mutation` (RFC 0012).
|
|
17
|
+
- Add `dry_run:` / `confirm:` / `preview:` on `SchemaField`, preview
|
|
18
|
+
short-circuit via `RunActionControlExtension`, and
|
|
19
|
+
`RunActionField.define` DSL sugar for custom run-action fields (RFC 0013).
|
|
20
|
+
|
|
21
|
+
## 0.3.3 (2026-10-12)
|
|
22
|
+
|
|
23
|
+
- Add `graphql { capability ... }` and namespace `graphql_capabilities` so one named grant can gate many fields, queries, and mutations (RFC 0008).
|
|
24
|
+
- Apply `fields:` capabilities to wired `belongs_to` associations; reject unknown capability field names and named visibility `profiles:` combined with `graphql_capabilities`.
|
|
25
|
+
- Add namespace setting `graphql_resource_enabled_default` (`true` by default) and `graphql { enable! }` so apps can opt resources into the schema instead of opting out with `disable!`.
|
|
26
|
+
- Add namespace toggles for `registered_resource` and `belongs_to` wiring (`graphql_registered_resource_enabled`, `graphql_belongs_to_associations_enabled`; both `true` by default).
|
|
27
|
+
- Add `graphql_policies_enabled` / `graphql_policies_enabled_default` for policy field publishing and per-resource seeds, plus `graphql_policy_adapter` (default `ActiveAdmin::GraphQL::PolicyAdapter`) for payload construction.
|
|
28
|
+
- Add per-resource surface defaults and DSL (`graphql_queries_enabled_default`, `graphql_mutations_enabled_default`, `graphql_run_actions_enabled_default`, plus `enable_*!` / `disable_*!`) so apps can trim list/show, CRUD, run-action, and policy fields without disabling the whole resource.
|
|
29
|
+
- Treat `queries_enabled` as the read surface: omit `registered_resource` union membership when queries are off; fail schema build when `Query` would have no fields.
|
|
4
30
|
|
|
5
31
|
## 0.3.2 (2026-10-10)
|
|
6
32
|
|
|
@@ -51,16 +51,31 @@ module ActiveAdmin
|
|
|
51
51
|
|
|
52
52
|
def graphql_context
|
|
53
53
|
ns = active_admin_namespace
|
|
54
|
-
{
|
|
54
|
+
context = {
|
|
55
55
|
auth: ActiveAdmin::GraphQL::AuthContext.new(
|
|
56
56
|
user: current_active_admin_user,
|
|
57
57
|
namespace: ns
|
|
58
58
|
),
|
|
59
59
|
namespace: ns,
|
|
60
60
|
request: request,
|
|
61
|
-
current_user: current_active_admin_user
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
current_user: current_active_admin_user
|
|
62
|
+
}
|
|
63
|
+
# Named visibility profiles cache a fixed context; per-request capabilities
|
|
64
|
+
# need the live request context (dynamic visibility). Skip the profile key.
|
|
65
|
+
unless ns.graphql_capabilities.respond_to?(:call)
|
|
66
|
+
profile = graphql_visibility_profile_for(ns)
|
|
67
|
+
context[:visibility_profile] = profile if profile
|
|
68
|
+
end
|
|
69
|
+
capabilities = graphql_capabilities_for(ns, context)
|
|
70
|
+
context[:capabilities] = capabilities unless capabilities.nil?
|
|
71
|
+
context
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def graphql_capabilities_for(ns, context)
|
|
75
|
+
hook = ns.graphql_capabilities
|
|
76
|
+
return nil unless hook.respond_to?(:call)
|
|
77
|
+
|
|
78
|
+
ActiveAdmin::GraphQL::Capability.normalize_set(hook.call(context))
|
|
64
79
|
end
|
|
65
80
|
|
|
66
81
|
def graphql_visibility_profile_for(ns)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# GraphQL resource enabled default
|
|
2
|
+
|
|
3
|
+
## Participants
|
|
4
|
+
|
|
5
|
+
Andrei Makarov
|
|
6
|
+
|
|
7
|
+
## Decisions
|
|
8
|
+
|
|
9
|
+
Add namespace setting `graphql_resource_enabled_default`, default `true`, so
|
|
10
|
+
0.3.x behavior stays: turning on the namespace endpoint still includes every
|
|
11
|
+
ActiveRecord resource unless `graphql { disable! }` is set.
|
|
12
|
+
|
|
13
|
+
Apps that want support-style opt-in set the setting to `false`. Then a resource
|
|
14
|
+
enters the schema only when registration runs `graphql { }` or
|
|
15
|
+
`graphql { enable! }`. `disable!` still omits.
|
|
16
|
+
|
|
17
|
+
`ResourceConfig` takes the initial `enabled` flag from the namespace setting.
|
|
18
|
+
Entering a `graphql` block sets `enabled = true` before the block body runs so
|
|
19
|
+
an empty block is a conscious opt-in.
|
|
20
|
+
|
|
21
|
+
## Effects
|
|
22
|
+
|
|
23
|
+
New request specs cover default true, default false without a block, empty
|
|
24
|
+
block, `enable!`, and `disable!`.
|
|
25
|
+
|
|
26
|
+
## Next
|
|
27
|
+
|
|
28
|
+
Folded into 0.3.3 release metadata.
|
|
29
|
+
|
|
30
|
+
## Source
|
|
31
|
+
|
|
32
|
+
CHANGELOG 0.3.3. docs/graphql-api.md namespace settings and per-resource
|
|
33
|
+
DSL. spec/requests/graphql_resource_enabled_default_spec.rb.
|
|
34
|
+
docs/changelogs/20261012113500_release-0-3-3.md.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# GraphQL surface toggles
|
|
2
|
+
|
|
3
|
+
## Participants
|
|
4
|
+
|
|
5
|
+
Andrei Makarov
|
|
6
|
+
|
|
7
|
+
## Decisions
|
|
8
|
+
|
|
9
|
+
Add namespace and per-resource controls for schema surfaces that were always on
|
|
10
|
+
once a resource was enabled. Defaults stay `true` so 0.3.x behavior is
|
|
11
|
+
unchanged.
|
|
12
|
+
|
|
13
|
+
Namespace-only switches: `graphql_registered_resource_enabled`,
|
|
14
|
+
`graphql_belongs_to_associations_enabled`, `graphql_policies_enabled`.
|
|
15
|
+
Policy payloads use `graphql_policy_adapter` (default `PolicyAdapter`).
|
|
16
|
+
Per-resource policy seed is `graphql_policies_enabled_default`.
|
|
17
|
+
|
|
18
|
+
Per-resource seeds from namespace defaults: queries, mutations (CRUD),
|
|
19
|
+
run-actions, and policies. Resource DSL exposes matching `enable_*!` /
|
|
20
|
+
`disable_*!` methods. `queries_enabled` also gates `registered_resource`
|
|
21
|
+
membership. Schema build raises if `Query` would have no fields.
|
|
22
|
+
|
|
23
|
+
## Effects
|
|
24
|
+
|
|
25
|
+
Schema builder skips policy query fields, registered_resource union, belongs_to
|
|
26
|
+
wiring, list/show fields, CRUD mutations, and run-action mutations when the
|
|
27
|
+
matching flag is off. Request specs cover the new settings and DSL, including
|
|
28
|
+
empty-Query rejection and registered_resource gating by queries.
|
|
29
|
+
|
|
30
|
+
## Next
|
|
31
|
+
|
|
32
|
+
Folded into 0.3.3 release metadata.
|
|
33
|
+
|
|
34
|
+
## Source
|
|
35
|
+
|
|
36
|
+
CHANGELOG 0.3.3. docs/graphql-api.md.
|
|
37
|
+
spec/requests/graphql_surface_toggles_spec.rb.
|
|
38
|
+
spec/requests/graphql_policy_surface_spec.rb.
|
|
39
|
+
spec/requests/graphql_query_surface_contract_spec.rb.
|
|
40
|
+
docs/changelogs/20261012113500_release-0-3-3.md.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# GraphQL capabilities
|
|
2
|
+
|
|
3
|
+
## Participants
|
|
4
|
+
|
|
5
|
+
Andrei Makarov
|
|
6
|
+
|
|
7
|
+
## Decisions
|
|
8
|
+
|
|
9
|
+
Add RFC 0008 capability grants. Resource DSL `capability` associates many
|
|
10
|
+
object fields, queries, and mutations with one name. Namespace
|
|
11
|
+
`graphql_capabilities` fills `context[:capabilities]` per request. SchemaField
|
|
12
|
+
checks capability in `visible?` and `authorized?`. Capabilities do not replace
|
|
13
|
+
ActiveAdmin authorization. Subscriptions stay out of scope.
|
|
14
|
+
|
|
15
|
+
## Effects
|
|
16
|
+
|
|
17
|
+
Gated members fail closed without the grant. With `graphql_visibility`,
|
|
18
|
+
introspection omits them. Aggregate run-action resolvers also check
|
|
19
|
+
per-action capability keys (`member_*`, `batch_*`, `collection_*`).
|
|
20
|
+
`belongs_to` association fields honor `fields:` capabilities. Schema build
|
|
21
|
+
rejects unknown capability field names and rejects named visibility profiles
|
|
22
|
+
combined with `graphql_capabilities` (dynamic visibility required).
|
|
23
|
+
|
|
24
|
+
## Next
|
|
25
|
+
|
|
26
|
+
Folded into 0.3.3 release metadata. Follow-ons remain: policy payloads listing
|
|
27
|
+
field capabilities, mutation input attribute maps, and transport gates if
|
|
28
|
+
subscriptions ship later.
|
|
29
|
+
|
|
30
|
+
## Source
|
|
31
|
+
|
|
32
|
+
RFC 0008. CHANGELOG 0.3.3. docs/graphql-api.md. spec/unit/capability_spec.rb,
|
|
33
|
+
spec/unit/capability_dsl_spec.rb, spec/requests/graphql_capabilities_spec.rb,
|
|
34
|
+
spec/requests/graphql_capabilities_edge_spec.rb.
|
|
35
|
+
docs/changelogs/20261012113500_release-0-3-3.md.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Release 0.3.3 metadata
|
|
2
|
+
|
|
3
|
+
## Participants
|
|
4
|
+
|
|
5
|
+
Andrei Makarov
|
|
6
|
+
|
|
7
|
+
## Decisions
|
|
8
|
+
|
|
9
|
+
Cut 0.3.3 after published 0.3.2. User-visible work since the 0.3.2 tag:
|
|
10
|
+
`graphql_resource_enabled_default` and `enable!` opt-in, surface toggles for
|
|
11
|
+
queries, mutations, run-actions, policies, `registered_resource`, and
|
|
12
|
+
`belongs_to`, plus GraphQL capabilities (RFC 0008). Defaults stay `true` so
|
|
13
|
+
0.3.x schema shape is unchanged unless an app opts in to narrower surfaces.
|
|
14
|
+
|
|
15
|
+
CHANGELOG Unreleased bullets moved under 0.3.3 dated 2026-10-12.
|
|
16
|
+
|
|
17
|
+
Version constant is 0.3.3. Path gem pins in Gemfile.lock and appraisal
|
|
18
|
+
lockfiles match.
|
|
19
|
+
|
|
20
|
+
Internal `stringify_attrs` safe-navigation cleanup stays out of CHANGELOG.md.
|
|
21
|
+
|
|
22
|
+
make release (usr/bin/release.rb) still owns gem build, gem push, git tag, and
|
|
23
|
+
GitHub release. This pass only prepares metadata.
|
|
24
|
+
|
|
25
|
+
## Effects
|
|
26
|
+
|
|
27
|
+
lib/active_admin/graphql/version.rb VERSION is 0.3.3.
|
|
28
|
+
|
|
29
|
+
CHANGELOG surface-toggle and capability bullets live under 0.3.3.
|
|
30
|
+
|
|
31
|
+
PATH specs for activeadmin-graphql in Gemfile.lock,
|
|
32
|
+
gemfiles/rails72.gemfile.lock, gemfiles/rails8ruby4.gemfile.lock, and
|
|
33
|
+
gemfiles/rails8ruby34.gemfile.lock are 0.3.3.
|
|
34
|
+
|
|
35
|
+
## Next
|
|
36
|
+
|
|
37
|
+
Run make release from a clean tree when ready to push the gem and tag 0.3.3.
|
|
38
|
+
|
|
39
|
+
## Source
|
|
40
|
+
|
|
41
|
+
docs/changelogs/20261010091415_graphql-resource-enabled-default.md
|
|
42
|
+
docs/changelogs/20261012050051_graphql-surface-toggles.md
|
|
43
|
+
docs/changelogs/20261012064500_graphql-capabilities.md
|
|
44
|
+
rfcs/0008-graphql-capabilities.md
|
|
45
|
+
usr/bin/release.rb
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Host customization hooks
|
|
2
|
+
|
|
3
|
+
## Decisions
|
|
4
|
+
|
|
5
|
+
Ship generic namespace hooks and DSL for field capability null mode, member-action
|
|
6
|
+
dry-run with preview, collection query policy, default run-action capabilities,
|
|
7
|
+
and confirm/dry-run/preview plus RunActionField.define for custom mutations.
|
|
8
|
+
Product allowlists and auth grants stay in the host application.
|
|
9
|
+
|
|
10
|
+
## Effects
|
|
11
|
+
|
|
12
|
+
RFCs 0009 through 0013 claimed and drafted. Implementation under 0.4.0 in
|
|
13
|
+
CHANGELOG.md. Request specs cover null-mode introspection, dry-run short-circuit,
|
|
14
|
+
collection filter refusal, default capability omit, and confirm_required.
|
|
15
|
+
|
|
16
|
+
## Next
|
|
17
|
+
|
|
18
|
+
Metadata prepared in docs/changelogs/20261013080000_release-0-4-0.md. Run make
|
|
19
|
+
release when ready to push the gem and tag. Host apps can drop prepends that
|
|
20
|
+
duplicated these mechanics after upgrading.
|
|
21
|
+
|
|
22
|
+
## Source
|
|
23
|
+
|
|
24
|
+
RFCs 0009–0013. Specs under spec/requests/graphql_capability_mode_spec.rb,
|
|
25
|
+
graphql_member_action_dry_run_spec.rb, graphql_collection_query_policy_spec.rb,
|
|
26
|
+
graphql_run_action_capability_default_spec.rb,
|
|
27
|
+
graphql_run_action_confirm_spec.rb.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Release 0.4.0 metadata
|
|
2
|
+
|
|
3
|
+
## Participants
|
|
4
|
+
|
|
5
|
+
Andrei Makarov
|
|
6
|
+
|
|
7
|
+
## Decisions
|
|
8
|
+
|
|
9
|
+
Cut 0.4.0 after published 0.3.3. User-visible work since the 0.3.3 tag:
|
|
10
|
+
field capability null mode and visibility hooks (RFC 0009), member-action
|
|
11
|
+
dry-run with preview and optional audit (RFC 0010), collection query policy
|
|
12
|
+
with filter grants inferred from field capabilities (RFC 0011), default
|
|
13
|
+
run-action capabilities and per-mutation `capability:` (RFC 0012), and
|
|
14
|
+
confirm / dry-run / preview plus `RunActionField.define` for custom
|
|
15
|
+
run-action fields (RFC 0013). Product allowlists and auth grants stay in the
|
|
16
|
+
host application.
|
|
17
|
+
|
|
18
|
+
CHANGELOG Unreleased bullets moved under 0.4.0 dated 2026-10-13.
|
|
19
|
+
|
|
20
|
+
Version constant is 0.4.0. Path gem pins in Gemfile.lock and appraisal
|
|
21
|
+
lockfiles match.
|
|
22
|
+
|
|
23
|
+
make release (usr/bin/release.rb) still owns gem build, gem push, git tag, and
|
|
24
|
+
GitHub release. This pass only prepares metadata.
|
|
25
|
+
|
|
26
|
+
## Effects
|
|
27
|
+
|
|
28
|
+
lib/active_admin/graphql/version.rb VERSION is 0.4.0.
|
|
29
|
+
|
|
30
|
+
CHANGELOG host-customization bullets live under 0.4.0.
|
|
31
|
+
|
|
32
|
+
PATH specs for activeadmin-graphql in Gemfile.lock,
|
|
33
|
+
gemfiles/rails72.gemfile.lock, gemfiles/rails8ruby4.gemfile.lock, and
|
|
34
|
+
gemfiles/rails8ruby34.gemfile.lock are 0.4.0.
|
|
35
|
+
|
|
36
|
+
## Next
|
|
37
|
+
|
|
38
|
+
Run make release from a clean tree when ready to push the gem and tag 0.4.0.
|
|
39
|
+
|
|
40
|
+
## Source
|
|
41
|
+
|
|
42
|
+
docs/changelogs/20261012200000_host-customization-hooks.md
|
|
43
|
+
rfcs/0009-field-capability-mode.md
|
|
44
|
+
rfcs/0010-member-action-dry-run.md
|
|
45
|
+
rfcs/0011-collection-query-policy.md
|
|
46
|
+
rfcs/0012-run-action-capability-defaults.md
|
|
47
|
+
rfcs/0013-run-action-confirm-dry-run.md
|
|
48
|
+
usr/bin/release.rb
|
data/docs/graphql-api.md
CHANGED
|
@@ -33,6 +33,12 @@ ActiveAdmin.setup do |config|
|
|
|
33
33
|
admin.graphql = true
|
|
34
34
|
# Optional — default is "graphql", i.e. POST /admin/graphql
|
|
35
35
|
# admin.graphql_path = "graphql"
|
|
36
|
+
# Optional — set false so only resources with a graphql block enter the schema
|
|
37
|
+
# admin.graphql_resource_enabled_default = false
|
|
38
|
+
# Optional — trim always-on surfaces for a narrow API
|
|
39
|
+
# admin.graphql_policies_enabled = false
|
|
40
|
+
# admin.graphql_registered_resource_enabled = false
|
|
41
|
+
# admin.graphql_belongs_to_associations_enabled = false
|
|
36
42
|
end
|
|
37
43
|
end
|
|
38
44
|
```
|
|
@@ -45,6 +51,33 @@ Run `bin/rails active_admin:install` or reload routes if needed so
|
|
|
45
51
|
Each namespace inherits these options (defaults in parentheses):
|
|
46
52
|
|
|
47
53
|
* `graphql` — set to `true` to mount the endpoint (`false` by default).
|
|
54
|
+
* `graphql_resource_enabled_default` — whether each registered ActiveRecord
|
|
55
|
+
resource is included in the schema without a `graphql` block (`true` by
|
|
56
|
+
default, matching 0.3.x). Set to `false` for opt-in: only resources that call
|
|
57
|
+
`graphql { }` (or `graphql { enable! }`) appear in the schema. `disable!`
|
|
58
|
+
still omits a resource.
|
|
59
|
+
* `graphql_queries_enabled_default` — seed for per-resource read fields
|
|
60
|
+
(`true` by default): named list/show fields and membership in
|
|
61
|
+
`registered_resource` / `ActiveAdminRegisteredResource`. Set `false` and use
|
|
62
|
+
`enable_queries!` for opt-in reads. Object types may still exist for mutations.
|
|
63
|
+
* `graphql_mutations_enabled_default` — seed for per-resource CRUD mutations
|
|
64
|
+
(`true` by default). Set `false` and use `enable_mutations!` for opt-in writes.
|
|
65
|
+
* `graphql_run_actions_enabled_default` — seed for batch/member/collection
|
|
66
|
+
action mutations (`true` by default).
|
|
67
|
+
* `graphql_policies_enabled` — publish `activeadmin_policies` query fields and
|
|
68
|
+
allow per-object policy fields (`true` by default).
|
|
69
|
+
* `graphql_policies_enabled_default` — seed for per-resource `policies_enabled`
|
|
70
|
+
(`true` by default). Use `enable_policies!` / `disable_policies!` per resource.
|
|
71
|
+
* `graphql_policy_adapter` — class that builds `activeadmin_policies` payloads
|
|
72
|
+
(`ActiveAdmin::GraphQL::PolicyAdapter` by default). Set a subclass (or constant
|
|
73
|
+
`String`) to replace payload logic; the default adapter still honors
|
|
74
|
+
`graphql_policy_actions` / `graphql_policy_action_mapper` /
|
|
75
|
+
`graphql_policy_extra` / `graphql_policy_transform`.
|
|
76
|
+
* `graphql_registered_resource_enabled` — include `registered_resource` and the
|
|
77
|
+
`ActiveAdminRegisteredResource` union when at least one queryable resource
|
|
78
|
+
exists (`true` by default).
|
|
79
|
+
* `graphql_belongs_to_associations_enabled` — wire non-polymorphic `belongs_to`
|
|
80
|
+
fields between registered resource types (`true` by default).
|
|
48
81
|
* `graphql_path` — path segment under the namespace mount (`"graphql"`).
|
|
49
82
|
* `graphql_multiplex_max` — maximum operations per multiplexed JSON array
|
|
50
83
|
request (`20`).
|
|
@@ -70,6 +103,27 @@ Each namespace inherits these options (defaults in parentheses):
|
|
|
70
103
|
default `context[:visibility_profile]` for each HTTP request (symbols accepted).
|
|
71
104
|
* `graphql_schema_visible` — optional `Proc` `(context, meta) -> Boolean` when
|
|
72
105
|
`graphql_visibility` is enabled; see Schema visibility below.
|
|
106
|
+
* `graphql_capabilities` — optional `Proc` `(context) -> Enumerable` of capability
|
|
107
|
+
names for the request (RFC 0008). Normalized into `context[:capabilities]`.
|
|
108
|
+
Cannot be combined with named `graphql_visibility` `profiles:`; schema build
|
|
109
|
+
forces `dynamic: true` and omits `visibility_profile` from the request context
|
|
110
|
+
so introspection uses the live capability set.
|
|
111
|
+
* `graphql_field_capability_mode_default` — `:omit` or `:null` when a field has a
|
|
112
|
+
capability but no per-field mode (RFC 0009). Default `:omit`.
|
|
113
|
+
* `graphql_field_visible` — optional `Proc` `(context, meta) -> Boolean` to omit
|
|
114
|
+
fields after capability checks (RFC 0009). Meta includes `graphql_type_name`,
|
|
115
|
+
`field_name`, and `resource` when known.
|
|
116
|
+
* `graphql_run_action_audit` — optional `Proc` `(context, meta) -> void` after
|
|
117
|
+
member-action dry-run, refused preview, or completed run (RFC 0010).
|
|
118
|
+
* `graphql_collection_query_policy` — optional `Proc` `(context, meta) -> void`
|
|
119
|
+
at the start of collection resolve (RFC 0011). Meta includes `aa_resource`,
|
|
120
|
+
`q`, `scope`, `order`, and `filter`.
|
|
121
|
+
* `graphql_member_action_capability_default` — optional capability symbol applied
|
|
122
|
+
to member-action mutation fields when the resource map has no entry (RFC 0012).
|
|
123
|
+
* `graphql_batch_action_capability_default` — same for the aggregate batch-action
|
|
124
|
+
field and per-action authorize checks (RFC 0012).
|
|
125
|
+
* `graphql_collection_action_capability_default` — same for collection-action
|
|
126
|
+
mutation fields (RFC 0012).
|
|
73
127
|
* `graphql_configure_schema` — `Proc` receiving the schema class after build
|
|
74
128
|
(extensions, extra types, and so on).
|
|
75
129
|
|
|
@@ -199,21 +253,103 @@ UI, including any `authorize!` or `authorize_resource!` calls.
|
|
|
199
253
|
|
|
200
254
|
See the ActiveAdmin guide [Authorization adapter](https://activeadmin.info/13-authorization-adapter) for adapter setup; the same rules apply to GraphQL.
|
|
201
255
|
|
|
256
|
+
Policy preflight fields (`activeadmin_policies`, `activeadmin_policies_for`, and
|
|
257
|
+
per-object `activeadmin_policies`) are published when `graphql_policies_enabled`
|
|
258
|
+
is true. Payloads come from `graphql_policy_adapter`. The default
|
|
259
|
+
`ActiveAdmin::GraphQL::PolicyAdapter` asks the authorization adapter which
|
|
260
|
+
actions are allowed and applies the optional `graphql_policy_*` hooks. Assign a
|
|
261
|
+
subclass that implements `policy_set` (and optionally `include_resource?`) to
|
|
262
|
+
replace the payload builder.
|
|
263
|
+
|
|
264
|
+
### Capabilities (RFC 0008)
|
|
265
|
+
|
|
266
|
+
Associate many object fields, queries, and mutations with one named capability
|
|
267
|
+
inside `graphql do`. The same capability name can cover a mixed set of members:
|
|
268
|
+
|
|
269
|
+
```ruby
|
|
270
|
+
ActiveAdmin.register Post do
|
|
271
|
+
graphql do
|
|
272
|
+
capability :pii do
|
|
273
|
+
fields :body
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
capability :editor do
|
|
277
|
+
fields :title
|
|
278
|
+
queries :index, :show
|
|
279
|
+
mutations :create, :update, :destroy
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
capability :publish, member_actions: %i[publish]
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Kwargs (`fields:`, `queries:`, `mutations:`, `member_actions:`,
|
|
288
|
+
`batch_actions:`, `collection_actions:`) work without a block. Query aliases:
|
|
289
|
+
`index` / `list` → collection, `show` → member. Mutation alias: `delete` →
|
|
290
|
+
`destroy`. Run-action sugar builds keys like `member_publish`.
|
|
291
|
+
|
|
292
|
+
Grant capabilities per request with `graphql_capabilities`. Map OAuth scopes or
|
|
293
|
+
roles there; the gem stores a symbol set on `context[:capabilities]`:
|
|
294
|
+
|
|
295
|
+
```ruby
|
|
296
|
+
admin.graphql_capabilities = lambda { |ctx|
|
|
297
|
+
Array(ctx[:current_user]&.oauth_scopes)
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
A gated member fails closed when the capability is missing from that set:
|
|
302
|
+
resolve returns null for the field (graphql-ruby unauthorized field). Enable
|
|
303
|
+
`graphql_visibility` so introspection and validation also omit ungated members
|
|
304
|
+
when the field mode is `:omit` (default). Use `capability_mode: :null` (or
|
|
305
|
+
`capability :pii, fields: %i[body], mode: :null`) so the field stays in the
|
|
306
|
+
schema and resolves to `null` without the grant (RFC 0009).
|
|
307
|
+
|
|
308
|
+
`fields:` applies to generated attributes and wired `belongs_to` associations.
|
|
309
|
+
Unknown field names raise at schema build. Capabilities do not replace the
|
|
310
|
+
authorization adapter.
|
|
311
|
+
|
|
312
|
+
Custom `SchemaField` definitions may pass `capability: :name` and
|
|
313
|
+
`capability_mode: :null` the same way. Set `graphql_field_visible` for a second
|
|
314
|
+
omit gate (for example a request allowlist). Do not use named visibility
|
|
315
|
+
`profiles:` together with `graphql_capabilities` (cached profile context ignores
|
|
316
|
+
per-request grants).
|
|
317
|
+
|
|
318
|
+
Collection list fields may call a host `graphql_collection_query_policy`. The
|
|
319
|
+
helper `ActiveAdmin::GraphQL::CollectionQueryPolicy.require_visible_fields!`
|
|
320
|
+
rejects Ransack `q` keys for hidden fields and requires capabilities from the
|
|
321
|
+
resource field map by default (needed for `capability_mode: :null` columns).
|
|
322
|
+
Optional `field_grants` overrides inference; `infer_field_grants: false` turns
|
|
323
|
+
it off (RFC 0011).
|
|
324
|
+
|
|
202
325
|
## Schema overview
|
|
203
326
|
|
|
204
|
-
|
|
205
|
-
(for example `posts`), plus a
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
327
|
+
With the default surface flags (`true`), the `Query` type includes one
|
|
328
|
+
Relay-style connection field per resource route (for example `posts`), plus a
|
|
329
|
+
singular field for a single record (for example `post`). Optional
|
|
330
|
+
`graphql_field` entries on `register_page` appear here too, plus
|
|
331
|
+
`registered_resource` (returning the `ActiveAdminRegisteredResource` union)
|
|
332
|
+
when at least one queryable resource exists.
|
|
333
|
+
|
|
334
|
+
List and show fields require per-resource `queries_enabled` (seeded from
|
|
335
|
+
`graphql_queries_enabled_default`). Turning queries off still leaves the object
|
|
336
|
+
type available for mutations. `registered_resource` and the union also require
|
|
337
|
+
`graphql_registered_resource_enabled`. Policy preflight fields require
|
|
338
|
+
`graphql_policies_enabled`. Schema build fails when `Query` would have no
|
|
339
|
+
fields: no list/show, no policies, no `registered_resource`, and no page
|
|
340
|
+
`graphql_field`.
|
|
209
341
|
|
|
210
342
|
Every resource object type implements the `ActiveAdminResource` interface
|
|
211
343
|
(`id: ID!`) so clients can share fragments or rely on a common shape.
|
|
344
|
+
Non-polymorphic `belongs_to` fields between registered types are wired when
|
|
345
|
+
`graphql_belongs_to_associations_enabled` is true.
|
|
212
346
|
|
|
213
347
|
The `Mutation` type is present when at least one operation exists: per-resource
|
|
214
|
-
`create_*`, `update_*`, and `delete_*` when those controller actions exist
|
|
215
|
-
`*_batch_action`, `*_member_action`, and
|
|
216
|
-
resource defines the corresponding batch,
|
|
348
|
+
`create_*`, `update_*`, and `delete_*` when those controller actions exist and
|
|
349
|
+
`mutations_enabled` is true, plus `*_batch_action`, `*_member_action`, and
|
|
350
|
+
`*_collection_action` fields when the resource defines the corresponding batch,
|
|
351
|
+
member, or collection actions and `run_actions_enabled` is true. Both flags are
|
|
352
|
+
seeded from the matching namespace defaults.
|
|
217
353
|
|
|
218
354
|
Object type names default to the model name (for example `Post`). Typed input
|
|
219
355
|
objects use assignable columns (see the per-resource section below):
|
|
@@ -405,7 +541,16 @@ ActiveAdmin.register Post do
|
|
|
405
541
|
end
|
|
406
542
|
```
|
|
407
543
|
|
|
544
|
+
* `enable!` — include this resource when `graphql_resource_enabled_default` is
|
|
545
|
+
`false`. An empty `graphql` block has the same effect.
|
|
408
546
|
* `disable!` — resource is not included in Query or Mutation.
|
|
547
|
+
* `enable_queries!` / `disable_queries!` — list/show fields and
|
|
548
|
+
`registered_resource` membership for this resource.
|
|
549
|
+
* `enable_mutations!` / `disable_mutations!` — create/update/delete mutations.
|
|
550
|
+
* `enable_run_actions!` / `disable_run_actions!` — batch/member/collection
|
|
551
|
+
action mutations.
|
|
552
|
+
* `enable_policies!` / `disable_policies!` — object `activeadmin_policies` and
|
|
553
|
+
inclusion in the `activeadmin_policies` resources matrix.
|
|
409
554
|
* `identity` — declare GraphQL id columns (and optional `separator`, `encode`,
|
|
410
555
|
`decode`) when the model has no ActiveRecord primary key and no `id` column
|
|
411
556
|
(RFC 0007).
|
|
@@ -456,8 +601,12 @@ graphql do
|
|
|
456
601
|
type(Members::MemberRunPayload)
|
|
457
602
|
end
|
|
458
603
|
|
|
459
|
-
member_action_mutation(:send_invoice) do
|
|
604
|
+
member_action_mutation(:send_invoice, dry_run: true, capability: :support_act) do
|
|
460
605
|
type(Members::SendInvoicePayload)
|
|
606
|
+
preview do |record, **|
|
|
607
|
+
record.may_send_invoice? ? ok("would_run:send_invoice:#{record.id}") : refuse("not_ready")
|
|
608
|
+
end
|
|
609
|
+
extra_params :note
|
|
461
610
|
arguments do
|
|
462
611
|
argument :note, GraphQL::Types::String, required: false, camelize: false
|
|
463
612
|
end
|
|
@@ -467,7 +616,21 @@ end
|
|
|
467
616
|
|
|
468
617
|
Call the named field as `posts_member_send_invoice(id: "...", note: "…")`. Extra
|
|
469
618
|
arguments are merged with `params` for the controller and passed as keyword args
|
|
470
|
-
to a custom `resolve` block.
|
|
619
|
+
to a custom `resolve` block. With `dry_run: true`, the field gains a Boolean
|
|
620
|
+
`dry_run` argument: preview runs first, dry-run returns without
|
|
621
|
+
`run_member_action`, and a refused preview never runs the action (RFC 0010).
|
|
622
|
+
`extra_params` allowlists which GraphQL kwargs forward into the AA request
|
|
623
|
+
(`id` cannot be rebound). `capability:` on batch / member / collection mutation
|
|
624
|
+
DSL overrides the resource map; otherwise the matching
|
|
625
|
+
`graphql_*_action_capability_default` applies (RFC 0012).
|
|
626
|
+
|
|
627
|
+
Custom mutations in `graphql_configure_schema` may use
|
|
628
|
+
`ActiveAdmin::GraphQL::RunActionField.define` (or `SchemaField` keywords
|
|
629
|
+
`dry_run:`, `confirm:`, `preview:`) for confirm/dry-run wiring (RFC 0013). When
|
|
630
|
+
`confirm` is required and both flags are false, the field returns
|
|
631
|
+
`body: "confirm_required"`. When `preview` is set, dry-run and refused preview
|
|
632
|
+
return without calling `resolve`; without `preview`, dry-run still calls
|
|
633
|
+
`resolve` with `dry_run: true`.
|
|
471
634
|
|
|
472
635
|
With no symbol argument, `member_action_mutation { … }` configures only the
|
|
473
636
|
aggregate `posts_member_action` field. With a symbol, it configures the
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Host customization gaps
|
|
2
|
+
|
|
3
|
+
## Decisions
|
|
4
|
+
|
|
5
|
+
The gem owns mechanics: when a field is visible, null, or omitted; dry-run
|
|
6
|
+
argument wiring; filter-key policy hooks; default member-action capability;
|
|
7
|
+
confirm/dry_run injection on custom fields. Hosts own product grants, domain
|
|
8
|
+
preview bodies, and audit storage.
|
|
9
|
+
|
|
10
|
+
Capabilities remain grant names in context[:capabilities]. Named visibility
|
|
11
|
+
profiles stay incompatible with graphql_capabilities.
|
|
12
|
+
|
|
13
|
+
## Effects
|
|
14
|
+
|
|
15
|
+
RFCs 0009–0013 specify the contract. Implementation landed on the feature
|
|
16
|
+
branch with request coverage for each hook.
|
|
17
|
+
|
|
18
|
+
## Next
|
|
19
|
+
|
|
20
|
+
Publish a release. Hosts migrate off local prepends in the order: capability
|
|
21
|
+
null mode and dry-run DSL, then collection policy, then field_visible and
|
|
22
|
+
capability defaults, then confirm helpers.
|
|
23
|
+
|
|
24
|
+
## Source
|
|
25
|
+
|
|
26
|
+
RFCs 0009–0013. docs/changelogs/20261012200000_host-customization-hooks.md.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveAdmin
|
|
4
|
+
module GraphQL
|
|
5
|
+
# Named grants carried in GraphQL +context[:capabilities]+ (RFC 0008).
|
|
6
|
+
module Capability
|
|
7
|
+
module_function
|
|
8
|
+
|
|
9
|
+
def normalize_set(raw)
|
|
10
|
+
return nil if raw.nil?
|
|
11
|
+
|
|
12
|
+
Set.new(
|
|
13
|
+
Array(raw).filter_map do |item|
|
|
14
|
+
next if item.nil?
|
|
15
|
+
|
|
16
|
+
name = item.to_s.strip
|
|
17
|
+
next if name.empty?
|
|
18
|
+
|
|
19
|
+
name.to_sym
|
|
20
|
+
end
|
|
21
|
+
)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def granted?(context, capability_name)
|
|
25
|
+
return true if capability_name.nil?
|
|
26
|
+
|
|
27
|
+
caps = context[:capabilities]
|
|
28
|
+
return false if caps.nil?
|
|
29
|
+
|
|
30
|
+
caps = normalize_set(caps) unless caps.is_a?(Set)
|
|
31
|
+
caps.include?(capability_name.to_sym)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|