diff --git a/edx_proctoring/api.py b/edx_proctoring/api.py index 372d42c95fc..b7ac420d105 100644 --- a/edx_proctoring/api.py +++ b/edx_proctoring/api.py @@ -1586,7 +1586,7 @@ def get_last_exam_completion_date(course_id, username): return exam_attempts[0].completed_at if exam_attempts and are_all_exams_attempted else None -def get_active_exams_for_user(user_id, course_id=None): +def get_active_exams_for_user(user_id, course_id=None, exam_id=None): """ This method will return a list of active exams for the user, i.e. started_at != None and completed_at == None. Theoretically there @@ -1607,7 +1607,7 @@ def get_active_exams_for_user(user_id, course_id=None): """ result = [] - student_active_exams = ProctoredExamStudentAttempt.objects.get_active_student_attempts(user_id, course_id) + student_active_exams = ProctoredExamStudentAttempt.objects.get_active_student_attempts(user_id, course_id, exam_id) for active_exam in student_active_exams: # convert the django orm objects # into the serialized form. diff --git a/edx_proctoring/models.py b/edx_proctoring/models.py index 79464976912..8bbd9a001fd 100644 --- a/edx_proctoring/models.py +++ b/edx_proctoring/models.py @@ -331,7 +331,7 @@ def get_proctored_exam_attempts(self, course_id, username): is_sample_attempt=False, ).order_by('-completed_at') - def get_active_student_attempts(self, user_id, course_id=None): + def get_active_student_attempts(self, user_id, course_id=None, exam_id=None): """ Returns the active student exams (user in-progress exams) """ @@ -340,6 +340,9 @@ def get_active_student_attempts(self, user_id, course_id=None): if course_id is not None: filtered_query = filtered_query & Q(proctored_exam__course_id=course_id) + if exam_id is not None: + filtered_query = filtered_query & Q(proctored_exam__id=exam_id) + return self.filter(filtered_query).order_by('-created') # pylint: disable=no-member def clear_onboarding_errors(self, user_id): diff --git a/edx_proctoring/urls.py b/edx_proctoring/urls.py index 0d3c736cd85..8d18c6965bb 100644 --- a/edx_proctoring/urls.py +++ b/edx_proctoring/urls.py @@ -9,6 +9,8 @@ app_name = u'edx_proctoring' +CONTENT_ID_PATTERN = r'(?P(?:i4x://?[^/]+/[^/]+/[^/]+/[^@]+(?:@[^/]+)?)|(?:[^/]+))' + urlpatterns = [ url( r'edx_proctoring/v1/proctored_exam/exam$', @@ -21,8 +23,10 @@ name='proctored_exam.exam_by_id' ), url( - r'edx_proctoring/v1/proctored_exam/exam/course_id/{}/content_id/(?P[A-z0-9]+)$'.format( - settings.COURSE_ID_PATTERN), + r'edx_proctoring/v1/proctored_exam/exam/course_id/{course_id}/content_id/{content_id}$'.format( + course_id=settings.COURSE_ID_PATTERN, + content_id=CONTENT_ID_PATTERN, + ), views.ProctoredExamView.as_view(), name='proctored_exam.exam_by_content_id' ), @@ -53,6 +57,11 @@ views.StudentProctoredExamAttemptCollection.as_view(), name='proctored_exam.attempt.collection' ), + url( + r'edx_proctoring/v1/proctored_exam/attempt/exam/(?P\d+)$', + views.StudentProctoredExamAttemptCollection.as_view(), + name='proctored_exam.attempt.collection' + ), url( r'edx_proctoring/v1/proctored_exam/attempt/(?P\d+)/review_status$', views.ProctoredExamAttemptReviewStatus.as_view(), diff --git a/edx_proctoring/views.py b/edx_proctoring/views.py index 6f5dc852399..7173c443737 100644 --- a/edx_proctoring/views.py +++ b/edx_proctoring/views.py @@ -36,6 +36,7 @@ get_allowances_for_course, get_backend_provider, get_enrollments_can_take_proctored_exams, + get_current_exam_attempt, get_exam_attempt_by_external_id, get_exam_attempt_by_id, get_exam_by_content_id, @@ -894,12 +895,12 @@ class StudentProctoredExamAttemptCollection(ProctoredAPIView): return the status of the exam attempt """ - def get(self, request): # pylint: disable=unused-argument + def get(self, request, exam_id=None): # pylint: disable=unused-argument """ HTTP GET Handler. Returns the status of the exam attempt. """ - exams = get_active_exams_for_user(request.user.id) + exams = get_active_exams_for_user(request.user.id, exam_id=exam_id) if exams: exam_info = exams[0] @@ -963,6 +964,10 @@ def get(self, request): # pylint: disable=unused-argument 'is_proctored': False } + if exam_id: + attempt = get_current_exam_attempt(exam_id, request.user.id) + response_dict['attempt_status'] = attempt['status'] if attempt else "not_started" + return Response(data=response_dict, status=status.HTTP_200_OK) def post(self, request):