Commit a5ba4769 by Jillian Vogel

Ensures that the following GeneratedCertificate fields are passed

through to the REST API:

* created_date: date/time the certificate was issued.
* is_passing: boolean flag denoting whether the certificate status is
  passing or non-passing.

And adds JwtAuthentication, so the Certificates REST API can be easily
accessed from Enterprise management commands.
parent 67e83f92
...@@ -63,6 +63,7 @@ def format_certificate_for_user(username, cert): ...@@ -63,6 +63,7 @@ def format_certificate_for_user(username, cert):
"grade": cert.grade, "grade": cert.grade,
"created": cert.created_date, "created": cert.created_date,
"modified": cert.modified_date, "modified": cert.modified_date,
"is_passing": is_passing_status(cert.status),
# NOTE: the download URL is not currently being set for webview certificates. # NOTE: the download URL is not currently being set for webview certificates.
# In the future, we can update this to construct a URL to the webview certificate # In the future, we can update this to construct a URL to the webview certificate
......
...@@ -4,6 +4,8 @@ Tests for the Certificate REST APIs. ...@@ -4,6 +4,8 @@ Tests for the Certificate REST APIs.
from datetime import datetime, timedelta from datetime import datetime, timedelta
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.utils import timezone
from freezegun import freeze_time
from oauth2_provider import models as dot_models from oauth2_provider import models as dot_models
from rest_framework import status from rest_framework import status
from rest_framework.test import APITestCase from rest_framework.test import APITestCase
...@@ -22,6 +24,8 @@ class CertificatesRestApiTest(SharedModuleStoreTestCase, APITestCase): ...@@ -22,6 +24,8 @@ class CertificatesRestApiTest(SharedModuleStoreTestCase, APITestCase):
""" """
Test for the Certificates REST APIs Test for the Certificates REST APIs
""" """
now = timezone.now()
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
super(CertificatesRestApiTest, cls).setUpClass() super(CertificatesRestApiTest, cls).setUpClass()
...@@ -31,6 +35,7 @@ class CertificatesRestApiTest(SharedModuleStoreTestCase, APITestCase): ...@@ -31,6 +35,7 @@ class CertificatesRestApiTest(SharedModuleStoreTestCase, APITestCase):
display_name='Verified Course' display_name='Verified Course'
) )
@freeze_time(now)
def setUp(self): def setUp(self):
super(CertificatesRestApiTest, self).setUp() super(CertificatesRestApiTest, self).setUp()
...@@ -175,9 +180,11 @@ class CertificatesRestApiTest(SharedModuleStoreTestCase, APITestCase): ...@@ -175,9 +180,11 @@ class CertificatesRestApiTest(SharedModuleStoreTestCase, APITestCase):
{ {
'username': self.student.username, 'username': self.student.username,
'status': CertificateStatuses.downloadable, 'status': CertificateStatuses.downloadable,
'is_passing': True,
'grade': '0.88', 'grade': '0.88',
'download_url': 'www.google.com', 'download_url': 'www.google.com',
'certificate_type': CourseMode.VERIFIED, 'certificate_type': CourseMode.VERIFIED,
'course_id': unicode(self.course.id), 'course_id': unicode(self.course.id),
'created_date': self.now,
} }
) )
...@@ -8,12 +8,12 @@ from rest_framework.permissions import IsAuthenticated ...@@ -8,12 +8,12 @@ from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response from rest_framework.response import Response
from lms.djangoapps.certificates.api import get_certificate_for_user from lms.djangoapps.certificates.api import get_certificate_for_user
from edx_rest_framework_extensions.authentication import JwtAuthentication
from openedx.core.lib.api import ( from openedx.core.lib.api import (
authentication, authentication,
permissions, permissions,
) )
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
...@@ -48,8 +48,12 @@ class CertificatesDetailView(GenericAPIView): ...@@ -48,8 +48,12 @@ class CertificatesDetailView(GenericAPIView):
* certificate_type: A string representation of the certificate type. * certificate_type: A string representation of the certificate type.
Can be honor|verified|professional Can be honor|verified|professional
* created_date: Date/time the certificate was created, in ISO-8661 format.
* status: A string representation of the certificate status. * status: A string representation of the certificate status.
* is_passing: True if the certificate has a passing status, False if not.
* download_url: A string representation of the certificate url. * download_url: A string representation of the certificate url.
* grade: A string representation of a float for the user's course grade. * grade: A string representation of a float for the user's course grade.
...@@ -60,7 +64,9 @@ class CertificatesDetailView(GenericAPIView): ...@@ -60,7 +64,9 @@ class CertificatesDetailView(GenericAPIView):
"username": "bob", "username": "bob",
"course_id": "edX/DemoX/Demo_Course", "course_id": "edX/DemoX/Demo_Course",
"certificate_type": "verified", "certificate_type": "verified",
"created_date": "2015-12-03T13:14:28+0000",
"status": "downloadable", "status": "downloadable",
"is_passing": true,
"download_url": "http://www.example.com/cert.pdf", "download_url": "http://www.example.com/cert.pdf",
"grade": "0.98" "grade": "0.98"
} }
...@@ -69,6 +75,7 @@ class CertificatesDetailView(GenericAPIView): ...@@ -69,6 +75,7 @@ class CertificatesDetailView(GenericAPIView):
authentication_classes = ( authentication_classes = (
authentication.OAuth2AuthenticationAllowInactiveUser, authentication.OAuth2AuthenticationAllowInactiveUser,
authentication.SessionAuthenticationAllowInactiveUser, authentication.SessionAuthenticationAllowInactiveUser,
JwtAuthentication,
) )
permission_classes = ( permission_classes = (
IsAuthenticated, IsAuthenticated,
...@@ -107,7 +114,9 @@ class CertificatesDetailView(GenericAPIView): ...@@ -107,7 +114,9 @@ class CertificatesDetailView(GenericAPIView):
"username": user_cert.get('username'), "username": user_cert.get('username'),
"course_id": unicode(user_cert.get('course_key')), "course_id": unicode(user_cert.get('course_key')),
"certificate_type": user_cert.get('type'), "certificate_type": user_cert.get('type'),
"created_date": user_cert.get('created'),
"status": user_cert.get('status'), "status": user_cert.get('status'),
"is_passing": user_cert.get('is_passing'),
"download_url": user_cert.get('download_url'), "download_url": user_cert.get('download_url'),
"grade": user_cert.get('grade') "grade": user_cert.get('grade')
} }
......
...@@ -8,6 +8,8 @@ from django.test import TestCase, RequestFactory ...@@ -8,6 +8,8 @@ from django.test import TestCase, RequestFactory
from django.test.utils import override_settings from django.test.utils import override_settings
from django.conf import settings from django.conf import settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.utils import timezone
from freezegun import freeze_time
from mock import patch from mock import patch
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from opaque_keys.edx.locator import CourseLocator from opaque_keys.edx.locator import CourseLocator
...@@ -321,7 +323,10 @@ class CertificateisInvalid(WebCertificateTestMixin, ModuleStoreTestCase): ...@@ -321,7 +323,10 @@ class CertificateisInvalid(WebCertificateTestMixin, ModuleStoreTestCase):
@attr(shard=1) @attr(shard=1)
class CertificateGetTests(SharedModuleStoreTestCase): class CertificateGetTests(SharedModuleStoreTestCase):
"""Tests for the `test_get_certificate_for_user` helper function. """ """Tests for the `test_get_certificate_for_user` helper function. """
now = timezone.now()
@classmethod @classmethod
@freeze_time(now)
def setUpClass(cls): def setUpClass(cls):
super(CertificateGetTests, cls).setUpClass() super(CertificateGetTests, cls).setUpClass()
cls.student = UserFactory() cls.student = UserFactory()
...@@ -368,9 +373,11 @@ class CertificateGetTests(SharedModuleStoreTestCase): ...@@ -368,9 +373,11 @@ class CertificateGetTests(SharedModuleStoreTestCase):
self.assertEqual(cert['username'], self.student.username) self.assertEqual(cert['username'], self.student.username)
self.assertEqual(cert['course_key'], self.web_cert_course.id) self.assertEqual(cert['course_key'], self.web_cert_course.id)
self.assertEqual(cert['created'], self.now)
self.assertEqual(cert['type'], CourseMode.VERIFIED) self.assertEqual(cert['type'], CourseMode.VERIFIED)
self.assertEqual(cert['status'], CertificateStatuses.downloadable) self.assertEqual(cert['status'], CertificateStatuses.downloadable)
self.assertEqual(cert['grade'], "0.88") self.assertEqual(cert['grade'], "0.88")
self.assertEqual(cert['is_passing'], True)
self.assertEqual(cert['download_url'], 'www.google.com') self.assertEqual(cert['download_url'], 'www.google.com')
def test_get_certificates_for_user(self): def test_get_certificates_for_user(self):
...@@ -383,10 +390,14 @@ class CertificateGetTests(SharedModuleStoreTestCase): ...@@ -383,10 +390,14 @@ class CertificateGetTests(SharedModuleStoreTestCase):
self.assertEqual(certs[1]['username'], self.student.username) self.assertEqual(certs[1]['username'], self.student.username)
self.assertEqual(certs[0]['course_key'], self.web_cert_course.id) self.assertEqual(certs[0]['course_key'], self.web_cert_course.id)
self.assertEqual(certs[1]['course_key'], self.pdf_cert_course.id) self.assertEqual(certs[1]['course_key'], self.pdf_cert_course.id)
self.assertEqual(certs[0]['created'], self.now)
self.assertEqual(certs[1]['created'], self.now)
self.assertEqual(certs[0]['type'], CourseMode.VERIFIED) self.assertEqual(certs[0]['type'], CourseMode.VERIFIED)
self.assertEqual(certs[1]['type'], CourseMode.HONOR) self.assertEqual(certs[1]['type'], CourseMode.HONOR)
self.assertEqual(certs[0]['status'], CertificateStatuses.downloadable) self.assertEqual(certs[0]['status'], CertificateStatuses.downloadable)
self.assertEqual(certs[1]['status'], CertificateStatuses.downloadable) self.assertEqual(certs[1]['status'], CertificateStatuses.downloadable)
self.assertEqual(certs[0]['is_passing'], True)
self.assertEqual(certs[1]['is_passing'], True)
self.assertEqual(certs[0]['grade'], '0.88') self.assertEqual(certs[0]['grade'], '0.88')
self.assertEqual(certs[1]['grade'], '0.99') self.assertEqual(certs[1]['grade'], '0.99')
self.assertEqual(certs[0]['download_url'], 'www.google.com') self.assertEqual(certs[0]['download_url'], 'www.google.com')
......
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