  Mappings:
    CognitoUserPoolMap:
      live:
        id: "eu-west-1_QZu5coAL8"
      test:
        id: "eu-west-1_bjHznr2j7"
      devel:
        id: "eu-west-1_lJBEwt8qW"

  Conditions:
    ShouldProvisionS3andCognito:
      Fn::Or:
        - Fn::Equals:
          - live
          - ${{self:provider.stage}}
        - Fn::Equals:
          - test
          - ${{self:provider.stage}}
        - Fn::Equals:
          - devel
          - ${{self:provider.stage}}

  Resources:

    CognitoUserPool:
      Type: AWS::Cognito::UserPool
      Condition: ShouldProvisionS3andCognito
      Properties:
        AccountRecoverySetting:
          RecoveryMechanisms: 
            - Name: verified_email
              Priority: 1
        AdminCreateUserConfig:
          AllowAdminCreateUserOnly: true
        AutoVerifiedAttributes: 
          - email
        UserPoolName: ${{self:custom.userPoolName}}
        LambdaConfig:
          PostConfirmation: 
            Fn::GetAtt: [CognitoPostConfirmationLambdaFunction, Arn]
          PostAuthentication:
            Fn::GetAtt: [CognitoPostAuthenticationLambdaFunction, Arn]
        Policies:
          PasswordPolicy:
            MinimumLength: 12
            RequireLowercase: true
            RequireNumbers: true
            RequireSymbols: false
            RequireUppercase: true
            TemporaryPasswordValidityDays: 30
        Schema:
          # AWS prefixes custom attributes name with 'custom:'
          - Name: "company"
            # Custom attributes cannot be required
            Required: false
            AttributeDataType: String
            Mutable: true
        UsernameAttributes:
          - email

    CognitoUserPoolClient:
      Type: AWS::Cognito::UserPoolClient
      Condition: ShouldProvisionS3andCognito
      Properties:
        ClientName: ${{self:custom.apiName}}-user-pool-client
        UserPoolId:
          Ref: CognitoUserPool
        EnableTokenRevocation: true
        AccessTokenValidity: 1 # hours
        IdTokenValidity: 1 # hours
        RefreshTokenValidity: 1 # days

    CognitoIdentityPool:
      Type: AWS::Cognito::IdentityPool
      Condition: ShouldProvisionS3andCognito
      Properties:
        IdentityPoolName: ${{self:custom.apiName}}-identity-pool
        AllowUnauthenticatedIdentities: false
        CognitoIdentityProviders:
          - ClientId:
              Ref: CognitoUserPoolClient
            ProviderName:
              Fn::GetAtt: [CognitoUserPool, ProviderName]

    CognitoIdentityPoolRoles:
      Type: AWS::Cognito::IdentityPoolRoleAttachment
      Condition: ShouldProvisionS3andCognito
      Properties:
        IdentityPoolId:
          Ref: CognitoIdentityPool
        Roles:
          authenticated:
            Fn::GetAtt: [CognitoAuthRole, Arn]
          unauthenticated:
            Fn::GetAtt: [CognitoUnauthRole, Arn]

    CognitoAuthRole:
      Type: AWS::IAM::Role
      Condition: ShouldProvisionS3andCognito
      Properties:
        RoleName: ${{self:custom.apiName}}-cognito-auth-role
        # TODO: meaning of this Path?
        Path: /
        AssumeRolePolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: "Allow"
              Principal:
                Federated: "cognito-identity.amazonaws.com"
              Action:
                - "sts:AssumeRoleWithWebIdentity"
              Condition:
                StringEquals:
                  "cognito-identity.amazonaws.com:aud":
                    Ref: CognitoIdentityPool
                "ForAnyValue:StringLike":
                  "cognito-identity.amazonaws.com:amr": authenticated
        Policies:
          - PolicyName: "CognitoAuthorizedPolicy"
            PolicyDocument:
              Version: "2012-10-17"
              Statement:
                - Effect: "Allow"
                  Action:
                    - "mobileanalytics:PutEvents"
                    - "cognito-sync:*"
                    - "cognito-identity:*"
                  Resource: "*"
                - Effect: "Allow"
                  Action:
                    - "execute-api:Invoke"
                  Resource: "*"

    CognitoUnauthRole:
      Type: AWS::IAM::Role
      Condition: ShouldProvisionS3andCognito
      Properties:
        RoleName: ${{self:custom.apiName}}-cognito-unauth-role
        Path: /
        AssumeRolePolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: "Allow"
              Principal:
                Federated: "cognito-identity.amazonaws.com"
              Action:
                - "sts:AssumeRoleWithWebIdentity"
              Condition:
                StringEquals:
                  "cognito-identity.amazonaws.com:aud":
                    Ref: CognitoIdentityPool
                "ForAnyValue:StringLike":
                  "cognito-identity.amazonaws.com:amr": unauthenticated
        Policies:
          - PolicyName: "CognitoUnauthorizedPolicy"
            PolicyDocument:
              Version: "2012-10-17"
              Statement:
                - Effect: "Allow"
                  Action:
                    - "mobileanalytics:PutEvents"
                    - "cognito-sync:Describe*"
                    - "cognito-sync:Get*"
                    - "cognito-identity:*"
                  Resource: "*"

    CognitoUserPoolLambdaInvokePermission:
      Type: "AWS::Lambda::Permission"
      Condition: ShouldProvisionS3andCognito
      Properties:
        Action: "lambda:invokeFunction"
        Principal: cognito-idp.amazonaws.com
        FunctionName: !GetAtt CognitoPostConfirmationLambdaFunction.Arn
        SourceArn: !GetAtt CognitoUserPool.Arn

    CognitoUserPoolLambdaInvokePermission2:
      Type: "AWS::Lambda::Permission"
      Condition: ShouldProvisionS3andCognito
      Properties:
        Action: "lambda:invokeFunction"
        Principal: cognito-idp.amazonaws.com
        FunctionName: !GetAtt CognitoPostAuthenticationLambdaFunction.Arn
        SourceArn: !GetAtt CognitoUserPool.Arn
