[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
This commit is contained in:
@@ -17,6 +17,8 @@ from django.views.decorators.http import require_http_methods
|
||||
from opaque_keys import InvalidKeyError
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
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 cms.djangoapps.course_creators.views import get_course_creator_status
|
||||
@@ -183,6 +185,7 @@ def _create_library(request):
|
||||
try:
|
||||
display_name = request.json['display_name']
|
||||
org = request.json['org']
|
||||
ensure_organization(org)
|
||||
library = request.json.get('number', None)
|
||||
if library is None:
|
||||
library = request.json['library']
|
||||
@@ -215,6 +218,13 @@ def _create_library(request):
|
||||
'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)
|
||||
return JsonResponse({
|
||||
|
||||
@@ -8,10 +8,13 @@ More important high-level tests are in contentstore/tests/test_libraries.py
|
||||
import ddt
|
||||
import mock
|
||||
from django.conf import settings
|
||||
from django.test.utils import override_settings
|
||||
from django.urls import reverse
|
||||
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 six import binary_type, text_type
|
||||
from six import text_type
|
||||
from six.moves import range
|
||||
|
||||
from cms.djangoapps.contentstore.tests.utils import AjaxEnabledTestClient, CourseTestCase, parse_json
|
||||
@@ -125,7 +128,7 @@ class UnitTestLibraries(CourseTestCase):
|
||||
"""
|
||||
# Create some more libraries
|
||||
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)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
@@ -227,6 +230,41 @@ class UnitTestLibraries(CourseTestCase):
|
||||
self.assertIn('already a library defined', parse_json(response)['ErrMsg'])
|
||||
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
|
||||
|
||||
@@ -308,7 +346,11 @@ class UnitTestLibraries(CourseTestCase):
|
||||
lib.save()
|
||||
|
||||
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'
|
||||
|
||||
Reference in New Issue
Block a user