Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat - Creating ability to add validators to api gw method without needing a model #2450

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 37 additions & 24 deletions samtranslator/model/eventsources/push.py
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,7 @@ class Api(PushEventSource):
"Auth": PropertyType(False, is_type(dict)),
"RequestModel": PropertyType(False, is_type(dict)),
"RequestParameters": PropertyType(False, is_type(list)),
"RequestValidators": PropertyType(False, is_type(dict)),
}

def resources_to_link(self, resources):
Expand Down Expand Up @@ -657,6 +658,33 @@ def _get_permission(self, resources_to_link, stage, suffix):

return self._construct_permission(resources_to_link["function"], source_arn=source_arn, suffix=suffix)

def _add_validators(self, editor, validate_body, validate_parameters):
# Checking if any of the fields are defined as it can be false we are checking if the field are not None
if validate_body is not None or validate_parameters is not None:

# as we are setting two different fields we are here setting as default False
# In case one of them are not defined
validate_body = False if validate_body is None else validate_body
validate_parameters = False if validate_parameters is None else validate_parameters

# If not type None but any other type it should explicitly invalidate the Spec
# Those fields should be only a boolean
if not isinstance(validate_body, bool) or not isinstance(validate_parameters, bool):
raise InvalidEventException(
self.relative_id,
"Unable to set Validator on API method [{method}] for path [{path}] "
"ValidateBody and ValidateParameters must be a boolean type, strings or intrinsics are not supported.".format(
method=self.Method, path=self.Path
),
)

editor.add_request_validator_to_method(
path=self.Path,
method_name=self.Method,
validate_body=validate_body,
validate_parameters=validate_parameters,
)

def _add_swagger_integration(self, api, function, intrinsics_resolver):
"""Adds the path and method for this Api event source to the Swagger body for the provided RestApi.

Expand Down Expand Up @@ -800,31 +828,16 @@ def _add_swagger_integration(self, api, function, intrinsics_resolver):
validate_body = self.RequestModel.get("ValidateBody")
validate_parameters = self.RequestModel.get("ValidateParameters")

# Checking if any of the fields are defined as it can be false we are checking if the field are not None
if validate_body is not None or validate_parameters is not None:

# as we are setting two different fields we are here setting as default False
# In case one of them are not defined
validate_body = False if validate_body is None else validate_body
validate_parameters = False if validate_parameters is None else validate_parameters
self._add_validators(editor, validate_body, validate_parameters)

# If not type None but any other type it should explicitly invalidate the Spec
# Those fields should be only a boolean
if not isinstance(validate_body, bool) or not isinstance(validate_parameters, bool):
raise InvalidEventException(
self.relative_id,
"Unable to set Validator to RequestModel [{model}] on API method [{method}] for path [{path}] "
"ValidateBody and ValidateParameters must be a boolean type, strings or intrinsics are not supported.".format(
model=method_model, method=self.Method, path=self.Path
),
)

editor.add_request_validator_to_method(
path=self.Path,
method_name=self.Method,
validate_body=validate_body,
validate_parameters=validate_parameters,
)
if self.RequestValidators:
# default is no Validators
# if we have validator configured to a request parameter
# we want to add it to the editor but remove it from original dict before it iterates
# If validators is present or not, this method will handle the check
self._add_validators(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if this should be the correct behaviour. I found it confusing, if the customer defined set the validation to True in the RequestModel but to False in the RequestValidators, why should we disable the validations. I think it is not a good customer experience.

editor, self.RequestValidators.get("ValidateBody"), self.RequestValidators.get("ValidateParameters")
)

if self.RequestParameters:

Expand Down
203 changes: 203 additions & 0 deletions tests/translator/input/api_request_parameters_with_validator.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
Resources:
HtmlFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://sam-demo-bucket/member_portal.zip
Handler: index.gethtml
Runtime: nodejs12.x
Events:
GetHtml:
Type: Api
Properties:
RestApiId: HtmlApi
Path: /
Method: get
RequestModel:
Model: User
Required: true
ValidateBody: true
ValidateParameters: true

HtmlFunctionNoValidation:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://sam-demo-bucket/member_portal.zip
Handler: index.gethtml
Runtime: nodejs12.x
Events:
GetHtml:
Type: Api
Properties:
RestApiId: HtmlApi
Path: /no-validation
Method: get
RequestModel:
Model: User
Required: true
ValidateBody: false
ValidateParameters: false

HtmlFunctionMixinValidation:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://sam-demo-bucket/member_portal.zip
Handler: index.gethtml
Runtime: nodejs12.x
Events:
GetHtml:
Type: Api
Properties:
RestApiId: HtmlApi
Path: /mixin
Method: get
RequestModel:
Model: User
Required: true
ValidateBody: true
ValidateParameters: false

HtmlFunctionOnlyBodyDefinition:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://sam-demo-bucket/member_portal.zip
Handler: index.gethtml
Runtime: nodejs12.x
Events:
GetHtml:
Type: Api
Properties:
RestApiId: HtmlApi
Path: /only-body-true
Method: get
RequestModel:
Model: User
Required: true
ValidateBody: true

HtmlFunctionOnlyRequestDefinition:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://sam-demo-bucket/member_portal.zip
Handler: index.gethtml
Runtime: nodejs12.x
Events:
GetHtml:
Type: Api
Properties:
RestApiId: HtmlApi
Path: /only-request-true
Method: get
RequestValidators:
ValidateParameters: true
RequestModel:
Model: User
Required: true

HtmlFunctionOnlyRequestDefinitionFalse:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://sam-demo-bucket/member_portal.zip
Handler: index.gethtml
Runtime: nodejs12.x
Events:
GetHtml:
Type: Api
Properties:
RestApiId: HtmlApi
Path: /only-request-false
Method: get
RequestModel:
Model: User
Required: true
ValidateParameters: false

HtmlFunctionOnlyBodyDefinitionFalse:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://sam-demo-bucket/member_portal.zip
Handler: index.gethtml
Runtime: nodejs12.x
Events:
GetHtml:
Type: Api
Properties:
RestApiId: HtmlApi
Path: /only-body-false
Method: get
RequestModel:
Model: User
Required: true
ValidateBody: false

HtmlFunctionApiRequestParameterAndValidators:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://sam-demo-bucket/member_portal.zip
Handler: index.gethtml
Runtime: nodejs12.x
Events:
GetHtml:
Type: Api
Properties:
RestApiId: HtmlApi
Path: /only-body-false-and-validator
Method: get
RequestValidators:
ValidateParameters: true
RequestParameters:
- method.request.header.Authorization:
Required: true
Caching: true

HtmlFunctionApiRequestParameterValidatorsAndModelBody:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://sam-demo-bucket/member_portal.zip
Handler: index.gethtml
Runtime: nodejs12.x
Events:
GetHtml:
Type: Api
Properties:
RestApiId: HtmlApi
Path: /only-body-false-and-validator-and-model
Method: get
RequestValidators:
ValidateParameters: false
RequestParameters:
- method.request.header.Authorization:
Required: true
Caching: true
RequestModel:
Model: User
Required: true
ValidateBody: true
ValidateParameters: true

HtmlFunctionNotDefinedValidation:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://sam-demo-bucket/member_portal.zip
Handler: index.gethtml
Runtime: nodejs12.x
Events:
GetHtml:
Type: Api
Properties:
RestApiId: HtmlApi
Path: /not-defined
Method: get
RequestModel:
Model: User
Required: true

HtmlApi:
Type: AWS::Serverless::Api
Properties:
StageName: Prod
Models:
User:
type: object
properties:
username:
type: string
Loading