"""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