Skip to content

Commit

Permalink
feat(AU-2283): Create transcript delete endpoint (#541)
Browse files Browse the repository at this point in the history
* feat(AU-2283): Create transcript bulk delete endpoint

* feat(AU-2283): Call get_available_transcript_languages outside loop

* feat(AU-2283): Move payload validation to serializer

* feat(AU-2283): Correct pylint

* feat(AU-2283): Add authorization layer to bulk delete

* chore: converted to use same APIView as the transcript create endpoint

* chore: fix quality

---------

Co-authored-by: Brandon Bodine <[email protected]>
  • Loading branch information
Rodra and BrandonHBodine authored Dec 2, 2024
1 parent 11521db commit b154484
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 3 deletions.
34 changes: 34 additions & 0 deletions edxval/tests/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,13 @@
status="test",
)

VIDEO_DICT_SIMPSONS = dict(
client_video_id="TheSimpsons",
duration=100.00,
edx_video_id="simpson-id",
status="test",
)

TRANSCRIPT_DATA = {
"overwatch": """
1
Expand Down Expand Up @@ -452,3 +459,30 @@
preferred_languages=['ar', 'en'],
video_source_language='en',
)

VIDEO_TRANSCRIPT_SIMPSON_ES = dict(
video_id='simpson-id',
language_code='es',
transcript='edxval/tests/data/The_Flash.srt',
provider=TranscriptProviderType.CIELO24,
file_format=TranscriptFormat.SRT,
file_data=TRANSCRIPT_DATA['flash']
)

VIDEO_TRANSCRIPT_SIMPSON_KO = dict(
video_id='simpson-id',
language_code='ko',
transcript='edxval/tests/data/The_Flash.srt',
provider=TranscriptProviderType.CIELO24,
file_format=TranscriptFormat.SRT,
file_data=TRANSCRIPT_DATA['flash']
)

VIDEO_TRANSCRIPT_SIMPSON_RU = dict(
video_id='simpson-id',
language_code='ru',
transcript='edxval/tests/data/The_Flash.srt',
provider=TranscriptProviderType.CIELO24,
file_format=TranscriptFormat.SRT,
file_data=TRANSCRIPT_DATA['flash']
)
69 changes: 69 additions & 0 deletions edxval/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

from ddt import data, ddt, unpack
from django.urls import reverse
from edx_rest_framework_extensions.permissions import IsStaff
from rest_framework import status
from rest_framework.permissions import IsAuthenticated

from edxval.models import CourseVideo, EncodedVideo, Profile, TranscriptProviderType, Video, VideoTranscript
from edxval.serializers import TranscriptSerializer
Expand Down Expand Up @@ -1152,3 +1154,70 @@ def test_successful_response(self):
mock_video_ids.assert_called_once_with(course_id)

self.assertEqual(response.status_code, status.HTTP_200_OK)


@ddt
class VideoTranscriptDeleteTest(APIAuthTestCase):
"""
Tests for transcript bulk deletion handler.
"""
def setUp(self):
"""
Tests setup.
"""
self.url = reverse('video-transcripts')
self.patcher = patch.object(IsAuthenticated, "has_permission", return_value=True)
self.patcher = patch.object(IsStaff, "has_permission", return_value=True)
self.patcher.start()

self.video_1 = Video.objects.create(**constants.VIDEO_DICT_SIMPSONS)
self.transcript_data_es = constants.VIDEO_TRANSCRIPT_SIMPSON_ES
self.transcript_data_ko = constants.VIDEO_TRANSCRIPT_SIMPSON_KO
self.transcript_data_ru = constants.VIDEO_TRANSCRIPT_SIMPSON_RU
super().setUp()

def tearDown(self):
self.patcher.stop()

def test_transcript_fail_authorized(self):
with patch.object(IsAuthenticated, "has_permission", return_value=False):
response = self.client.delete(self.url)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

def test_transcript_delete_fail_no_staff(self):
with patch.object(IsStaff, "has_permission", return_value=False):
response = self.client.delete(self.url)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

def test_transcript_delete_success(self):
VideoTranscript.objects.create(
video=self.video_1,
language_code=self.transcript_data_es['language_code'],
file_format=self.transcript_data_es['file_format'],
provider=self.transcript_data_es['provider'],
)
VideoTranscript.objects.create(
video=self.video_1,
language_code=self.transcript_data_ko['language_code'],
file_format=self.transcript_data_ko['file_format'],
provider=self.transcript_data_ko['provider'],
)
VideoTranscript.objects.create(
video=self.video_1,
language_code=self.transcript_data_ru['language_code'],
file_format=self.transcript_data_ru['file_format'],
provider=self.transcript_data_ru['provider'],
)

response1 = self.client.delete(f'{self.url}?video_id=simpson-id&language_code=es')
self.assertEqual(response1.status_code, status.HTTP_204_NO_CONTENT)

response2 = self.client.delete(f'{self.url}?video_id=simpson-id&language_code=ko')
self.assertEqual(response2.status_code, status.HTTP_204_NO_CONTENT)

response3 = self.client.delete(f'{self.url}?video_id=simpson-id&language_code=ru')
self.assertEqual(response3.status_code, status.HTTP_204_NO_CONTENT)

def test_transcript_delete_fail_bad_request(self):
response = self.client.delete(self.url)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
3 changes: 3 additions & 0 deletions edxval/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
path('videos/video-transcripts/create/', views.VideoTranscriptView.as_view(),
name='create-video-transcript'
),
path('videos/video-transcripts/', views.VideoTranscriptView.as_view(),
name='video-transcripts'
),
path('videos/video-images/update/', views.VideoImagesView.as_view(),
name='update-video-images'
),
Expand Down
49 changes: 46 additions & 3 deletions edxval/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,19 @@
from django.core.exceptions import ValidationError
from django.shortcuts import get_object_or_404
from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication
from edx_rest_framework_extensions.permissions import IsStaff
from rest_framework import generics, status
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import DjangoModelPermissions
from rest_framework.permissions import DjangoModelPermissions, IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

from edxval.api import create_or_update_video_transcript, get_transcript_details_for_course, get_video_ids_for_course
from edxval.api import (
create_or_update_video_transcript,
delete_video_transcript,
get_transcript_details_for_course,
get_video_ids_for_course,
)
from edxval.models import (
LIST_MAX_ITEMS,
CourseVideo,
Expand Down Expand Up @@ -119,7 +125,11 @@ class VideoTranscriptView(APIView):
"""
authentication_classes = (JwtAuthentication, SessionAuthentication)

# noinspection PyMethodMayBeStatic
def get_permissions(self):
if self.request.method == 'DELETE':
return [IsAuthenticated(), IsStaff()]
return []

def post(self, request):
"""
Creates a video transcript instance with the given information.
Expand Down Expand Up @@ -174,6 +184,39 @@ def post(self, request):

return response

def delete(self, request):
"""
Delete a video transcript instance with the given information.
Arguments:
request: A WSGI request.
"""
params = ('video_id', 'language_code')
missing = [param for param in params if param not in request.query_params]
if missing:
LOGGER.warning(
'[VAL] Required transcript params are missing. %s', ' and '.join(missing)
)
return Response(
status=status.HTTP_400_BAD_REQUEST,
data=dict(message='{missing} must be specified.'.format(missing=' and '.join(missing)))
)

video_id = request.query_params.get('video_id')
language_code = request.query_params.get('language_code')

try:
delete_video_transcript(video_id=video_id, language_code=language_code)
except Exception as e: # pylint: disable=broad-exception-caught
return Response(
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
data={'message': str(e)}
)

return Response(
status=status.HTTP_204_NO_CONTENT,
)


class CourseTranscriptsDetailView(APIView):
"""
Expand Down

0 comments on commit b154484

Please sign in to comment.