mirror of
https://github.com/Dvorinka/Primora.git
synced 2026-10-28 07:41:23 +00:00
POST /buckets/:id/object-presigns mints SigV4 query-signed GET/PUT URLs so clients move bytes directly against S3 — large transfers skip the backend entirely. - storage.Presigner optional interface; S3Store implements, local driver returns a clear error (no external surface to sign). - TTL 60s–1h (default 15m); download requires read role + existing object row (no key probing); upload requires write role. - S3_PUBLIC_ENDPOINT rewrites the client-facing host for internal S3_ENDPOINTs — signatures bind the host, URLs are valid only where minted. - CLI: primora objects:presign <bucket> <key> [--upload] [--ttl]. Verified live against cloudserver: GET fetched the object with no auth headers; PUT pushed 1 MB direct to S3; unsigned list → 403; untracked-key download presign → 404. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
32 lines
1.1 KiB
Go
32 lines
1.1 KiB
Go
package storage
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"time"
|
|
)
|
|
|
|
// Store is the object-storage contract the platform service depends on.
|
|
// LocalStore keeps objects on disk; S3Store targets S3-compatible APIs.
|
|
type Store interface {
|
|
Put(ctx context.Context, bucketID, objectKey string, reader io.Reader) (PutResult, error)
|
|
Open(bucketID, objectKey string) (io.ReadCloser, string, error)
|
|
Delete(bucketID, objectKey string) error
|
|
MoveBetweenBuckets(sourceBucketID, destinationBucketID, fromKey, toKey string) (string, error)
|
|
DeleteBucket(bucketID string) error
|
|
}
|
|
|
|
// PresignedURL is a short-lived direct-to-storage URL for one operation.
|
|
type PresignedURL struct {
|
|
URL string `json:"url"`
|
|
Method string `json:"method"`
|
|
ExpiresAt time.Time `json:"expires_at"`
|
|
}
|
|
|
|
// Presigner is an optional capability: stores backed by a real object API
|
|
// (S3) can mint URLs clients call directly. The local driver can't — its
|
|
// "URL" would have to be served by this backend anyway.
|
|
type Presigner interface {
|
|
Presign(ctx context.Context, bucketID, objectKey, method string, ttl time.Duration) (*PresignedURL, error)
|
|
}
|