From 0d7f34b5d3dafe8ca37113503699b9c24e16f402 Mon Sep 17 00:00:00 2001 From: Waqas Date: Tue, 29 Apr 2014 18:04:01 +0500 Subject: [PATCH] Update the software secure result call back by correcting the typo LMS-2516 --- .../verify_student/tests/test_views.py | 216 ++++++++++++++++++ lms/djangoapps/verify_student/views.py | 2 +- lms/envs/test.py | 6 + 3 files changed, 223 insertions(+), 1 deletion(-) diff --git a/lms/djangoapps/verify_student/tests/test_views.py b/lms/djangoapps/verify_student/tests/test_views.py index 22e406f776..47988dde44 100644 --- a/lms/djangoapps/verify_student/tests/test_views.py +++ b/lms/djangoapps/verify_student/tests/test_views.py @@ -10,11 +10,14 @@ verify_student/start?course_id=MITx/6.002x/2013_Spring # create ---> To Payment """ +import json +import mock import urllib from mock import patch, Mock import pytz from datetime import timedelta, datetime +from django.test.client import Client from django.test import TestCase from django.test.utils import override_settings from django.conf import settings @@ -31,6 +34,7 @@ from verify_student.models import SoftwareSecurePhotoVerification from reverification.tests.factories import MidcourseReverificationWindowFactory + def mock_render_to_response(*args, **kwargs): return render_to_response(*args, **kwargs) @@ -122,6 +126,218 @@ class TestReverifyView(TestCase): self.assertTrue(context['error']) +@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) +class TestPhotoVerificationResultsCallback(TestCase): + """ + Tests for the results_callback view. + """ + def setUp(self): + self.course_id = 'Robot/999/Test_Course' + CourseFactory.create(org='Robot', number='999', display_name='Test Course') + self.user = UserFactory.create() + self.attempt = SoftwareSecurePhotoVerification( + status="submitted", + user=self.user + ) + self.attempt.save() + self.receipt_id = self.attempt.receipt_id + self.client = Client() + + def mocked_has_valid_signature(method, headers_dict, body_dict, access_key, secret_key): + return True + + def test_invalid_json(self): + """ + Test for invalid json being posted by software secure. + """ + data = {"Testing invalid"} + response = self.client.post( + reverse('verify_student_results_callback'), + data=data, + content_type='application/json', + HTTP_AUTHORIZATION='test BBBBBBBBBBBBBBBBBBBB: testing', + HTTP_DATE='testdate' + ) + self.assertIn('Invalid JSON', response.content) + self.assertEqual(response.status_code, 400) + + def test_invalid_dict(self): + """ + Test for invalid dictionary being posted by software secure. + """ + data = '"\\"Test\\tTesting"' + response = self.client.post( + reverse('verify_student_results_callback'), + data=data, + content_type='application/json', + HTTP_AUTHORIZATION='test BBBBBBBBBBBBBBBBBBBB:testing', + HTTP_DATE='testdate' + ) + self.assertIn('JSON should be dict', response.content) + self.assertEqual(response.status_code, 400) + + @mock.patch('verify_student.ssencrypt.has_valid_signature', mock.Mock(side_effect=mocked_has_valid_signature)) + def test_invalid_access_key(self): + """ + Test for invalid access key. + """ + data = { + "EdX-ID": self.receipt_id, + "Result": "Testing", + "Reason": "Testing", + "MessageType": "Testing" + } + json_data = json.dumps(data) + response = self.client.post( + reverse('verify_student_results_callback'), + data=json_data, + content_type='application/json', + HTTP_AUTHORIZATION='test testing:testing', + HTTP_DATE='testdate' + ) + self.assertIn('Access key invalid', response.content) + self.assertEqual(response.status_code, 400) + + @mock.patch('verify_student.ssencrypt.has_valid_signature', mock.Mock(side_effect=mocked_has_valid_signature)) + def test_wrong_edx_id(self): + """ + Test for wrong id of Software secure verification attempt. + """ + data = { + "EdX-ID": "Invalid-Id", + "Result": "Testing", + "Reason": "Testing", + "MessageType": "Testing" + } + json_data = json.dumps(data) + response = self.client.post( + reverse('verify_student_results_callback'), + data=json_data, + content_type='application/json', + HTTP_AUTHORIZATION='test BBBBBBBBBBBBBBBBBBBB:testing', + HTTP_DATE='testdate' + ) + self.assertIn('edX ID Invalid-Id not found', response.content) + self.assertEqual(response.status_code, 400) + + @mock.patch('verify_student.ssencrypt.has_valid_signature', mock.Mock(side_effect=mocked_has_valid_signature)) + def test_pass_result(self): + """ + Test for verification passed. + """ + data = { + "EdX-ID": self.receipt_id, + "Result": "PASS", + "Reason": "", + "MessageType": "You have been verified." + } + json_data = json.dumps(data) + response = self.client.post( + reverse('verify_student_results_callback'), data=json_data, + content_type='application/json', + HTTP_AUTHORIZATION='test BBBBBBBBBBBBBBBBBBBB:testing', + HTTP_DATE='testdate' + ) + attempt = SoftwareSecurePhotoVerification.objects.get(receipt_id=self.receipt_id) + self.assertEqual(attempt.status, u'approved') + self.assertEquals(response.content, 'OK!') + + @mock.patch('verify_student.ssencrypt.has_valid_signature', mock.Mock(side_effect=mocked_has_valid_signature)) + def test_fail_result(self): + """ + Test for failed verification. + """ + data = { + "EdX-ID": self.receipt_id, + "Result": 'FAIL', + "Reason": 'Invalid photo', + "MessageType": 'Your photo doesn\'t meet standards.' + } + json_data = json.dumps(data) + response = self.client.post( + reverse('verify_student_results_callback'), + data=json_data, + content_type='application/json', + HTTP_AUTHORIZATION='test BBBBBBBBBBBBBBBBBBBB:testing', + HTTP_DATE='testdate' + ) + attempt = SoftwareSecurePhotoVerification.objects.get(receipt_id=self.receipt_id) + self.assertEqual(attempt.status, u'denied') + self.assertEqual(attempt.error_code, u'Your photo doesn\'t meet standards.') + self.assertEqual(attempt.error_msg, u'"Invalid photo"') + self.assertEquals(response.content, 'OK!') + + @mock.patch('verify_student.ssencrypt.has_valid_signature', mock.Mock(side_effect=mocked_has_valid_signature)) + def test_system_fail_result(self): + """ + Test for software secure result system failure. + """ + data = {"EdX-ID": self.receipt_id, + "Result": 'SYSTEM FAIL', + "Reason": 'Memory overflow', + "MessageType": 'You must retry the verification.'} + json_data = json.dumps(data) + response = self.client.post( + reverse('verify_student_results_callback'), + data=json_data, + content_type='application/json', + HTTP_AUTHORIZATION='test BBBBBBBBBBBBBBBBBBBB:testing', + HTTP_DATE='testdate' + ) + attempt = SoftwareSecurePhotoVerification.objects.get(receipt_id=self.receipt_id) + self.assertEqual(attempt.status, u'must_retry') + self.assertEqual(attempt.error_code, u'You must retry the verification.') + self.assertEqual(attempt.error_msg, u'"Memory overflow"') + self.assertEquals(response.content, 'OK!') + + @mock.patch('verify_student.ssencrypt.has_valid_signature', mock.Mock(side_effect=mocked_has_valid_signature)) + def test_unknown_result(self): + """ + test for unknown software secure result + """ + data = { + "EdX-ID": self.receipt_id, + "Result": 'Unknown', + "Reason": 'Unknown reason', + "MessageType": 'Unknown message' + } + json_data = json.dumps(data) + response = self.client.post( + reverse('verify_student_results_callback'), + data=json_data, + content_type='application/json', + HTTP_AUTHORIZATION='test BBBBBBBBBBBBBBBBBBBB:testing', + HTTP_DATE='testdate' + ) + self.assertIn('Result Unknown not understood', response.content) + + @mock.patch('verify_student.ssencrypt.has_valid_signature', mock.Mock(side_effect=mocked_has_valid_signature)) + def test_reverification(self): + """ + Test software secure result for reverification window. + """ + data = { + "EdX-ID": self.receipt_id, + "Result": "PASS", + "Reason": "", + "MessageType": "You have been verified." + } + window = MidcourseReverificationWindowFactory(course_id=self.course_id) + self.attempt.window = window + self.attempt.save() + json_data = json.dumps(data) + self.assertEqual(CourseEnrollment.objects.filter(course_id=self.course_id).count(), 0) + response = self.client.post( + reverse('verify_student_results_callback'), + data=json_data, + content_type='application/json', + HTTP_AUTHORIZATION='test BBBBBBBBBBBBBBBBBBBB:testing', + HTTP_DATE='testdate' + ) + self.assertEquals(response.content, 'OK!') + self.assertIsNotNone(CourseEnrollment.objects.get(course_id=self.course_id)) + + @override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) class TestMidCourseReverifyView(TestCase): """ Tests for the midcourse reverification views """ diff --git a/lms/djangoapps/verify_student/views.py b/lms/djangoapps/verify_student/views.py index 865db0ef0e..6246b72497 100644 --- a/lms/djangoapps/verify_student/views.py +++ b/lms/djangoapps/verify_student/views.py @@ -256,7 +256,7 @@ def results_callback(request): # If this is a reverification, log an event if attempt.window: - course_id = window.course_id + course_id = attempt.window.course_id course = course_from_id(course_id) course_enrollment = CourseEnrollment.get_or_create_enrollment(attempt.user, course_id) course_enrollment.emit_event(EVENT_NAME_USER_REVERIFICATION_REVIEWED_BY_SOFTWARESECURE) diff --git a/lms/envs/test.py b/lms/envs/test.py index f0f734532d..b20a23c470 100644 --- a/lms/envs/test.py +++ b/lms/envs/test.py @@ -315,3 +315,9 @@ FEATURES['USE_MICROSITES'] = True ######### LinkedIn ######## LINKEDIN_API['COMPANY_ID'] = '0000000' + +# Setting for the testing of Software Secure Result Callback +VERIFY_STUDENT["SOFTWARE_SECURE"] = { + "API_ACCESS_KEY": "BBBBBBBBBBBBBBBBBBBB", + "API_SECRET_KEY": "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC", +}