Skip to content

feat: avatar upload to S3, proxied through the backend (#733) - #872

Merged
ONEONUORA merged 1 commit into
Fracverse:masterfrom
benedictworks-home:fix/733-avatar-upload-s3
Aug 29, 2026
Merged

feat: avatar upload to S3, proxied through the backend (#733)#872
ONEONUORA merged 1 commit into
Fracverse:masterfrom
benedictworks-home:fix/733-avatar-upload-s3

Conversation

@benedictworks-home

Copy link
Copy Markdown
Contributor

Description:

Summary

Implements POST /api/users/profile/avatar as an authenticated multipart upload route. Users can upload an image (JPEG, PNG, GIF, WebP) which is decoded, resized to 256×256, re-encoded as JPEG, uploaded to S3, and the resulting public URL is saved to users.avatar_url.

Changes

Backend (backend/)

  • Cargo.toml — Added image, aws-sdk-s3, aws-config dependencies
  • src/config.rs — Added S3 config fields:
    • AWS_S3_BUCKET (required for upload to work)
    • AWS_S3_REGION (defaults to us-east-1)
    • AWS_S3_PUBLIC_URL_BASE (optional CloudFront/bucket URL prefix)
    • AWS credentials come from the standard SDK credential chain (env vars / instance role)
  • src/api/user.rs — Added upload_avatar handler:
    • Accepts multipart field named file or avatar
    • Validates image decoding, returns 400 for invalid/empty uploads
    • Resizes to 256×256 with Lanczos3, re-encodes as JPEG at quality 85
    • Uploads to S3 at avatars/{user_id}.jpg
    • Updates users.avatar_url in the database
    • Invalidates Redis username cache if present
    • Returns { "avatar_url": "..." }
  • src/api/mod.rs — Registered /profile/avatar route

How it works

  1. Client sends POST /api/users/profile/avatar with Authorization: Bearer <token> and multipart/form-data body containing the image file
  2. Backend validates auth, decodes + resizes the image, uploads to S3
  3. Public URL is built from AWS_S3_PUBLIC_URL_BASE (or falls back to the standard S3 URL pattern)
  4. users.avatar_url column is updated and the Redis cache is invalidated

Configuration

Set these environment variables in production:

AWS_S3_BUCKET=your-bucket-name
AWS_S3_REGION=us-east-1
AWS_S3_PUBLIC_URL_BASE=https://d1234.cloudfront.net/avatars

AWS credentials are resolved via the standard SDK chain (AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY, instance role, etc.).

Testing

  • Upload via: curl -X POST -H "Authorization: Bearer <token>" -F "file=@avatar.jpg" http://localhost:3000/api/users/profile/avatar
  • Verify avatar_url appears in GET /api/users/profile response

Closes #733

- POST /api/users/profile/avatar: authenticated multipart upload
- Accepts field name 'file' or 'avatar'
- Decodes image, resizes to 256x256, re-encodes as JPEG (quality 85)
- Uploads to S3 via aws-sdk-s3 (credentials from standard AWS chain)
- Saves public URL to users.avatar_url, invalidates Redis cache
- Config: AWS_S3_BUCKET, AWS_S3_REGION, AWS_S3_PUBLIC_URL_BASE env vars
@drips-wave

drips-wave Bot commented Aug 29, 2026

Copy link
Copy Markdown

@benedictworks-home Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@ONEONUORA

Copy link
Copy Markdown
Contributor

@benedictworks-home
PLs make your implementation to pass CI checks

@ONEONUORA ONEONUORA left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ONEONUORA
ONEONUORA merged commit 9fd09bf into Fracverse:master Aug 29, 2026
7 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

backend: Implement user profile avatar upload to S3/IPFS proxy route

2 participants