Skip to content

Commit f08a785

Browse files
authored
Add advanced queries and policies guides to GraphQL docs (#2634)
* Add advanced queries and policies guides to GraphQL docs * Update titles in YAML cartridge
1 parent 428ad92 commit f08a785

File tree

4 files changed

+133
-1
lines changed

4 files changed

+133
-1
lines changed

docusaurus/docs/cms/api/graphql.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ The GraphQL API does not support media upload. Use the [REST API `POST /upload`
7676
The GraphQL API exposes documents using only the `documentId` field. The previous numeric `id` is no longer available here, although it is still returned by the REST API for backward compatibility (see [breaking change](/cms/migration/v4-to-v5/breaking-changes/use-document-id) for details).
7777
:::
7878
79-
8079
## Queries
8180
8281
Queries in GraphQL are used to fetch data without modifying it.
@@ -1111,3 +1110,12 @@ mutation DeleteRestaurant($documentId: ID!, $locale: I18NLocaleCode) {
11111110
}
11121111
}
11131112
```
1113+
1114+
## Advanced use cases
1115+
1116+
Click on the following cards for short guides on more advanced use cases leveraging the GraphQL API and Strapi features:
1117+
1118+
<CustomDocCardsWrapper>
1119+
<CustomDocCard emoji="🖼️" title="Advanced queries" description="View examples of multi-level queries and custom resolver chains for the GraphQL API." link="/cms/api/graphql/advanced-queries" />
1120+
<CustomDocCard emoji="🖼️" title="Advanced policies" description="View examples of advanced policies such as conditional visibility and group membership for the GraphQL API." link="/cms/api/graphql/advanced-policies" />
1121+
</CustomDocCardsWrapper>
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
---
2+
title: Advanced policies for GraphQL
3+
displayed_sidebar: cmsSidebar
4+
tags:
5+
- GraphQL API
6+
- policies
7+
---
8+
9+
# Advanced policies for the GraphQL API
10+
11+
Requests sent to the [GraphQL API](/cms/api/graphql) pass through Strapi's [middlewares](/cms/backend-customization/middlewares.md) and [policies](/cms/backend-customization/policies.md) system. Policies can be attached to resolvers to implement complex authorization rules, as shown in the present short guide.
12+
13+
For additional information on GraphQL policies, please refer to the [GraphQL plugin configuration](/cms/plugins/graphql#extending-the-schema) documentation.
14+
15+
## Conditional visibility
16+
17+
To limit the number of returned entries for unauthenticated users you can write a policy that modifies resolver arguments:
18+
19+
```ts title="/src/policies/limit-public-results.ts"
20+
export default async (policyContext, config, { strapi }) => {
21+
const { state, args } = policyContext;
22+
23+
if (!state.user) {
24+
args.limit = 4; // only return 4 results for public
25+
}
26+
27+
return true;
28+
};
29+
```
30+
31+
Register the policy in `/config/policies.ts` and apply it to a resolver:
32+
33+
```ts title="/config/policies.ts"
34+
export default {
35+
'api::restaurant.restaurant': {
36+
find: [ 'global::limit-public-results' ],
37+
},
38+
};
39+
```
40+
41+
## Group membership
42+
43+
Policies can access `policyContext.state.user` to check group membership, as in the following example:
44+
45+
```ts title="/src/policies/is-group-member.ts"
46+
export default async ({ state }, config, { strapi }) => {
47+
const userGroups = await strapi.query('plugin::users-permissions.group').findMany({
48+
where: { users: { id: state.user.id } },
49+
});
50+
return userGroups.some(g => g.name === config.group);
51+
};
52+
```
53+
54+
Use the policy with the following configuration:
55+
56+
```ts title="/config/policies.ts"
57+
export default {
58+
'api::restaurant.restaurant': {
59+
find: [{ name: 'global::is-group-member', config: { group: 'editors' } }],
60+
},
61+
};
62+
```
63+
64+
With this setup the resolver only returns results if the authenticated user belongs to the `editors` group.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
title: Advanced queries for GraphQL
3+
displayed_sidebar: cmsSidebar
4+
tags:
5+
- GraphQL API
6+
---
7+
8+
# Advanced queries for the GraphQL API
9+
10+
Strapi's [GraphQL API](/cms/api/graphql) resolves many queries automatically, but complex data access can require deeper relation fetching or chaining resolvers. The present short guide explains how to handle such advanced scenarios.
11+
12+
For additional information, please refer to the [GraphQL customization](/cms/plugins/graphql#extending-the-schema) documentation.
13+
14+
## Multi-level queries
15+
16+
Use nested selection sets to fetch relations several levels deep, as in the following example:
17+
18+
```graphql
19+
{
20+
restaurants {
21+
documentId
22+
name
23+
categories {
24+
documentId
25+
name
26+
parent {
27+
documentId
28+
name
29+
}
30+
}
31+
}
32+
}
33+
```
34+
35+
The GraphQL plugin automatically resolves nested relations. If you need to apply custom logic at a specific level, create a custom resolver for that field.
36+
37+
## Resolver chains
38+
39+
Custom resolvers can call other resolvers to reuse existing logic. A common pattern is to resolve permissions or context data in a parent resolver and pass it down to child resolvers, as in the following example:
40+
41+
```js title="/src/api/restaurant/resolvers/restaurant.ts"
42+
export default {
43+
Query: {
44+
restaurants: async (parent, args, ctx) => {
45+
const documents = await strapi.documents('api::restaurant.restaurant').findMany(args);
46+
return documents.map(doc => ctx.request.graphql.resolve('Restaurant', doc));
47+
},
48+
},
49+
};
50+
```
51+
52+
In this example the parent resolver fetches restaurants using the [Document Service API](/cms/api/document-service), then delegates to the generated `Restaurant` resolver provided by the plugin so default behavior such as field selection still applies.

docusaurus/docs/cms/plugins/graphql.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,10 @@ When [extending the GraphQL schema](#extending-the-schema), the `resolversConfig
673673
* [policies with the `policies`](#policies) key
674674
* and [middlewares with the `middlewares`](#middlewares) key
675675

676+
:::tip
677+
The [advanced queries](/cms/api/graphql/advanced-queries) guide might contain additional information suitable for your use case, including multi-level queries and custom resolvers examples.
678+
:::
679+
676680
###### Authorization configuration
677681

678682
By default, the authorization of a GraphQL request is handled by the registered authorization strategy that can be either [API token](/cms/features/api-tokens) or through the [Users & Permissions plugin](#usage-with-the-users--permissions-plugin). The Users & Permissions plugin offers a more granular control.
@@ -877,6 +881,10 @@ export default {
877881

878882
</details>
879883

884+
:::tip
885+
The [advanced policies](/cms/api/graphql/advanced-policies) guide might contain additional information suitable for your use case.
886+
:::
887+
880888
###### Middlewares
881889

882890
[Middlewares](/cms/backend-customization/middlewares) can be applied to a GraphQL resolver through the `resolversConfig.[MyResolverName].middlewares` key. The only difference between the GraphQL and REST implementations is that the `config` key becomes `options`.

0 commit comments

Comments
 (0)