################
# KMS — resolve AWS-managed S3 key
################

data "aws_kms_alias" "s3" {
  name = "alias/aws/s3"
}

################
# S3 — File Uploads
################

# Bucket for user-uploaded files via presigned URLs.
# The Coda server generates presigned PUT/GET URLs; the client uploads directly to S3.
module "s3_ows_coda_uploads" {
  source             = "git@github.com:theorchard/terraform-s3.git//modules/s3_bucket?ref=3.15.7"
  env                = var.environment
  bucket_name        = "ows-coda-uploads"
  application_family = var.application_family

  apply_server_side_encryption_by_default = {
    sse_algorithm     = "aws:kms"
    kms_master_key_id = data.aws_kms_alias.s3.target_key_arn
  }

  block_public_access = true
}

################
# S3 — CORS
################

# Allow browser-based uploads/downloads from the Coda client via presigned URLs.
resource "aws_s3_bucket_cors_configuration" "ows_coda_uploads_cors" {
  bucket = module.s3_ows_coda_uploads.s3_bucket_name_output

  cors_rule {
    allowed_headers = ["*"]
    allowed_methods = ["PUT", "GET"]
    allowed_origins = [
      "https://prod-ows-coda.theorchard.io",
    ]
    expose_headers  = ["ETag"]
    max_age_seconds = 3600
  }
}

################
# S3 — Lifecycle
################

resource "aws_s3_bucket_lifecycle_configuration" "ows_coda_uploads_lifecycle" {
  bucket = module.s3_ows_coda_uploads.s3_bucket_name_output

  rule {
    id     = "archive-uploads"
    status = "Enabled"

    filter {}

    transition {
      days          = 30
      storage_class = "STANDARD_IA"
    }

    transition {
      days          = 90
      storage_class = "GLACIER"
    }

    transition {
      days          = 365
      storage_class = "DEEP_ARCHIVE"
    }
  }

  rule {
    id     = "abort-incomplete-multipart-uploads"
    status = "Enabled"

    filter {}

    abort_incomplete_multipart_upload {
      days_after_initiation = 7
    }
  }
}


################
# IAM — S3 access for Fargate task
################

data "aws_iam_policy_document" "ows_coda_uploads_policy_document" {
  # Allow the server to generate presigned PUT/GET URLs and manage objects.
  statement {
    effect = "Allow"

    actions = [
      "s3:GetObject",
      "s3:PutObject",
      "s3:DeleteObject",
    ]

    resources = [
      "${local.s3_arn}/*",
    ]
  }

  # Allow listing bucket contents (needed for management/cleanup).
  statement {
    effect = "Allow"

    actions = [
      "s3:GetBucketLocation",
      "s3:ListBucket",
    ]

    resources = [
      local.s3_arn,
    ]
  }

  # SSE-KMS: the Fargate task signs presigned URLs, so it needs KMS
  # permissions to encrypt (PUT) and decrypt (GET) objects.
  statement {
    effect = "Allow"

    actions = [
      "kms:GenerateDataKey",
      "kms:Decrypt",
    ]

    resources = [
      data.aws_kms_alias.s3.target_key_arn,
    ]
  }
}

resource "aws_iam_policy" "ows_coda_uploads_policy" {
  name        = "${var.environment}-${var.service_name}-uploads-policy"
  description = "Allow ows-coda Fargate task to manage upload objects via presigned URLs"
  policy      = data.aws_iam_policy_document.ows_coda_uploads_policy_document.json
}

resource "aws_iam_role_policy_attachment" "ows_coda_uploads_policy_attachment" {
  role       = module.ows_coda_fargate_environment.fargate_task_iam_role_name
  policy_arn = aws_iam_policy.ows_coda_uploads_policy.arn
}
