Merge pull request #9461 from edx/awais786/XCOM-538-otto-admin-restrict-nonexisting-course
adding validator to make sure course exists in db before creating in …
This commit is contained in:
@@ -2,11 +2,17 @@
|
||||
from datetime import datetime
|
||||
|
||||
import pytz
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from opaque_keys import InvalidKeyError
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from rest_framework import serializers
|
||||
|
||||
from commerce.api.v1.models import Course
|
||||
from course_modes.models import CourseMode
|
||||
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
|
||||
class CourseModeSerializer(serializers.ModelSerializer):
|
||||
""" CourseMode serializer. """
|
||||
@@ -25,9 +31,30 @@ class CourseModeSerializer(serializers.ModelSerializer):
|
||||
fields = ('name', 'currency', 'price', 'sku', 'expires')
|
||||
|
||||
|
||||
def validate_course_id(course_id):
|
||||
"""
|
||||
Check that course id is valid and exists in modulestore.
|
||||
"""
|
||||
try:
|
||||
course_key = CourseKey.from_string(unicode(course_id))
|
||||
except InvalidKeyError:
|
||||
raise serializers.ValidationError(
|
||||
_("{course_id} is not a valid course key.").format(
|
||||
course_id=course_id
|
||||
)
|
||||
)
|
||||
|
||||
if not modulestore().has_course(course_key):
|
||||
raise serializers.ValidationError(
|
||||
_('Course {course_id} does not exist.').format(
|
||||
course_id=course_id
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class CourseSerializer(serializers.Serializer):
|
||||
""" Course serializer. """
|
||||
id = serializers.CharField() # pylint: disable=invalid-name
|
||||
id = serializers.CharField(validators=[validate_course_id]) # pylint: disable=invalid-name
|
||||
name = serializers.CharField(read_only=True)
|
||||
verification_deadline = serializers.DateTimeField(blank=True)
|
||||
modes = CourseModeSerializer(many=True, allow_add_remove=True)
|
||||
|
||||
24
lms/djangoapps/commerce/api/v1/tests/test_serializers.py
Normal file
24
lms/djangoapps/commerce/api/v1/tests/test_serializers.py
Normal file
@@ -0,0 +1,24 @@
|
||||
""" Commerce API v1 serializer tests. """
|
||||
from django.test import TestCase
|
||||
|
||||
from commerce.api.v1.serializers import serializers, validate_course_id
|
||||
|
||||
|
||||
class CourseValidatorTests(TestCase):
|
||||
""" Tests for Course Validator method. """
|
||||
|
||||
def test_validate_course_id_with_non_existent_course(self):
|
||||
""" Verify a validator checking non-existent courses."""
|
||||
course_key = 'non/existing/keyone'
|
||||
|
||||
error_msg = u"Course {} does not exist.".format(course_key)
|
||||
with self.assertRaisesRegexp(serializers.ValidationError, error_msg):
|
||||
validate_course_id(course_key)
|
||||
|
||||
def test_validate_course_id_with_invalid_key(self):
|
||||
""" Verify a validator checking invalid course keys."""
|
||||
course_key = 'invalidkey'
|
||||
|
||||
error_msg = u"{} is not a valid course key.".format(course_key)
|
||||
with self.assertRaisesRegexp(serializers.ValidationError, error_msg):
|
||||
validate_course_id(course_key)
|
||||
@@ -267,3 +267,41 @@ class CourseRetrieveUpdateViewTests(CourseApiViewTestMixin, ModuleStoreTestCase)
|
||||
""" Verify the view supports creating a course when authenticated with the API header key. """
|
||||
self.client.logout()
|
||||
self.assert_can_create_course(HTTP_X_EDX_API_KEY=settings.EDX_API_KEY)
|
||||
|
||||
def test_create_with_non_existent_course(self):
|
||||
""" Verify the API does not allow data to be created for courses that do not exist. """
|
||||
|
||||
permissions = Permission.objects.filter(name__in=('Can add course mode', 'Can change course mode'))
|
||||
for permission in permissions:
|
||||
self.user.user_permissions.add(permission)
|
||||
|
||||
expected_modes = [
|
||||
CourseMode(
|
||||
mode_slug=u'honor',
|
||||
min_price=150, currency=u'USD',
|
||||
sku=u'ABC123'
|
||||
)
|
||||
]
|
||||
|
||||
course_key = 'non/existing/key'
|
||||
|
||||
course_dict = {
|
||||
u'id': unicode(course_key),
|
||||
u'name': unicode('Non Existing Course'),
|
||||
u'verification_deadline': None,
|
||||
u'modes': [self._serialize_course_mode(mode) for mode in expected_modes]
|
||||
}
|
||||
|
||||
path = reverse('commerce_api:v1:courses:retrieve_update', args=[unicode(course_key)])
|
||||
|
||||
response = self.client.put(path, json.dumps(course_dict), content_type=JSON_CONTENT_TYPE)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
expected_dict = {
|
||||
'id': [
|
||||
u'Course {} does not exist.'.format(
|
||||
course_key
|
||||
)
|
||||
]
|
||||
}
|
||||
self.assertDictEqual(expected_dict, json.loads(response.content))
|
||||
|
||||
Reference in New Issue
Block a user