Merge pull request #19366 from edx/dahlia/proctoring-master
Upgrade edx-proctoring to version 1.5
This commit is contained in:
@@ -88,7 +88,7 @@ class InstructorService(object):
|
||||
"""
|
||||
return auth.user_has_role(user, CourseStaffRole(CourseKey.from_string(course_id)))
|
||||
|
||||
def send_support_notification(self, course_id, exam_name, student_username, review_status):
|
||||
def send_support_notification(self, course_id, exam_name, student_username, review_status, review_url=None):
|
||||
"""
|
||||
Creates a Zendesk ticket for an exam attempt review from the proctoring system.
|
||||
Currently, it sends notifications for 'Suspicious" status, but additional statuses can be supported
|
||||
@@ -103,15 +103,17 @@ class InstructorService(object):
|
||||
if course.create_zendesk_tickets:
|
||||
requester_name = "edx-proctoring"
|
||||
email = "edx-proctoring@edx.org"
|
||||
subject = _("Proctored Exam Review: {review_status}").format(review_status=review_status)
|
||||
subject = _(u"Proctored Exam Review: {review_status}").format(review_status=review_status)
|
||||
body = _(
|
||||
"A proctored exam attempt for {exam_name} in {course_name} by username: {student_username} "
|
||||
"was reviewed as {review_status} by the proctored exam review provider."
|
||||
u"A proctored exam attempt for {exam_name} in {course_name} by username: {student_username} "
|
||||
"was reviewed as {review_status} by the proctored exam review provider.\n"
|
||||
"Review link: {review_url}"
|
||||
).format(
|
||||
exam_name=exam_name,
|
||||
course_name=course.display_name,
|
||||
student_username=student_username,
|
||||
review_status=review_status
|
||||
review_status=review_status,
|
||||
review_url=review_url or u'not available',
|
||||
)
|
||||
tags = ["proctoring"]
|
||||
create_zendesk_ticket(requester_name, email, subject, body, tags)
|
||||
|
||||
@@ -147,21 +147,40 @@ class InstructorServiceTests(SharedModuleStoreTestCase):
|
||||
"""
|
||||
requester_name = "edx-proctoring"
|
||||
email = "edx-proctoring@edx.org"
|
||||
subject = "Proctored Exam Review: {review_status}".format(review_status="Suspicious")
|
||||
subject = u"Proctored Exam Review: {review_status}".format(review_status="Suspicious")
|
||||
|
||||
body = "A proctored exam attempt for {exam_name} in {course_name} by username: {student_username} was " \
|
||||
"reviewed as {review_status} by the proctored exam review provider."
|
||||
body = body.format(
|
||||
exam_name="test_exam", course_name=self.course.display_name, student_username="test_student",
|
||||
review_status="Suspicious"
|
||||
)
|
||||
"reviewed as {review_status} by the proctored exam review provider.\n" \
|
||||
"Review link: {url}"
|
||||
args = {
|
||||
'exam_name': 'test_exam',
|
||||
'student_username': 'test_student',
|
||||
'url': 'not available',
|
||||
'course_name': self.course.display_name,
|
||||
'review_status': 'Suspicious',
|
||||
}
|
||||
expected_body = body.format(**args)
|
||||
tags = ["proctoring"]
|
||||
|
||||
with mock.patch("lms.djangoapps.instructor.services.create_zendesk_ticket") as mock_create_zendesk_ticket:
|
||||
self.service.send_support_notification(
|
||||
course_id=unicode(self.course.id),
|
||||
exam_name="test_exam",
|
||||
student_username="test_student",
|
||||
review_status="Suspicious"
|
||||
exam_name=args['exam_name'],
|
||||
student_username=args["student_username"],
|
||||
review_status="Suspicious",
|
||||
review_url=None,
|
||||
)
|
||||
|
||||
mock_create_zendesk_ticket.assert_called_with(requester_name, email, subject, body, tags)
|
||||
mock_create_zendesk_ticket.assert_called_with(requester_name, email, subject, expected_body, tags)
|
||||
# Now check sending a notification with a review link
|
||||
args['url'] = 'http://review/url'
|
||||
with mock.patch("lms.djangoapps.instructor.services.create_zendesk_ticket") as mock_create_zendesk_ticket:
|
||||
self.service.send_support_notification(
|
||||
course_id=unicode(self.course.id),
|
||||
exam_name=args['exam_name'],
|
||||
student_username=args["student_username"],
|
||||
review_status="Suspicious",
|
||||
review_url=args['url'],
|
||||
)
|
||||
expected_body = body.format(**args)
|
||||
mock_create_zendesk_ticket.assert_called_with(requester_name, email, subject, expected_body, tags)
|
||||
|
||||
@@ -892,11 +892,6 @@ CREDIT_HELP_LINK_URL = ENV_TOKENS.get('CREDIT_HELP_LINK_URL', CREDIT_HELP_LINK_U
|
||||
JWT_AUTH.update(ENV_TOKENS.get('JWT_AUTH', {}))
|
||||
JWT_AUTH.update(AUTH_TOKENS.get('JWT_AUTH', {}))
|
||||
|
||||
################# PROCTORING CONFIGURATION ##################
|
||||
|
||||
PROCTORING_BACKEND_PROVIDER = AUTH_TOKENS.get("PROCTORING_BACKEND_PROVIDER", PROCTORING_BACKEND_PROVIDER)
|
||||
PROCTORING_SETTINGS = ENV_TOKENS.get("PROCTORING_SETTINGS", PROCTORING_SETTINGS)
|
||||
|
||||
################# MICROSITE ####################
|
||||
MICROSITE_CONFIGURATION = ENV_TOKENS.get('MICROSITE_CONFIGURATION', {})
|
||||
MICROSITE_ROOT_DIR = path(ENV_TOKENS.get('MICROSITE_ROOT_DIR', ''))
|
||||
|
||||
@@ -1345,28 +1345,6 @@ courseware_js = [
|
||||
'js/modules/tab.js',
|
||||
]
|
||||
|
||||
proctoring_js = (
|
||||
[
|
||||
'proctoring/js/models/proctored_exam_allowance_model.js',
|
||||
'proctoring/js/models/proctored_exam_attempt_model.js',
|
||||
'proctoring/js/models/proctored_exam_model.js'
|
||||
] +
|
||||
[
|
||||
'proctoring/js/collections/proctored_exam_allowance_collection.js',
|
||||
'proctoring/js/collections/proctored_exam_attempt_collection.js',
|
||||
'proctoring/js/collections/proctored_exam_collection.js'
|
||||
] +
|
||||
[
|
||||
'proctoring/js/views/Backbone.ModalDialog.js',
|
||||
'proctoring/js/views/proctored_exam_add_allowance_view.js',
|
||||
'proctoring/js/views/proctored_exam_allowance_view.js',
|
||||
'proctoring/js/views/proctored_exam_attempt_view.js',
|
||||
'proctoring/js/views/proctored_exam_view.js'
|
||||
] +
|
||||
[
|
||||
'proctoring/js/proctored_app.js'
|
||||
]
|
||||
)
|
||||
|
||||
# Before a student accesses courseware, we do not
|
||||
# need many of the JS dependencies. This includes
|
||||
@@ -1693,10 +1671,6 @@ PIPELINE_JS = {
|
||||
),
|
||||
'output_filename': 'js/lms-application.js',
|
||||
},
|
||||
'proctoring': {
|
||||
'source_filenames': proctoring_js,
|
||||
'output_filename': 'js/lms-proctoring.js',
|
||||
},
|
||||
'courseware': {
|
||||
'source_filenames': courseware_js,
|
||||
'output_filename': 'js/lms-courseware.js',
|
||||
@@ -1841,6 +1815,10 @@ WEBPACK_LOADER = {
|
||||
'DEFAULT': {
|
||||
'BUNDLE_DIR_NAME': 'bundles/',
|
||||
'STATS_FILE': os.path.join(STATIC_ROOT, 'webpack-stats.json')
|
||||
},
|
||||
'WORKERS': {
|
||||
'BUNDLE_DIR_NAME': 'bundles/',
|
||||
'STATS_FILE': os.path.join(STATIC_ROOT, 'webpack-worker-stats.json')
|
||||
}
|
||||
}
|
||||
WEBPACK_CONFIG_PATH = 'webpack.prod.config.js'
|
||||
@@ -2881,9 +2859,6 @@ OPTIONAL_APPS = [
|
||||
# edxval
|
||||
('edxval', 'openedx.core.djangoapps.content.course_overviews.apps.CourseOverviewsConfig'),
|
||||
|
||||
# edX Proctoring
|
||||
('edx_proctoring', None),
|
||||
|
||||
# Organizations App (http://github.com/edx/edx-organizations)
|
||||
('organizations', None),
|
||||
|
||||
@@ -3215,14 +3190,6 @@ MICROSITE_DATABASE_TEMPLATE_CACHE_TTL = 5 * 60
|
||||
|
||||
RSS_PROXY_CACHE_TIMEOUT = 3600 # The length of time we cache RSS retrieved from remote URLs in seconds
|
||||
|
||||
#### PROCTORING CONFIGURATION DEFAULTS
|
||||
|
||||
PROCTORING_BACKEND_PROVIDER = {
|
||||
'class': 'edx_proctoring.backends.null.NullBackendProvider',
|
||||
'options': {},
|
||||
}
|
||||
PROCTORING_SETTINGS = {}
|
||||
|
||||
#### Custom Courses for EDX (CCX) configuration
|
||||
|
||||
# This is an arbitrary hard limit.
|
||||
|
||||
@@ -112,6 +112,7 @@ STATIC_ROOT_BASE = ENV_TOKENS.get('STATIC_ROOT_BASE', None)
|
||||
if STATIC_ROOT_BASE:
|
||||
STATIC_ROOT = path(STATIC_ROOT_BASE)
|
||||
WEBPACK_LOADER['DEFAULT']['STATS_FILE'] = STATIC_ROOT / "webpack-stats.json"
|
||||
WEBPACK_LOADER['WORKERS']['STATS_FILE'] = STATIC_ROOT / "webpack-worker-stats.json"
|
||||
|
||||
|
||||
# STATIC_URL_BASE specifies the base url to use for static files
|
||||
@@ -888,11 +889,6 @@ CREDIT_HELP_LINK_URL = ENV_TOKENS.get('CREDIT_HELP_LINK_URL', CREDIT_HELP_LINK_U
|
||||
JWT_AUTH.update(ENV_TOKENS.get('JWT_AUTH', {}))
|
||||
JWT_AUTH.update(AUTH_TOKENS.get('JWT_AUTH', {}))
|
||||
|
||||
################# PROCTORING CONFIGURATION ##################
|
||||
|
||||
PROCTORING_BACKEND_PROVIDER = AUTH_TOKENS.get("PROCTORING_BACKEND_PROVIDER", PROCTORING_BACKEND_PROVIDER)
|
||||
PROCTORING_SETTINGS = ENV_TOKENS.get("PROCTORING_SETTINGS", PROCTORING_SETTINGS)
|
||||
|
||||
################# MICROSITE ####################
|
||||
MICROSITE_CONFIGURATION = ENV_TOKENS.get('MICROSITE_CONFIGURATION', {})
|
||||
MICROSITE_ROOT_DIR = path(ENV_TOKENS.get('MICROSITE_ROOT_DIR', ''))
|
||||
|
||||
@@ -35,6 +35,11 @@ XQUEUE_INTERFACE = {
|
||||
"basic_auth": ('anant', 'agarwal'),
|
||||
}
|
||||
|
||||
PROCTORING_BACKENDS = {
|
||||
'DEFAULT': 'mock',
|
||||
'mock': {},
|
||||
'mock_proctoring_without_rules': {},
|
||||
}
|
||||
|
||||
######################### PIPELINE ####################################
|
||||
|
||||
|
||||
@@ -206,6 +206,9 @@ such that the value can be defined later than this assignment (file load order).
|
||||
}, {
|
||||
constructor: edx.instructor_dashboard.proctoring.ProctoredExamAttemptView,
|
||||
$element: idashContent.find('.' + CSS_IDASH_SECTION + '#special_exams')
|
||||
}, {
|
||||
constructor: edx.instructor_dashboard.proctoring.ProctoredExamDashboardView,
|
||||
$element: idashContent.find('.' + CSS_IDASH_SECTION + '#special_exams')
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -7,15 +7,9 @@ $(function() {
|
||||
$proctoringAccordionPane.accordion(
|
||||
{
|
||||
heightStyle: 'content',
|
||||
activate: function(event, ui) {
|
||||
var active = $proctoringAccordionPane.accordion('option', 'active');
|
||||
$.cookie('saved_index', null);
|
||||
$.cookie('saved_index', active);
|
||||
},
|
||||
animate: 400,
|
||||
header: '> .wrap > .hd',
|
||||
icons: icons,
|
||||
active: isNaN(parseInt($.cookie('saved_index'))) ? 0 : parseInt($.cookie('saved_index')),
|
||||
collapsible: true
|
||||
}
|
||||
);
|
||||
|
||||
@@ -14,5 +14,9 @@ import pytz
|
||||
<h3 class="hd hd-3">${_('Student Special Exam Attempts')}</h3>
|
||||
<div class="student-proctored-exam-container" data-course-id="${ section_data['course_id'] }"></div>
|
||||
</div>
|
||||
<div class="wrap">
|
||||
<h3 class="hd hd-3">${_('Review Dashboard')}</h3>
|
||||
<div class="student-review-dashboard-container" data-course-id="${ section_data['course_id'] }"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1012,11 +1012,6 @@ if 'debug_toolbar' in settings.INSTALLED_APPS:
|
||||
url(r'^__debug__/', include(debug_toolbar.urls)),
|
||||
]
|
||||
|
||||
# include into our URL patterns the HTTP REST API that comes with edx-proctoring.
|
||||
urlpatterns += [
|
||||
url(r'^api/', include('edx_proctoring.urls')),
|
||||
]
|
||||
|
||||
if settings.FEATURES.get('ENABLE_FINANCIAL_ASSISTANCE_FORM'):
|
||||
urlpatterns += [
|
||||
url(
|
||||
|
||||
Reference in New Issue
Block a user