diff --git a/openedx/core/djangoapps/oauth_dispatch/management/commands/create_dot_application.py b/openedx/core/djangoapps/oauth_dispatch/management/commands/create_dot_application.py index d8175aee06..f7d781b924 100644 --- a/openedx/core/djangoapps/oauth_dispatch/management/commands/create_dot_application.py +++ b/openedx/core/djangoapps/oauth_dispatch/management/commands/create_dot_application.py @@ -1,5 +1,7 @@ """ Management command for creating a Django OAuth Toolkit Application model. + +Also creates an oauth_dispatch application access if scopes are provided. """ from __future__ import unicode_literals @@ -9,6 +11,7 @@ import logging from django.contrib.auth.models import User from django.core.management.base import BaseCommand from oauth2_provider.models import get_application_model +from openedx.core.djangoapps.oauth_dispatch.models import ApplicationAccess logger = logging.getLogger(__name__) @@ -59,6 +62,35 @@ class Command(BaseCommand): dest='client_secret', default='', help='The client_secret for this application. If omitted, one will be generated.') + parser.add_argument('--scopes', + action='store', + dest='scopes', + default='', + help='Comma-separated list of scopes that this application will be allowed to request.') + + def _create_application_access(self, application, scopes): + """ + If scopes are supplied, creates an oauth_dispatch ApplicationAccess for the provided + scopes and DOT application. + """ + if not scopes: + return + + if ApplicationAccess.objects.filter(application_id=application.id).exists(): + logger.info('Application access for application {} already exists.'.format( + application.name, + )) + return + + application_access = ApplicationAccess.objects.create( + application_id=application.id, + scopes=scopes, + ) + application_access.save() + logger.info('Created application access for {} with scopes: {}'.format( + application.name, + application_access.scopes, + )) def handle(self, *args, **options): app_name = options['name'] @@ -69,6 +101,7 @@ class Command(BaseCommand): client_type = Application.CLIENT_PUBLIC if options['public'] else Application.CLIENT_CONFIDENTIAL client_id = options['client_id'] client_secret = options['client_secret'] + scopes = options['scopes'] user = User.objects.get(username=username) @@ -77,6 +110,8 @@ class Command(BaseCommand): app_name, username )) + application = Application.objects.get(user=user, name=app_name) + self._create_application_access(application, scopes) return create_kwargs = dict( @@ -100,3 +135,4 @@ class Command(BaseCommand): application.client_id, application.client_secret )) + self._create_application_access(application, scopes) diff --git a/openedx/core/djangoapps/oauth_dispatch/management/commands/tests/test_create_dot_application.py b/openedx/core/djangoapps/oauth_dispatch/management/commands/tests/test_create_dot_application.py index 7c2fe88c94..5e143cd19a 100644 --- a/openedx/core/djangoapps/oauth_dispatch/management/commands/tests/test_create_dot_application.py +++ b/openedx/core/djangoapps/oauth_dispatch/management/commands/tests/test_create_dot_application.py @@ -9,6 +9,7 @@ from django.core.management import call_command from django.test import TestCase from oauth2_provider.models import get_application_model +from openedx.core.djangoapps.oauth_dispatch.models import ApplicationAccess from student.tests.factories import UserFactory from ..create_dot_application import Command @@ -31,13 +32,13 @@ class TestCreateDotApplication(TestCase): Application.objects.filter(user=self.user).delete() @ddt.data( - (None, None, None, None, False), - (None, None, 'client-abc', None, False), - (None, None, None, 'great-big-secret', False), - ('password', True, 'client-dce', 'has-a-great-big-secret', True), + (None, None, None, None, False, None), + (None, None, 'client-abc', None, False, None), + (None, None, None, 'great-big-secret', False, 'email,profile,user_id'), + ('password', True, 'client-dce', 'has-a-great-big-secret', True, None), ) @ddt.unpack - def test_create_dot_application(self, grant_type, public, client_id, client_secret, skip_auth): + def test_create_dot_application(self, grant_type, public, client_id, client_secret, skip_auth, scopes): # Add optional arguments if provided call_args = ['testing_application', self.user.username] if grant_type: @@ -60,6 +61,9 @@ class TestCreateDotApplication(TestCase): call_args.append(client_secret) if skip_auth: call_args.append('--skip-authorization') + if scopes: + call_args.append('--scopes') + call_args.append(scopes) call_command(Command(), *call_args) @@ -78,8 +82,17 @@ class TestCreateDotApplication(TestCase): if client_secret: self.assertEqual(client_secret, application.client_secret) + if scopes: + app_access_list = ApplicationAccess.objects.filter(application_id=application.id) + self.assertEqual(1, len(app_access_list)) + app_access = app_access_list[0] + self.assertEqual(scopes.split(','), app_access.scopes) + # When called a second time with the same arguments, the command should # exit gracefully without creating a second application. call_command(Command(), *call_args) apps = Application.objects.filter(name='testing_application') self.assertEqual(1, len(apps)) + if scopes: + app_access_list = ApplicationAccess.objects.filter(application_id=application.id) + self.assertEqual(1, len(app_access_list))