Commit 1babebb6 by chrisndodge

Merge pull request #38 from edx/muhhshoaib/SOL-1085-record-last-polling-contact

SOL-1085
parents c1781f3b bceb10b0
......@@ -182,6 +182,16 @@ def get_exam_attempt_by_id(attempt_id):
return serialized_attempt_obj.data if exam_attempt_obj else None
def update_exam_attempt(attempt_id, **kwargs):
"""
update exam_attempt
"""
exam_attempt_obj = ProctoredExamStudentAttempt.objects.get_exam_attempt_by_id(attempt_id)
for key, value in kwargs.items():
setattr(exam_attempt_obj, key, value)
exam_attempt_obj.save()
def get_exam_attempt_by_code(attempt_code):
"""
Signals the beginning of an exam attempt when we only have
......
......@@ -5,6 +5,9 @@ Various callback paths that support callbacks from SoftwareSecure
import logging
from django.template import Context, loader
from django.http import HttpResponse
import pytz
from datetime import datetime
from ipware.ip import get_ip
from django.core.urlresolvers import reverse
from rest_framework.views import APIView
......@@ -13,7 +16,7 @@ from rest_framework.response import Response
from edx_proctoring.api import (
get_exam_attempt_by_code,
mark_exam_attempt_as_ready,
)
update_exam_attempt)
from edx_proctoring.backends import get_backend_provider
......@@ -33,7 +36,6 @@ def start_exam_callback(request, attempt_code): # pylint: disable=unused-argume
IMPORTANT: This is an unauthenticated endpoint, so be VERY CAREFUL about extending
this endpoint
"""
attempt = get_exam_attempt_by_code(attempt_code)
if not attempt:
return HttpResponse(
......@@ -100,12 +102,16 @@ class AttemptStatus(APIView):
"""
attempt = get_exam_attempt_by_code(attempt_code)
ip_address = get_ip(request)
timestamp = datetime.now(pytz.UTC)
if not attempt:
return HttpResponse(
content='You have entered an exam code that is not valid.',
status=404
)
update_exam_attempt(attempt['id'], last_poll_timestamp=timestamp, last_poll_ipaddr=ip_address)
return Response(
data={
# IMPORTANT: Don't add more information to this as it is an
......
......@@ -199,6 +199,9 @@ class ProctoredExamStudentAttempt(TimeStampedModel):
started_at = models.DateTimeField(null=True)
completed_at = models.DateTimeField(null=True)
last_poll_timestamp = models.DateTimeField(null=True)
last_poll_ipaddr = models.CharField(max_length=32, null=True)
# this will be a unique string ID that the user
# will have to use when starting the proctored exam
attempt_code = models.CharField(max_length=255, null=True, db_index=True)
......
<div class="wrapper-content wrapper">
<% var is_proctored_attempts = proctored_exam_attempts.length !== 0 %>
<% if (is_proctored_attempts) { %>
<section class="content">
<div class="top-header">
<div class='search-attempts'>
......@@ -89,6 +88,7 @@
<th class="c_action"><%- gettext("Actions") %> </th>
</tr>
</thead>
<% if (is_proctored_attempts) { %>
<tbody>
<% _.each(proctored_exam_attempts, function(proctored_exam_attempt){ %>
<tr class="allowance-items">
......@@ -118,9 +118,11 @@
</tr>
<% }); %>
</tbody>
<% } %>
</table>
<% if (!is_proctored_attempts) { %>
<p> No exam results found.
<% } %>
</section>
<% } else { %>
<p> No exam results found.
<% } %>
</div>
......@@ -943,7 +943,8 @@ class TestStudentProctoredExamAttempt(LoggedInTestCase):
)
)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data['status'], 'ready_to_start')
response_data = json.loads(response.content)
self.assertEqual(response_data['status'], 'ready_to_start')
def test_bad_exam_code_callback(self):
"""
......
......@@ -5,3 +5,6 @@ South>=0.7.6
djangorestframework>=2.3.5,<=2.3.14
pytz>=2012h
pycrypto>=2.6
# Third Party
-e git+https://github.com/un33k/django-ipware.git@42cb1bb1dc680a60c6452e8bb2b843c2a0382c90#egg=django-ipware
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment