AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Frontend Service Discovery on AWS (uksb-1tthgi8k7) (version:v1.3)
Globals:
  Function:
    Runtime: nodejs16.x
    Architectures:
    - arm64
    Tracing: Active
Parameters:
  Stage:
    Type: String
    Default: prod
  LogLevel:
    Type: String
    Default: INFO
    AllowedValues:
    - CRITICAL
    - FATAL
    - ERROR
    - WARNING
    - INFO
    - DEBUG
    - NOTSET
  AccessControlAllowOrigin:
    Type: String
    Description: The cors configuration for allow-origin for the consumer API. Specify
      a domain or * to allow all.
  DefaultUserEmail:
    Type: String
    Default: ''
    Description: Optional email for the default user for the Admin API. Leave blank
      to skip creation
  CognitoAdvancedSecurity:
    Description: The type of Cognito advanced security to enable. Disabled by default.
    Type: String
    Default: 'OFF'
    AllowedValues:
    - 'OFF'
    - AUDIT
    - ENFORCED
  CookieSettings:
    Description: Settings to be applied when setting cookies via Set-Cookie header
    Type: String
    Default: Secure
  DeleteExpiryMinutes:
    Description: The number of minutes deleted data will be retained.
    Type: Number
    Default: 1440
  EnableDynamoDBBackups:
    Description: Whether to enable point in time recovery for the DynamoDB tables
    Type: String
    Default: 'false'
    AllowedValues:
    - 'true'
    - 'false'
Conditions:
  CreateUser:
    Fn::Not:
    - Fn::Equals:
      - Ref: DefaultUserEmail
      - ''
Mappings:
  Solution:
    Constants:
      Version: '1.3'
Resources:
  ProjectStore:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
      - AttributeName: projectId
        AttributeType: S
      BillingMode: PAY_PER_REQUEST
      KeySchema:
      - AttributeName: projectId
        KeyType: HASH
      StreamSpecification:
        StreamViewType: NEW_IMAGE
      TimeToLiveSpecification:
        AttributeName: expiresAt
        Enabled: true
      SSESpecification:
        KMSMasterKeyId: alias/aws/dynamodb
        SSEEnabled: true
        SSEType: KMS
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled:
          Ref: EnableDynamoDBBackups
  FrontendStore:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
      - AttributeName: projectId
        AttributeType: S
      - AttributeName: microFrontendId
        AttributeType: S
      BillingMode: PAY_PER_REQUEST
      KeySchema:
      - AttributeName: projectId
        KeyType: HASH
      - AttributeName: microFrontendId
        KeyType: RANGE
      StreamSpecification:
        StreamViewType: NEW_IMAGE
      TimeToLiveSpecification:
        AttributeName: expiresAt
        Enabled: true
      SSESpecification:
        KMSMasterKeyId: alias/aws/dynamodb
        SSEEnabled: true
        SSEType: KMS
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled:
          Ref: EnableDynamoDBBackups
  ConsumerViewStore:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
      - AttributeName: projectId
        AttributeType: S
      - AttributeName: microFrontendId
        AttributeType: S
      BillingMode: PAY_PER_REQUEST
      KeySchema:
      - AttributeName: projectId
        KeyType: HASH
      - AttributeName: microFrontendId
        KeyType: RANGE
      SSESpecification:
        KMSMasterKeyId: alias/aws/dynamodb
        SSEEnabled: true
        SSEType: KMS
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled:
          Ref: EnableDynamoDBBackups
  DeploymentStore:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
      - AttributeName: deploymentId
        AttributeType: S
      - AttributeName: sk
        AttributeType: S
      BillingMode: PAY_PER_REQUEST
      KeySchema:
      - AttributeName: deploymentId
        KeyType: HASH
      - AttributeName: sk
        KeyType: RANGE
      TimeToLiveSpecification:
        AttributeName: expiresAt
        Enabled: true
      SSESpecification:
        KMSMasterKeyId: alias/aws/dynamodb
        SSEEnabled: true
        SSEType: KMS
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled:
          Ref: EnableDynamoDBBackups
  VersionStore:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
      - AttributeName: microFrontendId
        AttributeType: S
      - AttributeName: version
        AttributeType: S
      BillingMode: PAY_PER_REQUEST
      KeySchema:
      - AttributeName: microFrontendId
        KeyType: HASH
      - AttributeName: version
        KeyType: RANGE
      TimeToLiveSpecification:
        AttributeName: expiresAt
        Enabled: true
      SSESpecification:
        KMSMasterKeyId: alias/aws/dynamodb
        SSEEnabled: true
        SSEType: KMS
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled:
          Ref: EnableDynamoDBBackups
  ConsumerApi:
    Type: AWS::Serverless::Api
    Properties:
      Name: Frontend Service Discovery Consumer API
      StageName:
        Ref: Stage
      Cors:
        Fn::Sub: '''${AccessControlAllowOrigin}'''
      TracingEnabled: true
  StreamHandler:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: s3://solution-builders-ap-south-1/frontend-discovery-service/v1.3/a20a83ff9f2311bb340855d294ea8021
      Handler: app.handler
      Timeout: 60
      Environment:
        Variables:
          LOG_LEVEL:
            Ref: LogLevel
          REGION:
            Ref: AWS::Region
          POWERTOOLS_SERVICE_NAME: streamHandler
          CONSUMER_STORE:
            Ref: ConsumerViewStore
          PROJECT_STORE:
            Ref: ProjectStore
          FRONTEND_STORE:
            Ref: FrontendStore
          VERSION_STORE:
            Ref: VersionStore
          ALLOW_ORIGIN:
            Ref: AccessControlAllowOrigin
      Policies:
      - DynamoDBCrudPolicy:
          TableName:
            Ref: ConsumerViewStore
      - DynamoDBReadPolicy:
          TableName:
            Ref: ProjectStore
      - DynamoDBCrudPolicy:
          TableName:
            Ref: FrontendStore
      - DynamoDBCrudPolicy:
          TableName:
            Ref: VersionStore
      Events:
        ProjectStream:
          Type: DynamoDB
          Properties:
            Stream:
              Fn::GetAtt:
              - ProjectStore
              - StreamArn
            StartingPosition: TRIM_HORIZON
            Enabled: true
            FilterCriteria:
              Filters:
              - Pattern: '{"userIdentity": [ { "exists": false } ]}'
        FrontendStream:
          Type: DynamoDB
          Properties:
            Stream:
              Fn::GetAtt:
              - FrontendStore
              - StreamArn
            StartingPosition: TRIM_HORIZON
            Enabled: true
            FilterCriteria:
              Filters:
              - Pattern: '{"userIdentity": [ { "exists": false } ]}'
    Metadata:
      BuildMethod: esbuild
      BuildProperties:
        EntryPoints:
        - app.js
        Minify: false
        Sourcemap: false
        Target: es2020
      SamResourceId: StreamHandler
  ConsumerHandler:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: s3://solution-builders-ap-south-1/frontend-discovery-service/v1.3/640cedbe0ad9feef65d09b6ab9b60a13
      Handler: app.handler
      Timeout: 10
      Environment:
        Variables:
          LOG_LEVEL:
            Ref: LogLevel
          REGION:
            Ref: AWS::Region
          POWERTOOLS_SERVICE_NAME: consumerApi
          CONSUMER_STORE:
            Ref: ConsumerViewStore
          ALLOW_ORIGIN:
            Ref: AccessControlAllowOrigin
          COOKIE_SETTINGS:
            Ref: CookieSettings
      Policies:
      - DynamoDBReadPolicy:
          TableName:
            Ref: ConsumerViewStore
      Events:
        Any:
          Type: Api
          Properties:
            Path: /projects/{projectId}/microFrontends
            Method: GET
            RestApiId:
              Ref: ConsumerApi
    Metadata:
      BuildMethod: esbuild
      BuildProperties:
        EntryPoints:
        - app.js
        Minify: false
        Sourcemap: false
        Target: es2020
      SamResourceId: ConsumerHandler
  UserPool:
    Type: AWS::Cognito::UserPool
    Properties:
      AdminCreateUserConfig:
        AllowAdminCreateUserOnly: true
        InviteMessageTemplate:
          EmailMessage: Your Frontend Service Discovery username is {username} and
            the temporary password is {####}
          EmailSubject: Your temporary password for Frontend Service Discovery
      AutoVerifiedAttributes:
      - email
      UserPoolAddOns:
        AdvancedSecurityMode:
          Ref: CognitoAdvancedSecurity
      Policies:
        PasswordPolicy:
          MinimumLength: 8
          RequireLowercase: true
          RequireNumbers: true
          RequireSymbols: true
          RequireUppercase: true
  UserPoolClient:
    Type: AWS::Cognito::UserPoolClient
    Properties:
      UserPoolId:
        Ref: UserPool
      IdTokenValidity: 1
      AccessTokenValidity: 1
      RefreshTokenValidity: 1
      TokenValidityUnits:
        AccessToken: hours
        IdToken: hours
        RefreshToken: days
      SupportedIdentityProviders:
      - COGNITO
      ExplicitAuthFlows:
      - ALLOW_ADMIN_USER_PASSWORD_AUTH
      - ALLOW_REFRESH_TOKEN_AUTH
  CognitoUserPoolAdmin:
    Condition: CreateUser
    Type: AWS::Cognito::UserPoolUser
    Properties:
      Username:
        Ref: DefaultUserEmail
      DesiredDeliveryMediums:
      - EMAIL
      UserPoolId:
        Ref: UserPool
      UserAttributes:
      - Name: email
        Value:
          Ref: DefaultUserEmail
      - Name: email_verified
        Value: 'True'
  AdminAPI:
    Type: AWS::Serverless::Api
    Properties:
      StageName:
        Ref: Stage
      TracingEnabled: true
      Name: Frontend Service Discovery Admin API
      Auth:
        AddDefaultAuthorizerToCorsPreflight: false
        DefaultAuthorizer: Cognito
        Authorizers:
          Cognito:
            UserPoolArn:
              Fn::GetAtt:
              - UserPool
              - Arn
  AdminAPIHandler:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: s3://solution-builders-ap-south-1/frontend-discovery-service/v1.3/016aabe106df682b02eeb882c3cecc55
      Handler: app.handler
      Timeout: 10
      Environment:
        Variables:
          LOG_LEVEL:
            Ref: LogLevel
          ACCOUNT_ID:
            Ref: AWS::AccountId
          REGION:
            Ref: AWS::Region
          POWERTOOLS_SERVICE_NAME: AdminAPI
          PROJECT_STORE:
            Ref: ProjectStore
          FRONTEND_STORE:
            Ref: FrontendStore
          DEPLOYMENT_STORE:
            Ref: DeploymentStore
          VERSION_STORE:
            Ref: VersionStore
          DEPLOYMENT_STATE_MACHINE_ARN:
            Ref: DeploymentStateMachine
          DEPLOYMENT_STATE_MACHINE_NAME:
            Fn::GetAtt:
            - DeploymentStateMachine
            - Name
          DELETE_EXPIRY_MINUTES:
            Ref: DeleteExpiryMinutes
      Policies:
      - DynamoDBCrudPolicy:
          TableName:
            Ref: ProjectStore
      - DynamoDBCrudPolicy:
          TableName:
            Ref: FrontendStore
      - DynamoDBCrudPolicy:
          TableName:
            Ref: DeploymentStore
      - DynamoDBCrudPolicy:
          TableName:
            Ref: VersionStore
      - Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Action:
          - states:StartExecution
          Resource:
            Ref: DeploymentStateMachine
      - Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Action:
          - states:StopExecution
          Resource:
            Fn::Sub: arn:aws:states:${AWS::Region}:${AWS::AccountId}:execution:${DeploymentStateMachine.Name}:*
      Events:
        GetProjects:
          Type: Api
          Properties:
            Path: /projects
            Method: GET
            RestApiId:
              Ref: AdminAPI
        PostProjects:
          Type: Api
          Properties:
            Path: /projects
            Method: POST
            RestApiId:
              Ref: AdminAPI
        PatchProject:
          Type: Api
          Properties:
            Path: /projects/{projectId}
            Method: PATCH
            RestApiId:
              Ref: AdminAPI
        DeleteProject:
          Type: Api
          Properties:
            Path: /projects/{projectId}
            Method: DELETE
            RestApiId:
              Ref: AdminAPI
        DeleteMicroFrontend:
          Type: Api
          Properties:
            Path: /projects/{projectId}/microFrontends/{microFrontendId}
            Method: DELETE
            RestApiId:
              Ref: AdminAPI
        GetMicroFrontends:
          Type: Api
          Properties:
            Path: /projects/{projectId}/microFrontends
            Method: GET
            RestApiId:
              Ref: AdminAPI
        GetMicroFrontendVersions:
          Type: Api
          Properties:
            Path: /projects/{projectId}/microFrontends/{microFrontendId}/versions
            Method: GET
            RestApiId:
              Ref: AdminAPI
        PostMicroFrontends:
          Type: Api
          Properties:
            Path: /projects/{projectId}/microFrontends
            Method: POST
            RestApiId:
              Ref: AdminAPI
        PatchMicroFrontend:
          Type: Api
          Properties:
            Path: /projects/{projectId}/microFrontends/{microFrontendId}
            Method: PATCH
            RestApiId:
              Ref: AdminAPI
        PostMicroFrontendVersion:
          Type: Api
          Properties:
            Path: /projects/{projectId}/microFrontends/{microFrontendId}/versions
            Method: POST
            RestApiId:
              Ref: AdminAPI
        PostDeployment:
          Type: Api
          Properties:
            Path: /projects/{projectId}/microFrontends/{microFrontendId}/deployment
            Method: POST
            RestApiId:
              Ref: AdminAPI
        DeleteDeployment:
          Type: Api
          Properties:
            Path: /projects/{projectId}/microFrontends/{microFrontendId}/deployment/{deploymentId}
            Method: DELETE
            RestApiId:
              Ref: AdminAPI
    Metadata:
      BuildMethod: esbuild
      BuildProperties:
        EntryPoints:
        - app.js
        Minify: false
        Sourcemap: false
        Target: es2020
      SamResourceId: AdminAPIHandler
  StateMachineRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal:
            Service:
              Fn::Sub: states.${AWS::Region}.amazonaws.com
          Action: sts:AssumeRole
      Policies:
      - PolicyName: dynamodb
        PolicyDocument:
          Statement:
          - Effect: Allow
            Action:
            - dynamodb:GetItem
            - dynamodb:UpdateItem
            Resource:
            - Fn::Sub: arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${FrontendStore}
            - Fn::GetAtt:
              - DeploymentStore
              - Arn
  DeploymentStateMachine:
    Type: AWS::StepFunctions::StateMachine
    Properties:
      Definition:
        Fn::Transform:
          Name: AWS::Include
          Parameters:
            Location: s3://solution-builders-ap-south-1/frontend-discovery-service/v1.3/791e8dadf4cb8e49ee3970ab7b8cfb3a
      RoleArn:
        Fn::GetAtt:
        - StateMachineRole
        - Arn
Outputs:
  ConsumerApi:
    Description: Consumer Api API Gateway endpoint URL
    Value:
      Fn::Sub: https://${ConsumerApi}.execute-api.${AWS::Region}.amazonaws.com/${Stage}
  AdminApi:
    Description: Admin API Gateway endpoint URL
    Value:
      Fn::Sub: https://${AdminAPI}.execute-api.${AWS::Region}.amazonaws.com/${Stage}
  CognitoUserPoolArn:
    Description: Cognito User Pool Arn
    Value:
      Fn::GetAtt:
      - UserPool
      - Arn
  CognitoUserPoolID:
    Description: Cognito User Pool Id
    Value:
      Ref: UserPool
  CognitoWebClientID:
    Description: Cognito User Pool Client Id
    Value:
      Ref: UserPoolClient
  Region:
    Description: The AWS region where the infrastructure is deployed
    Value:
      Ref: AWS::Region
  SolutionVersion:
    Value:
      Fn::FindInMap:
      - Solution
      - Constants
      - Version
