From f1a65c588ab9b077e23cfe4dab01423f02502a99 Mon Sep 17 00:00:00 2001 From: Jillian Vogel Date: Thu, 10 Jan 2019 19:49:24 +1030 Subject: [PATCH] Adds optional args to create_dot_application command Allows for the creation of public applications, and the passing of the client_id or client_secret to the command, e.g. from a configuration playbook --- .../commands/create_dot_application.py | 28 ++++++++++- .../tests/test_create_dot_application.py | 46 +++++++++++++++++-- 2 files changed, 67 insertions(+), 7 deletions(-) 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 54142a5a0e..3ef28991b2 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 @@ -40,12 +40,30 @@ class Command(BaseCommand): dest='redirect_uris', default='', help='The redirect URI(s) for this application. Multiple URIs should be space separated.') + parser.add_argument('--public', + action='store_true', + dest='public', + default=False, + help='Make the application public? Confidential by default.') + parser.add_argument('--client-id', + action='store', + dest='client_id', + default='', + help='The client_id for this application. If omitted, one will be generated.') + parser.add_argument('--client-secret', + action='store', + dest='client_secret', + default='', + help='The client_secret for this application. If omitted, one will be generated.') def handle(self, *args, **options): app_name = options['name'] username = options['username'] grant_type = options['grant_type'] redirect_uris = options['redirect_uris'] + client_type = Application.CLIENT_PUBLIC if options['public'] else Application.CLIENT_CONFIDENTIAL + client_id = options['client_id'] + client_secret = options['client_secret'] user = User.objects.get(username=username) @@ -56,13 +74,19 @@ class Command(BaseCommand): )) return - application = Application.objects.create( + create_kwargs = dict( name=app_name, user=user, redirect_uris=redirect_uris, - client_type=Application.CLIENT_CONFIDENTIAL, + client_type=client_type, authorization_grant_type=grant_type ) + if client_id: + create_kwargs['client_id'] = client_id + if client_secret: + create_kwargs['client_secret'] = client_secret + + application = Application.objects.create(**create_kwargs) application.save() logger.info('Created {} application with id: {}, client_id: {}, and client_secret: {}'.format( app_name, 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 847aa161b6..f7e5727e7e 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 @@ -3,6 +3,8 @@ Tests the ``create_dot_application`` management command. """ from __future__ import absolute_import, unicode_literals +import ddt + from django.core.management import call_command from django.test import TestCase from oauth2_provider.models import get_application_model @@ -15,6 +17,7 @@ from ..create_dot_application import Command Application = get_application_model() +@ddt.ddt class TestCreateDotApplication(TestCase): """ Tests the ``create_dot_application`` management command. @@ -27,20 +30,53 @@ class TestCreateDotApplication(TestCase): super(TestCreateDotApplication, self).tearDown() Application.objects.filter(user=self.user).delete() - def test_create_dot_application(self): - call_command(Command(), 'testing_application', self.user.username) + @ddt.data( + (None, None, None, None), + (None, None, 'client-abc', None), + (None, None, None, 'great-big-secret'), + ('password', True, 'client-dce', 'has-a-great-big-secret'), + ) + @ddt.unpack + def test_create_dot_application(self, grant_type, public, client_id, client_secret): + # Add optional arguments if provided + call_args = ['testing_application', self.user.username] + if grant_type: + call_args.append('--grant-type') + call_args.append(grant_type) + else: + grant_type = Application.GRANT_CLIENT_CREDENTIALS + + if public: + call_args.append('--public') + client_type = Application.CLIENT_PUBLIC + else: + client_type = Application.CLIENT_CONFIDENTIAL + + if client_id: + call_args.append('--client-id') + call_args.append(client_id) + if client_secret: + call_args.append('--client-secret') + call_args.append(client_secret) + + call_command(Command(), *call_args) apps = Application.objects.filter(name='testing_application') self.assertEqual(1, len(apps)) application = apps[0] self.assertEqual('testing_application', application.name) self.assertEqual(self.user, application.user) - self.assertEqual(Application.GRANT_CLIENT_CREDENTIALS, application.authorization_grant_type) - self.assertEqual(Application.CLIENT_CONFIDENTIAL, application.client_type) + self.assertEqual(grant_type, application.authorization_grant_type) + self.assertEqual(client_type, application.client_type) self.assertEqual('', application.redirect_uris) + if client_id: + self.assertEqual(client_id, application.client_id) + if client_secret: + self.assertEqual(client_secret, application.client_secret) + # When called a second time with the same arguments, the command should # exit gracefully without creating a second application. - call_command(Command(), 'testing_application', self.user.username) + call_command(Command(), *call_args) apps = Application.objects.filter(name='testing_application') self.assertEqual(1, len(apps))