Skip to content

Commit

Permalink
docs(core): add the description about validation filters
Browse files Browse the repository at this point in the history
  • Loading branch information
oscar60310 committed Oct 6, 2022
1 parent ab6e7f4 commit eca492d
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 15 deletions.
174 changes: 161 additions & 13 deletions packages/doc/docs/api-building/api-validation.mdx
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# API Validation

In the [Data API Schema](./configuration/data-api-schema), we talked about how to define the API Schema, and also mentioned the `validators` field feature could assist each request parameter to check the format. In the chapter we will talk more about the validator's usage and currently how many validators VulcanSQL supports.
In the [Data API Schema](./configuration/data-api-schema), we talked about how to define the API Schema, and also mentioned the `validators` field feature could assist each request parameter to check the format. In the chapter, we will talk more about the validator's usage and currently how many validators VulcanSQL supported.

## Apply validators

# Parameter Validators
There are two ways to apply validators: define them in [date API schema](./configuration/data-api-schema) and use validation filters.

The `validators` field in the API Schema is an array type, also you could use the multiple validators to check the format like below example:
### Define validators in data api schema

The most common way to apply validators is by `validators` property for parameters, this field in the API Schema is an array type, so you could add the multiple validators on a single parameter like the example below:

```yaml
urlPath: /orders/order_id
urlPath: /orders/:order_id
request:
- fieldName: orders_id
fieldIn: path
Expand All @@ -16,11 +23,16 @@ request:
- uuid
```
In the above example, because our request path parameter `order_id` is UUID format, and we require users to provide the path parameter when sending a request, so we could combine `uuid` validator and `required` validators ( but if you don’t set `required`, the VulcanSQL will make it be **required default.**
In the above example, we restricted the parameter `order_id` to be in `UUID` format and be required. All the requests that aren't fit these requirements will be rejected.

:::info
VulcanSQL sometimes applys some validators automatically, e.g. when a parameter is used in url path, we'd apply `required` validator on it.

## Set the args in the validator
:::

Some validators could set the `args` field to give some extra restrict, e.g: `number` and `date` validators:
#### Set the arguments for the validators

Some validators accept some extra arguments. We could set them by adding `args` field, e.g: to add arguments for `number` and `date` validators:

```yaml
urlPath: /orders
Expand All @@ -40,11 +52,38 @@ request:
max: 1000000
```

As you see, the `args` will have different fields by each validator, and when setting the `args`, we should use the `name` field to set the validator name to make the YAML format correct.
As you saw, to add argument for a validator, we need to use the `name` field to indicate the validator name, and use `args` filed to specify arguments.

### Validation filters

Another way to apply validators is using validation filters, it allows you to define validators with [SQL Syntax](./sql-syntax#filters). Every validator has a unique filter named with prefix `is_`, e.g. `integer` validator has the `is_integer` filter.

To use these filter, chain them after your parameters:

```sql
-- orders.sql
SELECT * FROM
orders
WHERE order_id = {{ context.params.order_id | is_required | is_uuid }}
```

#### Set the arguments for the validators

To set arguments for validators, use Python's keyword arguments:

```sql
-- orders.sql
SELECT * FROM
orders
WHERE create_date = {{ context.params.create_date | is_date(format='YYYY-MM-DD') }}
AND price = {{ context.params.price | is_integer(min=0, max=1000000) }}
```

For more information and further use cases, please check the document [Validation Filter](./api-validation/validation-filter).

## Error Response when sending request
## Error Response when sending invalid requests

When the validator check the format and it's failed, it will return the error response, below is the example:
When a request doesn't fit the requirements of validators, we'd reject the request and return an error response, below is an example:

```yaml
# order.yaml
Expand All @@ -68,14 +107,17 @@ Then when you sent the request with GET`<endpoint>/api/orders?price=1000001`, it
}
```

## Current support validators
## Current supported validators

### `required` validator

Make the request parameter field the **required** parameter, use the [**Joi to check required**](https://joi.dev/api/?v=17.6.1#anyrequired---aliases-exist). The `args` field:

- `disallow` - Array type. Specifies what input values are also not as required and if the parameter value appeared in the `disallow` value, send the response with the error message.

<Tabs groupId="validator-method">
<TabItem value="schema" label="API Schema">

```yaml
# dep_users.yaml
urlPath: /dep_users
Expand All @@ -91,6 +133,17 @@ request:
- 'null'
```

</TabItem>
<TabItem value="validation-filter" label="Validation Filter">

```sql
SELECT * FROM users
WHERE department = {{ context.params.department | is_required(disallow=['', ' ', 'null']) }}
```

</TabItem>
</Tabs>

Then when you sent the request with GET`<endpoint>/api/dep_users?department=null`, it will return an HTTP status code with **400** and the below message:

```yaml
Expand All @@ -102,10 +155,13 @@ Then when you sent the request with GET`<endpoint>/api/dep_users?department=null

### `uuid` validator

Validate the UUID format for the request parameter, use the [\*\*Joi to check UUID](https://joi.dev/api/?v=17.6.1#stringguid---aliases-uuid).\*\* The `args` field:
Validate the UUID format for the request parameter, use the [Joi to check UUID](https://joi.dev/api/?v=17.6.1#stringguid---aliases-uuid). The `args` field:

- `version` - String type. Specifies the UUID version. the option could be `uuidv1`, `uuidv4` or `uuidv5`

<Tabs groupId="validator-method">
<TabItem value="schema" label="API Schema">

```yaml
# order.yaml
urlPath: /orders/:id
Expand All @@ -118,12 +174,26 @@ request:
version: uuidv5
```

</TabItem>
<TabItem value="validation-filter" label="Validation Filter">

```sql
SELECT * FROM order
WHERE id = {{ context.params.id | is_uuid(version='uuidv5') }}
```

</TabItem>
</Tabs>

### `date` validator

Validate whether the request parameter is Date Format type or not, use the [**dayjs package**](https://day.js.org/docs/en/parse/string) to be the format source. The `args` field:

- `format` - String type. Specifies the date needed format, supported [ISO_8601](https://www.w3.org/TR/NOTE-datetime) token, e.g: `'YYYYMMDD'`, `'YYYY-MM-DD'`, `'YYYY-MM-DD HH:mm'`.

<Tabs groupId="validator-method">
<TabItem value="schema" label="API Schema">

```yaml
# order.yaml
urlPath: /orders
Expand All @@ -136,6 +206,17 @@ request:
format: 'YYYY-MM-DD' # make the date only support 'YYYY-MM-DD' format
```

</TabItem>
<TabItem value="validation-filter" label="Validation Filter">

```sql
SELECT * FROM order
WHERE create_date = {{ context.params.date | is_date(format='YYYY-MM-DD') }} -- make the date only support 'YYYY-MM-DD' format
```

</TabItem>
</Tabs>

### `string` validator

Validate whether the request parameter is a String type, use the [Joi to check String](https://joi.dev/api/?v=17.6.1#string) ( including the `args` field ). The `args` field:
Expand All @@ -145,9 +226,12 @@ Validate whether the request parameter is a String type, use the [Joi to check S
- `max` - Number type. Specifies the minimum number of string characters.
- `min` - Number type. Specifies the maximum number of string characters.

<Tabs groupId="validator-method">
<TabItem value="schema" label="API Schema">

```yaml
# bank_account.yaml
urlPath: /bank_account/id
urlPath: /bank_account/:id
request:
- fieldName: id
fieldIn: path
Expand All @@ -158,6 +242,17 @@ request:
length: 10
```

</TabItem>
<TabItem value="validation-filter" label="Validation Filter">

```sql
SELECT * FROM bank_account
WHERE id = {{ context.params.id | is_string(format='^09[0-9]{8}$', length=10) }}
```

</TabItem>
</Tabs>

### `integer` validator

Validate whether the request parameter is an Integer type, use the [Joi to check Integer](https://joi.dev/api/?v=17.6.1#numberinteger). ( including the `args` field ). The `args` field:
Expand All @@ -167,6 +262,9 @@ Validate whether the request parameter is an Integer type, use the [Joi to check
- `greater` - Number type. Specifies that the integer value must be greater than the limit.
- `less` - Number type. Specifies that the value must be less than the limit.

<Tabs groupId="validator-method">
<TabItem value="schema" label="API Schema">

```yaml
# bank_account.yaml
urlPath: /youth_users
Expand All @@ -179,3 +277,53 @@ request:
- greater: 10
- less: 19
```

</TabItem>
<TabItem value="validation-filter" label="Validation Filter">

```sql
SELECT * FROM bank_account
WHERE age = {{ context.params.age | is_integer(greater=10, less=19) }}
```

</TabItem>
</Tabs>

### `enum` validator

Constraint the input values with a whitelist. The `args` field:

- `items` - Array type (**Required**). Specifies the whitelist, you must add at least one element to this array.

:::tip
Enum validator won't care about the data type, so the both `[1]` amd `["1"]` allow the value `1` no mater it is string or number.
:::

<Tabs groupId="validator-method">
<TabItem value="schema" label="API Schema">

```yaml
# customers.yaml
urlPath: /customers
request:
- fieldName: marital_status
fieldIn: query
validators:
- name: enum
args:
items:
- Married
- Single
- Unknown
```

</TabItem>
<TabItem value="validation-filter" label="Validation Filter">

```sql
SELECT * FROM customers
WHERE marital_status = {{ context.params.marital_status | is_enum(items=['Married', 'Single', 'Unknown']) }}
```

</TabItem>
</Tabs>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Validation Filter

TBD
11 changes: 9 additions & 2 deletions packages/doc/sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,15 @@ const sidebars = {
id: 'api-building/build-from-dbt',
},
{
type: 'doc',
id: 'api-building/api-validation',
type: 'category',
label: 'API Validation',
link: { type: 'doc', id: 'api-building/api-validation' },
items: [
{
type: 'doc',
id: 'api-building/api-validation/validation-filter',
},
]
},
{
type: 'doc',
Expand Down

0 comments on commit eca492d

Please sign in to comment.