Upload board: dismiss all, real previews for indexed records
- 'dismiss all' clears every indexed record at once - Indexed cards show the actual file preview: completed records now get a signed library media URL (raw for images, thumbnail for videos) so <img>/<video> tags can load it, including items hidden from guests - Media raw/thumbnail endpoints accept the signature for anonymous requests and fall back to the normal guest-filtered path otherwise - Guest blacklist keeps a persistent Redis mirror: an expired TTL or an unreachable e621 keeps the last successful list instead of falling back to the small local list
This commit is contained in:
@@ -3,6 +3,7 @@ from pathlib import Path
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from django.conf import settings
|
||||
from django.core import signing
|
||||
from django.db.models import Min
|
||||
from django.http import Http404
|
||||
from django.shortcuts import get_object_or_404
|
||||
@@ -67,9 +68,32 @@ class MediaItemViewSet(
|
||||
self.check_object_permissions(self.request, obj)
|
||||
return obj
|
||||
|
||||
def _signed_media_item(self, request, action_name):
|
||||
"""Signed media URLs let <img>/<video> tags bypass guest filtering."""
|
||||
if request.user.is_authenticated:
|
||||
return None
|
||||
signature = request.query_params.get("sig")
|
||||
if not signature:
|
||||
return None
|
||||
try:
|
||||
payload = signing.loads(
|
||||
signature, salt=services.MEDIA_FILE_SALT, max_age=86400
|
||||
)
|
||||
except signing.BadSignature:
|
||||
return None
|
||||
if payload.get("action") != action_name:
|
||||
return None
|
||||
return MediaItem.objects.filter(pk=payload.get("item")).first()
|
||||
|
||||
def _media_object(self, request, action_name):
|
||||
item = self._signed_media_item(request, action_name)
|
||||
if item is not None:
|
||||
return item
|
||||
return self.get_object()
|
||||
|
||||
@action(detail=True, methods=["get"])
|
||||
def raw(self, request, pk=None):
|
||||
item = self.get_object()
|
||||
item = self._media_object(request, "raw")
|
||||
location = item.locations.first()
|
||||
if location is None:
|
||||
return Response(
|
||||
@@ -82,7 +106,7 @@ class MediaItemViewSet(
|
||||
|
||||
@action(detail=True, methods=["get"])
|
||||
def thumbnail(self, request, pk=None):
|
||||
item = self.get_object()
|
||||
item = self._media_object(request, "thumbnail")
|
||||
location = item.locations.first()
|
||||
if location is None:
|
||||
return Response(
|
||||
|
||||
Reference in New Issue
Block a user