Authentication and Authorization for Cert Rest APIs fixed

parent 18cddf6e
"""
Tests for the Certificate REST APIs.
"""
from datetime import datetime, timedelta
from django.core.urlresolvers import reverse
from oauth2_provider import models as dot_models
from rest_framework import status
from rest_framework.test import APITestCase
......@@ -12,6 +15,8 @@ from student.tests.factories import UserFactory
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
USER_PASSWORD = 'test'
class CertificatesRestApiTest(SharedModuleStoreTestCase, APITestCase):
"""
......@@ -29,9 +34,9 @@ class CertificatesRestApiTest(SharedModuleStoreTestCase, APITestCase):
def setUp(self):
super(CertificatesRestApiTest, self).setUp()
self.student = UserFactory.create(password='test')
self.student_no_cert = UserFactory.create(password='test')
self.staff_user = UserFactory.create(password='test', is_staff=True)
self.student = UserFactory.create(password=USER_PASSWORD)
self.student_no_cert = UserFactory.create(password=USER_PASSWORD)
self.staff_user = UserFactory.create(password=USER_PASSWORD, is_staff=True)
GeneratedCertificateFactory.create(
user=self.student,
......@@ -44,6 +49,23 @@ class CertificatesRestApiTest(SharedModuleStoreTestCase, APITestCase):
self.namespaced_url = 'certificates_api:v0:certificates:detail'
# create a configuration for django-oauth-toolkit (DOT)
dot_app_user = UserFactory.create(password=USER_PASSWORD)
dot_app = dot_models.Application.objects.create(
name='test app',
user=dot_app_user,
client_type='confidential',
authorization_grant_type='authorization-code',
redirect_uris='http://localhost:8079/complete/edxorg/'
)
self.dot_access_token = dot_models.AccessToken.objects.create(
user=self.student,
application=dot_app,
expires=datetime.utcnow() + timedelta(weeks=1),
scope='read write',
token='16MGyP3OaQYHmpT1lK7Q6MMNAZsjwF'
)
def get_url(self, username):
"""
Helper function to create the url for certificates
......@@ -56,6 +78,15 @@ class CertificatesRestApiTest(SharedModuleStoreTestCase, APITestCase):
}
)
def assert_oauth_status(self, access_token, expected_status):
"""
Helper method for requests with OAUTH token
"""
self.client.logout()
auth_header = "Bearer {0}".format(access_token)
response = self.client.get(self.get_url(self.student.username), HTTP_AUTHORIZATION=auth_header)
self.assertEqual(response.status_code, expected_status)
def test_permissions(self):
"""
Test that only the owner of the certificate can access the url
......@@ -65,7 +96,7 @@ class CertificatesRestApiTest(SharedModuleStoreTestCase, APITestCase):
self.assertEqual(resp.status_code, status.HTTP_401_UNAUTHORIZED)
# another student
self.client.login(username=self.student_no_cert.username, password='test')
self.client.login(username=self.student_no_cert.username, password=USER_PASSWORD)
resp = self.client.get(self.get_url(self.student.username))
# gets 404 instead of 403 for security reasons
self.assertEqual(resp.status_code, status.HTTP_404_NOT_FOUND)
......@@ -73,21 +104,57 @@ class CertificatesRestApiTest(SharedModuleStoreTestCase, APITestCase):
self.client.logout()
# same student of the certificate
self.client.login(username=self.student.username, password='test')
self.client.login(username=self.student.username, password=USER_PASSWORD)
resp = self.client.get(self.get_url(self.student.username))
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.client.logout()
# staff user
self.client.login(username=self.staff_user.username, password='test')
self.client.login(username=self.staff_user.username, password=USER_PASSWORD)
resp = self.client.get(self.get_url(self.student.username))
self.assertEqual(resp.status_code, status.HTTP_200_OK)
def test_inactive_user_access(self):
"""
Verify inactive users - those who have not verified their email addresses -
are allowed to access the endpoint.
"""
self.client.login(username=self.student.username, password=USER_PASSWORD)
self.student.is_active = False
self.student.save()
resp = self.client.get(self.get_url(self.student.username))
self.assertEqual(resp.status_code, status.HTTP_200_OK)
def test_dot_valid_accesstoken(self):
"""
Verify access with a valid Django Oauth Toolkit access token.
"""
self.assert_oauth_status(self.dot_access_token, status.HTTP_200_OK)
def test_dot_invalid_accesstoken(self):
"""
Verify the endpoint is inaccessible for authorization
attempts made with an invalid OAuth access token.
"""
self.assert_oauth_status("fooooooooooToken", status.HTTP_401_UNAUTHORIZED)
def test_dot_expired_accesstoken(self):
"""
Verify the endpoint is inaccessible for authorization
attempts made with an expired OAuth access token.
"""
# set the expiration date in the past
self.dot_access_token.expires = datetime.utcnow() - timedelta(weeks=1)
self.dot_access_token.save()
self.assert_oauth_status(self.dot_access_token, status.HTTP_401_UNAUTHORIZED)
def test_no_certificate_for_user(self):
"""
Test for case with no certificate available
"""
self.client.login(username=self.student_no_cert.username, password='test')
self.client.login(username=self.student_no_cert.username, password=USER_PASSWORD)
resp = self.client.get(self.get_url(self.student_no_cert.username))
self.assertEqual(resp.status_code, status.HTTP_404_NOT_FOUND)
self.assertIn('error_code', resp.data) # pylint: disable=no-member
......@@ -100,7 +167,7 @@ class CertificatesRestApiTest(SharedModuleStoreTestCase, APITestCase):
"""
Tests case user that pulls her own certificate
"""
self.client.login(username=self.student.username, password='test')
self.client.login(username=self.student.username, password=USER_PASSWORD)
resp = self.client.get(self.get_url(self.student.username))
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.assertEqual(
......
......@@ -3,14 +3,16 @@ import logging
from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey
from rest_framework.authentication import SessionAuthentication
from rest_framework.generics import GenericAPIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework_oauth.authentication import OAuth2Authentication
from lms.djangoapps.certificates.api import get_certificate_for_user
from openedx.core.lib.api import permissions
from openedx.core.lib.api import (
authentication,
permissions,
)
log = logging.getLogger(__name__)
......@@ -64,8 +66,14 @@ class CertificatesDetailView(GenericAPIView):
}
"""
authentication_classes = (OAuth2Authentication, SessionAuthentication,)
permission_classes = (IsAuthenticated, permissions.IsUserInUrlOrStaff)
authentication_classes = (
authentication.OAuth2AuthenticationAllowInactiveUser,
authentication.SessionAuthenticationAllowInactiveUser,
)
permission_classes = (
IsAuthenticated,
permissions.IsUserInUrlOrStaff
)
def get(self, request, username, course_id):
"""
......
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