def test_validate_and_update_from_json_wrong_inputs(self): # input incorrectly formatted data is_valid, errors, test_model = CourseMetadata.validate_and_update_from_json( self.course, { "advertised_start": {"value": 1, "display_name": "Course Advertised Start Date", }, "days_early_for_beta": {"value": "supposed to be an integer", "display_name": "Days Early for Beta Users", }, "advanced_modules": {"value": 1, "display_name": "Advanced Module List", }, }, user=self.user ) # Check valid results from validate_and_update_from_json self.assertFalse(is_valid) self.assertEqual(len(errors), 3) self.assertFalse(test_model) error_keys = set([error_obj['model']['display_name'] for error_obj in errors]) test_keys = set(['Advanced Module List', 'Course Advertised Start Date', 'Days Early for Beta Users']) self.assertEqual(error_keys, test_keys) # try fresh fetch to ensure no update happened fresh = modulestore().get_course(self.course.id) test_model = CourseMetadata.fetch(fresh) self.assertNotEqual(test_model['advertised_start']['value'], 1, 'advertised_start should not be updated to a wrong value') self.assertNotEqual(test_model['days_early_for_beta']['value'], "supposed to be an integer", 'days_early_for beta should not be updated to a wrong value')
def test_validate_and_update_from_json_wrong_inputs(self): # input incorrectly formatted data is_valid, errors, test_model = CourseMetadata.validate_and_update_from_json( self.course, { "advertised_start": {"value": 1, "display_name": "Course Advertised Start Date", }, "days_early_for_beta": {"value": "supposed to be an integer", "display_name": "Days Early for Beta Users", }, "advanced_modules": {"value": 1, "display_name": "Advanced Module List", }, }, user=self.user ) # Check valid results from validate_and_update_from_json self.assertFalse(is_valid) self.assertEqual(len(errors), 3) self.assertFalse(test_model) error_keys = set([error_obj['model']['display_name'] for error_obj in errors]) test_keys = set(['Advanced Module List', 'Course Advertised Start Date', 'Days Early for Beta Users']) self.assertEqual(error_keys, test_keys) # try fresh fetch to ensure no update happened fresh = modulestore().get_course(self.course.id) test_model = CourseMetadata.fetch(fresh) self.assertNotEqual(test_model['advertised_start']['value'], 1, 'advertised_start should not be updated to a wrong value') self.assertNotEqual(test_model['days_early_for_beta']['value'], "supposed to be an integer", 'days_early_for beta should not be updated to a wrong value')
def test_validate_and_update_from_json_correct_inputs(self): is_valid, errors, test_model = CourseMetadata.validate_and_update_from_json( self.course, { "advertised_start": { "value": "start A" }, "days_early_for_beta": { "value": 2 }, "advanced_modules": { "value": ['combinedopenended'] }, }, user=self.user) self.assertTrue(is_valid) self.assertTrue(len(errors) == 0) self.update_check(test_model) # fresh fetch to ensure persistence fresh = modulestore().get_course(self.course.id) test_model = CourseMetadata.fetch(fresh) self.update_check(test_model) # Tab gets tested in test_advanced_settings_munge_tabs self.assertIn('advanced_modules', test_model, 'Missing advanced_modules') self.assertEqual(test_model['advanced_modules']['value'], ['combinedopenended'], 'advanced_module is not updated')
def test_validate_update_filtered_edxnotes_on(self): """ If feature flag is on, then edxnotes must not be filtered. """ # pylint: disable=unused-variable is_valid, errors, test_model = CourseMetadata.validate_and_update_from_json( self.course, { "edxnotes": {"value": "true"}, }, user=self.user ) self.assertIn('edxnotes', test_model)
def test_validate_update_filtered_on(self): """ If feature flag is on, then giturl must not be filtered. """ # pylint: disable=unused-variable is_valid, errors, test_model = CourseMetadata.validate_and_update_from_json( self.course, { "giturl": {"value": "http://example.com"}, }, user=self.user ) self.assertIn('giturl', test_model)
def test_validate_update_filtered_edxnotes_on(self): """ If feature flag is on, then edxnotes must not be filtered. """ # pylint: disable=unused-variable is_valid, errors, test_model = CourseMetadata.validate_and_update_from_json( self.course, { "edxnotes": {"value": "true"}, }, user=self.user ) self.assertIn('edxnotes', test_model)
def test_validate_update_filtered_on(self): """ If feature flag is on, then giturl must not be filtered. """ # pylint: disable=unused-variable is_valid, errors, test_model = CourseMetadata.validate_and_update_from_json( self.course, { "giturl": {"value": "http://example.com"}, }, user=self.user ) self.assertIn('giturl', test_model)
def post(self, request, course_id): """ POST handler """ serializer = ProctoredExamSettingsSerializer if request.user.is_staff else LimitedProctoredExamSettingsSerializer exam_config = serializer( data=request.data.get('proctored_exam_settings', {})) valid_request = exam_config.is_valid() if not request.user.is_staff and valid_request and ProctoredExamSettingsSerializer( data=request.data.get('proctored_exam_settings', {})).is_valid(): return Response(status=status.HTTP_403_FORBIDDEN) with modulestore().bulk_operations(CourseKey.from_string(course_id)): course_module = self._get_and_validate_course_access( request.user, course_id) course_metadata = CourseMetadata().fetch_all(course_module) models_to_update = {} for setting_key, value in exam_config.data.items(): model = course_metadata.get(setting_key) if model: models_to_update[setting_key] = copy.deepcopy(model) models_to_update[setting_key]['value'] = value # validate data formats and update the course module object is_valid, errors, updated_data = CourseMetadata.validate_and_update_from_json( course_module, models_to_update, user=request.user, ) if not is_valid: error_messages = [{ error.get('key'): error.get('message') } for error in errors] return Response({'detail': error_messages}, status=status.HTTP_400_BAD_REQUEST) # save to mongo modulestore().update_item(course_module, request.user.id) # merge updated settings with all existing settings. # do this because fields that could not be modified are excluded from the result course_metadata = {**course_metadata, **updated_data} updated_setttings = self._get_proctored_exam_setting_values( course_metadata) serializer = ProctoredExamSettingsSerializer(updated_setttings) return Response({'proctored_exam_settings': serializer.data})
def test_validate_from_json_correct_inputs(self): is_valid, errors, test_model = CourseMetadata.validate_and_update_from_json( self.course, { "advertised_start": {"value": "start A"}, "days_early_for_beta": {"value": 2}, "advanced_modules": {"value": ['combinedopenended']}, }, user=self.user ) self.assertTrue(is_valid) self.assertTrue(len(errors) == 0) self.update_check(test_model) # Tab gets tested in test_advanced_settings_munge_tabs self.assertIn('advanced_modules', test_model, 'Missing advanced_modules') self.assertEqual(test_model['advanced_modules']['value'], ['combinedopenended'], 'advanced_module is not updated')
def test_validate_and_update_from_json_correct_inputs(self): is_valid, errors, test_model = CourseMetadata.validate_and_update_from_json( self.course, { "advertised_start": {"value": "start A"}, "days_early_for_beta": {"value": 2}, "advanced_modules": {"value": ["combinedopenended"]}, }, user=self.user, ) self.assertTrue(is_valid) self.assertTrue(len(errors) == 0) self.update_check(test_model) # fresh fetch to ensure persistence fresh = modulestore().get_course(self.course.id) test_model = CourseMetadata.fetch(fresh) self.update_check(test_model) # Tab gets tested in test_advanced_settings_munge_tabs self.assertIn("advanced_modules", test_model, "Missing advanced_modules") self.assertEqual( test_model["advanced_modules"]["value"], ["combinedopenended"], "advanced_module is not updated" )
def custom_settings_handler(request, course_key_string): """ Course settings configuration GET html: get the page json: get the model PUT, POST json: update the Course's settings. The payload is a json rep of the metadata dicts. """ course_key = CourseKey.from_string(course_key_string) with modulestore().bulk_operations(course_key): course_module = get_course_and_check_access(course_key, request.user) if 'text/html' in request.META.get('HTTP_ACCEPT', '') and request.method == 'GET': return render_to_response( 'custom_settings.html', { 'context_course': course_module, 'is_new': course_module.is_new, 'invitation_only': course_module.invitation_only, 'visible_to_manager_only': course_module.visible_to_manager_only, }) elif 'application/json' in request.META.get('HTTP_ACCEPT', ''): if request.method == 'GET': return JsonResponse(CourseMetadata.fetch(course_module)) else: try: # validate data formats and update the course module. # Note: don't update mongo yet, but wait until after any tabs are changed is_valid, errors, updated_data = CourseMetadata.validate_and_update_from_json( course_module, request.json, user=request.user, ) if is_valid: try: additional_info = { 'is_new': request.POST.get('is_new', False), 'invitation_only': request.POST.get('invitation_only', False), 'visible_to_manager_only': request.POST.get('visible_to_manager_only', False) } CourseMetadata.update_from_dict( additional_info, course_module, request.user) course_search_index_handler( request, course_key_string) except InvalidTabsException as err: log.exception(err.message) response_message = [{ 'message': _('An error occurred while trying to save your tabs' ), 'model': { 'display_name': _('Tabs Exception') } }] return JsonResponseBadRequest(response_message) return JsonResponse(updated_data) else: return JsonResponseBadRequest(errors) # Handle all errors that validation doesn't catch except (TypeError, ValueError, InvalidTabsException) as err: return HttpResponseBadRequest(django.utils.html.escape( err.message), content_type="text/plain")