Files
rentall-app/backend/S3.md
2025-12-12 11:47:16 -05:00

4.2 KiB

AWS S3 Image Storage Integration Plan

Overview

Integrate AWS S3 for image storage using direct-to-S3 uploads with presigned URLs. Frontend will upload directly to S3, reducing backend load. Images will use a hybrid access model: public URLs for profiles/items/forum, private signed URLs for messages and condition-checks.

Architecture

Frontend                          Backend                         AWS S3
   │                                 │                               │
   │  1. POST /api/upload/presign    │                               │
   │────────────────────────────────>│                               │
   │                                 │  2. Generate presigned URL    │
   │  3. Return {uploadUrl, key}     │                               │
   │<────────────────────────────────│                               │
   │                                 │                               │
   │  4. PUT file directly to S3     │                               │
   │────────────────────────────────────────────────────────────────>│
   │                                 │                               │
   │  5. POST /api/upload/confirm    │                               │
   │────────────────────────────────>│  6. Verify object exists      │
   │                                 │──────────────────────────────>│
   │  7. Return confirmation         │                               │
   │<────────────────────────────────│                               │

S3 Bucket Structure

s3://village-share-{env}/
├── profiles/{uuid}.{ext}           # Public access
├── items/{uuid}.{ext}              # Public access
├── forum/{uuid}.{ext}              # Public access
├── messages/{uuid}.{ext}           # Private (signed URLs)
└── condition-checks/{uuid}.{ext}   # Private (signed URLs)

AWS S3 Bucket Setup

Bucket Policy (Hybrid: Public + Private)

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicRead",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": [
        "arn:aws:s3:::village-share-dev/profiles/*",
        "arn:aws:s3:::village-share-dev/items/*",
        "arn:aws:s3:::village-share-dev/forum/*"
      ]
    }
  ]
}

Note: messages/* and condition-checks/* are NOT included - require signed URLs.

CORS Configuration

[
  {
    "AllowedHeaders": [
      "Content-Type",
      "Content-Length",
      "Content-Disposition",
      "Cache-Control",
      "x-amz-content-sha256",
      "x-amz-date",
      "x-amz-security-token"
    ],
    "AllowedMethods": ["PUT", "GET"],
    "AllowedOrigins": ["http://localhost:3000"],
    "ExposeHeaders": ["ETag"],
    "MaxAgeSeconds": 3600
  }
]

IAM Policy for Backend

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:PutObject", "s3:GetObject"],
      "Resource": "arn:aws:s3:::village-share-dev/*"
    }
  ]
}

Security Note: s3:DeleteObject is intentionally NOT included. File deletion is not exposed via the API to prevent unauthorized deletion attacks. Use S3 lifecycle policies for cleanup instead.

Environment Variables to Add

# Backend (.env)
S3_ENABLED=true                       # Set to "true" to enable S3
S3_BUCKET=village-share-{env}

# Frontend (.env)
REACT_APP_S3_BUCKET=village-share-{env}
REACT_APP_AWS_REGION=us-east-1

Deployment Checklist

  1. Create S3 buckets for each environment (dev, qa, prod)
  2. Apply bucket policies (public folders + private messages)
  3. Configure CORS on each bucket
  4. Attach IAM policy to EC2/ECS role
  5. Add environment variables
  6. Deploy backend changes
  7. Deploy frontend changes