locals {
  read_enabled        = length(var.read_arns) == 0 ? [] : ["Allow external read IAM entity"]
  upload_enabled      = length(var.upload_arns) == 0 ? [] : ["Allow external upload IAM entity"]
  delete_enabled      = length(var.delete_arns) == 0 ? [] : ["Allow external delete IAM entity"]
  full_access_enabled = length(var.full_access_arns) == 0 ? [] : ["Allow external delete IAM entity"]
  ses_account_id      = var.ses_account_id != "" ? [var.ses_account_id] : []
}

data "aws_iam_policy_document" "main" {
  version                 = "2012-10-17"
  source_policy_documents = var.encryption_in_transit ? [module.default_bucket_policy.document.json] : null

  dynamic "statement" {
    for_each = local.delete_enabled
    content {
      sid    = "Explicit allow for external delete"
      effect = "Allow"
      actions = [
        "s3:DeleteObject",
        "s3:DeleteObjectTagging",
        "s3:DeleteObjectVersion",
        "s3:DeleteObjectVersionTagging"
      ]
      resources = sort([
        "${var.template_bucket_arn}/*",
        var.template_bucket_arn
      ])
      principals {
        type        = "AWS"
        identifiers = sort(var.delete_arns)
      }
    }
  }

  dynamic "statement" {
    for_each = local.read_enabled
    content {
      sid    = "Explicit allow for external read"
      effect = "Allow"
      actions = sort([
        "s3:GetObject",
        "s3:ListBucket",
        "s3:GetObjectTagging",
        "s3:GetObjectVersion",
        "s3:GetObjectVersionTagging"
      ])
      resources = sort([
        "${var.template_bucket_arn}/*",
        var.template_bucket_arn
      ])
      principals {
        type        = "AWS"
        identifiers = sort(var.read_arns)
      }
    }
  }

  dynamic "statement" {
    for_each = local.upload_enabled
    content {
      sid    = "Explicit allow for external write"
      effect = "Allow"
      actions = sort([
        "s3:ListMultipartUploadParts",
        "s3:AbortMultipartUpload",
        "s3:ListBucketMultipartUploads",
        "s3:PutObjectVersionTagging",
        "s3:PutObjectTagging",
        "s3:PutObject",
        "s3:PutObjectAcl",
      ])
      resources = sort([
        "${var.template_bucket_arn}/*",
        var.template_bucket_arn
      ])
      principals {
        type        = "AWS"
        identifiers = sort(var.upload_arns)
      }
    }
  }

  dynamic "statement" {
    for_each = local.full_access_enabled
    content {
      sid    = "Explicit allow for full access"
      effect = "Allow"
      actions = sort([
        "s3:GetObject",
        "s3:ListBucket",
        "s3:GetObjectTagging",
        "s3:GetObjectVersion",
        "s3:GetObjectVersionTagging",
        "s3:ListMultipartUploadParts",
        "s3:AbortMultipartUpload",
        "s3:ListBucketMultipartUploads",
        "s3:PutObjectVersionTagging",
        "s3:PutObjectTagging",
        "s3:PutObject",
        "s3:PutObjectAcl",
        "s3:DeleteObject",
        "s3:DeleteObjectTagging",
        "s3:DeleteObjectVersion",
        "s3:DeleteObjectVersionTagging",
      ])
      resources = sort([
        "${var.template_bucket_arn}/*",
        var.template_bucket_arn
      ])
      principals {
        type        = "AWS"
        identifiers = sort(var.full_access_arns)
      }
    }
  }

  dynamic "statement" {
    for_each = var.custom_path_role_permissions
    content {
      sid    = "Custom permissions for ${statement.value.arn} path ${statement.value.path}"
      effect = "Allow"
      actions = sort(concat(statement.value.read ? [
        "s3:GetObject",
        "s3:ListBucket",
        "s3:GetObjectTagging",
        "s3:GetObjectVersion",
        "s3:GetObjectVersionTagging"
        ] : [],
        statement.value.write ? [
          "s3:ListMultipartUploadParts",
          "s3:AbortMultipartUpload",
          "s3:ListBucketMultipartUploads",
          "s3:PutObjectVersionTagging",
          "s3:PutObjectTagging",
          "s3:PutObject",
          "s3:PutObjectAcl",
        ] : [],
        statement.value.delete ? [
          "s3:DeleteObject",
          "s3:DeleteObjectTagging",
          "s3:DeleteObjectVersion",
          "s3:DeleteObjectVersionTagging"
        ] : []
      ))
      resources = sort([
        "${var.template_bucket_arn}/${statement.value.path}*",
        var.template_bucket_arn
      ])
      principals {
        type        = "AWS"
        identifiers = [statement.value.arn]
      }
    }
  }

  dynamic "statement" {
    for_each = local.ses_account_id
    content {
      sid    = "Allow SES to write"
      effect = "Allow"
      actions = [
        "s3:PutObject",
      ]
      resources = [
        "${var.template_bucket_arn}/*"
      ]
      principals {
        type        = "Service"
        identifiers = ["ses.amazonaws.com"]
      }
      condition {
        test     = "StringEquals"
        values   = [statement.value]
        variable = "aws:Referer"
      }
    }
  }

  # Replication statements
  dynamic "statement" {
    for_each = length(var.replication_roles) > 0 ? ["Enabled"] : []
    content {
      sid    = "ReplicationPolicy1"
      effect = "Allow"
      actions = [
        "s3:ReplicateDelete",
        "s3:ReplicateObject",
        "s3:ObjectOwnerOverrideToBucketOwner",
      ]
      resources = ["${var.template_bucket_arn}/*"]
      principals {
        type        = "AWS"
        identifiers = var.replication_roles
      }
    }
  }

  dynamic "statement" {
    for_each = length(var.replication_roles) > 0 ? ["Enabled"] : []
    content {
      sid    = "ReplicationPolicy2"
      effect = "Allow"
      actions = [
        "s3:List*",
        "s3:GetBucketVersioning",
        "s3:PutBucketVersioning",
      ]
      resources = ["${var.template_bucket_arn}"]
      principals {
        type        = "AWS"
        identifiers = var.replication_roles
      }
    }
  }
}

module "default_bucket_policy" {
  source              = "../default_policy_template"
  template_bucket_arn = var.template_bucket_arn
}
