Skip to content

Serve thumbnails for private/draft projects (self-authenticating URLs) #1341

Description

@mihow

Background

The server-side thumbnail layer (#1306) routes capture-image display through an authentication-gated Django endpoint (SourceImageThumbnailViewSet). The frontend loads images via a plain <img src>, which cannot attach an Authorization header. For public projects the anonymous request passes the permission check and the thumbnail serves; for draft / non-public projects it returns 401 and the image renders broken.

PR #1340 ships an interim fix: the serializer omits thumbnail-endpoint URLs for draft projects so the UI falls back to the capture's source URL (capture.url, the pre-#1306 behavior, which bypasses the auth-gated endpoint). That unbreaks rendering but means draft projects get no thumbnail performance benefit, and it leaves the endpoint itself unguarded against authenticated generation into public default storage.

Note: project visibility is independent of storage. Whether a capture's source URL is presigned depends on its bucket, not on whether the project is draft — a draft project may live on a public bucket and a public project on a private one. The determinant for this bug is the draft flag / anonymous-retrieve permission, not bucket type.

Goal

Let private/draft projects benefit from thumbnails too, without exposing restricted imagery.

Directions to discuss

  1. Self-authenticating thumbnail URLs — serializer/endpoint returns a presigned or short-lived signed-token URL that works in a bare <img> and expires.
  2. Per-project thumbnail storage — write generated thumbnails to each project's own object store and serve them with the same access posture as the project's captures, instead of the shared public default storage (thumbnails/capture_{pk}/{label}.jpg, currently world-readable and pk-enumerable).
  3. Server-side thumbnail warming — backfill + generate-on-import/sync, so cold→warm does not depend on an anonymous browser hit (today generation is lazy and only triggered by a permitted request to the endpoint; Serve direct thumbnail URLs to reduce load on main app server #1331's warm-direct-URL optimization can't help a project that can never warm).

Any fix must cover the 401 case without making genuinely private captures more accessible than the source URLs already made them.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions