22
33from django .conf import settings
44from django .db .models import Q
5- from django .utils import timezone
65
76import django_filters
87from rest_framework import filters , mixins , viewsets
98from rest_framework .decorators import action
109from rest_framework .response import Response
1110from rest_framework .status import HTTP_200_OK , HTTP_400_BAD_REQUEST
1211
13- from marsha .core import defaults , permissions as core_permissions
12+ from marsha .core import defaults , permissions as core_permissions , storage
1413from marsha .core .api import APIViewMixin , ObjectPkMixin , ObjectRelatedMixin
1514from marsha .core .models import ADMINISTRATOR
16- from marsha .core .utils .s3_utils import create_presigned_post
17- from marsha .core .utils .time_utils import to_timestamp
15+ from marsha .core .utils .time_utils import to_datetime
1816from marsha .markdown import permissions as markdown_permissions , serializers
1917from marsha .markdown .defaults import LTI_ROUTE
2018from marsha .markdown .forms import MarkdownDocumentForm
@@ -333,7 +331,7 @@ def initiate_upload(self, request, *args, pk=None, **kwargs):
333331 """Get an upload policy for a Markdown image.
334332
335333 Calling the endpoint resets the upload state to `pending` and returns an upload policy to
336- our AWS S3 source bucket.
334+ our S3 storage bucket.
337335
338336 Parameters
339337 ----------
@@ -345,33 +343,31 @@ def initiate_upload(self, request, *args, pk=None, **kwargs):
345343 Returns
346344 -------
347345 Type[rest_framework.response.Response]
348- HttpResponse carrying the AWS S3 upload policy as a JSON object.
346+ HttpResponse carrying the S3 storage upload policy as a JSON object.
349347
350348 """
351349 markdown_image = self .get_object () # check permissions first
352350
353- serializer = serializers .MarkdownImageUploadSerializer (
351+ serializer = serializers .MarkdownImageInitiateUploadSerializer (
354352 data = request .data ,
355353 )
356354
357355 if not serializer .is_valid ():
358356 return Response (serializer .errors , status = HTTP_400_BAD_REQUEST )
359357
360- now = timezone .now ()
361- stamp = to_timestamp (now )
362-
363- key = markdown_image .get_source_s3_key (
364- stamp = stamp ,
365- extension = serializer .validated_data ["extension" ],
366- )
367-
368- presigned_post = create_presigned_post (
369- [
370- ["starts-with" , "$Content-Type" , "image/" ],
371- ["content-length-range" , 0 , settings .MARKDOWN_IMAGE_SOURCE_MAX_SIZE ],
372- ],
373- {},
374- key ,
358+ presigned_post = (
359+ storage .get_initiate_backend ().initiate_markdown_image_storage_upload (
360+ request ,
361+ markdown_image ,
362+ [
363+ ["starts-with" , "$Content-Type" , "image/" ],
364+ [
365+ "content-length-range" ,
366+ 0 ,
367+ settings .MARKDOWN_IMAGE_SOURCE_MAX_SIZE ,
368+ ],
369+ ],
370+ )
375371 )
376372
377373 # Reset the upload state of the Markdown image
@@ -381,3 +377,46 @@ def initiate_upload(self, request, *args, pk=None, **kwargs):
381377 )
382378
383379 return Response (presigned_post )
380+
381+ @action (methods = ["post" ], detail = True , url_path = "upload-ended" )
382+ # pylint: disable=unused-argument
383+ def upload_ended (
384+ self ,
385+ request ,
386+ pk = None ,
387+ markdown_document_id = None ,
388+ ):
389+ """Notify the API that the markdown image upload has ended.
390+
391+ Calling the endpoint will update the upload state of the markdown image.
392+ The request should have a file_key in the body, which is the key of the
393+ uploaded file.
394+
395+ Parameters
396+ ----------
397+ request : Type[django.http.request.HttpRequest]
398+ The request on the API endpoint
399+ pk: string
400+ The primary key of the markdown image
401+
402+ Returns
403+ -------
404+ Type[rest_framework.response.Response]
405+ HttpResponse with the serialized markdown image.
406+ """
407+ markdown_image = self .get_object () # check permissions first
408+
409+ serializer = serializers .MarkdownImageUploadEndedSerializer (
410+ data = request .data , context = {"obj" : markdown_image }
411+ )
412+
413+ serializer .is_valid (raise_exception = True )
414+
415+ file_key = serializer .validated_data ["file_key" ]
416+ # The file_key have the "markdown/{markdown_pk}/markdownimage/{markdownimage}/
417+ # {stamp}" format
418+ stamp = file_key .split ("/" )[- 1 ]
419+
420+ markdown_image .update_upload_state (defaults .READY , to_datetime (stamp ))
421+
422+ return Response (serializer .data )
0 commit comments