Is there a form to make loopback automatically validate input parameters in a remote method?
Let's assume we have the following definition of a remote method:
WebuserModel.remoteMethod('overLogin', {
description: "Performs a Webuser's login to the system",
accepts: [
{
arg: 'credentials', type: {
"username": { type: "string", required:true },
"password": { type: "string", required: true }
},
http: {source: 'body'},
required: true
},
],
returns: {arg: 'accesToken', type: "object", root: true},
http: {path: '/login', verb: 'post'}
}
I would here expect from loopback to perform validation of the input parameter on each request and to raise an error if the passed object does not comply with the defined schema (mandatory object with two mandatory properties).
Apparently it does not happen.
Any clue?
Disclaimer: I am a core developer of LoopBack and the author of argument validation in strong-remoting#3.x.
LoopBack does not support validation of nested object properties provided by the clients when invoking remote methods. Right now, we check only that the value is an object, see lib/types/object.js in strong-remoting.
In the upcoming LoopBack 4 version, we are planning to support full OpenAPI and/or JSON Schema validation for input arguments, see https://github.com/strongloop/loopback-next/issues/118
Based on the comments in that GitHub issue, it should be relatively easy to add JSONSchema-based validations to LoopBack 3.x too.
Related
Can someone help me please ?
"RefeItem": [
{
"Key": "dev",
"Value": "dev234"
}
]
how can i set this in API Definition publisher wso2
Latest versions of WSO2 API Manager supports Swagger 3.0.0 OpenAPI definitions. So any swagger definition adhering to that standard is supported.
You requirement can be achieved using the following snippet,
responses:
200:
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/RefeItem'
components:
schemas:
RefeItem:
type: array
items:
$ref: '#/components/schemas/keyValueObj'
keyValueObj:
type: object
properties:
Key:
type: string
Value:
type: string
You can find more information on using array data types in swagger here
Just learning my way through AWS - I have an APIGateway REST API setup with Lambda proxy integration. The API has a model defined, and request validation setup on the body using this model.
Say the model is
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"propertyA": {
"type": "string"
},
"propertyB": {
"type": "string"
},
"propertyC": {
"type": "string"
},
"propertyD": {
"type": "string"
}
},
"required": ["propertyA", "propertyB", "propertyC", "propertyD"]
}
Now, if I test the API via APIGateway console, and purposely give an invalid input (omitting a required property propertyD):
{
"propertyA": "valueA",
"propertyB": "valueB",
"propertyC": "valueC"
}
the request fails with the error(400): Sun Jul 11 13:07:07 UTC 2021 : Request body does not match model schema for content type application/json: [object has missing required properties (["propertyD"])]
But when I invoke the same API(and stage) with the same invalid input from Postman, the validation seems to be not happening, and request is proxied to Lambda, which even returns a 200 OK as long as I comment out the parts of code that depend on propertyD.
What's the difference here? Should I be passing in any request header from the client side? I couldn't find anything from the AWS documentations
Answering my question-
Issue was with the headers used in the request - Postman defaulted the JSON as a Content-Type of text/plain, I had to switch to JSON using the dropdown in Body tab to make PostMan set the Content-Type to application/json
Following this post seems to have fixed the problem: https://itnext.io/how-to-validate-http-requests-before-they-reach-lambda-2fff68bfe93b, although it doesn't explain how
Apparently the magic lies with the config adding Content-Type Header under HTTP Request Headers section, even though the header is set correctly as application/json in PostMan.
I am trying to validate an incoming XML payload via API gateway. To be specific, I actually don't even care about the schema, I just want to make sure that the body is not empty (and maybe that it is valid XML if I can get that functionality). I see a variety of posts from years ago stating that XML input validation is not yet supported in API Gateway.
Can somebody confirm if this is still the case? To provide a specific example, I have a model like this:
{
"$schema" : "http://json-schema.org/draft-04/schema#",
"title" : "Test Schema",
"type" : "object",
"minProperties": 1,
"properties": {
"account_id": {
"type": "string",
"pattern": "[A-Za-z]{6}[0-9]{6}"
}
},
"required": ["account_id"]
}
If I add request body validation using this model for content type "application/json" all is well, but if I do the same for content type "application/xml" no validation is performed.
Yes APIGW only supports json payload validation.
I want to define request and response models. I use the Serverless Framework with AWS and everything I'm seeing recommends using serverless-aws-documentation
The README says that I need to have this line in custom.documentation.models.MODELNAME
schema: ${file(models/error.json)}
But they don't have an example file of models/error.json to use as a baseline.
In the actual example serverless.yml they have a definition like this:
-
name: DoSomethingRequest
contentType: "application/json"
schema:
type: array
items:
type: string
This doesn't provide enough detail for what I'm trying to do.
My goal is to have a schema defined for an array of string objects, a message and a status code. The message and status code, though, are optional. These could also be part of other models and if possible I'd like to not repeat their definition for each model.
My current attempt is:
-
name: ReturnArrayResponse
contentType: "application/json"
schema:
type: array
itemsArray:
type: string
message:
type: string
statusCode:
type: number
I think this is going to do what I want, but how can I have message and statusCode be optional and repeat these two items in my other models?
I'd be happy with either a yml solution I can put in my serverless.yml file or a json file that I can reference.
Including a file
In the example given, error.json can contain any valid schema. So something as simple as this is fine:
{"type":"object","properties":{"message":{"type":"string"}}}
It's also fine to include attributes like $schema and title:
{
"$schema" : "http://json-schema.org/draft-04/schema#",
"title" : "Error Schema",
"type" : "object",
"properties" : {
"message" : { "type" : "string" },
"statusCode": { "type": "number" },
"itemsArray": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
This is especially handy when you have models already defined in AWS, but you don't have the serverless yaml to build them. You can simply copy the schema out of the AWS console, paste the json into a file, and use the schema: ${file()} syntax mentioned in the question. As far as I can tell anything that you can get the AWS console to accept will work.
DRY
I don't know of a way to reference models from within other models in a serverless file, but you could use the same approach as the plugin authors, and just put anything you need to reuse outside of the models and somewhere it's easier to reuse. The plugin authors use commonModelSchemaFragments.
So if you have some fragments like so:
commonModelSchemaFragments:
# defining common fragments means you can reference them with a single line
StringArrayFragment:
type: array
items:
type: string
HttpResponse:
type: object
properties:
message:
type: string
statusCode:
type: number
You can reference those fragments in models like this:
-
name: HttpStatusResponse
contentType: "application/json"
schema:
type: object
properties:
serverResponse:
${self:custom.commonModelSchemaFragments.HttpResponse}
messageArray:
${self:custom.commonModelSchemaFragments.StringArrayFragment}
Marking attributes optional
You can accomplish this by marking attributes as required. Simply provide a list of all attributes, except the ones you want to be optional. The json schema for that looks like this:
{
"type": "object",
"required": ["message"],
"properties": {
"optionalMessage": {
"type": "string"
},
"message": {
"type": "string"
}
}
}
which you would build by using yaml like this in your serverless file:
-
name: OptionalResponse
contentType: "application/json"
schema:
type: object
required:
- "message"
properties:
message:
type: string
optionalMessage:
type: string
Note on request validation
Marking attributes required or optional only matters if request body validation is turned on:
I don't know of a way to turn on request validation using any special serverless syntax. It looks like you can do this in the resources section, but I haven't tried it. Source.
Just a guess (posting it as an answer to preserve formatting) - your top-level entity in the schema should be an object, not an array, something like this:
schema:
type: object
properties:
items:
type: array
items:
type: string
message:
type: string
statusCode:
type: number
Aws cognito console screen
While creating user-pool using cloudformation template i wanted to add the following attributes(marked in the attached image link). I didn't find anything helpful in the AWS documentation.
It allows setting up Alias attributes as said in the aws cloudformation cognito documentation.
Has anybody tried this or has any idea regarding this?
I managed to get it done using the schema attribute of the AWS::cognito::UserPool:
"myApiUserPool": {
"Type": "AWS::Cognito::UserPool",
"Properties": {
"AdminCreateUserConfig": {
"AllowAdminCreateUserOnly": true
},
"Schema": [
{
"Mutable": false,
"Name": "email",
"Required": true
},
{
"Mutable": false,
"Name": "family_name",
"Required": true
},
{
"Mutable": false,
"Name": "name",
"Required": true
}
],
"AutoVerifiedAttributes": [
"email"
],
"UserPoolName": {
"Fn::Sub": "myApiUserPool${envParameter}"
}
}
}
Here is the example with YAML.
Note: you cannot just update a attribute you need to delete the userpool and create it again with the new attributes (just comment out your pool section and redeploy it). Otherwise it will ask for a AttributeDataType, and if you include it, it will create a custom attribute instead of standard one.
CognitoUserPool:
Type: AWS::Cognito::UserPool
Properties:
# Generate a name based on the stage
UserPoolName: ${self:custom.stage}-cfp-user-pool
AliasAttributes:
- phone_number
- email
- preferred_username
Policies:
PasswordPolicy:
MinimumLength: 8
Schema:
- Name: email
Required: true
Mutable: true
Adding on #jWang1 and considering you don't want to delete a user pool with lots of active users but you really need to add a parameter during for sign up process, then you can just add a custom attribute to the template and enforce it as required through your authentication library or custom implementation
The minimum parameters to achieve this are:
UserPool:
Type: AWS::Cognito::UserPool
Properties:
Schema:
-
Name: <attr name>
AttributeDataType: Boolean | DateTime | Number | String