diff --git a/cms/djangoapps/contentstore/rest_api/v1/serializers.py b/cms/djangoapps/contentstore/rest_api/v1/serializers.py index 8ff3ecef53..157ae681d4 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/serializers.py +++ b/cms/djangoapps/contentstore/rest_api/v1/serializers.py @@ -8,7 +8,7 @@ from common.lib.xmodule.xmodule.course_module import get_available_providers class ProctoredExamSettingsSerializer(serializers.Serializer): - """ Serializer for proctored exam settings. """ + """ Serializer for edX Staff proctored exam settings. """ enable_proctored_exams = serializers.BooleanField() allow_proctoring_opt_out = serializers.BooleanField() proctoring_provider = serializers.CharField() @@ -16,6 +16,13 @@ class ProctoredExamSettingsSerializer(serializers.Serializer): create_zendesk_tickets = serializers.BooleanField() +class LimitedProctoredExamSettingsSerializer(serializers.Serializer): + """Serializer for non edX Staff for proctored exam settings""" + enable_proctored_exams = serializers.BooleanField() + proctoring_provider = serializers.CharField() + proctoring_escalation_email = serializers.CharField(allow_blank=True) + + class ProctoredExamConfigurationSerializer(serializers.Serializer): """ Serializer for various metadata associated with proctored exam settings. """ proctored_exam_settings = ProctoredExamSettingsSerializer() diff --git a/cms/djangoapps/contentstore/rest_api/v1/tests/test_views.py b/cms/djangoapps/contentstore/rest_api/v1/tests/test_views.py index bd850450cd..eb2fdf19c6 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/tests/test_views.py +++ b/cms/djangoapps/contentstore/rest_api/v1/tests/test_views.py @@ -274,3 +274,21 @@ class ProctoringExamSettingsPostTests(ProctoringExamSettingsTestMixin, ModuleSto updated = modulestore().get_item(self.course.location) assert updated.enable_proctored_exams is False assert updated.proctoring_provider == 'null' + + def test_403_if_instructor_request_includes_opting_out_or_zendesk(self): + self.client.login(username=self.course_instructor, password=self.password) + data = self.get_request_data() + response = self.make_request(data=data) + assert response.status_code == status.HTTP_403_FORBIDDEN + + def test_200_for_instructor_request(self): + self.client.login(username=self.course_instructor, password=self.password) + data = { + 'proctored_exam_settings': { + 'enable_proctored_exams': True, + 'proctoring_provider': 'proctortrack', + 'proctoring_escalation_email': 'foo@bar.com', + } + } + response = self.make_request(data=data) + assert response.status_code == status.HTTP_200_OK diff --git a/cms/djangoapps/contentstore/rest_api/v1/views.py b/cms/djangoapps/contentstore/rest_api/v1/views.py index 292142eefa..b069097028 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/views.py +++ b/cms/djangoapps/contentstore/rest_api/v1/views.py @@ -16,6 +16,7 @@ from xmodule.modulestore.django import modulestore from contentstore.rest_api.v1.serializers import ( ProctoredExamConfigurationSerializer, ProctoredExamSettingsSerializer, + LimitedProctoredExamSettingsSerializer, ) @@ -108,8 +109,12 @@ class ProctoredExamSettingsView(APIView): def post(self, request, course_id): """ POST handler """ - exam_config = ProctoredExamSettingsSerializer(data=request.data.get('proctored_exam_settings', {})) - exam_config.is_valid(raise_exception=True) + 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)