mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-14 17:02:49 +03:00
docs: add input validation docs (#9734)
* docs: add input validation docs * Optimised images with calibre/image-actions * remove input validation feature from experimental flag * Docs edits * Docs edits * Docs edits * implement review comments * Optimised images with calibre/image-actions * Apply suggestions from code review Co-authored-by: Sean Park-Ross <94021366+seanparkross@users.noreply.github.com> * fix brackets in request payload * deduplicate data * Update input-validations.mdx * Update docs/docs/schema/postgres/data-validations.mdx Co-authored-by: Tirumarai Selvan <tiru@hasura.io> * Update input-validations.mdx --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Sean Park-Ross <sean@hasura.io> Co-authored-by: Sean Park-Ross <94021366+seanparkross@users.noreply.github.com> Co-authored-by: Tirumarai Selvan <tiru@hasura.io> GitOrigin-RevId: 5a36f61260c1a11f49f291ea6987192971d33239
This commit is contained in:
parent
ad64379876
commit
151a888289
@ -60,7 +60,16 @@ X-Hasura-Role: admin
|
||||
"set":{
|
||||
"id":"X-HASURA-USER-ID"
|
||||
},
|
||||
"columns":["name","author_id"]
|
||||
"columns":["name","author_id"],
|
||||
"validate_input": {
|
||||
"type": "http",
|
||||
"definition": {
|
||||
"forward_client_headers": true,
|
||||
"headers": [],
|
||||
"timeout": 10,
|
||||
"url": "http://www.somedomain.com/validateUser"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -310,6 +319,15 @@ X-Hasura-Role: admin
|
||||
},
|
||||
"set":{
|
||||
"updated_at" : "NOW()"
|
||||
},
|
||||
"validate_input": {
|
||||
"type": "http",
|
||||
"definition": {
|
||||
"forward_client_headers": true,
|
||||
"headers": [],
|
||||
"timeout": 10,
|
||||
"url": "http://www.somedomain.com/validateUser"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -399,6 +417,15 @@ X-Hasura-Role: admin
|
||||
"permission" : {
|
||||
"filter" : {
|
||||
"author_id" : "X-HASURA-USER-ID"
|
||||
},
|
||||
"validate_input": {
|
||||
"type": "http",
|
||||
"definition": {
|
||||
"forward_client_headers": true,
|
||||
"headers": [],
|
||||
"timeout": 10,
|
||||
"url": "http://www.somedomain.com/validateUser"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -337,14 +337,31 @@ Configuration properties for particular column, as specified on [ColumnConfig](#
|
||||
| function | false | `String` | Customize the `<function-name>` root field |
|
||||
| function_aggregate | false | `String` | Customize the `<function-name>_aggregate` root field |
|
||||
|
||||
## InputValidationDefinition {#input-validation-definition}
|
||||
|
||||
| Key | Required | Schema | Description |
|
||||
| ----------- | -------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
|
||||
| url | true | [WebhookURL](#webhookurl) | The input validations's webhook URL |
|
||||
| headers | false | \[[HeaderFromValue](#headerfromvalue) \| [HeaderFromEnv](#headerfromenv) \] | List of defined headers to be sent to the handler |
|
||||
| forward_client_headers | false | boolean | If set to `true` the client headers are forwarded to the webhook handler (default: `false`) |
|
||||
| timeout | false | Integer | Number of seconds to wait for response before timing out. Default: 10 |
|
||||
|
||||
## InputValidation {#input-validation}
|
||||
|
||||
| Key | Required | Schema | Description |
|
||||
| ---------------------- | -------- | -------- | -------------------------------------------------------------------- |
|
||||
| type | true | `String` | The interface for input validation. (Currently only supports "http") |
|
||||
| definition | true | [InputValidationDefinition](#input-validation-definition) | The definition for the input validation |
|
||||
|
||||
## InsertPermission {#insertpermission}
|
||||
|
||||
| Key | Required | Schema | Description |
|
||||
| ------------ | -------- | -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| check | true | [BoolExp](#boolexp) | This expression has to hold true for every new row that is inserted |
|
||||
| set | false | [ColumnPresetsExp](#columnpresetexp) | Preset values for columns that can be sourced from session variables or static values |
|
||||
| columns | false | [PGColumn](#pgcolumn) array (or) `'*'` | Can insert into only these columns (or all when `'*'` is specified) |
|
||||
| backend_only | false | Boolean | When set to `true` the mutation is accessible only if the `x-hasura-use-backend-only-permissions` session variable exists and is set to `true` and the request is made with `x-hasura-admin-secret` set if any auth is configured |
|
||||
| Key | Required | Schema | Description |
|
||||
| ------------ | -------- | -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| check | true | [BoolExp](#boolexp) | This expression has to hold true for every new row that is inserted |
|
||||
| set | false | [ColumnPresetsExp](#columnpresetexp) | Preset values for columns that can be sourced from session variables or static values |
|
||||
| columns | false | [PGColumn](#pgcolumn) array (or) `'*'` | Can insert into only these columns (or all when `'*'` is specified) |
|
||||
| backend_only | false | Boolean | When set to `true` the mutation is accessible only if the `x-hasura-use-backend-only-permissions` session variable exists and is set to `true` and the request is made with `x-hasura-admin-secret` set if any auth is configured |
|
||||
| validate_input | false | [InputValidation](#input-validation) | The input validation definition for the insert mutation. |
|
||||
|
||||
## SelectPermission {#selectpermission}
|
||||
|
||||
@ -366,20 +383,23 @@ The `query_root_fields` and the `subscription_root_fields` are only available in
|
||||
|
||||
## UpdatePermission {#updatepermission}
|
||||
|
||||
| Key | Required | Schema | Description |
|
||||
| ------------ | -------- | -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| columns | true | [PGColumn](#pgcolumn) array (or) `'*'` | Only these columns are selectable (or all when `'*'` is specified) |
|
||||
| filter | true | [BoolExp](#boolexp) | Only the rows where this precondition holds true are updatable |
|
||||
| check | false | [BoolExp](#boolexp) | Postcondition which must be satisfied by rows which have been updated |
|
||||
| set | false | [ColumnPresetsExp](#columnpresetexp) | Preset values for columns that can be sourced from session variables or static values. |
|
||||
| backend_only | false | Boolean | When set to `true` the mutation is accessible only if the `x-hasura-use-backend-only-permissions` session variable exists and is set to `true` and the request is made with `x-hasura-admin-secret` set if any auth is configured |
|
||||
| Key | Required | Schema | Description |
|
||||
| ------------ | -------- | -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| columns | true | [PGColumn](#pgcolumn) array (or) `'*'` | Only these columns are selectable (or all when `'*'` is specified) |
|
||||
| filter | true | [BoolExp](#boolexp) | Only the rows where this precondition holds true are updatable |
|
||||
| check | false | [BoolExp](#boolexp) | Postcondition which must be satisfied by rows which have been updated |
|
||||
| set | false | [ColumnPresetsExp](#columnpresetexp) | Preset values for columns that can be sourced from session variables or static values. |
|
||||
| backend_only | false | Boolean | When set to `true` the mutation is accessible only if the `x-hasura-use-backend-only-permissions` session variable exists and is set to `true` and the request is made with `x-hasura-admin-secret` set if any auth is configured |
|
||||
| validate_input | false | [InputValidation](#input-validation) | The input validation definition for the insert mutation. |
|
||||
|
||||
|
||||
## DeletePermission {#deletepermission}
|
||||
|
||||
| Key | Required | Schema | Description |
|
||||
| ------------ | -------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| filter | true | [BoolExp](#boolexp) | Only the rows where this expression holds true are deletable |
|
||||
| backend_only | false | Boolean | When set to `true` the mutation is accessible only if the `x-hasura-use-backend-only-permissions` session variable exists and is set to `true` and the request is made with `x-hasura-admin-secret` set if any auth is configured |
|
||||
| Key | Required | Schema | Description |
|
||||
| ------------ | -------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| filter | true | [BoolExp](#boolexp) | Only the rows where this expression holds true are deletable |
|
||||
| backend_only | false | Boolean | When set to `true` the mutation is accessible only if the `x-hasura-use-backend-only-permissions` session variable exists and is set to `true` and the request is made with `x-hasura-admin-secret` set if any auth is configured |
|
||||
| validate_input | false | [InputValidation](#input-validation) | The input validation definition for the insert mutation. |
|
||||
|
||||
## LogicalModelSelectPermission {#logicalmodelselectpermission}
|
||||
|
||||
|
@ -245,11 +245,130 @@ Learn more about [Postgres triggers](https://www.postgresql.org/docs/current/sql
|
||||
|
||||
## Using Hasura permissions
|
||||
|
||||
If the validation logic can be expressed **declaratively** using static values and data from the database, then you can
|
||||
use [row level permissions](/auth/authorization/permissions/row-level-permissions.mdx) to perform the validations.
|
||||
(Read more about [Authorization](/auth/authorization/index.mdx)).
|
||||
Hasura permissions provides two different ways to validate data:
|
||||
|
||||
**Example 1:** Validate that an `article` can be inserted only if `title` is not empty.
|
||||
1. If input arguments of a mutations needs to be validated, you can use the
|
||||
[input validation](/docs/schema/postgres/input-validations.mdx) feature. This
|
||||
allows you to write custom validation logic that is run in an external webhook before hitting the
|
||||
database to execute the mutation.
|
||||
2. If the validation logic can be expressed **declaratively** using static
|
||||
values and data from the database, then you can use [row level
|
||||
permissions](/auth/authorization/permissions/row-level-permissions.mdx) to
|
||||
perform the validations. (Read more
|
||||
about[Authorization](/auth/authorization/index.mdx)).
|
||||
|
||||
**Example 1:** Validate that a valid email is being inserted
|
||||
|
||||
Suppose, we have the following table in our schema:
|
||||
```sql
|
||||
customer (id uuid, name text, city text, email text)
|
||||
```
|
||||
Now, we can create a role `user` and add an input validation rule as follows:
|
||||
|
||||
|
||||
<Tabs className="api-tabs">
|
||||
<TabItem value="console" label="Console">
|
||||
|
||||
<Thumbnail
|
||||
src="/img/schema/input-validation-create-permission.png"
|
||||
alt="Using boolean expressions to build rules"
|
||||
width="500px"
|
||||
/>
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
You can define the input validation in the `metadata -> databases -> [database-name] -> tables -> [table-name].yaml`
|
||||
file, eg:
|
||||
|
||||
```yaml {9-14}
|
||||
- table:
|
||||
schema: public
|
||||
name: customer
|
||||
insert_permissions:
|
||||
- role: user
|
||||
permission:
|
||||
columns: []
|
||||
filter: {}
|
||||
validate_input:
|
||||
type: http
|
||||
definition:
|
||||
url: http://www.somedomain.com/validateCustomerMutation
|
||||
forward_client_headers: true
|
||||
timeout: 5
|
||||
|
||||
```
|
||||
|
||||
Apply the Metadata by running:
|
||||
|
||||
```bash
|
||||
hasura metadata apply
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="api" label="API">
|
||||
|
||||
You can define the input validations when using the [permissions Metadata API](/api-reference/metadata-api/permission.mdx).
|
||||
Example with a Postgres DB:
|
||||
|
||||
```http {14-21}
|
||||
POST /v1/metadata HTTP/1.1
|
||||
Content-Type: application/json
|
||||
X-Hasura-Role: admin
|
||||
|
||||
{
|
||||
"type": "pg_create_insert_permission",
|
||||
"args": {
|
||||
"source": "<db_name>",
|
||||
"table": "customer",
|
||||
"role": "user",
|
||||
"permission": {
|
||||
"columns": "*",
|
||||
"filter": {},
|
||||
"validate_input": {
|
||||
"type": "http",
|
||||
"definition": {
|
||||
"forward_client_headers": true,
|
||||
"headers": [],
|
||||
"timeout": 5,
|
||||
"url": "http://www.somedomain.com/validateCustomerMutation"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
If we try to insert a customer with an invalid email, we will get a `validation-failed` error:
|
||||
|
||||
<GraphiQLIDE
|
||||
query={`mutation {
|
||||
insert_customer(
|
||||
objects: {
|
||||
name: "customer 1"
|
||||
email: "random-email",
|
||||
}
|
||||
) {
|
||||
affected_rows
|
||||
}
|
||||
}`}
|
||||
response={`{
|
||||
"errors": [
|
||||
{
|
||||
"message": "customer email id is not valid",
|
||||
"extensions": {
|
||||
"path": "$",
|
||||
"code": "validation-dfailed"
|
||||
}
|
||||
}
|
||||
]
|
||||
}`}
|
||||
/>
|
||||
|
||||
**Example 2:** Validate that an `article` can be inserted only if `title` is not empty.
|
||||
|
||||
Suppose, we have the following table in our schema:
|
||||
|
||||
@ -325,7 +444,7 @@ If we try to insert an article with `title = ""`, we will get a `permission-erro
|
||||
query={`mutation {
|
||||
insert_article(
|
||||
objects: {
|
||||
title: "
|
||||
title: ""
|
||||
content: "Lorem ipsum dolor sit amet",
|
||||
}
|
||||
) {
|
||||
@ -345,7 +464,7 @@ If we try to insert an article with `title = ""`, we will get a `permission-erro
|
||||
}`}
|
||||
/>
|
||||
|
||||
**Example 2:** Validate that an `article` can be inserted only if its `author` is active.
|
||||
**Example 3:** Validate that an `article` can be inserted only if its `author` is active.
|
||||
|
||||
Suppose, we have 2 tables:
|
||||
|
||||
|
332
docs/docs/schema/postgres/input-validations.mdx
Normal file
332
docs/docs/schema/postgres/input-validations.mdx
Normal file
@ -0,0 +1,332 @@
|
||||
---
|
||||
sidebar_label: Input validations
|
||||
sidebar_position: 11
|
||||
description: Input validations in Hasura over Postgres
|
||||
sidebar_class_name: beta-tag
|
||||
keywords:
|
||||
- hasura
|
||||
- docs
|
||||
- postgres
|
||||
- schema
|
||||
- mutations
|
||||
- input validation
|
||||
---
|
||||
|
||||
import ProductBadge from '@site/src/components/ProductBadge';
|
||||
import GraphiQLIDE from '@site/src/components/GraphiQLIDE';
|
||||
import Thumbnail from '@site/src/components/Thumbnail';
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
# Postgres: Input Validations
|
||||
|
||||
<ProductBadge ce free standard pro ee self />
|
||||
|
||||
## Introduction
|
||||
|
||||
:::tip Supported from
|
||||
|
||||
Input validations are supported for versions `v2.29.0` and above.
|
||||
|
||||
:::
|
||||
|
||||
Many times, we need to perform validations on the input arguments of a GraphQL mutation before inserting, deleting
|
||||
or updating the data.
|
||||
|
||||
Hasura provides a way to add input validations to your GraphQL mutations which route the input arguments of a
|
||||
GraphQL mutation to an HTTP webhook to perform complex validation logic.
|
||||
|
||||
### Example
|
||||
|
||||
Consider you have the following GraphQL mutation:
|
||||
|
||||
```graphql
|
||||
mutation insert_users {
|
||||
insert_users(objects: [{name: "John", phone: "999"}]) {
|
||||
affected_rows
|
||||
}
|
||||
}
|
||||
|
||||
mutation update_users {
|
||||
update_users(where: {id: {_eq: 1}}, _set: {name: "John", email : "random email"}) {
|
||||
affected_rows
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can define the input validations for the above mutations to perform the following checks:
|
||||
1. Check that the `name` field is not empty
|
||||
2. Check that the `phone` field is a valid phone number
|
||||
3. Check that the `email` field is a valid email address
|
||||
4. Do not allow more than 5 insertions in a single insert mutation
|
||||
|
||||
## Setting up validation permissions
|
||||
|
||||
<Tabs className="api-tabs">
|
||||
<TabItem value="console" label="Console">
|
||||
|
||||
You can define the input validations for `insert/update/delete` permissions on the Hasura Console in **Data -> [table]
|
||||
-> Permissions -> (insert/update/delete)**.
|
||||
|
||||
<Thumbnail
|
||||
src="/img/schema/input-validation-create-permission.png"
|
||||
alt="Using boolean expressions to build rules"
|
||||
width="500px"
|
||||
/>
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
You can define the input validations in the `metadata -> databases -> [database-name] -> tables -> [table-name].yaml`
|
||||
file, eg:
|
||||
|
||||
```yaml {9-17}
|
||||
- table:
|
||||
schema: public
|
||||
name: products
|
||||
insert_permissions:
|
||||
- role: user
|
||||
permission:
|
||||
columns: []
|
||||
filter: {}
|
||||
validate_input:
|
||||
type: http
|
||||
definition:
|
||||
url: http://www.somedomain.com/validateProducts
|
||||
headers:
|
||||
- name: X-Validate-Input-API-Key
|
||||
value_from_env: VALIDATION_HOOK_API_KEY
|
||||
forward_client_headers: true
|
||||
timeout: 5
|
||||
|
||||
```
|
||||
|
||||
Apply the Metadata by running:
|
||||
|
||||
```bash
|
||||
hasura metadata apply
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="api" label="API">
|
||||
|
||||
You can define the input validations when using the [permissions Metadata API](/api-reference/metadata-api/permission.mdx).
|
||||
Example with a Postgres DB:
|
||||
|
||||
```http {14-21}
|
||||
POST /v1/metadata HTTP/1.1
|
||||
Content-Type: application/json
|
||||
X-Hasura-Role: admin
|
||||
|
||||
{
|
||||
"type": "pg_create_(insert|update|delete)_permission",
|
||||
"args": {
|
||||
"source": "<db_name>",
|
||||
"table": "products",
|
||||
"role": "user",
|
||||
"permission": {
|
||||
"columns": "*",
|
||||
"filter": {},
|
||||
"validate_input": {
|
||||
"type": "http",
|
||||
"definition": {
|
||||
"forward_client_headers": true,
|
||||
"headers": [],
|
||||
"timeout": 10,
|
||||
"url": "http://www.somedomain.com/validateUser"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
The `type` determines the interface for the input validation, which initially only supports an `http` webhook URL.
|
||||
|
||||
The `definition` field provides the necessary context for communicating and submitting the data for input validation.
|
||||
It is an object with the following fields.
|
||||
- `url` - *Required*, a [string value](https://hasura.io/docs/latest/api-reference/syntax-defs/#webhookurl) which
|
||||
supports templating environment variables.
|
||||
- `headers` - *Optional*, a list of headers to be sent to the URL.
|
||||
- `forward_client_headers` - *Optional*, default is `false`. If set to `true` the client headers are forwarded to
|
||||
the URL.
|
||||
- `timeout` - *Optional*, default is `10`. The number of seconds to wait for a response before timing out.
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::caution Reduced performance
|
||||
|
||||
Mutations that involve input validation **may exhibit slower performance** compared to mutations without
|
||||
validation. The execution time of the webhook URL can become a bottleneck, potentially reaching the maximum limit
|
||||
specified by the `timeout` configuration value, the default of which is 10 seconds.
|
||||
|
||||
:::
|
||||
|
||||
## How it works
|
||||
Following are the steps that are performed by mutations types (`insert/update/delete`)
|
||||
|
||||
When an mutation arrives with a role, the following steps are performed:
|
||||
|
||||
1. First, "collect" all the tables that the mutation targets (because there could be more than one table involved via
|
||||
nested inserts)
|
||||
2. If there is a `validate_input` permission defined on a table, then any mutation arguments targeting that table are
|
||||
sent to the validation URL. This is done for all tables.
|
||||
3. If all handlers validate the mutation arguments, then the request proceeds. **A transaction with
|
||||
the database will only be started after the validation is completed and successful.**
|
||||
4. If any webhook rejects the mutation data, then the request is aborted. An `error` message from the URL can also
|
||||
be forwarded to the client.
|
||||
|
||||
Consider the following sample mutation:
|
||||
|
||||
```graphql
|
||||
mutation insertAuthorWithArticles($name: String, $email:String, $articles_content:[article_insert_input!]!) {
|
||||
insert_author(objects: {name: $name, email: $email, articles: {data: $articles_content}}){
|
||||
returning {
|
||||
first_name
|
||||
articles {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The above mutation targets the `author` and `article` tables, involving a nested insert of an article into the
|
||||
author model. Assuming that the `validate_input` permission is defined for both tables, the validation process
|
||||
unfolds as follows:
|
||||
|
||||
1. The validation webhook specified for the `author` table is contacted first, including the inserted row with
|
||||
`articles`
|
||||
2. Subsequently, the validation webhook designated for the `article` table is contacted with `$articles_content` rows.
|
||||
3. If both of the above webhook calls result in successful validation, a database transaction is started to insert the
|
||||
rows into the respective tables.
|
||||
|
||||
|
||||
## Webhook specification per mutation type
|
||||
|
||||
### Request
|
||||
|
||||
When a mutation on a table with `validate_input` configuration is executed, before making a database
|
||||
transaction, Hasura sends the mutation argument data to the validation HTTP webhook using a `POST` request.
|
||||
|
||||
The request payload is of the format:
|
||||
```json
|
||||
{
|
||||
"version": "<version-integer>",
|
||||
"role": "<role-name>",
|
||||
"session_variables": {
|
||||
"x-hasura-user-id": "<session-user-id>",
|
||||
"x-hasura-user-name": "<session-user-name>"
|
||||
},
|
||||
"data": {
|
||||
"input": <mutation specific schema>
|
||||
}
|
||||
}
|
||||
```
|
||||
- `version`: An integer version serves to indicate the request format. Whenever a breaking update occurs in the
|
||||
request payload, the version will be incremented. The initial version is set to `1`.
|
||||
- `role`: Hasura session role on which permissions are enforced.
|
||||
- `session_variables`: Session variables that aid in enforcing permissions. Session variable names always starts with
|
||||
`x-hasura-*`.
|
||||
- `data.input`: The schema of `data.input` varies per mutation type. This schema is defined below.
|
||||
|
||||
#### Insert Mutations
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "<version-integer>",
|
||||
"role": "<role-name>",
|
||||
"session_variables": {<session-variables>},
|
||||
"data": {
|
||||
"input": [{JSON-fied <model_name>_insert_input!}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- `data.input`: List of rows to be inserted which are specified in the `objects` input field of insert mutation.
|
||||
Also includes nested data of relationships. The structure of this field will be similar to the JSONified structure
|
||||
of the `<model_name>_insert_input!` graphql type.
|
||||
|
||||
Note that, in `data.input`, if the data to be inserted contains nested inserts, then:
|
||||
|
||||
1. The `data.input` for the root model will have the type `JSON-fied <model_name>_insert_input!`, i.e: the nested
|
||||
inserts will be present as `JSON-fied <model_name>_(arr|obj)_rel_insert_input!`
|
||||
2. The `data.input` for the nested inserts payload will have the type `JSON-fied <nested_model_name>_insert_input!`
|
||||
|
||||
#### Update Mutations
|
||||
|
||||
The user may want to validate the input values in the `where`, `_set`, `_inc` etc clause and `pk_columns`. So, the
|
||||
upstream webhook is expected to receive those values in the payload.
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "<version-integer>",
|
||||
"role": "<role-name>",
|
||||
"session_variables": {<session-variables>},
|
||||
"data": {
|
||||
"input": [
|
||||
{
|
||||
JSON-fied <model_name>_updates!,
|
||||
"pk_columns": JSON-fied <model_name>_pk_columns_input! (only included for update_<mode_name>_by_pk)
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
- `data.input`: List of the multiple updates to run. The structure of this field will be similar to the JSONified
|
||||
structure of the `<model_name>_updates!` graphql type. If it is an update mutation by primary key, then it will
|
||||
also contain the `<model_name>_pk_columns_input!`
|
||||
|
||||
#### Delete Mutations
|
||||
|
||||
The user may want to validate the input values in the `where` clause and `pk_columns`. So the upstream webhook is
|
||||
expected to receive those values in the payload.
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "<version-integer>",
|
||||
"role": "<role-name>",
|
||||
"session_variables": {<session-variables>},
|
||||
"data": {
|
||||
"input": [
|
||||
{
|
||||
JSON-fied <model_name>_bool_exp!,
|
||||
"pk_columns": JSON-fied <model_name>_pk_columns_input! (only included for delete_<mode_name>_by_pk)
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- `data.input`: The delete condition. The structure of this field will be similar to the JSONified structure of the
|
||||
`<model_name>_bool_exp!` graphql type. If it is a delete mutation by primary key, then it will also contain the
|
||||
`<model_name>_pk_columns_input!`
|
||||
|
||||
### Response
|
||||
|
||||
The following is the expected response from the upstream webhook for all mutation types (`insert/update/delete`).
|
||||
|
||||
1. **Successful Response**
|
||||
|
||||
The HTTP validation URL should return a `200` status code to represent a successful validation.
|
||||
|
||||
```http
|
||||
200 OK
|
||||
```
|
||||
|
||||
2. **Failed Response**
|
||||
|
||||
The HTTP validation URL should return an optional JSON object with `400` status code to represent a failed validation.
|
||||
The object should contain a `message` field whose value is a string and this message is forwarded to client.
|
||||
|
||||
If no JSON object is returned then no message is forwarded to client.
|
||||
|
||||
```http
|
||||
400 BAD REQUEST
|
||||
|
||||
{
|
||||
"message": "Phone number invalid"
|
||||
}
|
||||
```
|
||||
|
||||
**When an unexpected response format is received, Hasura raises internal exception**
|
BIN
docs/static/img/schema/input-validation-create-permission.png
vendored
Normal file
BIN
docs/static/img/schema/input-validation-create-permission.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 96 KiB |
Loading…
Reference in New Issue
Block a user