diff --git a/openedx/core/djangoapps/video_pipeline/api.py b/openedx/core/djangoapps/video_pipeline/api.py index e9289fe654..a6a335699b 100644 --- a/openedx/core/djangoapps/video_pipeline/api.py +++ b/openedx/core/djangoapps/video_pipeline/api.py @@ -5,11 +5,13 @@ import json import logging from django.core.exceptions import ObjectDoesNotExist +from provider.oauth2.models import Client from slumber.exceptions import HttpClientError from openedx.core.djangoapps.video_pipeline.models import VideoPipelineIntegration from openedx.core.djangoapps.video_pipeline.utils import create_video_pipeline_api_client + log = logging.getLogger(__name__) @@ -29,10 +31,16 @@ def update_3rd_party_transcription_service_credentials(**credentials_payload): if pipeline_integration.enabled: try: video_pipeline_user = pipeline_integration.get_service_user() + oauth_client = Client.objects.get(name=pipeline_integration.client_name) except ObjectDoesNotExist: return error_response, is_updated - client = create_video_pipeline_api_client(user=video_pipeline_user, api_url=pipeline_integration.api_url) + client = create_video_pipeline_api_client( + user=video_pipeline_user, + api_client_id=oauth_client.client_id, + api_client_secret=oauth_client.client_secret, + api_url=pipeline_integration.api_url + ) try: client.transcript_credentials.post(credentials_payload) diff --git a/openedx/core/djangoapps/video_pipeline/migrations/0002_auto_20171114_0704.py b/openedx/core/djangoapps/video_pipeline/migrations/0002_auto_20171114_0704.py new file mode 100644 index 0000000000..904f9ceb17 --- /dev/null +++ b/openedx/core/djangoapps/video_pipeline/migrations/0002_auto_20171114_0704.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('video_pipeline', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='videopipelineintegration', + name='client_name', + field=models.CharField(default=b'VEDA-Prod', help_text='Oauth client name of video pipeline service.', max_length=100), + ), + migrations.AlterField( + model_name='videopipelineintegration', + name='service_username', + field=models.CharField(default=b'veda_service_user', help_text='Username created for Video Pipeline Integration, e.g. veda_service_user.', max_length=100), + ), + ] diff --git a/openedx/core/djangoapps/video_pipeline/models.py b/openedx/core/djangoapps/video_pipeline/models.py index fa3ae783cb..35c96d7100 100644 --- a/openedx/core/djangoapps/video_pipeline/models.py +++ b/openedx/core/djangoapps/video_pipeline/models.py @@ -11,6 +11,14 @@ class VideoPipelineIntegration(ConfigurationModel): """ Manages configuration for connecting to the edx-video-pipeline service and using its API. """ + client_name = models.CharField( + max_length=100, + default='VEDA-Prod', + null=False, + blank=False, + help_text=_('Oauth client name of video pipeline service.') + ) + api_url = models.URLField( verbose_name=_('Internal API URL'), help_text=_('edx-video-pipeline API URL.') @@ -18,10 +26,10 @@ class VideoPipelineIntegration(ConfigurationModel): service_username = models.CharField( max_length=100, - default='video_pipeline_service_user', + default='veda_service_user', null=False, blank=False, - help_text=_('Username created for Video Pipeline Integration, e.g. video_pipeline_service_user.') + help_text=_('Username created for Video Pipeline Integration, e.g. veda_service_user.') ) def get_service_user(self): diff --git a/openedx/core/djangoapps/video_pipeline/tests/mixins.py b/openedx/core/djangoapps/video_pipeline/tests/mixins.py index a1e2c0928d..47d230e142 100644 --- a/openedx/core/djangoapps/video_pipeline/tests/mixins.py +++ b/openedx/core/djangoapps/video_pipeline/tests/mixins.py @@ -1,6 +1,9 @@ """ Mixins to test video pipeline integration. """ +from provider.constants import CONFIDENTIAL +from provider.oauth2.models import Client + from openedx.core.djangoapps.video_pipeline.models import VideoPipelineIntegration @@ -12,6 +15,17 @@ class VideoPipelineIntegrationMixin(object): 'enabled': True, 'api_url': 'https://video-pipeline.example.com/api/v1/', 'service_username': 'cms_video_pipeline_service_user', + 'client_name': 'video_pipeline' + } + + video_pipelien_oauth_client_defaults = { + 'name': 'video_pipeline', + 'url': 'https://video-pipeline.example.com/api/v1/', + 'redirect_uri': 'https://video-pipeline.example.com/api/v1/redirect', + 'logout_uri': 'https://video-pipeline.example.com/api/v1/logout', + 'client_id': 'video_pipeline_client_id', + 'client_secret': 'video_pipeline_client_secret', + 'client_type': CONFIDENTIAL } def create_video_pipeline_integration(self, **kwargs): @@ -21,3 +35,12 @@ class VideoPipelineIntegrationMixin(object): """ fields = dict(self.video_pipeline_integration_defaults, **kwargs) return VideoPipelineIntegration.objects.create(**fields) + + def create_video_pipeline_oauth_client(self, user, **kwargs): + """ + Creates a new `Client` record with `video_pipelien_oauth_client_defaults`, + and it can be updated with any provided overrides. + """ + fields = dict(self.video_pipelien_oauth_client_defaults, **kwargs) + fields['user'] = user + return Client.objects.create(**fields) diff --git a/openedx/core/djangoapps/video_pipeline/tests/test_api.py b/openedx/core/djangoapps/video_pipeline/tests/test_api.py index d93118fb13..b500dfa4b5 100644 --- a/openedx/core/djangoapps/video_pipeline/tests/test_api.py +++ b/openedx/core/djangoapps/video_pipeline/tests/test_api.py @@ -22,6 +22,7 @@ class TestAPIUtils(VideoPipelineIntegrationMixin, TestCase): def setUp(self): self.pipeline_integration = self.create_video_pipeline_integration() self.user = UserFactory(username=self.pipeline_integration.service_username) + self.oauth_client = self.create_video_pipeline_oauth_client(user=self.user) def test_update_transcription_service_credentials_with_integration_disabled(self): """ @@ -41,6 +42,15 @@ class TestAPIUtils(VideoPipelineIntegrationMixin, TestCase): __, is_updated = update_3rd_party_transcription_service_credentials() self.assertFalse(is_updated) + def test_update_transcription_service_credentials_with_unknown_oauth_client(self): + """ + Test updating the credentials when expected oauth cleint is not present. + """ + self.pipeline_integration.client_name = 'non_existent_client' + self.pipeline_integration.save() + __, is_updated = update_3rd_party_transcription_service_credentials() + self.assertFalse(is_updated) + @ddt.data( { 'username': 'Jason_cielo_24', diff --git a/openedx/core/djangoapps/video_pipeline/utils.py b/openedx/core/djangoapps/video_pipeline/utils.py index df7b8b49a0..58290d96ac 100644 --- a/openedx/core/djangoapps/video_pipeline/utils.py +++ b/openedx/core/djangoapps/video_pipeline/utils.py @@ -1,19 +1,25 @@ +""" +Utils for video_pipeline app. +""" from django.conf import settings from edx_rest_api_client.client import EdxRestApiClient from openedx.core.lib.token_utils import JwtBuilder -def create_video_pipeline_api_client(user, api_url): +def create_video_pipeline_api_client(user, api_client_id, api_client_secret, api_url): """ Returns an API client which can be used to make Video Pipeline API requests. Arguments: user(User): A requesting user. + api_client_id(unicode): Video pipeline client id. + api_client_secret(unicode): Video pipeline client secret. api_url(unicode): It is video pipeline's API URL. """ - jwt_token = JwtBuilder(user).build_token( + jwt_token = JwtBuilder(user, secret=api_client_secret).build_token( scopes=[], - expires_in=settings.OAUTH_ID_TOKEN_EXPIRATION + expires_in=settings.OAUTH_ID_TOKEN_EXPIRATION, + aud=api_client_id ) return EdxRestApiClient(api_url, jwt=jwt_token)