Documentation
¶
Overview ¶
Package upload is the admin surface for merchant asset uploads (product images). A merchant POSTs multipart file(s); each is content-sniffed (image bytes only — the client Content-Type header is never trusted), size-capped, and stored under a per-tenant prefix in the house S3 client (github.com/hanzoai/s3-go). The response is the public URL(s).
Tenant isolation: every object key is prefixed tenant/<org>/uploads/ from the AUTHENTICATED org (middleware.GetOrganization) — a caller can only ever write under its own tenant. Admin-gated INSIDE the handler (middleware.RequireAdmin) because the route-level TokenRequired(Admin) middleware no-ops on the IAM path (Red HIGH-4) — a handler must never trust that gate alone.
Index ¶
Constants ¶
const MaxUploadBytes = 10 << 20
MaxUploadBytes caps a single upload at 10 MiB — large enough for a high-resolution product photo, small enough to bound memory + storage abuse.
Variables ¶
var ErrNoStorage = errors.New("upload: object storage not configured")
ErrNoStorage is returned when the object store is not configured for this deployment (no S3_URL / S3_ENDPOINT). Uploads 503 rather than silently drop.
Functions ¶
func Images ¶
Images stores one or more posted image files under the caller's tenant prefix and returns their public URLs. Files may arrive under the "file" or "files" multipart field (repeated), so both a single-file and a gallery upload work.
func Route ¶
Route mounts the admin upload surface. args are the route-level guards (adminRequired) shared with the rest of the /v1 admin bundle; the handler re-checks admin internally.
func SetStorage ¶
func SetStorage(s Storer)
SetStorage wires the object store (called once at bootstrap after the infra manager connects). Passing a nil client is a no-op — the handler stays 503.
Types ¶
type Storer ¶
type Storer interface {
Upload(ctx context.Context, opts *infra.UploadOptions) (*infra.UploadResult, error)
}
Storer is the object-store surface the handler needs — satisfied by *infra.StorageClient. An interface (not the concrete client) so tests inject a fake and run with no real S3.