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

128 lines
4.2 KiB
Markdown

# 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)
```json
{
"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
```json
[
{
"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
```json
{
"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
```bash
# 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