Re-sign visual-match thumbnails on every detail fetch
Match rows stored a signed URL minted when the scan ran, so it aged out (or used the pre-stable signing scheme) and the modal showed broken tiles even after legacy signatures were fixed. Rows now carry item_id/j_id and the detail serializer mints a fresh thumbnail URL per request; matches whose item no longer exists are dropped.
This commit is contained in:
@@ -150,6 +150,7 @@ class TempUploadSerializer(serializers.ModelSerializer):
|
||||
iqdb_checked = serializers.SerializerMethodField()
|
||||
processing = serializers.SerializerMethodField()
|
||||
similar_count = serializers.SerializerMethodField()
|
||||
visual_matches = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = TempUpload
|
||||
@@ -242,6 +243,57 @@ class TempUploadSerializer(serializers.ModelSerializer):
|
||||
def get_similar_count(self, obj):
|
||||
return len(obj.iqdb_data or []) + len(obj.visual_matches or [])
|
||||
|
||||
@staticmethod
|
||||
def _visual_item_id(entry):
|
||||
if not isinstance(entry, dict):
|
||||
return None
|
||||
item_id = entry.get("item_id")
|
||||
if item_id is None:
|
||||
j_id = str(entry.get("j_id") or "")
|
||||
if j_id.upper().startswith("J-"):
|
||||
j_id = j_id[2:]
|
||||
item_id = j_id if j_id.isdigit() else None
|
||||
try:
|
||||
return int(item_id)
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
|
||||
def get_visual_matches(self, obj):
|
||||
"""Rebuild match rows with fresh signed thumbnail URLs.
|
||||
|
||||
Storing the signed URL meant it aged out (or came from an older
|
||||
signing scheme) and the "Already in your library" grid showed broken
|
||||
tiles. The stored rows only carry the item reference now.
|
||||
"""
|
||||
entries = obj.visual_matches or []
|
||||
if not entries:
|
||||
return entries
|
||||
wanted = {}
|
||||
for entry in entries:
|
||||
item_id = self._visual_item_id(entry)
|
||||
if item_id is not None:
|
||||
wanted[item_id] = None
|
||||
items = MediaItem.objects.in_bulk(list(wanted))
|
||||
user = self._request_user()
|
||||
request = self.context.get("request")
|
||||
matches = []
|
||||
for entry in entries:
|
||||
item_id = self._visual_item_id(entry)
|
||||
item = items.get(item_id) if item_id is not None else None
|
||||
if item is None:
|
||||
continue
|
||||
matches.append(
|
||||
{
|
||||
"j_id": f"J-{item.id}",
|
||||
"filename": entry.get("filename") or item.md5,
|
||||
"similarity": entry.get("similarity"),
|
||||
"thumbnail_url": signed_media_url(
|
||||
item, user, "thumbnail", request=request
|
||||
),
|
||||
}
|
||||
)
|
||||
return matches
|
||||
|
||||
|
||||
class TempUploadListSerializer(TempUploadSerializer):
|
||||
"""Compact staged-upload row for the board and the status polling.
|
||||
|
||||
Reference in New Issue
Block a user