Skip to content
Snippets Groups Projects
Commit c95dc593 authored by Bianca Severino's avatar Bianca Severino
Browse files

Add function to InstructorService to retrieve proctoring_escalation_email

parent 135e9acf
No related branches found
Tags release-2020-12-18-12.59
No related merge requests found
......@@ -9,6 +9,7 @@ from django.core.exceptions import ObjectDoesNotExist
from django.utils.translation import ugettext as _
from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey, UsageKey
from opaque_keys.edx.locator import CourseLocator
import lms.djangoapps.instructor.enrollment as enrollment
from lms.djangoapps.courseware.models import StudentModule
......@@ -27,6 +28,9 @@ class InstructorService(object):
for the edx_proctoring's dependency injection to cater for a requirement where edx_proctoring
needs to call into edx-platform's functions to delete the students' existing answers, grades
and attempt counts if there had been an earlier attempt.
This service also contains utility functions to check if a user is course staff, send notifications
related to proctored exam attempts, and retrieve a course team's proctoring escalation email.
"""
def delete_student_attempt(self, student_identifier, course_id, content_id, requesting_user):
......@@ -118,3 +122,18 @@ class InstructorService(object):
)
tags = ["proctoring"]
create_zendesk_ticket(requester_name, email, subject, body, tags)
def get_proctoring_escalation_email(self, course_key):
"""
Returns the proctoring escalation email for a course, or None if not given.
Example arguments:
* course_key (String): 'block-v1:edX+DemoX+Demo_Course'
"""
# Convert course key into id
course_id = CourseLocator.from_string(course_key)
course = modulestore().get_course(course_id)
if course is None:
raise ObjectDoesNotExist('Course not found for course_key {course_key}.')
return course.proctoring_escalation_email
......@@ -7,6 +7,9 @@ import json
import mock
import six
from opaque_keys import InvalidKeyError
from django.core.exceptions import ObjectDoesNotExist
from lms.djangoapps.courseware.models import StudentModule
from lms.djangoapps.instructor.access import allow_access
......@@ -26,7 +29,8 @@ class InstructorServiceTests(SharedModuleStoreTestCase):
@classmethod
def setUpClass(cls):
super(InstructorServiceTests, cls).setUpClass()
cls.course = CourseFactory.create()
cls.email = 'escalation@test.com'
cls.course = CourseFactory.create(proctoring_escalation_email=cls.email)
cls.problem_location = msk_from_problem_urlname(
cls.course.id,
'robot-some-problem-urlname'
......@@ -185,3 +189,24 @@ class InstructorServiceTests(SharedModuleStoreTestCase):
)
expected_body = body.format(**args)
mock_create_zendesk_ticket.assert_called_with(requester_name, email, subject, expected_body, tags)
def test_get_proctoring_escalation_email(self):
"""
Test that it returns the correct proctoring escalation email
"""
email = self.service.get_proctoring_escalation_email(str(self.course.id))
self.assertEqual(email, self.email)
def test_get_proctoring_escalation_email_no_course(self):
"""
Test that it raises an exception if the course is not found
"""
with self.assertRaises(ObjectDoesNotExist):
self.service.get_proctoring_escalation_email('a/b/c')
def test_get_proctoring_escalation_email_invalid_key(self):
"""
Test that it raises an exception if the course_key is invalid
"""
with self.assertRaises(InvalidKeyError):
self.service.get_proctoring_escalation_email('invalid key')
......@@ -105,7 +105,7 @@ edx-milestones==0.3.0 # via -r requirements/edx/base.in
edx-opaque-keys[django]==2.1.1 # via -r requirements/edx/paver.txt, edx-bulk-grades, edx-ccx-keys, edx-completion, edx-drf-extensions, edx-enterprise, edx-milestones, edx-organizations, edx-proctoring, edx-user-state-client, edx-when, lti-consumer-xblock, xmodule
edx-organizations==6.7.1 # via -r requirements/edx/base.in
edx-proctoring-proctortrack==1.0.5 # via -r requirements/edx/base.in
edx-proctoring==2.5.13 # via -r requirements/edx/base.in, edx-proctoring-proctortrack
edx-proctoring==2.6.0 # via -r requirements/edx/base.in, edx-proctoring-proctortrack
edx-rbac==1.4.1 # via edx-enterprise
edx-rest-api-client==5.3.0 # via -r requirements/edx/base.in, edx-enterprise, edx-proctoring
edx-search==3.0.0 # via -r requirements/edx/base.in
......
......@@ -117,7 +117,7 @@ edx-milestones==0.3.0 # via -r requirements/edx/testing.txt
edx-opaque-keys[django]==2.1.1 # via -r requirements/edx/testing.txt, edx-bulk-grades, edx-ccx-keys, edx-completion, edx-drf-extensions, edx-enterprise, edx-milestones, edx-organizations, edx-proctoring, edx-user-state-client, edx-when, lti-consumer-xblock, xmodule
edx-organizations==6.7.1 # via -r requirements/edx/testing.txt
edx-proctoring-proctortrack==1.0.5 # via -r requirements/edx/testing.txt
edx-proctoring==2.5.13 # via -r requirements/edx/testing.txt, edx-proctoring-proctortrack
edx-proctoring==2.6.0 # via -r requirements/edx/testing.txt, edx-proctoring-proctortrack
edx-rbac==1.4.1 # via -r requirements/edx/testing.txt, edx-enterprise
edx-rest-api-client==5.3.0 # via -r requirements/edx/testing.txt, edx-enterprise, edx-proctoring
edx-search==3.0.0 # via -r requirements/edx/testing.txt
......
......@@ -114,7 +114,7 @@ edx-milestones==0.3.0 # via -r requirements/edx/base.txt
edx-opaque-keys[django]==2.1.1 # via -r requirements/edx/base.txt, edx-bulk-grades, edx-ccx-keys, edx-completion, edx-drf-extensions, edx-enterprise, edx-milestones, edx-organizations, edx-proctoring, edx-user-state-client, edx-when, lti-consumer-xblock, xmodule
edx-organizations==6.7.1 # via -r requirements/edx/base.txt
edx-proctoring-proctortrack==1.0.5 # via -r requirements/edx/base.txt
edx-proctoring==2.5.13 # via -r requirements/edx/base.txt, edx-proctoring-proctortrack
edx-proctoring==2.6.0 # via -r requirements/edx/base.txt, edx-proctoring-proctortrack
edx-rbac==1.4.1 # via -r requirements/edx/base.txt, edx-enterprise
edx-rest-api-client==5.3.0 # via -r requirements/edx/base.txt, edx-enterprise, edx-proctoring
edx-search==3.0.0 # via -r requirements/edx/base.txt
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment