From 027a9bd2cce8250985cf886c613185e26293becf Mon Sep 17 00:00:00 2001
From: jansenk <jkantor@edx.org>
Date: Fri, 14 Jun 2019 14:22:26 -0400
Subject: [PATCH] add api access request management command

---
 .../commands/create_api_access_request.py     | 101 ++++++++++++++++++
 .../tests/test_create_api_access_request.py   |  97 +++++++++++++++++
 2 files changed, 198 insertions(+)
 create mode 100644 openedx/core/djangoapps/api_admin/management/commands/create_api_access_request.py
 create mode 100644 openedx/core/djangoapps/api_admin/management/commands/tests/test_create_api_access_request.py

diff --git a/openedx/core/djangoapps/api_admin/management/commands/create_api_access_request.py b/openedx/core/djangoapps/api_admin/management/commands/create_api_access_request.py
new file mode 100644
index 00000000000..0073acc7063
--- /dev/null
+++ b/openedx/core/djangoapps/api_admin/management/commands/create_api_access_request.py
@@ -0,0 +1,101 @@
+""" Management command to create an ApiAccessRequest for given users """
+import logging
+from django.core.management.base import BaseCommand, CommandError
+from django.contrib.auth.models import User
+from django.contrib.sites.models import Site
+
+from openedx.core.djangoapps.api_admin.models import (
+    ApiAccessConfig,
+    ApiAccessRequest,
+)
+
+logger = logging.getLogger(__name__)
+
+
+class Command(BaseCommand):
+    """
+    Create an ApiAccessRequest for the given user
+
+    Example usage:
+        $ ./manage.py lms create_api_request <username> --create-config
+    """
+
+    help = 'Create an ApiAccessRequest for the given user'
+    DEFAULT_WEBSITE = 'www.test-edx-example-website.edu'
+    DEFAULT_REASON = 'Generated by management job create_api_request'
+
+    def add_arguments(self, parser):
+        parser.add_argument('username')
+        parser.add_argument(
+            '--create-config',
+            action='store_true',
+            help='Create ApiAccessConfig if it does not exist'
+        )
+        parser.add_argument(
+            '--status',
+            choices=[choice[0] for choice in ApiAccessRequest.STATUS_CHOICES],
+            default=ApiAccessRequest.APPROVED,
+            help='Status of the created ApiAccessRequest'
+        )
+        parser.add_argument(
+            '--reason',
+            default=self.DEFAULT_REASON,
+            help='Reason that the ApiAccessRequest is being created'
+        )
+        parser.add_argument(
+            '--website',
+            default=self.DEFAULT_WEBSITE,
+            help='Website associated with the user of the created ApiAccessRequest'
+        )
+
+    def handle(self, *args, **options):
+        if options.get('create_config'):
+            self.create_api_access_config()
+        user = self.get_user(options.get('username'))
+        self.create_api_access_request(
+            user,
+            options.get('status'),
+            options.get('reason'),
+            options.get('website'),
+        )
+
+    def get_user(self, username):
+        try:
+            return User.objects.get(username=username)
+        except User.DoesNotExist:
+            raise CommandError(u'User {} not found'.format(username))
+
+    def create_api_access_request(self, user, status, reason, website):
+        """
+        Creates an ApiAccessRequest with the given values.
+        """
+        try:
+            ApiAccessRequest.objects.create(
+                user=user,
+                status=status,
+                website=website,
+                reason=reason,
+                site=Site.objects.get_current(),
+            )
+        except Exception as e:
+            msg = u'Unable to create ApiAccessRequest for {}. Exception is {}: {}'.format(
+                user.username,
+                type(e).__name__,
+                e
+            )
+            raise CommandError(msg)
+        logger.info(u'Created ApiAccessRequest for user {}'.format(user.username))
+
+    def create_api_access_config(self):
+        """
+        Creates an active ApiAccessConfig if one does not currectly exist
+        """
+        try:
+            _, created = ApiAccessConfig.objects.get_or_create(enabled=True)
+        except Exception as e:
+            msg = u'Unable to create ApiAccessConfig. Exception is {}: {}'.format(type(e).__name__, e)
+            raise CommandError(msg)
+        if created:
+            logger.info(u'Created ApiAccessConfig')
+        else:
+            logger.info(u'ApiAccessConfig already exists')
diff --git a/openedx/core/djangoapps/api_admin/management/commands/tests/test_create_api_access_request.py b/openedx/core/djangoapps/api_admin/management/commands/tests/test_create_api_access_request.py
new file mode 100644
index 00000000000..118730974f8
--- /dev/null
+++ b/openedx/core/djangoapps/api_admin/management/commands/tests/test_create_api_access_request.py
@@ -0,0 +1,97 @@
+from mock import patch
+
+import ddt
+from django.conf import settings
+from django.contrib.sites.models import Site
+from django.core.management import call_command
+from django.core.management.base import CommandError
+from django.test import TestCase
+import unittest
+
+from openedx.core.djangoapps.api_admin.management.commands import create_api_access_request
+from openedx.core.djangoapps.api_admin.models import (
+    ApiAccessConfig,
+    ApiAccessRequest,
+)
+from student.tests.factories import UserFactory
+
+
+@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Tests only valid in lms')
+@ddt.ddt
+class TestCreateApiAccessRequest(TestCase):
+    """ Test create_api_access_request command """
+
+    @classmethod
+    def setUpClass(cls):
+        super(TestCreateApiAccessRequest, cls).setUpClass()
+        cls.command = 'create_api_access_request'
+        cls.user = UserFactory()
+
+    def assert_models_exist(self, expect_request_exists, expect_config_exists):
+        self.assertEqual(
+            ApiAccessRequest.objects.filter(user=self.user).exists(),
+            expect_request_exists
+        )
+        self.assertEqual(
+            ApiAccessConfig.objects.filter(enabled=True).exists(),
+            expect_config_exists
+        )
+
+    @ddt.data(False, True)
+    def test_create_api_access_request(self, create_config):
+        self.assert_models_exist(False, False)
+        call_command(self.command, self.user.username, create_config=create_config)
+        self.assert_models_exist(True, create_config)
+
+    def test_config_already_exists(self):
+        ApiAccessConfig.objects.create(enabled=True)
+        self.assert_models_exist(False, True)
+        call_command(self.command, self.user.username, create_config=True)
+        self.assert_models_exist(True, True)
+
+    def test_user_not_found(self):
+        with self.assertRaisesRegex(CommandError, r'User .*? not found'):
+            call_command(self.command, 'not-a-user-notfound-nope')
+
+    @patch('openedx.core.djangoapps.api_admin.models.ApiAccessRequest.objects.create')
+    def test_api_request_error(self, mocked_method):
+        mocked_method.side_effect = Exception()
+
+        self.assert_models_exist(False, False)
+
+        with self.assertRaisesRegex(CommandError, r'Unable to create ApiAccessRequest .*'):
+            call_command(self.command, self.user.username)
+
+        self.assert_models_exist(False, False)
+
+    @patch('openedx.core.djangoapps.api_admin.models.ApiAccessConfig.objects.get_or_create')
+    def test_api_config_error(self, mocked_method):
+        mocked_method.side_effect = Exception()
+        self.assert_models_exist(False, False)
+
+        with self.assertRaisesRegex(CommandError, r'Unable to create ApiAccessConfig\. .*'):
+            call_command(self.command, self.user.username, create_config=True)
+
+        self.assert_models_exist(False, False)
+
+    def test_optional_fields(self):
+        self.assert_models_exist(False, False)
+
+        call_command(
+            self.command,
+            self.user.username,
+            status='approved',
+            reason='whatever',
+            website='test-site.edx.horse'
+        )
+        self.assert_models_exist(True, False)
+        request = ApiAccessRequest.objects.get(user=self.user)
+        self.assertEqual(request.status, 'approved')
+        self.assertEqual(request.reason, 'whatever')
+        self.assertEqual(request.website, 'test-site.edx.horse')
+
+    def test_default_values(self):
+        call_command(self.command, self.user.username)
+        request = ApiAccessRequest.objects.get(user=self.user)
+        self.assertEqual(request.site, Site.objects.get_current())
+        self.assertEqual(request.status, ApiAccessRequest.APPROVED)
-- 
GitLab