Merge pull request #20076 from edx/robrap/ARCH-603-oauth-application-access-command
ARCH-603: add optional scopes to create application access
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user