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:
@@ -1,10 +1,11 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from django.core import signing
|
||||
from rest_framework import serializers
|
||||
|
||||
from .models import MediaItem, MediaLocation, TempUpload
|
||||
from .services import UPLOAD_FILE_SALT, VIDEO_EXTENSIONS
|
||||
from .services import MEDIA_FILE_SALT, UPLOAD_FILE_SALT, VIDEO_EXTENSIONS
|
||||
|
||||
|
||||
class MediaLocationSerializer(serializers.ModelSerializer):
|
||||
@@ -99,6 +100,7 @@ class TempUploadSerializer(serializers.ModelSerializer):
|
||||
temp_id = serializers.UUIDField(source="id", read_only=True)
|
||||
library_j_id = serializers.SerializerMethodField()
|
||||
file_url = serializers.SerializerMethodField()
|
||||
preview_url = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = TempUpload
|
||||
@@ -117,11 +119,19 @@ class TempUploadSerializer(serializers.ModelSerializer):
|
||||
"iqdb_data",
|
||||
"library_j_id",
|
||||
"file_url",
|
||||
"preview_url",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
]
|
||||
read_only_fields = fields
|
||||
|
||||
def _request_user(self):
|
||||
request = self.context.get("request")
|
||||
user = getattr(request, "user", None)
|
||||
if user is None or not getattr(user, "is_authenticated", False):
|
||||
return None
|
||||
return user
|
||||
|
||||
def get_library_j_id(self, obj):
|
||||
return f"J-{obj.library_item_id}" if obj.library_item_id else None
|
||||
|
||||
@@ -129,12 +139,33 @@ class TempUploadSerializer(serializers.ModelSerializer):
|
||||
"""Signed URL so <img>/<video> tags can fetch the staged file."""
|
||||
if not obj.file:
|
||||
return None
|
||||
request = self.context.get("request")
|
||||
user = getattr(request, "user", None)
|
||||
if user is None or not getattr(user, "is_authenticated", False):
|
||||
user = self._request_user()
|
||||
if user is None:
|
||||
return None
|
||||
signature = signing.dumps(
|
||||
{"temp": str(obj.id), "user": user.id},
|
||||
salt=UPLOAD_FILE_SALT,
|
||||
)
|
||||
return f"/api/uploads/{obj.id}/file/?sig={signature}"
|
||||
|
||||
def get_preview_url(self, obj):
|
||||
"""A URL an <img>/<video> tag can load: staged file or library item."""
|
||||
user = self._request_user()
|
||||
if user is None:
|
||||
return None
|
||||
if obj.file:
|
||||
return self.get_file_url(obj)
|
||||
item = obj.library_item
|
||||
if item is None:
|
||||
return None
|
||||
location = item.locations.first()
|
||||
is_video = (
|
||||
location is not None
|
||||
and Path(location.rel_path).suffix.lower() in VIDEO_EXTENSIONS
|
||||
)
|
||||
action = "thumbnail" if is_video else "raw"
|
||||
signature = signing.dumps(
|
||||
{"item": item.id, "user": user.id, "action": action},
|
||||
salt=MEDIA_FILE_SALT,
|
||||
)
|
||||
return f"/api/files/J-{item.id}/{action}/?sig={signature}"
|
||||
|
||||
Reference in New Issue
Block a user