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 4 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
64 changes: 39 additions & 25 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,17 @@ 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

# 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,
)
self._add_validators(editor, validate_body, validate_parameters)

if self.RequestValidators:
# default is no Validators
validators = {"ValidateBody": None, "ValidateParameters": None}
Rondineli marked this conversation as resolved.
Show resolved Hide resolved
# 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
validators["ValidateBody"] = self.RequestValidators.get("ValidateBody")
validators["ValidateParameters"] = self.RequestValidators.get("ValidateParameters")
# If validators is present or not, this method will handle the check
self._add_validators(editor, validators["ValidateBody"], validators["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