diff --git a/lms/djangoapps/verify_student/services.py b/lms/djangoapps/verify_student/services.py index 435cc1e18f..ab29d05107 100644 --- a/lms/djangoapps/verify_student/services.py +++ b/lms/djangoapps/verify_student/services.py @@ -46,5 +46,12 @@ class ReverificationService(object): """ course_key = CourseKey.from_string(course_id) VerificationCheckpoint.objects.get_or_create(course_id=course_key, checkpoint_name=checkpoint_name) - re_verification_link = reverse("verify_student_incourse_reverify", args=(course_id, checkpoint_name, item_id)) + re_verification_link = reverse( + 'verify_student_incourse_reverify', + args=( + unicode(course_key), + unicode(checkpoint_name), + unicode(item_id) + ) + ) return re_verification_link diff --git a/lms/djangoapps/verify_student/tests/test_services.py b/lms/djangoapps/verify_student/tests/test_services.py new file mode 100644 index 0000000000..5af5b3006e --- /dev/null +++ b/lms/djangoapps/verify_student/tests/test_services.py @@ -0,0 +1,64 @@ +# encoding: utf-8 +""" +Tests of reverify service. +""" +import ddt +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory +from student.tests.factories import UserFactory +from course_modes.tests.factories import CourseModeFactory +from verify_student.services import ReverificationService +from verify_student.models import VerificationCheckpoint, VerificationStatus + + +@ddt.ddt +class TestReverifyService(ModuleStoreTestCase): + """ + Tests for the re-verification service + """ + + def setUp(self): + super(TestReverifyService, self).setUp() + + self.user = UserFactory.create(username="rusty", password="test") + course = CourseFactory.create(org='Robot', number='999', display_name='Test Course') + self.course_key = course.id + CourseModeFactory( + mode_slug="verified", + course_id=self.course_key, + min_price=100, + suggested_prices='' + ) + self.item = ItemFactory.create(parent=course, category='chapter', display_name='Test Section') + + @ddt.data("final_term", "mid_term") + def test_start_verification(self, checkpoint_name): + """Testing start verification service. If checkpoint exists for specific course then returns the checkpoint + otherwise created that checkpoint. + """ + + rev = ReverificationService() + rev.start_verification(unicode(self.course_key), checkpoint_name, self.item.location) + expected_url = ( + '/verify_student/reverify' + '/{course_key}' + '/{checkpoint_name}' + '/{usage_id}/' + ).format(course_key=unicode(self.course_key), checkpoint_name=checkpoint_name, usage_id=self.item.location) + + self.assertEqual( + expected_url, rev.start_verification(unicode(self.course_key), checkpoint_name, self.item.location) + ) + + def test_get_status(self): + """ Check if the user has any verification attempt for the checkpoint and course_id """ + + checkpoint_name = 'final_term' + rev = ReverificationService() + self.assertIsNone(rev.get_status(self.user.id, unicode(self.course_key), checkpoint_name)) + checkpoint_obj = VerificationCheckpoint.objects.create( + course_id=unicode(self.course_key), checkpoint_name=checkpoint_name + ) + + VerificationStatus.objects.create(checkpoint=checkpoint_obj, user=self.user, status='submitted') + self.assertEqual(rev.get_status(self.user.id, unicode(self.course_key), checkpoint_name), 'submitted') diff --git a/lms/djangoapps/verify_student/tests/test_views.py b/lms/djangoapps/verify_student/tests/test_views.py index 05000bb1e1..3cb81a82e7 100644 --- a/lms/djangoapps/verify_student/tests/test_views.py +++ b/lms/djangoapps/verify_student/tests/test_views.py @@ -1888,5 +1888,5 @@ class TestInCourseReverifyView(ModuleStoreTestCase): kwargs={ "course_id": unicode(course_key), "checkpoint_name": checkpoint, - "location": unicode(self.reverification_location) + "usage_id": unicode(self.reverification_location) }) diff --git a/lms/djangoapps/verify_student/urls.py b/lms/djangoapps/verify_student/urls.py index 00ff3b0a79..0010b6d451 100644 --- a/lms/djangoapps/verify_student/urls.py +++ b/lms/djangoapps/verify_student/urls.py @@ -143,8 +143,10 @@ urlpatterns = patterns( # Users are sent to this end-point from within courseware # to re-verify their identities by re-submitting face photos. url( - r'^reverify/{course_id}/{checkpoint}/(?P.*)/$'.format( - course_id=settings.COURSE_ID_PATTERN, checkpoint=settings.CHECKPOINT_PATTERN + r'^reverify/{course_id}/{checkpoint}/{usage_id}/$'.format( + course_id=settings.COURSE_ID_PATTERN, + checkpoint=settings.CHECKPOINT_PATTERN, + usage_id=settings.USAGE_ID_PATTERN ), views.InCourseReverifyView.as_view(), name="verify_student_incourse_reverify" diff --git a/lms/djangoapps/verify_student/views.py b/lms/djangoapps/verify_student/views.py index 2928be0703..6367f69978 100644 --- a/lms/djangoapps/verify_student/views.py +++ b/lms/djangoapps/verify_student/views.py @@ -1115,9 +1115,10 @@ class InCourseReverifyView(View): Does not need to worry about pricing """ @method_decorator(login_required) - def get(self, request, course_id, checkpoint_name, location): + def get(self, request, course_id, checkpoint_name, usage_id): """ Display the view for face photo submission""" # Check the in-course re-verification is enabled or not + incourse_reverify_enabled = InCourseReverificationConfiguration.current().enabled if not incourse_reverify_enabled: raise Http404 @@ -1146,12 +1147,12 @@ class InCourseReverifyView(View): 'course_name': course.display_name_with_default, 'checkpoint_name': checkpoint_name, 'platform_name': settings.PLATFORM_NAME, - 'location': location + 'usage_id': usage_id } return render_to_response("verify_student/incourse_reverify.html", context) @method_decorator(login_required) - def post(self, request, course_id, checkpoint_name, location): + def post(self, request, course_id, checkpoint_name, usage_id): """Submits the re-verification attempt to SoftwareSecure Args: @@ -1172,7 +1173,7 @@ class InCourseReverifyView(View): user = request.user try: course_key = CourseKey.from_string(course_id) - usage_key = UsageKey.from_string(location).replace(course_key=course_key) + usage_key = UsageKey.from_string(usage_id).replace(course_key=course_key) except InvalidKeyError: raise Http404(u"Invalid course_key or usage_key") course = modulestore().get_course(course_key) @@ -1187,7 +1188,7 @@ class InCourseReverifyView(View): 'error': True, 'errorMsg': _("No checkpoint found"), 'platform_name': settings.PLATFORM_NAME, - 'location': location + 'usage_id': usage_id } return render_to_response("verify_student/incourse_reverify.html", context) init_verification = SoftwareSecurePhotoVerification.get_initial_verification(user) diff --git a/lms/envs/common.py b/lms/envs/common.py index ba3a01992b..1b72043016 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -2252,7 +2252,7 @@ ECOMMERCE_API_SIGNING_KEY = None ECOMMERCE_API_TIMEOUT = 5 # Reverification checkpoint name pattern -CHECKPOINT_PATTERN = r'(?P\w+)' +CHECKPOINT_PATTERN = r'(?P[\w ]+)' # For the fields override feature # If using FEATURES['INDIVIDUAL_DUE_DATES'], you should add diff --git a/lms/static/js/verify_student/incourse_reverify.js b/lms/static/js/verify_student/incourse_reverify.js index faa0bea90b..61bb2e0ae6 100644 --- a/lms/static/js/verify_student/incourse_reverify.js +++ b/lms/static/js/verify_student/incourse_reverify.js @@ -22,7 +22,7 @@ courseKey: el.data('course-key'), checkpointName: el.data('checkpoint-name'), platformName: el.data('platform-name'), - location: el.data('location'), + usageId: el.data('usage-id'), errorModel: errorView.model }).render(); diff --git a/lms/static/js/verify_student/models/reverification_model.js b/lms/static/js/verify_student/models/reverification_model.js index a5dbc5b63b..566dfe375f 100644 --- a/lms/static/js/verify_student/models/reverification_model.js +++ b/lms/static/js/verify_student/models/reverification_model.js @@ -18,7 +18,7 @@ var edx = edx || {}; courseKey: '', checkpointName: '', faceImage: '', - location: '' + usageId: '' }, sync: function( method ) { @@ -28,10 +28,10 @@ var edx = edx || {}; face_image: model.get( 'faceImage' ) }, url = _.str.sprintf( - '/verify_student/reverify/%(courseKey)s/%(checkpointName)s/%(location)s/', { + '/verify_student/reverify/%(courseKey)s/%(checkpointName)s/%(usageId)s/', { courseKey: model.get('courseKey'), checkpointName: model.get('checkpointName'), - location: model.get('location') + usageId: model.get('usageId') } ); diff --git a/lms/static/js/verify_student/views/incourse_reverify_view.js b/lms/static/js/verify_student/views/incourse_reverify_view.js index 2d6ebf6f3f..621a530f9d 100644 --- a/lms/static/js/verify_student/views/incourse_reverify_view.js +++ b/lms/static/js/verify_student/views/incourse_reverify_view.js @@ -28,13 +28,13 @@ this.courseKey = obj.courseKey || null; this.checkpointName = obj.checkpointName || null; this.platformName = obj.platformName || null; - this.location = obj.location || null; + this.usageId = obj.usageId || null; this.model = new edx.verify_student.ReverificationModel({ courseKey: this.courseKey, checkpointName: this.checkpointName, - location: this.location + usageId: this.usageId }); this.listenTo( this.model, 'sync', _.bind( this.handleSubmitPhotoSuccess, this )); diff --git a/lms/templates/verify_student/incourse_reverify.html b/lms/templates/verify_student/incourse_reverify.html index c2228e7ec3..554dcddbe3 100644 --- a/lms/templates/verify_student/incourse_reverify.html +++ b/lms/templates/verify_student/incourse_reverify.html @@ -46,7 +46,7 @@ checkpoint_name=checkpoint_name)} data-course-key='${course_key}' data-checkpoint-name='${checkpoint_name}' data-platform-name='${platform_name}' - data-location='${location}' + data-usage-id='${usage_id}' >