AWS API Gateway Query parameter validation - api

I have been trying to validate my request parameters using x-amazon-apigateway-request-validator, but unfortunately it is not working. Below is swagger file-
{
"swagger": "2.0",
"info": {
"title": "API Gateway - Request Validation Demo"
},
"schemes": [
"https"
],
"produces": [
"application/json"
],
"x-amazon-apigateway-request-validators" : {
"full" : {
"validateRequestBody" : true,
"validateRequestParameters" : true
},
"body-only" : {
"validateRequestBody" : true,
"validateRequestParameters" : false
}
},
"x-amazon-apigateway-request-validator" : "full",
"paths": {
"/orders": {
"post": {
"x-amazon-apigateway-request-validator": "body-only",
"parameters": [
{
"in": "body",
"name": "CreateOrders",
"required": true,
"schema": {
"$ref": "#/definitions/CreateOrders"
}
}
],
"responses": {
"200": {
"schema": {
"$ref": "#/definitions/Message"
}
},
"400" : {
"schema": {
"$ref": "#/definitions/Message"
}
}
},
"x-amazon-apigateway-integration": {
"responses": {
"default": {
"statusCode": "200",
"responseTemplates": {
"application/json": "{\"message\" : \"Orders successfully created\"}"
}
}
},
"requestTemplates": {
"application/json": "{\"statusCode\": 200}"
},
"passthroughBehavior": "never",
"type": "mock"
}
},
"get": {
"x-amazon-apigateway-request-validator": "full",
"parameters": [
{
"in": "header",
"name": "Account-Id",
"required": true
},
{
"in": "query",
"name": "type",
"required": false,
"schema": {
"$ref": "#/definitions/InputOrders"
}
}
],
"responses": {
"200" : {
"schema": {
"$ref": "#/definitions/Orders"
}
},
"400" : {
"schema": {
"$ref": "#/definitions/Message"
}
}
},
"x-amazon-apigateway-integration": {
"responses": {
"default": {
"statusCode": "200",
"responseTemplates": {
"application/json": "[{\"order-id\" : \"qrx987\",\n \"type\" : \"STOCK\",\n \"symbol\" : \"AMZN\",\n \"shares\" : 100,\n \"time\" : \"1488217405\",\n \"state\" : \"COMPLETED\"\n},\n{\n \"order-id\" : \"foo123\",\n \"type\" : \"STOCK\",\n \"symbol\" : \"BA\",\n \"shares\" : 100,\n \"time\" : \"1488213043\",\n \"state\" : \"COMPLETED\"\n}\n]"
}
}
},
"requestTemplates": {
"application/json": "{\"statusCode\": 200}"
},
"passthroughBehavior": "never",
"type": "mock"
}
}
}
},
"definitions": {
"CreateOrders": {
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Create Orders Schema",
"type": "array",
"minItems" : 1,
"items": {
"type": "object",
"$ref" : "#/definitions/Order"
}
},
"Orders" : {
"type": "array",
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Get Orders Schema",
"items": {
"type": "object",
"properties": {
"order_id": { "type": "string" },
"time" : { "type": "string" },
"state" : {
"type": "string",
"enum": [
"PENDING",
"COMPLETED"
]
},
"order" : {
"$ref" : "#/definitions/Order"
}
}
}
},
"Order" : {
"type": "object",
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Schema for a single Order",
"required": [
"account-id",
"type",
"symbol",
"shares",
"details"
],
"properties" : {
"account-id": {
"type": "string",
"pattern": "[A-Za-z]{6}[0-9]{6}"
},
"type": {
"type" : "string",
"enum" : [
"STOCK",
"BOND",
"CASH"]
},
"symbol" : {
"type": "string",
"minLength": 1,
"maxLength": 4
},
"shares": {
"type": "number",
"minimum": 1,
"maximum": 1000
},
"details": {
"type": "object",
"required": [
"limit"
],
"properties": {
"limit": {
"type": "number"
}
}
}
}
},
"InputOrder" : {
"type": "object",
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Schema for a Input Order",
"required": [
"type"
],
"properties" : {
"type": {
"type" : "string",
"enum" : [
"STOCK",
"BOND",
"CASH"]
}
}
},
"Message": {
"type": "object",
"properties": {
"message" : {
"type" : "string"
}
}
}
}
}
I am trying to validate my request parameters against some regex and enum values.
I am not sure if this is even possible or not. Can anybody please help me with this?

For HTTP parameter validation, API Gateway only supports marking one as 'required'. It does not support regex/enum values for parameters.

Related

Easy way to group custom defined types to use for reference?

How to reference types by group instead of doing it individually?
For example here, I want "sum" and "subtract" types to accept types that are "number"-related types only("number", "sum", "subtract"). While "concatenate" can accept both "number" and "string"-related types. Including their selves. This will be really helpful for me if in case I added more types and want them to be automatically included.
"sum": {
"title": "sum",
"type": "object",
"properties": {
"values": {
"type": "array",
"items": {
"anyOf": [
{
"type": "number"
},
{
"$ref": "#/definitions/sum"
},
{
"$ref": "#/definitions/subtract"
}
]
}
}
},
"required": [
"values"
]
},
"subtract": {
"title": "subtract",
"type": "object",
"properties": {
"minuend": {
"type": "number"
},
"subtrahend": {
"type": "number"
}
},
"required": [
"minuend",
"subtrahend"
]
},
"concatenate": {
"title": "concatenate",
"type": "object",
"properties": {
"strings": {
"type": "array",
"items": {
"anyOf": [
{
"type": "number"
},
{
"type": "string"
},
{
"$ref": "#/definitions/sum"
},
{
"$ref": "#/definitions/subtract"
}
]
}
}
},
"required": [
"strings"
]
}
}
Here's the full schema:
{
"definitions": {
"sum": {
"title": "sum",
"type": "object",
"properties": {
"values": {
"type": "array",
"items": {
"anyOf": [
{
"type": "number"
},
{
"$ref": "#/definitions/sum"
},
{
"$ref": "#/definitions/subtract"
}
]
}
}
},
"required": [
"values"
]
},
"subtract": {
"title": "subtract",
"type": "object",
"properties": {
"minuend": {
"type": "number"
},
"subtrahend": {
"type": "number"
}
},
"required": [
"minuend",
"subtrahend"
]
},
"concatenate": {
"title": "concatenate",
"type": "object",
"properties": {
"strings": {
"type": "array",
"items": {
"anyOf": [
{
"type": "number"
},
{
"type": "string"
},
{
"$ref": "#/definitions/sum"
},
{
"$ref": "#/definitions/subtract"
}
]
}
}
},
"required": [
"strings"
]
}
},
"title": "Step",
"type": "object",
"properties": {
"value": {
"oneOf": [
{
"type": "number",
"minimum": 0
},
{
"$ref": "#/definitions/sum"
},
{
"$ref": "#/definitions/subtract"
}
]
}
}
}

JSON Schema - How to narrow down possible array object values

How can the following requirements be configured in a JSON schema.
I have the following JSON
{
"orderMethods": [
{
"requestType": "some service",
"deployType": "MANUAL",
"deployLabel": "some label"
},
{
"requestType": "some service",
"deployType": "MANUAL",
"deployLabel": "some label"
},
{
"requestType": "some service",
"deployType": "AUTO",
"deploySubType": "REST",
"deployLabel": "some label",
"deployConfig": "some config"
},
{
"requestType": "some service",
"deployType": "AUTO",
"deploySubType": "DB",
"deployLabel": "some label",
"deployConfig": "some config"
}
]
}
Requirements:
only one deployType = "MANUAL" is allowed
only one deployType = "AUTO" is allowed
additionally, only one deploySubType = "REST or "DB" is allowed
Currently I have the following JSON schema. Unfortunately the above JSON is valid. How can the above requirements be addressed?
{
"$schema": "http://json-schema.org/draft-07/schema",
"type": "object",
"properties": {
"orderMethods": {
"$ref": "#/definitions/OrderMethods"
}
},
"additionalProperties": false,
"definitions": {
"OrderMethods": {
"type": "array",
"items": {
"$ref": "#/definitions/OrderMethod"
}
},
"OrderMethod": {
"oneOf": [
{
"$ref": "#/definitions/OrderMethodManualDeploy"
},
{
"$ref": "#/definitions/OrderMethodAutoDeploy"
}
],
"uniqueItems": true
},
"OrderMethodAutoDeploy": {
"oneOf": [
{
"$ref": "#/definitions/OrderMethodAutoRestDeploy"
},
{
"$ref": "#/definitions/OrderMethodAutoDBDeploy"
}
],
"uniqueItems": true
},
"OrderMethodManualDeploy": {
"type": "object",
"properties": {
"requestType": {
"type": "string"
},
"deployType": {
"const": "MANUAL"
},
"deployLabel": {
"type": "string"
}
},
"required": [
"requestType",
"deployType",
"deployLabel"
],
"additionalProperties": false
},
"OrderMethodAutoRestDeploy": {
"type": "object",
"properties": {
"requestType": {
"type": "string"
},
"deployType": {
"const": "AUTO"
},
"deploySubType": {
"const": "REST"
},
"deployLabel": {
"type": "string"
},
"deployConfig": {
"type": "string"
}
},
"additionalProperties": false,
"required": [
"requestType",
"deployType",
"deploySubType",
"deployLabel",
"deployConfig"
]
},
"OrderMethodAutoDBDeploy": {
"type": "object",
"properties": {
"requestType": {
"type": "string"
},
"deployType": {
"const": "AUTO"
},
"deploySubType": {
"const": "DB"
},
"deployConfig": {
"type": "string"
},
"deployLabel": {
"type": "string"
}
},
"additionalProperties": false,
"required": [
"requestType",
"deployType",
"deploySubType",
"deployLabel",
"deployConfig"
]
}
}
}
Thanks for your help/ideas.

Using a json schema in multiple layouts

I'm helping to build an interface that works with Json Schema, and I have a question about interface generation based on that schema. There are two display types - one for internal users and one for external users. Both are dealing with the same data, but the external users should see a smaller subset of fields than the internal users.
For example, here is one schema, it defines an obituary:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "",
"type": "object",
"required": [
"id",
"deceased"
],
"properties": {
"id": { "type": "string" },
"account": {
"type": "object",
"required": [
"name"
],
"properties": {
"id": { "type": "number" },
"name": { "type": "string" },
"website": {
"anyOf": [
{
"type": "string",
"format": "uri"
},
{
"type": "string",
"maxLength": 0
}
]
},
"email": {
"anyOf": [
{
"type": "string",
"format": "email"
},
{
"type": "string",
"maxLength": 0
}
]
},
"address": {
"type": "object",
"properties": {
"address1": { "type": "string" },
"address2": { "type": "string" },
"city": { "type": "string" },
"state": { "type": "string" },
"postalCode": { "type": "string" },
"country": { "type": "string" }
}
},
"phoneNumber": {
"anyOf": [
{
"type": "string",
"format": "phone"
},
{
"type": "string",
"maxLength": 0
}
]
},
"faxNumber": {
"anyOf": [
{
"type": "string",
"format": "phone"
},
{
"type": "string",
"maxLength": 0
}
]
},
"type": { "type": "string" }
}
},
"deceased": {
"type": "object",
"required": [
"fullName"
],
"properties": {
"fullName": { "type": "string" },
"prefix": { "type": "string" },
"firstName": { "type": "string" },
"middleName": { "type": "string" },
"nickName": { "type": "string" },
"lastName1": { "type": "string" },
"lastName2": { "type": "string" },
"maidenName": { "type": "string" },
"suffix": { "type": "string" }
}
},
"description": { "type": "string" },
"photos": {
"type": "array",
"items": { "type": "string" }
}
}
}
Internal users would be able to access all the fields, but external users shouldn't be able to read/write the account fields.
Should I make a second schema for the external users, or is there a way to indicate different display levels or public/private on each field?
You cannot restrict acess to the fields defined in a schema, but you can have 2 schema files, one defining the "public" fields, and the other one defining the restricted fields plus including the restricted fields.
So
public-schema.json:
{
"properties" : {
"id" : ...
}
}
restricted-schema.json:
{
"allOf" : [
{
"$ref" : "./public-schema.json"
},
{
"properties" : {
"account": ...
}
}
]
}

TypeError: datastore.getRootCollection is not a function

I assumed a dstore that was created using dmodel was still a dstore and inherited all the dstore functionality. So there's a method listed called getRootCollection but when i try to run this method on the store it fails with an error (no such function)
Here is my code
<script>
require(
[
'dojo/_base/declare',
'dstore/Memory',
'dmodel/extensions/jsonSchema',
'dmodel/validators/StringValidator',
'dmodel/store/Validating',
"dmodel/Model"
],
function (declare, Memory, jsonSchema, StringValidator, Validating, Model) {
var vMem = (declare([Memory, Validating]))({
Model: jsonSchema(
{
"$schema": "http://json-schema.org/draft-04/schema",
"description": "my schema",
"type": "object",
"properties": {
"page": {
"type": "object",
"properties": {
"detailsCanvas": {
"description": "test value",
"type": "object",
"$ref": "#/definitions/details"
}
}
},
"elements": {
"type": "array",
"items": {
"title": "Element",
"type": "object",
"properties": {
"id": {
"type": "string"
},
"positionX": {
"description": "The X coordinate",
"type": "number"
},
"elementSpecificProperties": {
"type": "object",
"oneOf": [
{ "$ref": "#/definitions/label" }
]
}
}
}
}
},
"definitions": {
"details": {
"type": "object",
"properties": {
"height": {
"type": "string"
}
}
},
"label": {
"type": "object",
"properties": {
"value": {
"type": "string"
}
}
}
}
}
)
});
vMem.setData(
{
"page": {
"detailsCanvas": {
"height": "100px"
}
},
"elements": [
{
"id": "1",
"positionX": 20,
"elementSpecificProperties": {
"value": "value_1"
}
},
{
"id": "2",
"positionX": 5,
"elementSpecificProperties": {
"value": "value_2"
}
}
]
});
var blah = vMem.getRootCollection(); //type error - getRootCollection is not a function
});
</script>
getRootCollection() is part of the Tree model of dstore. You only mixin the dstore/Memory. So that is why you get that error. Checkout the documentation of dstore for more information.

JsonSchema is not validated with oneOf

Need help to find the bug with this schema. It has oneOf operator.
Schema is here :
`{
"type": "object",
"required": [
"type",
"body"
],
"properties": {
"type": {
"description": "type of the document to post",
"type": "string",
"enum": [
"123",
"456"
]
},
"body": {
"type": "object",
"description": "body",
"oneOf": [{
"$ref": "#/definitions/abc",
"$ref": "#/definitions/def"
}]
}
},
"definitions": {
"abc": {
"type": "array",
"description": "abc",
"properties" : {
"name" : { "type" : "string" }
}
},
"def": {
"type": "array",
"description": "users","properties" : {
"name" : { "type" : "string" }
}
}
}
}`
My Json is this :
`{
"type": "123",
"body": {
"abc": [{
"name": "test"
}]
}
}`
It does not validate with tv4 and I also tried this online tool. It works without oneOf operator. Otherwise it does not validate it any tool.
Edit :
After reading the answers I modified the schema. New schema is :
{
"type": "object",
"properties": {
"type": {
"description": "type of the document to post",
"type": "string",
},
"body": {
"type": "object",
"description": "body",
"properties": {
"customers": {
"type": "array"
}
},
"anyOf": [
{
"title": "customers prop",
"properties": {
"customers": {
"type": "array",
"description": "customers",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
}
}
}
}
]
}
}
}
And json is here
{
"type": "customer",
"body": {
"none": [
{
"name": "test"
}
]
}
}
But it validates. I want to enforce one of "customers" or "users" in the body. To test I have removed users from the body.
Pl help.
The issue is that the data is passing both of your sub-schemas. oneOf means "match exactly one" - if you want "match at least one", then use anyOf.
In fact, both of your sub-schemas will pass all data. The reason is that properties is ignored when dealing with arrays.
What you presumably wanted to do instead is specify properties for the items in the array. For this, you need the items keyword:
"definitions": {
"abc": {
"type": "array",
"items": {
"type": "object",
"properties" : {
"name" : { "type" : "string" }
}
}
}
}
(You'll also need to add some distinct constraints - at the moment, both the "abc" and "def" definitions are identical apart from description, which makes the oneOf impossible because it will always match both or neither.)
Since you have the type at root level, you probably want the oneOf statement to check that an object with type "customer" has customers in the body (even though I would suggest skipping the body and placing customers and users directly in root object).
This works with your example, will require that an object with type "customer" has a body with "customers", and to clarify the matching, I let customer have the property "name" while the user has "username":
{
"type": "object",
"properties": {
"type": { "type": "string" },
"body": {
"type": "object",
"properties": {
"customers": {
"type": "array",
"items": { "$ref": "#/definitions/customer" }
},
"users": {
"type": "array",
"items": { "$ref": "#/definitions/user" }
}
}
}
},
"definitions": {
"customer": {
"type": "object",
"properties": { "name": { "type": "string" } },
"required": [ "name" ]
},
"user": {
"type": "object",
"properties": { "username": { "type": "string" } },
"required": [ "username" ]
}
},
"oneOf": [
{
"properties": {
"type": {
"pattern": "customer"
},
"body": {
"required": [ "customers" ]
}
}
},
{
"properties": {
"type": {
"pattern": "user"
},
"body": {
"required": [ "users" ]
}
}
}
]
}
When using "type": "array" then the item type is defined in the "items" property not "properties" property... Also both types in oneOf are same, but only one must match.
Try
...
"definitions": {
"abc": {
"type": "array",
"description": "abc",
"items" : {
"name" : { "type" : "string" }
}
},
"def": {
"type": "array",
"description": "users",
"items" : {
"username" : { "type" : "string" }
}
}
}