Commit 9277b5a7 by chrisndodge

Merge pull request #3 from edx/muhhshoaib/PHX-35

PHX-35 Expose REST API to populate Timer Bar
parents a06ca51c b65acd5b
...@@ -4,3 +4,4 @@ source = edx_proctoring ...@@ -4,3 +4,4 @@ source = edx_proctoring
omit = omit =
**/__init__.py **/__init__.py
**/migrations/* **/migrations/*
**/tests/*
"""
In-Proc API (aka Library) for the edx_proctoring subsystem. This is not to be confused with a HTTP REST
API which is in the views.py file, per edX coding standards
"""
"""
All tests for the proctored_exams.py
"""
from django.test.client import Client
from django.core.urlresolvers import reverse, NoReverseMatch
from .utils import (
LoggedInTestCase
)
from edx_proctoring.urls import urlpatterns
class ProctoredExamsApiTests(LoggedInTestCase):
"""
All tests for the views.py
"""
def setUp(self):
"""
Build out test harnessing
"""
super(ProctoredExamsApiTests, self).setUp()
def test_no_anonymous_access(self):
"""
Make sure we cannot access any API methods without being logged in
"""
self.client = Client() # use AnonymousUser on the API calls
for urlpattern in urlpatterns:
if hasattr(urlpattern, 'name'):
try:
response = self.client.get(reverse(urlpattern.name))
except NoReverseMatch:
# some of our URL mappings may require a argument substitution
response = self.client.get(reverse(urlpattern.name, args=[0]))
self.assertEqual(response.status_code, 403)
def test_get_proctored_exam_status(self):
"""
Test Case for retrieving student proctored exam status.
"""
response = self.client.get(
reverse('edx_proctoring.proctored_exam.status')
)
self.assertEqual(response.status_code, 200)
"""
Subclasses Django test client to allow for easy login
"""
from importlib import import_module
from django.conf import settings
from django.contrib.auth import login
from django.http import HttpRequest
from django.test.client import Client
from django.test import TestCase
from django.contrib.auth.models import User
class TestClient(Client):
"""
Allows for 'fake logins' of a user so we don't need to expose a 'login' HTTP endpoint
"""
def login_user(self, user):
"""
Login as specified user, does not depend on auth backend (hopefully)
This is based on Client.login() with a small hack that does not
require the call to authenticate()
"""
if 'django.contrib.sessions' not in settings.INSTALLED_APPS:
raise AssertionError("Unable to login without django.contrib.sessions in INSTALLED_APPS")
user.backend = "django.contrib.auth.backends.ModelBackend"
engine = import_module(settings.SESSION_ENGINE)
# Create a fake request to store login details.
request = HttpRequest()
if self.session:
request.session = self.session
else:
request.session = engine.SessionStore()
login(request, user)
# Set the cookie to represent the session.
session_cookie = settings.SESSION_COOKIE_NAME
self.cookies[session_cookie] = request.session.session_key
cookie_data = {
'max-age': None,
'path': '/',
'domain': settings.SESSION_COOKIE_DOMAIN,
'secure': settings.SESSION_COOKIE_SECURE or None,
'expires': None,
}
self.cookies[session_cookie].update(cookie_data)
# Save the session values.
request.session.save()
class LoggedInTestCase(TestCase):
"""
All tests for the views.py
"""
def setUp(self):
"""
Setup for tests
"""
self.client = TestClient()
self.user = User(username='tester')
self.user.save()
self.client.login_user(self.user)
""" """
URL definitions for the edx proctoring subsystem URL mappings for edX Proctoring Server.
""" """
from edx_proctoring import views
from django.conf.urls import patterns, url, include
urlpatterns = patterns( # pylint: disable=invalid-name
'',
url(
r'edx_proctoring/v1/proctored_exam/status$',
views.StudentProctoredExamStatus.as_view(),
name='edx_proctoring.proctored_exam.status'
),
url(r'^', include('rest_framework.urls', namespace='rest_framework'))
)
"""
Helpers for the HTTP APIs
"""
from rest_framework.views import APIView
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated
class AuthenticatedAPIView(APIView):
"""
Authenticate APi View.
"""
authentication_classes = (SessionAuthentication,)
permission_classes = (IsAuthenticated,)
"""
Proctored Exams HTTP-based API endpoints
"""
import logging
from rest_framework import status
from rest_framework.response import Response
from .utils import AuthenticatedAPIView
LOG = logging.getLogger("edx_proctoring_views")
class StudentProctoredExamStatus(AuthenticatedAPIView):
"""
Returns the status of the proctored exam.
"""
def get(self, request): # pylint: disable=unused-argument
"""
HTTP GET Handler
"""
response_dict = {
'in_timed_exam': True,
'is_proctored': True,
'exam_display_name': 'Midterm',
'exam_url_path': '',
'time_remaining_seconds': 45,
'low_threshold': 30,
'critically_low_threshold': 15,
}
return Response(response_dict, status=status.HTTP_200_OK)
...@@ -20,22 +20,30 @@ SECRET_KEY='SHHHHHH' ...@@ -20,22 +20,30 @@ SECRET_KEY='SHHHHHH'
DATABASES = { DATABASES = {
'default': { 'default': {
'ENGINE': 'django.db.backends.sqlite3', 'ENGINE': 'django.db.backends.sqlite3',
'NAME': '{}/db/edx_proctoring.db'.format(TEST_ROOT) 'NAME': os.path.join(BASE_DIR, 'edx_proctoring.db'),
}, },
} }
SITE_ID = 1
INSTALLED_APPS = ( INSTALLED_APPS = (
'django.contrib.auth', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.contenttypes',
'django.contrib.sessions', 'django.contrib.sessions',
'django.contrib.sites', 'django.contrib.sites',
'django.contrib.messages', 'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework', 'rest_framework',
'edx_proctoring', 'edx_proctoring',
'django_nose', 'django_nose',
'south', 'south',
) )
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.6/howto/static-files/
STATIC_URL = '/static/'
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': ( 'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.UserRateThrottle', 'rest_framework.throttling.UserRateThrottle',
......
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