Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add transcript credentials api #210

Merged
merged 5 commits into from
Apr 1, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion edxval/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,15 @@
EncodedVideo,
Profile,
ThirdPartyTranscriptCredentialsState,
TranscriptCredentials,
TranscriptPreference,
TranscriptProviderType,
Video,
VideoImage,
VideoTranscript,
)
from edxval.serializers import TranscriptPreferenceSerializer, TranscriptSerializer, VideoSerializer
from edxval.transcript_utils import Transcript
from edxval.transcript_utils import Transcript, validate_transcript_credentials
from edxval.utils import THIRD_PARTY_TRANSCRIPTION_PLANS, TranscriptFormat, create_file_in_fs, get_transcript_format

logger = logging.getLogger(__name__) # pylint: disable=C0103
Expand Down Expand Up @@ -1230,3 +1231,20 @@ def create_transcript_objects(xml, edx_video_id, resource_fs, static_dir, extern
resource_fs=file_system,
static_dir=static_dir
)


def create_or_update_transcript_credentials(**credentials):
"""
Internal API method to create or update transcript credentials.
"""
provider = credentials.pop('provider', None)
error_type, error_message, validated_credentials = validate_transcript_credentials(
provider=provider, **credentials
)
if not error_message:
TranscriptCredentials.objects.update_or_create(
org=validated_credentials.pop('org'), provider=provider, defaults=validated_credentials
)
error_type = None

return dict(error_type=error_type, message=error_message)
49 changes: 49 additions & 0 deletions edxval/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from tempfile import mkdtemp

import mock
import responses
import six
from ddt import data, ddt, unpack
from django.conf import settings
Expand Down Expand Up @@ -45,6 +46,7 @@
EncodedVideo,
Profile,
ThirdPartyTranscriptCredentialsState,
TranscriptCredentials,
TranscriptPreference,
TranscriptProviderType,
Video,
Expand Down Expand Up @@ -3073,3 +3075,50 @@ def test_get_credentials_state(self, org, provider, result):
"""
credentials_state = api.get_transcript_credentials_state_for_org(org=org, provider=provider)
self.assertEqual(credentials_state, result)


@ddt
class CreateUpdateTranscriptCredentialsTest(TestCase):
"""
Test Suite for transcript credentials create or update internal API.
"""
CIELO24_LOGIN_URL = "https://sandbox.cielo24.com/api/account/login"

@data(
{
'org': 'test',
'provider': TranscriptProviderType.CIELO24,
'api_key': 'test-api-key',
'username': 'test-cielo-user'
},
{
'org': 'test',
'provider': TranscriptProviderType.THREE_PLAY_MEDIA,
'api_key': 'test-api-key',
'api_secret_key': 'test-secret-key'
}
)
@responses.activate
def test_transcript_credentials_success(self, credentials):
"""
Test that creating credentials works as expected with correct set of data.
"""
responses.add(
responses.GET,
self.CIELO24_LOGIN_URL,
body='{"ApiToken": "cielo-api-token"}',
status=status.HTTP_200_OK
)

transcript_credentials = TranscriptCredentials.objects.filter(
org=credentials.get('org'),
provider=credentials.get('provider')
)
self.assertFalse(transcript_credentials.exists())

_ = api.create_or_update_transcript_credentials(**credentials)
transcript_credentials = TranscriptCredentials.objects.filter(
org=credentials.get('org'),
provider=credentials.get('provider')
)
self.assertTrue(transcript_credentials.exists())
113 changes: 106 additions & 7 deletions edxval/tests/test_transcript_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,21 @@

import json
import textwrap
import unittest

import ddt
import responses
from ddt import data, ddt, unpack
from django.test import TestCase
from mock import patch
from rest_framework import status

from edxval.enum import TranscriptionProviderErrorType
from edxval.exceptions import TranscriptsGenerationException
from edxval.transcript_utils import Transcript
from edxval.models import TranscriptProviderType
from edxval.transcript_utils import Transcript, validate_transcript_credentials


@ddt.ddt
class TestTranscriptUtils(unittest.TestCase):
@ddt
class TestTranscriptUtils(TestCase):
"""
Tests transcripts conversion util.
"""
Expand Down Expand Up @@ -50,12 +55,12 @@ def setUp(self):
}
""").encode('utf8')

@ddt.data(
@data(
('invalid_input_format', 'sjson'),
('sjson', 'invalid_output_format'),
('invalid_input_format', 'invalid_output_format')
)
@ddt.unpack
@unpack
def test_invalid_transcript_format(self, input_format, output_format):
"""
Tests that transcript conversion raises `AssertionError` on invalid input/output formats.
Expand Down Expand Up @@ -95,3 +100,97 @@ def test_convert_invalid_srt_to_sjson(self):
invalid_srt_transcript = b'invalid SubRip file content'
with self.assertRaises(TranscriptsGenerationException):
Transcript.convert(invalid_srt_transcript, 'srt', 'sjson')


@ddt
class TestCredentialsUtils(TestCase):
"""
Test Suite for various transcript credential utilities.
"""

CIELO24_LOGIN_URL = "https://sandbox.cielo24.com/api/account/login"

@patch('edxval.transcript_utils.LOGGER')
@responses.activate
def test_cielo24_error(self, mock_logger):
"""
Test that when invalid cielo credentials are supplied, we get correct error response.
"""
expected_error_message = 'Invalid credentials supplied.'
responses.add(
responses.GET,
self.CIELO24_LOGIN_URL,
body=json.dumps({'error': expected_error_message}),
status=status.HTTP_400_BAD_REQUEST
)

credentials = {
'org': 'test',
'provider': TranscriptProviderType.CIELO24,
'api_key': 'test-api-key',
'username': 'test-cielo-user',
'api_secret_key': ''
}
error_type, error_message, _ = validate_transcript_credentials(**credentials)
self.assertEqual(error_type, TranscriptionProviderErrorType.INVALID_CREDENTIALS)
self.assertEqual(error_message, expected_error_message)

mock_logger.warning.assert_called_with(
'[Transcript Credentials] Unable to get api token -- response %s -- status %s.',
json.dumps({'error': error_message}),
status.HTTP_400_BAD_REQUEST
)

@data(
{
'provider': 'unsupported-provider'
},
{
'org': 'test',
'api_key': 'test-api-key'
}
)
def test_transcript_credentials_invalid_provider(self, credentials):
"""
Test that validating credentials gives proper error in case of invalid provider.
"""
provider = credentials.pop('provider', '')
error_type, error_message, _ = validate_transcript_credentials(provider, **credentials)
self.assertEqual(error_type, TranscriptionProviderErrorType.INVALID_PROVIDER)
self.assertEqual(error_message, 'Invalid provider {provider}.'.format(provider=provider))

@data(
(
{'provider': TranscriptProviderType.CIELO24},
'org and api_key and username'
),
(
{'provider': TranscriptProviderType.THREE_PLAY_MEDIA},
'org and api_key and api_secret_key'
),
(
{'provider': TranscriptProviderType.CIELO24, 'org': 'test-org'},
'api_key and username'
),
(
{'provider': TranscriptProviderType.CIELO24, 'org': 'test-org', 'api_key': 'test-api-key'},
'username'
),
(
{'org': 'test', 'provider': TranscriptProviderType.THREE_PLAY_MEDIA, 'api_key': 'test-api-key'},
'api_secret_key'
)
)
@unpack
def test_transcript_credentials_error(self, credentials, missing_keys):
"""
Test that validating credentials gives proper error in case of invalid input.
"""
provider = credentials.pop('provider')
expected_error_message = '{missing} must be specified for {provider}.'.format(
provider=provider,
missing=missing_keys
)
error_type, error_message, _ = validate_transcript_credentials(provider, **credentials)
self.assertEqual(error_type, TranscriptionProviderErrorType.MISSING_REQUIRED_ATTRIBUTES)
self.assertEqual(error_message, expected_error_message)
Loading