feat(document): expose thumbnailUrl to JSON serialisation

@JsonProperty makes the computed getter part of every Document response
Jackson produces, so any DTO returning a Document automatically carries
the thumbnail URL without per-controller plumbing. The accompanying
comment warns future readers that the cache-buster is load-bearing
for the endpoint's `immutable` cache header (CWE-525) (#309).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-23 22:02:05 +02:00
parent 9862a51ac7
commit ad999c47ea

View File

@@ -6,6 +6,7 @@ import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import java.net.URLEncoder;
@@ -134,6 +135,14 @@ public class Document {
@Builder.Default
private Set<TrainingLabel> trainingLabels = new HashSet<>();
// The `?v={thumbnailGeneratedAt}` cache-buster is load-bearing: the thumbnail
// endpoint sends `Cache-Control: private, max-age=31536000, immutable`
// (DocumentController.getDocumentThumbnail). `immutable` is only safe because
// this URL changes whenever the underlying file does. Dropping the query param
// would let browsers serve a stale thumbnail for a year after the file is
// replaced, and shared caches could leak one user's thumbnail to another
// (CWE-525).
@JsonProperty("thumbnailUrl")
public String getThumbnailUrl() {
if (thumbnailKey == null) return null;
String base = "/api/documents/" + id + "/thumbnail";