Commit 26532648 by Afzal Wali

Added more implementation of endpoints.

parent c57e6dc7
...@@ -8,7 +8,8 @@ from django.db.models import Model ...@@ -8,7 +8,8 @@ from django.db.models import Model
from rest_framework import status from rest_framework import status
from rest_framework.response import Response from rest_framework.response import Response
from edx_proctoring.api import create_exam, update_exam from edx_proctoring.api import create_exam, update_exam, get_exam_by_id, get_exam_by_content_id, start_exam_attempt, \
stop_exam_attempt, add_allowance_for_user, remove_allowance_for_user, get_active_exams_for_user
from .utils import AuthenticatedAPIView from .utils import AuthenticatedAPIView
...@@ -17,12 +18,17 @@ LOG = logging.getLogger("edx_proctoring_views") ...@@ -17,12 +18,17 @@ LOG = logging.getLogger("edx_proctoring_views")
class ProctoredExamView(AuthenticatedAPIView): class ProctoredExamView(AuthenticatedAPIView):
""" """
Endpoint for the Proctored Exams
/edx_proctoring/v1/proctored_exam/exam /edx_proctoring/v1/proctored_exam/exam
Supports:
HTTP POST: Creates a new Exam.
HTTP PUT: Updates an existing Exam.
HTTP GET: Returns an existing exam (by id or by content id)
HTTP POST HTTP POST
Creates a new Exam. Creates a new Exam.
{ Expected POST data: {
"course_id": "edX/DemoX/Demo_Course", "course_id": "edX/DemoX/Demo_Course",
"content_id": 123, "content_id": 123,
"exam_name": "Midterm", "exam_name": "Midterm",
...@@ -32,7 +38,7 @@ class ProctoredExamView(AuthenticatedAPIView): ...@@ -32,7 +38,7 @@ class ProctoredExamView(AuthenticatedAPIView):
"is_active": true, "is_active": true,
} }
**Post Parameters** **POST data Parameters**
* course_id: The unique identifier for the course. * course_id: The unique identifier for the course.
* content_id: This will be the pointer to the id of the piece of course_ware which is the proctored exam. * content_id: This will be the pointer to the id of the piece of course_ware which is the proctored exam.
* exam_name: This is the display name of the Exam (Midterm etc). * exam_name: This is the display name of the Exam (Midterm etc).
...@@ -50,19 +56,29 @@ class ProctoredExamView(AuthenticatedAPIView): ...@@ -50,19 +56,29 @@ class ProctoredExamView(AuthenticatedAPIView):
HTTP PUT HTTP PUT
Updates an existing Exam. Updates an existing Exam.
exam_id, PUT data : {
exam_name=None, "exam_id": 533,
time_limit_mins=None, "exam_name": "Final",
is_proctored=None, "time_limit_mins": 120,
external_id=None, "is_proctored": true,
is_active=None "external_id": 235
"is_active": true
}
**PUT data Parameters**
see the POST data parameters
**Response Values**
* {'exam_id': ##}, The exam_id of the created Proctored Exam.
HTTP GET HTTP GET
returns an existing exam ** Scenarios **
Scenarios ?exam_id=533
by id returns an existing exam object matching the exam_id
by content id
?course_id=edX/DemoX/Demo_Course&content_id=123
returns an existing exam object matching the course_id and the content_id
""" """
def post(self, request): def post(self, request):
""" """
...@@ -106,20 +122,53 @@ class ProctoredExamView(AuthenticatedAPIView): ...@@ -106,20 +122,53 @@ class ProctoredExamView(AuthenticatedAPIView):
data={"detail": "The exam_id does not exist."} data={"detail": "The exam_id does not exist."}
) )
def get(self, request): def get(self, request):
""" """
HTTP GET handler. HTTP GET handler.
Scenarios:
Scenarios: by exam_id: calls get_exam_by_id()
by id by course_id, content_id: get_exam_by_content_id()
by content id
""" """
course_id = request.QUERY_PARAMS.get('course_id', None)
content_id = request.QUERY_PARAMS.get('content_id', None)
exam_id = request.QUERY_PARAMS.get('exam_id', None)
if exam_id:
try:
return Response(
data=get_exam_by_id(exam_id),
status=status.HTTP_200_OK
)
except Model.DoesNotExist:
return Response(
status=status.HTTP_400_BAD_REQUEST,
data={"detail": "The exam_id does not exist."}
)
elif course_id is not None and content_id is not None:
try:
return Response(
data=get_exam_by_content_id(course_id, content_id),
status=status.HTTP_200_OK
)
except Model.DoesNotExist:
return Response(
status=status.HTTP_400_BAD_REQUEST,
data={"detail": "The exam with course_id, content_id does not exist."}
)
else:
return Response(
status=status.HTTP_400_BAD_REQUEST,
data={"detail": "Bad input data."}
)
class StudentProctoredExamAttempt(AuthenticatedAPIView): class StudentProctoredExamAttempt(AuthenticatedAPIView):
""" """
Returns the status of the proctored exam. Endpoint for the StudentProctoredExamAttempt
/edx_proctoring/v1/proctored_exam/exam
""" """
def get(self, request): # pylint: disable=unused-argument def get(self, request): # pylint: disable=unused-argument
...@@ -137,17 +186,46 @@ class StudentProctoredExamAttempt(AuthenticatedAPIView): ...@@ -137,17 +186,46 @@ class StudentProctoredExamAttempt(AuthenticatedAPIView):
'critically_low_threshold': 15, 'critically_low_threshold': 15,
} }
return Response(response_dict, status=status.HTTP_200_OK) return Response(
data=response_dict,
status=status.HTTP_200_OK
)
def post(self, request): def post(self, request):
""" """
HTTP POST handler. To start an exam. HTTP POST handler. To start an exam.
""" """
try:
exam_attempt_id = start_exam_attempt(
exam_id=request.DATA.get('exam_id', ""),
user_id=request.DATA.get('user_id', ""),
external_id=request.DATA.get('external_id', "")
)
return Response({'exam_attempt_id': exam_attempt_id})
except Exception:
return Response(
status=status.HTTP_400_BAD_REQUEST,
data={"detail": "Exam already started."}
)
def put(self, request): def put(self, request):
""" """
HTTP POST handler. To stop an exam. HTTP POST handler. To stop an exam.
""" """
try:
exam_attempt_id = stop_exam_attempt(
exam_id=request.DATA.get('exam_id', ""),
user=request.DATA.get('user_id', "")
)
return Response()
except Exception:
return Response(
status=status.HTTP_400_BAD_REQUEST,
data={"detail": "Exam Not in progress."}
)
class ExamAllowanceView(AuthenticatedAPIView): class ExamAllowanceView(AuthenticatedAPIView):
...@@ -158,10 +236,35 @@ class ExamAllowanceView(AuthenticatedAPIView): ...@@ -158,10 +236,35 @@ class ExamAllowanceView(AuthenticatedAPIView):
""" """
HTTP GET handler. Adds or updates Allowance HTTP GET handler. Adds or updates Allowance
""" """
try:
return Response(add_allowance_for_user(
exam_id=request.DATA.get('exam_id', ""),
user_id=request.DATA.get('user_id', ""),
key=request.DATA.get('key', ""),
value=request.DATA.get('value', "")
))
except:
return Response(
status=status.HTTP_400_BAD_REQUEST,
data={"detail": "Could not add Allowance."}
)
def delete(self, request): def delete(self, request):
""" """
HTTP DELETE handler. Removes Allowance. HTTP DELETE handler. Removes Allowance.
""" """
try:
return Response(remove_allowance_for_user(
exam_id=request.DATA.get('exam_id', ""),
user_id=request.DATA.get('user_id', ""),
key=request.DATA.get('key', "")
))
except:
return Response(
status=status.HTTP_400_BAD_REQUEST,
data={"detail": "Could not remove Allowance."}
)
class ActiveExamsForUserView(AuthenticatedAPIView): class ActiveExamsForUserView(AuthenticatedAPIView):
""" """
...@@ -171,3 +274,13 @@ class ActiveExamsForUserView(AuthenticatedAPIView): ...@@ -171,3 +274,13 @@ class ActiveExamsForUserView(AuthenticatedAPIView):
""" """
returns the get_active_exams_for_user returns the get_active_exams_for_user
""" """
try:
return Response(get_active_exams_for_user(
user_id=request.DATA.get('user_id', ""),
course_id=request.DATA.get('course_id', "")
))
except:
return Response(
status=status.HTTP_400_BAD_REQUEST,
data={"detail": "Error."}
)
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