AWSTemplateFormatVersion: '2010-09-09'
Description: Cognito Stack for Admin users
Parameters:
  EnvironmentName:
    Description: An environment name that is prefixed to resource names
    Type: String

Resources:
  UserPool:
    Type: "AWS::Cognito::UserPool"
    Properties:
      UserPoolName: !Sub admin-user-pool-${EnvironmentName}
      AutoVerifiedAttributes:
        - email
        - phone_number
      UsernameAttributes: [email]
      MfaConfiguration: "OFF"
      SmsConfiguration:
        ExternalId: !Sub admin-external-${EnvironmentName}
        SnsCallerArn: !ImportValue CognitoSNSRoleARN
      Schema:
        - Name: name
          AttributeDataType: String
          Mutable: true
          Required: true
        - Name: email
          AttributeDataType: String
          Mutable: false
          Required: true
        - Name: phone_number
          AttributeDataType: String
          Mutable: true
          Required: true
  
  # Creates a User Pool Client to be used by the identity pool
  UserPoolClient:
    Type: "AWS::Cognito::UserPoolClient"
    Properties:
      ClientName: !Sub admin-client-${EnvironmentName}
      GenerateSecret: false
      UserPoolId: !Ref UserPool
  
  # Creates a federeated Identity pool
  IdentityPool:
    Type: "AWS::Cognito::IdentityPool"
    Properties:
      IdentityPoolName: !Sub adminIdentity-${EnvironmentName}
      AllowUnauthenticatedIdentities: true
      CognitoIdentityProviders: 
        - ClientId: !Ref UserPoolClient
          ProviderName: !GetAtt UserPool.ProviderName

  # Create a role for unauthorized acces to AWS resources. Very limited access. Only allows users in the previously created Identity Pool
  CognitoUnAuthorizedRole:
    Type: "AWS::IAM::Role"
    Properties:
      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 IdentityPool
              "ForAnyValue:StringLike":
                "cognito-identity.amazonaws.com:amr": unauthenticated
      Policies:
        - PolicyName: !Sub "CognitoAdminUnauthorizedPolicy-${EnvironmentName}"
          PolicyDocument: 
            Version: "2012-10-17"
            Statement: 
              - Effect: "Allow"
                Action:
                  - "mobileanalytics:PutEvents"
                  - "cognito-sync:*"
                Resource: "*"

  # Create a role for authorized acces to AWS resources. Control what your user can access. This example only allows Lambda invokation
  # Only allows users in the previously created Identity Pool
  CognitoAuthorizedRole:
    Type: "AWS::IAM::Role"
    Properties:
      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 IdentityPool
              "ForAnyValue:StringLike":
                "cognito-identity.amazonaws.com:amr": authenticated
      Policies:
        - PolicyName: !Sub "CognitoAdminAuthorizedPolicy-${EnvironmentName}"
          PolicyDocument: 
            Version: "2012-10-17"
            Statement: 
              - Effect: "Allow"
                Action:
                  - "mobileanalytics:PutEvents"
                  - "cognito-sync:*"
                  - "cognito-identity:*"
                Resource: "*"
              - Effect: "Allow"
                Action:
                  - "lambda:InvokeFunction"
                Resource: "*"
  
  # Assigns the roles to the Identity Pool
  IdentityPoolRoleMapping:
    Type: "AWS::Cognito::IdentityPoolRoleAttachment"
    Properties:
      IdentityPoolId: !Ref IdentityPool
      Roles:
        authenticated: !GetAtt CognitoAuthorizedRole.Arn
        unauthenticated: !GetAtt CognitoUnAuthorizedRole.Arn

  
  SuperAdminUserGroup:
    Type: AWS::Cognito::UserPoolGroup
    Properties: 
      Description: "Super admin users can perform all actions in the system."
      GroupName: "SuperAdmin"
      UserPoolId: !Ref UserPool

  PrescriptionUserGroup:
    Type: AWS::Cognito::UserPoolGroup
    Properties: 
      Description: "Prescription Users can intake and manage prescriptions."
      GroupName: "Prescription"
      UserPoolId: !Ref UserPool

  FulfilmentUserGroup:
    Type: AWS::Cognito::UserPoolGroup
    Properties: 
      Description: "Fulfilment users can manage orders and medicine batches."
      GroupName: "Fulfilment"
      UserPoolId: !Ref UserPool

  PackagingUserGroup:
    Type: AWS::Cognito::UserPoolGroup
    Properties: 
      Description: "Packaging users can manage orders and medicine batches."
      GroupName: "Packaging"
      UserPoolId: !Ref UserPool
  
  CustomerUserGroup:
    Type: AWS::Cognito::UserPoolGroup
    Properties: 
      Description: "Customer users have more access to prescription creation features."
      GroupName: "Customer"
      UserPoolId: !Ref UserPool

Outputs:
  UserPoolId:
    Value: !Ref UserPool
    Export:
      Name: !Sub "${EnvironmentName}AdminUserPool::Id"
  UserPoolARN:
    Value: !GetAtt UserPool.Arn
    Export:
      Name: !Sub "${EnvironmentName}AdminUserPool::ARN"
  UserPoolClientId:
    Value: !Ref UserPoolClient
    Export:
      Name: !Sub "${EnvironmentName}AdminUserPoolClient::Id"
  IdentityPoolId:
    Value: !Ref IdentityPool
    Export:
      Name: !Sub "${EnvironmentName}AdminIdentityPool::Id"