You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: guides/authorization/visibility.md
+58-1
Original file line number
Diff line number
Diff line change
@@ -18,7 +18,16 @@ Here are some reasons you might want to hide parts of your schema:
18
18
19
19
## Hiding Parts of the Schema
20
20
21
-
You can customize the visibility of parts of your schema by reimplementing various `visible?` methods:
21
+
To start limiting visibility of your schema, add the plugin:
22
+
23
+
```ruby
24
+
classMySchema < GraphQL::Schema
25
+
# ...
26
+
use GraphQL::Schema::Visibility# see below for options
27
+
end
28
+
```
29
+
30
+
Then, you can customize the visibility of parts of your schema by reimplementing various `visible?` methods:
22
31
23
32
- Type classes have a `.visible?(context)` class method
24
33
- Fields and arguments have a `#visible?(context)` instance method
@@ -30,6 +39,31 @@ These methods are called with the query context, based on the hash you pass as `
30
39
- In introspection, the member will _not_ be included in the result
31
40
- In normal queries, if a query references that member, it will return a validation error, since that member doesn't exist
32
41
42
+
## Visibility Profiles
43
+
44
+
You can use named profiles to cache your schema's visibility modes. For example:
45
+
46
+
```ruby
47
+
use GraphQL::Schema::Visibility, profiles: {
48
+
# mode_name => example_context_hash
49
+
public: { public:true },
50
+
beta: { public:true, beta:true },
51
+
internal_admin: { internal_admin:true }
52
+
}
53
+
```
54
+
55
+
Then, you can run queries with `context[:visibility_profile]` equal to one of the pre-defined profiles. When you do, GraphQL-Ruby will use a precomputed set of types and fields for that query.
56
+
57
+
### Preloading profiles
58
+
59
+
By default, GraphQL-Ruby will preload all named visibility profiles when `Rails.env.production?` is present and true. You can manually set this option by passing `use ... preload: true` (or `false`). Enable preloading in production to reduce latency of the first request to each visibility profile. Disable preloading in development to speed up application boot.
60
+
61
+
### Dynamic profiles
62
+
63
+
When you provide named visibility profiles, `context[:visibility_profile]` is required for query execution. You can also permit dynamic visibility for queries which _don't_ have that key set by passing `use ..., dynamic: true`. You could use this to support backwards compatibility or when visibility calculations are too complex to predefine.
64
+
65
+
When no named profiles are defined, all queries use dynamic visibility.
66
+
33
67
## Object Visibility
34
68
35
69
Let's say you're working on a new feature which should remain secret for a while. You can implement `.visible?` in a type:
@@ -107,3 +141,26 @@ end
107
141
```
108
142
109
143
For big schemas, this can be a worthwhile speed-up.
144
+
145
+
## Migration Notes
146
+
147
+
{% "GraphQL::Schema::Visibility" | api_doc %} is a _new_ implementation of visibility in GraphQL-Ruby. It has some slight differences from the previous implementation ({% "GraphQL::Schema::Warden" | api_doc %}):
148
+
149
+
-`Visibility` speeds up Rails app boot because it doesn't require all types to be loaded during boot and only loads types as they are used by queries.
150
+
-`Visibility` supports predefined, reusable visibility profiles which speeds up queries using complicated `visible?` checks.
151
+
-`Visibility` hides types differently in a few edge cases:
152
+
- Previously, `Warden` hide interface and union types which had no possible types. `Visibility` doesn't check possible types (in order to support performance improvements), so those types must return `false` for `visible?` in the same cases where all possible types were hidden. Otherwise, that interface or union type will be visible but have no possible types.
153
+
- Some other thing, see TODO
154
+
- When `Visibility` is used, several (Ruby-level) Schema introspection methods don't work because the caches they draw on haven't been calculated (`Schema.references_to`, `Schema.union_memberships`). If you're using these, please get in touch so that we can find a way forward.
155
+
156
+
### Migration Mode
157
+
158
+
You can use `use GraphQL::Schema::Visibility, ... migration_errors: true` to enable migration mode. In this mode, GraphQL-Ruby will make visibility checks with _both_`Visibility` and `Warden` and compare the result, raising a descriptive error when the two systems return different results. As you migrate to `Visibility`, enable this mode in test to find any unexpected discrepancies.
159
+
160
+
Sometimes, there's a discrepancy that is hard to resolve but doesn't make any _real_ difference in application behavior. To address these cases, you can use these flags in `context`:
161
+
162
+
-`context[:visibility_migration_running] = true` is set in the main query context.
163
+
-`context[:visibility_migration_warden_running] = true` is set in the _duplicate_ context which is passed to a `Warden` instance.
164
+
- If you set `context[:skip_migration_error] = true`, then no migration error will be raised for that query.
165
+
166
+
You can use these flags to conditionally handle edge cases that should be ignored in testing.
Copy file name to clipboardexpand all lines: guides/schema/dynamic_types.md
+4-1
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,10 @@ desc: Using different schema members for each request
8
8
index: 8
9
9
---
10
10
11
-
You can use different versions of your GraphQL schema for each operation. To do this, implement `visible?(context)` on the parts of your schema that will be conditionally accessible. Additionally, many schema elements have definition methods which are called at runtime by GraphQL-Ruby. You can re-implement those to return any valid schema objects. GraphQL-Ruby caches schema elements for the duration of the operation, but if you're making external service calls to implement the methods below, consider adding a cache layer to improve the client experience and reduce load on your backend.
11
+
You can use different versions of your GraphQL schema for each operation. To do this, add `use GraphQL::Schema::Visibility` and implement `visible?(context)` on the parts of your schema that will be conditionally accessible. Additionally, many schema elements have definition methods which are called at runtime by GraphQL-Ruby. You can re-implement those to return any valid schema objects.
12
+
13
+
14
+
GraphQL-Ruby caches schema elements for the duration of the operation, but if you're making external service calls to implement the methods below, consider adding a cache layer to improve the client experience and reduce load on your backend.
12
15
13
16
At runtime, ensure that only one object is visible per name (type name, field name, etc.). (If `.visible?(context)` returns `false`, then that part of the schema will be hidden for the current operation.)
raiseGraphQL::Error,"Second definition of `subscription(...)` (#{dup_defn.inspect}) is invalid, already configured with #{@subscription_object.inspect}"
0 commit comments