import uuid from datetime import timedelta from django.conf import settings from drf_spectacular.utils import extend_schema from rest_framework import status from rest_framework.response import Response from rest_framework.views import APIView from apps.core.serializers import MediaPresignInputSerializer, MediaPresignOutputSerializer from apps.gooyal_oauth2.rest_framework import IsAuthenticatedOrTokenMatchesOASRequirements from utils.clients.minio_client import minio_client from utils.exceptions import ServiceUnavailable class MediaPresignView(APIView): """Presigned MinIO upload URL for product/store images (icon, logo, cover, ...). The client uploads the file bytes directly to MinIO with the returned upload_url, then submits the returned object_key as the field value when creating/updating the owning resource (e.g. Store.logo, Product.image). """ schema_tags = ['Media'] permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements] required_alternate_scopes = { "POST": [[]], } @extend_schema(request=MediaPresignInputSerializer, responses={201: MediaPresignOutputSerializer}) def post(self, request): serializer = MediaPresignInputSerializer(data=request.data) serializer.is_valid(raise_exception=True) filename = serializer.validated_data['filename'] extension = filename.rsplit('.', 1)[-1] if '.' in filename else 'bin' object_key = f'uploads/{uuid.uuid4()}.{extension}' try: upload_url = minio_client.presigned_put_object( settings.MINIO_MEDIA_FILES_BUCKET, object_key, expires=timedelta(minutes=30), ) except Exception: raise ServiceUnavailable('خطا در دریافت لینک آپلود. لطفاً دوباره تلاش کنید.') return Response( MediaPresignOutputSerializer({'upload_url': upload_url, 'object_key': object_key}).data, status=status.HTTP_201_CREATED, )