lizerk 2768d2f1b3
Some checks failed
Deploy production / deploy (push) Failing after 14m49s
Restore reliable chat realtime and media playback
2026-09-10 20:26:58 +03:00

78 lines
2.7 KiB
Python

"""Credential-scoped streaming endpoints for protected chat media."""
from django.contrib.auth import get_user_model
from django.http import Http404
from django.shortcuts import get_object_or_404
from drf_spectacular.utils import OpenApiParameter, OpenApiTypes, extend_schema
from rest_framework.permissions import AllowAny
from rest_framework.views import APIView
from communications.media_delivery import chat_file_response
from communications.media_tickets import (
ChatMediaTicketError,
consume_chat_media_ticket,
)
from communications.models import Message, MessageAttachment
from communications.utils import user_can_access_chat
User = get_user_model()
class ChatAttachmentMediaAPIView(APIView):
"""Serve inline audio/video after validating a short-lived scoped ticket."""
authentication_classes = []
permission_classes = [AllowAny]
@extend_schema(
parameters=[
OpenApiParameter(
"ticket",
OpenApiTypes.STR,
OpenApiParameter.QUERY,
required=True,
)
],
responses={(200, "application/octet-stream"): OpenApiTypes.BINARY},
)
def get(self, request, message_id: int, attachment_id: int):
raw_ticket = request.query_params.get("ticket")
if not isinstance(raw_ticket, str) or not raw_ticket:
raise Http404("Медиафайл недоступен")
try:
identity = consume_chat_media_ticket(
raw_ticket,
message_id=message_id,
attachment_id=attachment_id,
)
except ChatMediaTicketError as error:
raise Http404("Медиафайл недоступен") from error
user = get_object_or_404(User, pk=identity.user_id, is_active=True)
message = get_object_or_404(
Message.objects.select_related("chat"),
pk=message_id,
is_deleted=False,
)
if not user_can_access_chat(message.chat, user):
raise Http404("Медиафайл недоступен")
attachment = get_object_or_404(
MessageAttachment,
pk=attachment_id,
message=message,
)
if attachment.file_type not in {"audio", "video"} or not attachment.file:
raise Http404("Медиафайл недоступен")
try:
response = chat_file_response(
attachment.file,
filename=attachment.file_name,
as_attachment=False,
)
except (OSError, ValueError) as error:
raise Http404("Медиафайл недоступен") from error
response["Referrer-Policy"] = "no-referrer"
return response