Commit 26532648 by Afzal Wali

Added more implementation of endpoints.

parent c57e6dc7
......@@ -8,7 +8,8 @@ from django.db.models import Model
from rest_framework import status
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
......@@ -17,12 +18,17 @@ LOG = logging.getLogger("edx_proctoring_views")
class ProctoredExamView(AuthenticatedAPIView):
"""
Endpoint for the Proctored Exams
/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
Creates a new Exam.
{
Expected POST data: {
"course_id": "edX/DemoX/Demo_Course",
"content_id": 123,
"exam_name": "Midterm",
......@@ -32,7 +38,7 @@ class ProctoredExamView(AuthenticatedAPIView):
"is_active": true,
}
**Post Parameters**
**POST data Parameters**
* 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.
* exam_name: This is the display name of the Exam (Midterm etc).
......@@ -50,19 +56,29 @@ class ProctoredExamView(AuthenticatedAPIView):
HTTP PUT
Updates an existing Exam.
exam_id,
exam_name=None,
time_limit_mins=None,
is_proctored=None,
external_id=None,
is_active=None
PUT data : {
"exam_id": 533,
"exam_name": "Final",
"time_limit_mins": 120,
"is_proctored": true,
"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
returns an existing exam
Scenarios
by id
by content id
** Scenarios **
?exam_id=533
returns an existing exam object matching the exam_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):
"""
......@@ -106,20 +122,53 @@ class ProctoredExamView(AuthenticatedAPIView):
data={"detail": "The exam_id does not exist."}
)
def get(self, request):
"""
HTTP GET handler.
Scenarios:
by id
by content id
Scenarios:
by exam_id: calls get_exam_by_id()
by course_id, content_id: get_exam_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):
"""
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
......@@ -137,17 +186,46 @@ class StudentProctoredExamAttempt(AuthenticatedAPIView):
'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):
"""
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):
"""
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):
......@@ -158,10 +236,35 @@ class ExamAllowanceView(AuthenticatedAPIView):
"""
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):
"""
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):
"""
......@@ -171,3 +274,13 @@ class ActiveExamsForUserView(AuthenticatedAPIView):
"""
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