service: heisenberg-user
package:
  excludeDevDependencies: true
  individually: true
  exclude:
    - database/**
    - docker/**
    - openapi/**
    - .serverless/**
    - serverless/**
    - src/**
    - tests/**
    - .env
    - .env.example
    - env.yml.example
    - "*.env.yml"
    - .gitlab-ci.yml
    - .gitignore
    - README.md
    - node_modules/**
    - tests/**

plugins:
  - serverless-jetpack
  - serverless-import-apigateway

app: heisenberg-user

provider:
  name: aws
  runtime: nodejs14.x
  stage: dev
  region: eu-west-1
  deploymentBucket:
    name: heisenberg-serverless-deployments-${self:custom.stage}
  logs:
    restApi: true

custom:
  # General
  stage: "${opt:stage, self:provider.stage}"
  region: ${opt:region, self:provider.region}
  accountId: ${file(./serverless/helpers/account-id.js):getAccountId}
  # API Gateway
  importApiGateway:
    name: admin-${self:custom.stage} # Required
    path: /
  # Authorizer
  superAdminAuthorizer: !ImportValue ${self:custom.stage}AdminApiGatewaySuperAdminAuthorizerId
  prescriptionAuthorizer: !ImportValue ${self:custom.stage}AdminApiGatewayPrescriptionAuthorizerId
  fulfilmentAuthorizer: !ImportValue ${self:custom.stage}AdminApiGatewayFulfilmentAuthorizerId
  packagingAuthorizer: !ImportValue ${self:custom.stage}AdminApiGatewayPackagingAuthorizerId
  # RDS
  rdsUser: ${file(${self:custom.stage}.env.yml):db_details.RDS_USER}
  rdsPass: ${file(${self:custom.stage}.env.yml):db_details.RDS_PASS}
  rdsDBName: ${file(${self:custom.stage}.env.yml):db_details.RDS_DB}
  # Layers
  authorizeLayer: arn:aws:lambda:${self:custom.region}:${self:custom.accountId}:layer:authorize-${self:custom.stage}:${file(${self:custom.stage}.env.yml):layer-versions.AUTHORIZE}
  awsServicesLayer: arn:aws:lambda:${self:custom.region}:${self:custom.accountId}:layer:aws-services-${self:custom.stage}:${file(${self:custom.stage}.env.yml):layer-versions.AWS_SERVICES}
  databaseLayer: arn:aws:lambda:${self:custom.region}:${self:custom.accountId}:layer:database-${self:custom.stage}:${file(${self:custom.stage}.env.yml):layer-versions.DATABASE}
  generalUtilsLayer: arn:aws:lambda:${self:custom.region}:${self:custom.accountId}:layer:general-utils-${self:custom.stage}:${file(${self:custom.stage}.env.yml):layer-versions.GENERAL_UTILS}
  emailLayer: arn:aws:lambda:${self:custom.region}:${self:custom.accountId}:layer:email-${self:custom.stage}:${file(${self:custom.stage}.env.yml):layer-versions.EMAIL}
  

functions:
  UserCreateFunction:
    handler: src/user/create/handler.handle
    name: user-create-${self:custom.stage}
    memorySize: 128
    timeout: 6
    environment: ${file(${self:custom.stage}.env.yml):admin-cognito-lambda}
    role: UserCreateRole
    events:
      - http: 
          path: user
          method: post
          cors:
            origin: '*'
            headers: 
              - Content-Type
              - X-Amz-Date
              - Authorization
              - X-Api-Key
              - X-Amz-Security-Token
              - AccessToken
              - IdToken
            allowCredentials: false
          authorizer:
            type: TOKEN
            authorizerId: ${self:custom.superAdminAuthorizer}
    layers:
      - ${self:custom.generalUtilsLayer}
      - ${self:custom.awsServicesLayer}
    package:  
      include:
        - src/user/create/**
    dependsOn:
      - VPCPermissionPolicy

  UserDeleteFunction:
    handler: src/user/delete/handler.handle
    name: user-delete-${self:custom.stage}
    memorySize: 128
    timeout: 6
    environment: ${file(${self:custom.stage}.env.yml):admin-cognito-lambda}
    role: UserDeleteRole
    events:
      - http: 
          path: user/{username}
          method: delete
          cors:
            origin: '*'
            headers: 
              - Content-Type
              - X-Amz-Date
              - Authorization
              - X-Api-Key
              - X-Amz-Security-Token
              - AccessToken
              - IdToken
            allowCredentials: false
          authorizer:
            type: TOKEN
            authorizerId: ${self:custom.superAdminAuthorizer}
    layers:
      - ${self:custom.generalUtilsLayer}
      - ${self:custom.awsServicesLayer}
    package:  
      include:
        - src/user/delete/**
    dependsOn:
      - VPCPermissionPolicy

  UserListFunction:
    handler: src/user/list/handler.handle
    name: user-list-${self:custom.stage}
    memorySize: 128
    timeout: 6
    environment: ${file(${self:custom.stage}.env.yml):admin-cognito-lambda}
    role: UserListRole
    events:
      - http: 
          path: user
          method: get
          cors:
            origin: '*'
            headers: 
              - Content-Type
              - X-Amz-Date
              - Authorization
              - X-Api-Key
              - X-Amz-Security-Token
              - AccessToken
              - IdToken
            allowCredentials: false
          authorizer:
            type: TOKEN
            authorizerId: ${self:custom.superAdminAuthorizer}
    layers:
      - ${self:custom.generalUtilsLayer}
      - ${self:custom.awsServicesLayer}
    package:  
      include:
        - src/user/list/**
    dependsOn:
      - VPCPermissionPolicy

  UserEditFunction:
    handler: src/user/edit/handler.handle
    name: user-edit-${self:custom.stage}
    memorySize: 128
    timeout: 6
    environment: ${file(${self:custom.stage}.env.yml):admin-cognito-lambda}
    role: UserEditRole
    events:
      - http: 
          path: user/{username}
          method: put
          cors:
            origin: '*'
            headers: 
              - Content-Type
              - X-Amz-Date
              - Authorization
              - X-Api-Key
              - X-Amz-Security-Token
              - AccessToken
              - IdToken
            allowCredentials: false
          authorizer:
            type: TOKEN
            authorizerId: ${self:custom.superAdminAuthorizer}
    layers:
      - ${self:custom.generalUtilsLayer}
      - ${self:custom.awsServicesLayer}
    package:  
      include:
        - src/user/edit/**
    dependsOn:
      - VPCPermissionPolicy

  UserViewFunction:
    handler: src/user/view/handler.handle
    name: user-view-${self:custom.stage}
    memorySize: 128
    timeout: 6
    environment: ${file(${self:custom.stage}.env.yml):admin-cognito-lambda}
    role: UserViewRole
    events:
      - http: 
          path: user/{username}
          method: get
          cors:
            origin: '*'
            headers: 
              - Content-Type
              - X-Amz-Date
              - Authorization
              - X-Api-Key
              - X-Amz-Security-Token
              - AccessToken
              - IdToken
            allowCredentials: false
          authorizer:
            type: TOKEN
            authorizerId: ${self:custom.superAdminAuthorizer}
    layers:
      - ${self:custom.generalUtilsLayer}
      - ${self:custom.awsServicesLayer}
    package:  
      include:
        - src/user/view/**
    dependsOn:
      - VPCPermissionPolicy

resources:
  Resources:
    UserCreateRole:
      Type: AWS::IAM::Role
      Properties:
        RoleName: ${self:service}-UserCreateRole-${self:custom.stage}
        AssumeRolePolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - lambda.amazonaws.com
              Action: sts:AssumeRole
    UserEditRole:
      Type: AWS::IAM::Role
      Properties:
        RoleName: ${self:service}-UserEditRole-${self:custom.stage}
        AssumeRolePolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - lambda.amazonaws.com
              Action: sts:AssumeRole
    UserDeleteRole:
      Type: AWS::IAM::Role
      Properties:
        RoleName: ${self:service}-UserDeleteRole-${self:custom.stage}
        AssumeRolePolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - lambda.amazonaws.com
              Action: sts:AssumeRole
    UserListRole:
      Type: AWS::IAM::Role
      Properties:
        RoleName: ${self:service}-UserListRole-${self:custom.stage}
        AssumeRolePolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - lambda.amazonaws.com
              Action: sts:AssumeRole
    UserViewRole:
      Type: AWS::IAM::Role
      Properties:
        RoleName: ${self:service}-UserViewRole-${self:custom.stage}
        AssumeRolePolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - lambda.amazonaws.com
              Action: sts:AssumeRole

    # Policies
    ViewUserPolicy:
      Type: AWS::IAM::Policy
      Properties:
        PolicyName: ${self:service}-ViewUser-${self:custom.stage}
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Action:
                - cognito-idp:GetUser
              Resource:
                - {"Fn::ImportValue": "${self:custom.stage}AdminUserPool::ARN"}
        Roles:
          - Ref: UserViewRole

    ListUserPolicy:
      Type: AWS::IAM::Policy
      Properties:
        PolicyName: ${self:service}-ListUser-${self:custom.stage}
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Action:
                - cognito-idp:ListUsers
                - cognito-idp:ListGroupsForUser
              Resource:
                - {"Fn::ImportValue": "${self:custom.stage}AdminUserPool::ARN"}
        Roles:
          - Ref: UserListRole

    CreateUserPolicy:
      Type: AWS::IAM::Policy
      Properties:
        PolicyName: ${self:service}-CreateUser-${self:custom.stage}
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Action:
                - cognito-idp:AdminCreateUser
                - cognito-idp:AddUserToGroup
              Resource:
                - {"Fn::ImportValue": "${self:custom.stage}AdminUserPool::ARN"}
        Roles:
          - Ref: UserCreateRole

    EditUserPolicy:
      Type: AWS::IAM::Policy
      Properties:
        PolicyName: ${self:service}-EditUser-${self:custom.stage}
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Action:
                - cognito-idp:UpdateUserAttributes
              Resource:
                - {"Fn::ImportValue": "${self:custom.stage}AdminUserPool::ARN"}
        Roles:
          - Ref: UserEditRole

    DeleteUserPolicy:
      Type: AWS::IAM::Policy
      Properties:
        PolicyName: ${self:service}-DeleteUser-${self:custom.stage}
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Action:
                - cognito-idp:AdminDisableUser
              Resource:
                - {"Fn::ImportValue": "${self:custom.stage}AdminUserPool::ARN"}
        Roles:
          - Ref: UserDeleteRole
    
    LoggingPermissionPolicy:
      Type: AWS::IAM::Policy
      Properties:
        PolicyName: ${self:service}-LoggingPermission-${self:custom.stage}
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Action:
                - logs:CreateLogGroup
                - logs:CreateLogStream
                - logs:PutLogEvents
              Resource:
                - Fn::Join:
                    - ""
                    - - "arn:aws:logs:${self:custom.region}:"
                      - Ref: "AWS::AccountId"
                      - ":log-group:/aws/lambda/*"
        Roles:
          - Ref: UserCreateRole
          - Ref: UserEditRole
          - Ref: UserDeleteRole
          - Ref: UserListRole
          - Ref: UserViewRole
          
    VPCPermissionPolicy:
      Type: AWS::IAM::Policy
      Properties:
        PolicyName: ${self:service}-VPCPermission-${self:custom.stage}
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Action:
                - ec2:DescribeNetworkInterfaces
                - ec2:CreateNetworkInterface
                - ec2:DeleteNetworkInterface
                - ec2:DescribeInstances
                - ec2:AttachNetworkInterface
              Resource: "*"
        Roles:
          - Ref: UserCreateRole
          - Ref: UserEditRole
          - Ref: UserDeleteRole
          - Ref: UserListRole
          - Ref: UserViewRole
