Resources:
  MyApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: Prod
      Auth:
        Authorizers:
          MyCognitoAuthorizer:
            UserPoolArn:
              Fn::GetAtt: MyCognitoUserPool.Arn
          MyLambdaTokenAuth:
            FunctionArn:
              Fn::GetAtt: MyLambdaAuthFunction.Arn
          MyLambdaRequestAuth:
            FunctionPayloadType: REQUEST
            FunctionArn:
              Fn::GetAtt: MyLambdaAuthFunction.Arn
            Identity:
              QueryStrings:
              - authorization

  MyFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: nodejs18.x
      InlineCode: |
        exports.handler = async (event, context, callback) => {
          return {
            statusCode: 200,
            body: 'Success'
          }
        }
      Events:
        None:
          Type: Api
          Properties:
            RestApiId:
              Ref: MyApi
            Method: get
            Path: /none
        Cognito:
          Type: Api
          Properties:
            RestApiId:
              Ref: MyApi
            Method: get
            Path: /cognito
            Auth:
              Authorizer: MyCognitoAuthorizer
        LambdaToken:
          Type: Api
          Properties:
            RestApiId:
              Ref: MyApi
            Method: get
            Path: /lambda-token
            Auth:
              Authorizer: MyLambdaTokenAuth
        LambdaRequest:
          Type: Api
          Properties:
            RestApiId:
              Ref: MyApi
            Method: get
            Path: /lambda-request
            Auth:
              Authorizer: MyLambdaRequestAuth
        Iam:
          Type: Api
          Properties:
            RestApiId:
              Ref: MyApi
            Method: get
            Path: /iam
            Auth:
              Authorizer: AWS_IAM

  MyLambdaAuthFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: nodejs18.x
      InlineCode: |
        exports.handler = async (event, context, callback) => {
          const token = event.type === 'TOKEN' ? event.authorizationToken : event.queryStringParameters.authorization
          const policyDocument = {
            Version: '2012-10-17',
            Statement: [{
              Action: 'execute-api:Invoke',
              Effect: token && token.toLowerCase() === 'allow' ? 'Allow' : 'Deny',
              Resource: event.methodArn
            }]
          }
          
          return {
            principalId: 'user',
            context: {},
            policyDocument
          }
        }

  MyCognitoUserPool:
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Type: AWS::Cognito::UserPool
    Properties:
      UserPoolName: MyCognitoUserPool

  MyCognitoUserPoolClient:
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Type: AWS::Cognito::UserPoolClient
    Properties:
      UserPoolId:
        Ref: MyCognitoUserPool
      ClientName: MyCognitoUserPoolClient
      GenerateSecret: false

Outputs:
  ApiUrl:
    Description: API endpoint URL for Prod environment
    Value:
      Fn::Sub: https://${MyApi}.execute-api.${AWS::Region}.${AWS::URLSuffix}/Prod/

  AuthorizerFunctionArn:
    Description: Authorizer Function Arn
    Value:
      Fn::GetAtt: MyLambdaAuthFunction.Arn

  CognitoUserPoolArn:
    Description: Cognito User Pool Arn
    Value:
      Fn::GetAtt: MyCognitoUserPool.Arn
Metadata:
  SamTransformTest: true
