---
Parameters:
  Stage:
    Description: Stage name
    Type: String
    AllowedValues:
      - PROD
      - CODE
    Default: CODE
Mappings:
  StageMap:
    PROD:
      authDomain: gnmtouchpoint.my.salesforce.com
      reqDomain: gnmtouchpoint.my.salesforce.com
      SalesforceStage: PROD
      AppName: TouchpointUpdate
      AppSecretsVersion: d338b761-cb81-4adf-aca4-163678e65a59
      UserSecretsVersion: dfbf9eba-5215-4cb8-91f1-ff5bcbbf5201
      DomainName: contact-us-api.support.guardianapis.com
    CODE:
      authDomain: test.salesforce.com
      reqDomain: gnmtouchpoint--DEV1.sandbox.my.salesforce.com
      SalesforceStage: CODE
      AppName: AwsConnectorSandbox
      AppSecretsVersion: abaa595b-e6c8-4d13-81e0-2d02627536c7
      UserSecretsVersion: 4a0eabf6-7940-47ef-87d0-36c3ef7f5741
      DomainName: contact-us-api-code.support.guardianapis.com
Resources:
  ContactUsApiGateway:
    Type: AWS::ApiGateway::RestApi
    Properties:
      Body:
        info:
          version: '1.0'
          title:
            Ref: AWS::StackName
        paths:
          "/":
            post:
              x-amazon-apigateway-integration:
                httpMethod: POST
                type: aws_proxy
                uri:
                  Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ContactUsLambda.Arn}/invocations
              security:
                - api_key: []
              responses: {}
        swagger: '2.0'
        securityDefinitions:
          api_key:
            type: apiKey
            name: x-api-key
            in: header
      Name:
        Fn::Sub: contact-us-api-${Stage}-ApiGateway
  ContactUsApiGatewayDeployment18d4f4d63b:
    Type: AWS::ApiGateway::Deployment
    Properties:
      Description: 'RestApi deployment id: 18d4f4d63b13b7bad95a556b1a598aebc104f418'
      RestApiId:
        Ref: ContactUsApiGateway
  4xxApiAlarm:
    Type: AWS::CloudWatch::Alarm
    Condition: IsProd
    DependsOn:
      - ContactUsApiGateway
    Properties:
      AlarmActions:
        - !Sub arn:aws:sns:${AWS::Region}:${AWS::AccountId}:alarms-handler-topic-PROD
      AlarmName:
        Fn::Sub: 4XX rate from contact-us-api-${Stage}
      AlarmDescription: 'See https://github.com/guardian/support-service-lambdas/blob/main/handlers/contact-us-api/README.md#4XX-Errors
        for possible causes, impacts and fixes.

        '
      ComparisonOperator: GreaterThanThreshold
      Dimensions:
        - Name: ApiName
          Value:
            Fn::Sub: contact-us-api-${Stage}-ApiGateway
        - Name: Stage
          Value:
            Fn::Sub: "${Stage}"
      EvaluationPeriods: 1
      MetricName: 4XXError
      Namespace: AWS/ApiGateway
      Period: 3600
      Statistic: Sum
      Threshold: 1
      TreatMissingData: notBreaching
  5xxApiAlarm:
    Type: AWS::CloudWatch::Alarm
    Condition: IsProd
    DependsOn:
      - ContactUsApiGateway
    Properties:
      AlarmActions:
        - !Sub arn:aws:sns:${AWS::Region}:${AWS::AccountId}:alarms-handler-topic-PROD
      AlarmName:
        Fn::Sub: 5XX rate from contact-us-api-${Stage}
      AlarmDescription: 'See https://github.com/guardian/support-service-lambdas/blob/main/handlers/contact-us-api/README.md#5XX-Errors
        for possible causes, impacts and fixes.

        '
      ComparisonOperator: GreaterThanThreshold
      Dimensions:
        - Name: ApiName
          Value:
            Fn::Sub: contact-us-api-${Stage}-ApiGateway
        - Name: Stage
          Value:
            Fn::Sub: "${Stage}"
      EvaluationPeriods: 1
      MetricName: 5XXError
      Namespace: AWS/ApiGateway
      Period: 3600
      Statistic: Sum
      Threshold: 1
      TreatMissingData: notBreaching
  ContactUsLambda:
    Type: AWS::Lambda::Function
    DependsOn:
      - ContactUsLambdaRole
    Properties:
      Code:
        S3Bucket: support-service-lambdas-dist
        S3Key:
          Fn::Sub: membership/${Stage}/contact-us-api/contact-us-api.jar
      FunctionName:
        Fn::Sub: contact-us-api-${Stage}
      Handler: com.gu.contact_us_api.Handler
      MemorySize: 1024
      Role:
        Fn::GetAtt:
          - ContactUsLambdaRole
          - Arn
      Runtime: java21
      Timeout: 60
      Environment:
        Variables:
          stage:
            Ref: Stage
          authDomain:
            Fn::FindInMap:
              - StageMap
              - Ref: Stage
              - authDomain
          reqDomain:
            Fn::FindInMap:
              - StageMap
              - Ref: Stage
              - reqDomain
      Tags:
        - Key: lambda:createdBy
          Value: SAM
      Architectures:
        - arm64
  ContactUsLambdaApiEventPermissionStage:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Ref: ContactUsLambda
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Sub:
          - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/POST/
          - __ApiId__:
              Ref: ContactUsApiGateway
            __Stage__: "*"
  ContactUsApiGatewayUsagePlan:
    Type: AWS::ApiGateway::UsagePlan
    DependsOn:
      - ContactUsApiGateway
    Properties:
      ApiStages:
        - ApiId:
            Ref: ContactUsApiGateway
          Stage:
            Ref: ContactUsApiGatewayStage
      Description:
        Fn::Sub: Usage plan for contact-us-api-PROD
      UsagePlanName:
        Fn::Sub: contact-us-api-PROD-UsagePlan
  ContactUsApiGatewayStage:
    Type: AWS::ApiGateway::Stage
    Properties:
      DeploymentId:
        Ref: ContactUsApiGatewayDeployment18d4f4d63b
      RestApiId:
        Ref: ContactUsApiGateway
      StageName:
        Fn::Sub: "${Stage}"
  ContactUsApiGatewayApiKey:
    Type: AWS::ApiGateway::ApiKey
    DependsOn:
      - ContactUsApiGatewayUsagePlan
    Properties:
      Enabled: true
      StageKeys:
        - RestApiId:
            Ref: ContactUsApiGateway
          StageName:
            Ref: ContactUsApiGatewayStage
  ContactUsApiGatewayUsagePlanKey:
    Type: AWS::ApiGateway::UsagePlanKey
    DependsOn:
      - ContactUsApiGatewayApiKey
    Properties:
      KeyId:
        Ref: ContactUsApiGatewayApiKey
      KeyType: API_KEY
      UsagePlanId:
        Ref: ContactUsApiGatewayUsagePlan
  noRequestsAlarm:
    Type: AWS::CloudWatch::Alarm
    Condition: IsProd
    DependsOn:
      - ContactUsApiGateway
    Properties:
      AlarmActions:
        - !Sub arn:aws:sns:${AWS::Region}:${AWS::AccountId}:alarms-handler-topic-PROD
      AlarmName:
        Fn::Sub: No requests coming into contact-us-api-${Stage}
      AlarmDescription: 'This is a last line catch-all alarm. It means no requests
        were received in the last 6 hours. It might mean something''s (silently) gone
        wrong with a part of the system that sends these requests (eg. MMA client
        or server-side). Or it could mean our users are happy and don''t need to contact
        us. :)

        '
      ComparisonOperator: LessThanThreshold
      Threshold: 1
      EvaluationPeriods: 12
      Metrics:
        - Id: actualCount
          Expression: FILL(rawCount, 0)
        - Id: rawCount
          ReturnData: false
          MetricStat:
            Metric:
              MetricName: Count
              Namespace: AWS/ApiGateway
              Dimensions:
                - Name: ApiName
                  Value:
                    Fn::Sub: contact-us-api-${Stage}-ApiGateway
                - Name: Stage
                  Value:
                    Fn::Sub: "${Stage}"
            Period: 3600
            Stat: Sum
            Unit: Count
      TreatMissingData: breaching
  ContactUsLambdaRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
        Version: '2012-10-17'
      Tags:
        - Key: App
          Value: contact-us-api
        - Key: Stage
          Value:
            Ref: Stage
        - Key: Stack
          Value: membership
      Path: "/"
      Policies:
        - PolicyName: ContactUsLambdaPolicy
          PolicyDocument:
            Statement:
              - Effect: Allow
                Action:
                  - lambda:InvokeFunction
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource:
                  Fn::Sub: arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/contact-us-api-${Stage}:log-stream:*
        - PolicyName: ReadFromSecretsManagerPolicy
          PolicyDocument:
            Statement:
              - Effect: Allow
                Action:
                  - secretsmanager:DescribeSecret
                  - secretsmanager:GetSecretValue
                Resource:
                  - arn:aws:secretsmanager:eu-west-1:865473395570:secret:PROD/Salesforce/ConnectedApp/TouchpointUpdate-lolLqP
                  - arn:aws:secretsmanager:eu-west-1:865473395570:secret:CODE/Salesforce/ConnectedApp/AwsConnectorSandbox-jaCgRl
                  - arn:aws:secretsmanager:eu-west-1:865473395570:secret:PROD/Salesforce/User/MembersDataAPI-1wX7Rg
                  - arn:aws:secretsmanager:eu-west-1:865473395570:secret:CODE/Salesforce/User/MembersDataAPI-xpUthA

  ContactUsApiDomainName:
    Type: "AWS::ApiGateway::DomainName"
    Properties:
      RegionalCertificateArn: # only for *.support.guardianapis.com
        !Sub arn:aws:acm:${AWS::Region}:${AWS::AccountId}:certificate/b384a6a0-2f54-4874-b99b-96eeff96c009
      DomainName: !FindInMap [ StageMap, !Ref Stage, DomainName ]
      EndpointConfiguration:
        Types:
          - REGIONAL

  ContactUsApiBasePathMapping:
    Type: "AWS::ApiGateway::BasePathMapping"
    Properties:
      RestApiId: !Ref ContactUsApiGateway
      DomainName: !Ref ContactUsApiDomainName
      Stage: !Sub ${Stage}
    DependsOn:
      - ContactUsApiGateway
      - ContactUsApiDomainName
      - ContactUsApiGatewayStage

  ContactUsApiDNSRecord:
    Type: AWS::Route53::RecordSet
    Properties:
      HostedZoneName: support.guardianapis.com.
      Name: !FindInMap [ StageMap, !Ref Stage, DomainName ]
      Type: CNAME
      TTL: '120'
      ResourceRecords:
        - !GetAtt ContactUsApiDomainName.RegionalDomainName
Conditions:
  IsProd:
    Fn::Equals:
      - Ref: Stage
      - PROD
