Skip to content
Snippets Groups Projects
Unverified Commit d4026382 authored by Kyle McCormick's avatar Kyle McCormick Committed by GitHub
Browse files

[BD-14] Ensure new content libraries map to valid organizations (#25752)

If ORGANIZATIONS_AUTOCREATE, this will create a new
org in the case that the organization is missing.

If !ORGANIZATIONS_AUTOCREATE, this will raise a
validation error in the case that the organization is
missing.

TNL-7646
parent 81a97781
No related branches found
No related tags found
No related merge requests found
...@@ -17,6 +17,8 @@ from django.views.decorators.http import require_http_methods ...@@ -17,6 +17,8 @@ from django.views.decorators.http import require_http_methods
from opaque_keys import InvalidKeyError from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.keys import CourseKey
from opaque_keys.edx.locator import LibraryLocator, LibraryUsageLocator from opaque_keys.edx.locator import LibraryLocator, LibraryUsageLocator
from organizations.api import ensure_organization
from organizations.exceptions import InvalidOrganizationException
from six import text_type from six import text_type
from cms.djangoapps.course_creators.views import get_course_creator_status from cms.djangoapps.course_creators.views import get_course_creator_status
...@@ -183,6 +185,7 @@ def _create_library(request): ...@@ -183,6 +185,7 @@ def _create_library(request):
try: try:
display_name = request.json['display_name'] display_name = request.json['display_name']
org = request.json['org'] org = request.json['org']
ensure_organization(org)
library = request.json.get('number', None) library = request.json.get('number', None)
if library is None: if library is None:
library = request.json['library'] library = request.json['library']
...@@ -215,6 +218,13 @@ def _create_library(request): ...@@ -215,6 +218,13 @@ def _create_library(request):
'change your library code so that it is unique within your organization.' 'change your library code so that it is unique within your organization.'
) )
}) })
except InvalidOrganizationException:
log.exception("Unable to create library - %s is not a valid org short_name.", org)
return JsonResponseBadRequest({
'ErrMsg': _(
"'{organization_key}' is not a valid organization identifier."
).format(organization_key=org)
})
lib_key_str = text_type(new_lib.location.library_key) lib_key_str = text_type(new_lib.location.library_key)
return JsonResponse({ return JsonResponse({
......
...@@ -8,10 +8,13 @@ More important high-level tests are in contentstore/tests/test_libraries.py ...@@ -8,10 +8,13 @@ More important high-level tests are in contentstore/tests/test_libraries.py
import ddt import ddt
import mock import mock
from django.conf import settings from django.conf import settings
from django.test.utils import override_settings
from django.urls import reverse from django.urls import reverse
from mock import patch from mock import patch
from organizations.api import get_organization_by_short_name
from organizations.exceptions import InvalidOrganizationException
from opaque_keys.edx.locator import CourseKey, LibraryLocator from opaque_keys.edx.locator import CourseKey, LibraryLocator
from six import binary_type, text_type from six import text_type
from six.moves import range from six.moves import range
from cms.djangoapps.contentstore.tests.utils import AjaxEnabledTestClient, CourseTestCase, parse_json from cms.djangoapps.contentstore.tests.utils import AjaxEnabledTestClient, CourseTestCase, parse_json
...@@ -125,7 +128,7 @@ class UnitTestLibraries(CourseTestCase): ...@@ -125,7 +128,7 @@ class UnitTestLibraries(CourseTestCase):
""" """
# Create some more libraries # Create some more libraries
libraries = [LibraryFactory.create() for _ in range(3)] libraries = [LibraryFactory.create() for _ in range(3)]
lib_dict = dict([(lib.location.library_key, lib) for lib in libraries]) lib_dict = {lib.location.library_key: lib for lib in libraries}
response = self.client.get_json(LIBRARY_REST_URL) response = self.client.get_json(LIBRARY_REST_URL)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
...@@ -227,6 +230,41 @@ class UnitTestLibraries(CourseTestCase): ...@@ -227,6 +230,41 @@ class UnitTestLibraries(CourseTestCase):
self.assertIn('already a library defined', parse_json(response)['ErrMsg']) self.assertIn('already a library defined', parse_json(response)['ErrMsg'])
self.assertEqual(response.status_code, 400) self.assertEqual(response.status_code, 400)
@override_settings(ORGANIZATIONS_AUTOCREATE=True)
def test_library_with_unknown_organization_autocreation(self):
"""
Test that when automatic organization creation is enabled,
creating a content library with an unknown organization auto-creates
said organization.
"""
with self.assertRaises(InvalidOrganizationException):
get_organization_by_short_name("org_xyz")
response = self.client.ajax_post(LIBRARY_REST_URL, {
'org': "org_xyz",
'library': "org_test_lib",
'display_name': "This library's organization doesn't exist... yet.",
})
assert response.status_code == 200
assert get_organization_by_short_name("org_xyz")
@override_settings(ORGANIZATIONS_AUTOCREATE=False)
def test_library_with_unknown_organization_validation_error(self):
"""
Test that when automatic organization creation is disabled,
creating a content library with an unknown organization raises an error.
"""
with self.assertRaises(InvalidOrganizationException):
get_organization_by_short_name("org_xyz")
response = self.client.ajax_post(LIBRARY_REST_URL, {
'org': "org_xyz",
'library': "org_test_lib",
'display_name': "This library's organization doesn't exist!",
})
assert response.status_code == 400
assert "'org_xyz' is not a valid organization identifier" in parse_json(response)['ErrMsg']
with self.assertRaises(InvalidOrganizationException):
get_organization_by_short_name("org_xyz")
###################################################### ######################################################
# Tests for /library/:lib_key/ - get a specific library as JSON or HTML editing view # Tests for /library/:lib_key/ - get a specific library as JSON or HTML editing view
...@@ -308,7 +346,11 @@ class UnitTestLibraries(CourseTestCase): ...@@ -308,7 +346,11 @@ class UnitTestLibraries(CourseTestCase):
lib.save() lib.save()
problem_type_templates = next( problem_type_templates = next(
(component['templates'] for component in get_component_templates(lib, library=True) if component['type'] == 'problem'), (
component['templates']
for component in get_component_templates(lib, library=True)
if component['type'] == 'problem'
),
[] []
) )
# Each problem template has a category which shows whether problem is a 'problem' # Each problem template has a category which shows whether problem is a 'problem'
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment