From c1d0aba3cbb08f6ffaff1f963d30bc425c03b00a Mon Sep 17 00:00:00 2001 From: ambaliyav Date: Wed, 2 Mar 2022 10:48:08 +0530 Subject: [PATCH 1/3] feature: upgrade proctoring version with custom changes --- edx_proctoring/urls.py | 13 +++++++++++-- edx_proctoring/views.py | 7 ++++++- 2 files changed, 17 insertions(+), 3 deletions(-) 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..ab6ea7f2b3b 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_exam_attempt, get_exam_attempt_by_external_id, get_exam_attempt_by_id, get_exam_by_content_id, @@ -894,7 +895,7 @@ 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. """ @@ -963,6 +964,10 @@ def get(self, request): # pylint: disable=unused-argument 'is_proctored': False } + if exam_id: + attempt = get_exam_attempt(exam_id, request.user.id) + response_dict['status'] = attempt['status'] if attempt else "not_started" + return Response(data=response_dict, status=status.HTTP_200_OK) def post(self, request): From 3183c95eeb84b9f58d39bba14525b3e5578e1700 Mon Sep 17 00:00:00 2001 From: ambaliyav Date: Wed, 2 Mar 2022 10:56:52 +0530 Subject: [PATCH 2/3] fix: change method to get exam details --- edx_proctoring/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/edx_proctoring/views.py b/edx_proctoring/views.py index ab6ea7f2b3b..415998e179a 100644 --- a/edx_proctoring/views.py +++ b/edx_proctoring/views.py @@ -36,7 +36,7 @@ get_allowances_for_course, get_backend_provider, get_enrollments_can_take_proctored_exams, - get_exam_attempt, + get_current_exam_attempt, get_exam_attempt_by_external_id, get_exam_attempt_by_id, get_exam_by_content_id, @@ -965,7 +965,7 @@ def get(self, request, exam_id=None): # pylint: disable=unused-argument } if exam_id: - attempt = get_exam_attempt(exam_id, request.user.id) + attempt = get_current_exam_attempt(exam_id, request.user.id) response_dict['status'] = attempt['status'] if attempt else "not_started" return Response(data=response_dict, status=status.HTTP_200_OK) From 161efe30a6e26536d3d955ab61d525de8e4ec1cb Mon Sep 17 00:00:00 2001 From: ambaliyav Date: Wed, 2 Mar 2022 12:21:43 +0530 Subject: [PATCH 3/3] fix: update api for started state --- edx_proctoring/api.py | 4 ++-- edx_proctoring/models.py | 5 ++++- edx_proctoring/views.py | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) 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/views.py b/edx_proctoring/views.py index 415998e179a..7173c443737 100644 --- a/edx_proctoring/views.py +++ b/edx_proctoring/views.py @@ -900,7 +900,7 @@ 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] @@ -966,7 +966,7 @@ def get(self, request, exam_id=None): # pylint: disable=unused-argument if exam_id: attempt = get_current_exam_attempt(exam_id, request.user.id) - response_dict['status'] = attempt['status'] if attempt else "not_started" + response_dict['attempt_status'] = attempt['status'] if attempt else "not_started" return Response(data=response_dict, status=status.HTTP_200_OK)