feat: miler POD upload — presigned Spaces PUT (/miler/uploads/sign)

Rider proof-of-delivery / signature photos need a way to reach storage.
The legacy (jupiter) rider app shipped the DigitalOcean Spaces access/secret
key inside the Flutter build and PUT to the bucket directly. This moves the
key server-side and hands the app a short-lived presigned PUT URL instead.

- internal/storage/spaces.go: self-contained AWS SigV4 query presigner for
  Spaces (S3 API) — no aws-sdk-go-v2 dependency for a single presign op.
  Verified live end-to-end (presign -> PUT 200 -> CDN GET matches).
- controllers/uploadController.go: POST /miler/uploads/sign returns
  { uploadurl, url, method, headers, key, expiresin }. Same bucket/folders/
  CDN (images.nearle.app) as jupiter so images share one store.
- Reads DO_SPACES_* from .env via godotenv; returns 503 UPLOAD_NOT_CONFIGURED
  when unset rather than handing out URLs that 403.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WRaFH5hMRqmUQvVPQsyjZD
This commit is contained in:
Suriyakumarvijayanayagam
2026-08-24 18:18:52 +05:30
parent f6d339a33f
commit b0f733ae38
4 changed files with 357 additions and 0 deletions

View File

@@ -174,6 +174,12 @@ func RegisterRoutes(app *fiber.App, cfg *config.Config) {
// Miler's own bookings
milerAuth.Get("/bookings", controllers.MilerGetMyBookings)
// Proof-of-delivery / signature upload: hands the app a short-lived presigned
// PUT URL so the Spaces credentials stay server-side (the legacy rider app
// shipped the bucket key). App PUTs the image, then sends back the returned
// public URL as photourl / receiversignatureurl on deliver.
milerAuth.Post("/uploads/sign", controllers.MilerSignUpload)
// Consignment current-state read: lets the app know whether a consignment is
// collected / out-for-delivery / delivered without replaying the logs history.
milerAuth.Get("/consignments/:consignmentid", controllers.MilerGetConsignment)