AWS S3 — uploads de mídia de templates (imagem, vídeo, PDF)
O app envia arquivos pelo backend usando @aws-sdk/client-s3 (PutObject). Os objetos são gravados com prefixo:
public/tenants/<tenantId>/templates/<timestamp>-<random>.<ext>
Endpoints (fullstack)
| Rota | MIME | Tamanho máximo | Extensão |
|------|------|----------------|----------|
| POST /api/internal/uploads/template-image | image/png, image/jpeg, image/webp, image/gif | 5 MB | .png, .jpg, .webp, .gif |
| POST /api/internal/uploads/template-video | video/mp4 | 16 MB | .mp4 |
| POST /api/internal/uploads/template-document | application/pdf | 10 MB | .pdf |
Resposta típica: { "url": "...", "key": "public/tenants/..." }.
O JSON do template (body) pode incluir mediaUrl, mediaType ("image" | "video" | "document") e, para PDF, fileName opcional. Templates antigos só com mediaUrl continuam tratados como imagem (inferência por extensão quando aplicável).
Variáveis de ambiente (fullstack)
| Variável | Obrigatória | Descrição |
|----------|-------------|-----------|
| AWS_REGION | Não | Padrão: us-east-1 |
| AWS_S3_BUCKET | Não | Padrão: pilot-status |
| AWS_ACCESS_KEY_ID | Sim* | Credencial IAM |
| AWS_SECRET_ACCESS_KEY | Sim* | Credencial IAM |
| AWS_S3_PUBLIC_BASE_URL | Não | Se definida, a API retorna URLs com esse prefixo em vez do host virtual do S3 |
* Em produção na AWS (ECS/EC2/Lambda), prefira IAM role em vez de access key; o SDK usa a cadeia padrão de credenciais.
Docker Compose (dev)
O docker-compose.dev.yml repassa AWS_REGION, AWS_S3_BUCKET, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY e AWS_S3_PUBLIC_BASE_URL do arquivo usado em --env-file (ex.: npm run dev:docker:compose usa .env.development). Defina as credenciais nesse arquivo e recrie o container (docker compose ... up -d --force-recreate web-fullstack-dev) para aplicar.
Passos na AWS
1) Bucket
- Região: us-east-1 (alinhado ao exemplo
pilot-status.s3.us-east-1.amazonaws.com). - Nome sugerido:
pilot-status(ou o valor deAWS_S3_BUCKET).
2) IAM — permissão mínima de escrita
Crie um usuário ou role (ex.: pilot-status-app-s3-uploader) com policy inline ou gerenciada contendo apenas:
s3:PutObjectemarn:aws:s3:::pilot-status/public/tenants/*(ajuste o nome do bucket se diferente).
Exemplo de statement (JSON):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "TemplateMediaUpload",
"Effect": "Allow",
"Action": ["s3:PutObject"],
"Resource": ["arn:aws:s3:::pilot-status/public/tenants/*"]
}
]
}
Se usar usuário IAM, gere Access key e configure AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY no deploy.
3) Leitura pública (URLs fixas para mediaUrl)
Para o WhatsApp e o app usarem a URL pública (https://<bucket>.s3.<region>.amazonaws.com/<key>), o objeto precisa ser legível publicamente ou você precisa de outro mecanismo (CloudFront + OAI, etc.).
Opção simples (objetos públicos só no prefixo):
- Em S3 → bucket → Permissions → Block public access, permita bucket policies públicas (desbloqueie só o necessário; não precisa abrir listagem do bucket).
- Adicione uma Bucket policy permitindo
s3:GetObjectparaarn:aws:s3:::pilot-status/public/tenants/*comPrincipal: "*"(ou restrinja por IP/CloudFront conforme sua arquitetura).
Exemplo (leitura pública no prefixo public/tenants/):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadTemplateMedia",
"Effect": "Allow",
"Principal": "*",
"Action": ["s3:GetObject"],
"Resource": ["arn:aws:s3:::pilot-status/public/tenants/*"]
}
]
}
Nota: Não é necessário CORS no bucket para este fluxo (upload via backend). CORS no S3 só seria obrigatório se o navegador enviasse o arquivo direto para o S3 (presigned URL).
4) Validação
- Configure as env vars no serviço fullstack e faça deploy.
- Na UI de templates, teste Imagem → Upload (PNG/JPEG/WebP/GIF < 5MB), Vídeo → Upload (MP4 < 16MB) e PDF → Upload (< 10MB).
- Confirme que a API retorna
201e umaurlque abre no navegador (HTTP 200). - Salve o template e verifique que o
bodyJSON contémmediaUrlemediaTypeadequados.
Tipos e limites no backend
- Imagem:
image/png,image/jpeg,image/webp,image/gif— máx. 5 MB - Vídeo:
video/mp4— máx. 16 MB - Documento:
application/pdf— máx. 10 MB