From cdfc9da4d9d5d0836e07e238b763df2eac1583a8 Mon Sep 17 00:00:00 2001 From: Awais Date: Tue, 25 Aug 2015 19:28:51 +0500 Subject: [PATCH] adding validator to make sure course exists in db before creating in otto. --- lms/djangoapps/commerce/api/v1/serializers.py | 29 +++++++++++++- .../commerce/api/v1/tests/test_serializers.py | 24 ++++++++++++ .../commerce/api/v1/tests/test_views.py | 38 +++++++++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 lms/djangoapps/commerce/api/v1/tests/test_serializers.py diff --git a/lms/djangoapps/commerce/api/v1/serializers.py b/lms/djangoapps/commerce/api/v1/serializers.py index fa8c2754f3..a904fa7238 100644 --- a/lms/djangoapps/commerce/api/v1/serializers.py +++ b/lms/djangoapps/commerce/api/v1/serializers.py @@ -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) diff --git a/lms/djangoapps/commerce/api/v1/tests/test_serializers.py b/lms/djangoapps/commerce/api/v1/tests/test_serializers.py new file mode 100644 index 0000000000..93bcb9aee3 --- /dev/null +++ b/lms/djangoapps/commerce/api/v1/tests/test_serializers.py @@ -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) diff --git a/lms/djangoapps/commerce/api/v1/tests/test_views.py b/lms/djangoapps/commerce/api/v1/tests/test_views.py index 365a286b0d..eb43f7a660 100644 --- a/lms/djangoapps/commerce/api/v1/tests/test_views.py +++ b/lms/djangoapps/commerce/api/v1/tests/test_views.py @@ -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))