Commit 4f939f79 by Zia Fazal

added new endpoint which renders certificate by uuid

fixed broken tests and added some optimisations

fixed migration history
parent 9fc7c73b
...@@ -82,12 +82,9 @@ class CertificateDisplayTest(ModuleStoreTestCase): ...@@ -82,12 +82,9 @@ class CertificateDisplayTest(ModuleStoreTestCase):
@override_settings(CERT_NAME_SHORT='Test_Certificate') @override_settings(CERT_NAME_SHORT='Test_Certificate')
@patch.dict('django.conf.settings.FEATURES', {'CERTIFICATES_HTML_VIEW': True}) @patch.dict('django.conf.settings.FEATURES', {'CERTIFICATES_HTML_VIEW': True})
def test_linked_student_to_web_view_credential(self, enrollment_mode): def test_linked_student_to_web_view_credential(self, enrollment_mode):
test_url = get_certificate_url( cert = self._create_certificate(enrollment_mode)
user_id=self.user.id, test_url = get_certificate_url(uuid=cert.verify_uuid)
course_id=unicode(self.course.id)
)
self._create_certificate(enrollment_mode)
certificates = [ certificates = [
{ {
'id': 0, 'id': 0,
...@@ -165,7 +162,7 @@ class CertificateDisplayTest(ModuleStoreTestCase): ...@@ -165,7 +162,7 @@ class CertificateDisplayTest(ModuleStoreTestCase):
def _create_certificate(self, enrollment_mode): def _create_certificate(self, enrollment_mode):
"""Simulate that the user has a generated certificate. """ """Simulate that the user has a generated certificate. """
CourseEnrollmentFactory.create(user=self.user, course_id=self.course.id, mode=enrollment_mode) CourseEnrollmentFactory.create(user=self.user, course_id=self.course.id, mode=enrollment_mode)
GeneratedCertificateFactory( return GeneratedCertificateFactory(
user=self.user, user=self.user,
course_id=self.course.id, course_id=self.course.id,
mode=enrollment_mode, mode=enrollment_mode,
......
...@@ -337,13 +337,9 @@ def _cert_info(user, course_overview, cert_status, course_mode): # pylint: disa ...@@ -337,13 +337,9 @@ def _cert_info(user, course_overview, cert_status, course_mode): # pylint: disa
# showing the certificate web view button if certificate is ready state and feature flags are enabled. # showing the certificate web view button if certificate is ready state and feature flags are enabled.
if has_html_certificates_enabled(course_overview.id, course_overview): if has_html_certificates_enabled(course_overview.id, course_overview):
if course_overview.has_any_active_web_certificate: if course_overview.has_any_active_web_certificate:
certificate_url = get_certificate_url(
user_id=user.id,
course_id=unicode(course_overview.id),
)
status_dict.update({ status_dict.update({
'show_cert_web_view': True, 'show_cert_web_view': True,
'cert_web_view_url': u'{url}'.format(url=certificate_url) 'cert_web_view_url': get_certificate_url(uuid=cert_status['uuid'])
}) })
else: else:
# don't show download certificate button if we don't have an active certificate for course # don't show download certificate button if we don't have an active certificate for course
......
...@@ -167,7 +167,7 @@ def certificate_downloadable_status(student, course_key): ...@@ -167,7 +167,7 @@ def certificate_downloadable_status(student, course_key):
course_key (CourseKey): ID associated with the course course_key (CourseKey): ID associated with the course
Returns: Returns:
Dict containing student passed status also download url for cert if available Dict containing student passed status also download url, uuid for cert if available
""" """
current_status = certificate_status_for_student(student, course_key) current_status = certificate_status_for_student(student, course_key)
...@@ -178,12 +178,14 @@ def certificate_downloadable_status(student, course_key): ...@@ -178,12 +178,14 @@ def certificate_downloadable_status(student, course_key):
'is_downloadable': False, 'is_downloadable': False,
'is_generating': True if current_status['status'] in [CertificateStatuses.generating, 'is_generating': True if current_status['status'] in [CertificateStatuses.generating,
CertificateStatuses.error] else False, CertificateStatuses.error] else False,
'download_url': None 'download_url': None,
'uuid': None,
} }
if current_status['status'] == CertificateStatuses.downloadable: if current_status['status'] == CertificateStatuses.downloadable:
response_data['is_downloadable'] = True response_data['is_downloadable'] = True
response_data['download_url'] = current_status['download_url'] or get_certificate_url(student.id, course_key) response_data['download_url'] = current_status['download_url'] or get_certificate_url(student.id, course_key)
response_data['uuid'] = current_status['uuid']
return response_data return response_data
...@@ -332,19 +334,27 @@ def example_certificates_status(course_key): ...@@ -332,19 +334,27 @@ def example_certificates_status(course_key):
return ExampleCertificateSet.latest_status(course_key) return ExampleCertificateSet.latest_status(course_key)
def get_certificate_url(user_id, course_id): def get_certificate_url(user_id=None, course_id=None, uuid=None):
""" """
:return certificate url :return certificate url for web or pdf certs. In case of web certs returns either old
or new cert url based on given parameters. For web certs if `uuid` is it would return
new uuid based cert url url otherwise old url.
""" """
url = "" url = ""
if settings.FEATURES.get('CERTIFICATES_HTML_VIEW', False): if settings.FEATURES.get('CERTIFICATES_HTML_VIEW', False):
url = reverse( if uuid:
'certificates:html_view', url = reverse(
kwargs={ 'certificates:render_cert_by_uuid',
"user_id": str(user_id), kwargs=dict(certificate_uuid=uuid)
"course_id": unicode(course_id), )
} elif user_id and course_id:
) url = reverse(
'certificates:html_view',
kwargs={
"user_id": str(user_id),
"course_id": unicode(course_id),
}
)
else: else:
try: try:
if isinstance(course_id, basestring): if isinstance(course_id, basestring):
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('certificates', '0004_certificategenerationhistory'),
]
operations = [
migrations.AlterField(
model_name='generatedcertificate',
name='verify_uuid',
field=models.CharField(default=b'', max_length=32, db_index=True, blank=True),
),
]
...@@ -162,7 +162,7 @@ class GeneratedCertificate(models.Model): ...@@ -162,7 +162,7 @@ class GeneratedCertificate(models.Model):
user = models.ForeignKey(User) user = models.ForeignKey(User)
course_id = CourseKeyField(max_length=255, blank=True, default=None) course_id = CourseKeyField(max_length=255, blank=True, default=None)
verify_uuid = models.CharField(max_length=32, blank=True, default='') verify_uuid = models.CharField(max_length=32, blank=True, default='', db_index=True)
download_uuid = models.CharField(max_length=32, blank=True, default='') download_uuid = models.CharField(max_length=32, blank=True, default='')
download_url = models.CharField(max_length=128, blank=True, default='') download_url = models.CharField(max_length=128, blank=True, default='')
grade = models.CharField(max_length=5, blank=True, default='') grade = models.CharField(max_length=5, blank=True, default='')
...@@ -301,7 +301,8 @@ def certificate_status_for_student(student, course_id): ...@@ -301,7 +301,8 @@ def certificate_status_for_student(student, course_id):
user=student, course_id=course_id) user=student, course_id=course_id)
cert_status = { cert_status = {
'status': generated_certificate.status, 'status': generated_certificate.status,
'mode': generated_certificate.mode 'mode': generated_certificate.mode,
'uuid': generated_certificate.verify_uuid,
} }
if generated_certificate.grade: if generated_certificate.grade:
cert_status['grade'] = generated_certificate.grade cert_status['grade'] = generated_certificate.grade
...@@ -311,7 +312,7 @@ def certificate_status_for_student(student, course_id): ...@@ -311,7 +312,7 @@ def certificate_status_for_student(student, course_id):
return cert_status return cert_status
except GeneratedCertificate.DoesNotExist: except GeneratedCertificate.DoesNotExist:
pass pass
return {'status': CertificateStatuses.unavailable, 'mode': GeneratedCertificate.MODES.honor} return {'status': CertificateStatuses.unavailable, 'mode': GeneratedCertificate.MODES.honor, 'uuid': None}
def certificate_info_for_user(user, course_id, grade, user_is_whitelisted=None): def certificate_info_for_user(user, course_id, grade, user_is_whitelisted=None):
......
# Factories are self documenting # Factories are self documenting
# pylint: disable=missing-docstring # pylint: disable=missing-docstring
import factory import factory
from uuid import uuid4
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
from factory.django import DjangoModelFactory, ImageField from factory.django import DjangoModelFactory, ImageField
...@@ -21,6 +22,7 @@ class GeneratedCertificateFactory(DjangoModelFactory): ...@@ -21,6 +22,7 @@ class GeneratedCertificateFactory(DjangoModelFactory):
status = CertificateStatuses.unavailable status = CertificateStatuses.unavailable
mode = GeneratedCertificate.MODES.honor mode = GeneratedCertificate.MODES.honor
name = '' name = ''
verify_uuid = uuid4().hex
class CertificateWhitelistFactory(DjangoModelFactory): class CertificateWhitelistFactory(DjangoModelFactory):
......
...@@ -23,7 +23,8 @@ from certificates.models import ( ...@@ -23,7 +23,8 @@ from certificates.models import (
CertificateStatuses, CertificateStatuses,
CertificateGenerationConfiguration, CertificateGenerationConfiguration,
ExampleCertificate, ExampleCertificate,
GeneratedCertificate GeneratedCertificate,
certificate_status_for_student,
) )
from certificates.queue import XQueueCertInterface, XQueueAddToQueueError from certificates.queue import XQueueCertInterface, XQueueAddToQueueError
from certificates.tests.factories import GeneratedCertificateFactory from certificates.tests.factories import GeneratedCertificateFactory
...@@ -105,13 +106,13 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes ...@@ -105,13 +106,13 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes
status=CertificateStatuses.generating, status=CertificateStatuses.generating,
mode='verified' mode='verified'
) )
self.assertEqual( self.assertEqual(
certs_api.certificate_downloadable_status(self.student, self.course.id), certs_api.certificate_downloadable_status(self.student, self.course.id),
{ {
'is_downloadable': False, 'is_downloadable': False,
'is_generating': True, 'is_generating': True,
'download_url': None 'download_url': None,
'uuid': None,
} }
) )
...@@ -128,7 +129,8 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes ...@@ -128,7 +129,8 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes
{ {
'is_downloadable': False, 'is_downloadable': False,
'is_generating': True, 'is_generating': True,
'download_url': None 'download_url': None,
'uuid': None
} }
) )
...@@ -138,7 +140,8 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes ...@@ -138,7 +140,8 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes
{ {
'is_downloadable': False, 'is_downloadable': False,
'is_generating': False, 'is_generating': False,
'download_url': None 'download_url': None,
'uuid': None,
} }
) )
...@@ -147,12 +150,12 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes ...@@ -147,12 +150,12 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes
Verifies certificate_downloadable_status returns the Verifies certificate_downloadable_status returns the
correct response for PDF certificates. correct response for PDF certificates.
""" """
GeneratedCertificateFactory.create( cert = GeneratedCertificateFactory.create(
user=self.student, user=self.student,
course_id=self.course.id, course_id=self.course.id,
status=CertificateStatuses.downloadable, status=CertificateStatuses.downloadable,
mode='verified', mode='verified',
download_url='www.google.com' download_url='www.google.com',
) )
self.assertEqual( self.assertEqual(
...@@ -160,7 +163,8 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes ...@@ -160,7 +163,8 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes
{ {
'is_downloadable': True, 'is_downloadable': True,
'is_generating': False, 'is_generating': False,
'download_url': 'www.google.com' 'download_url': 'www.google.com',
'uuid': cert.verify_uuid
} }
) )
...@@ -178,6 +182,7 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes ...@@ -178,6 +182,7 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes
with self._mock_passing_grade(): with self._mock_passing_grade():
certs_api.generate_user_certificates(self.student, self.course.id) certs_api.generate_user_certificates(self.student, self.course.id)
cert_status = certificate_status_for_student(self.student, self.course.id)
self.assertEqual( self.assertEqual(
certs_api.certificate_downloadable_status(self.student, self.course.id), certs_api.certificate_downloadable_status(self.student, self.course.id),
{ {
...@@ -187,6 +192,7 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes ...@@ -187,6 +192,7 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes
user_id=self.student.id, # pylint: disable=no-member user_id=self.student.id, # pylint: disable=no-member
course_id=self.course.id, course_id=self.course.id,
), ),
'uuid': cert_status['uuid']
} }
) )
......
...@@ -210,7 +210,6 @@ class MicrositeCertificatesViewsTests(ModuleStoreTestCase): ...@@ -210,7 +210,6 @@ class MicrositeCertificatesViewsTests(ModuleStoreTestCase):
self.cert = GeneratedCertificate.objects.create( self.cert = GeneratedCertificate.objects.create(
user=self.user, user=self.user,
course_id=self.course_id, course_id=self.course_id,
verify_uuid=uuid4(),
download_uuid=uuid4(), download_uuid=uuid4(),
grade="0.95", grade="0.95",
key='the_key', key='the_key',
......
...@@ -33,6 +33,7 @@ from certificates.tests.factories import ( ...@@ -33,6 +33,7 @@ from certificates.tests.factories import (
CertificateHtmlViewConfigurationFactory, CertificateHtmlViewConfigurationFactory,
LinkedInAddToProfileConfigurationFactory, LinkedInAddToProfileConfigurationFactory,
BadgeAssertionFactory, BadgeAssertionFactory,
GeneratedCertificateFactory,
) )
from util import organizations_helpers as organizations_api from util import organizations_helpers as organizations_api
from django.test.client import RequestFactory from django.test.client import RequestFactory
...@@ -80,10 +81,9 @@ class CertificatesViewsTests(ModuleStoreTestCase, EventTrackingTestCase): ...@@ -80,10 +81,9 @@ class CertificatesViewsTests(ModuleStoreTestCase, EventTrackingTestCase):
self.client.login(username=self.user.username, password='foo') self.client.login(username=self.user.username, password='foo')
self.request = RequestFactory().request() self.request = RequestFactory().request()
self.cert = GeneratedCertificate.objects.create( self.cert = GeneratedCertificateFactory.create(
user=self.user, user=self.user,
course_id=self.course_id, course_id=self.course_id,
verify_uuid=uuid4(),
download_uuid=uuid4(), download_uuid=uuid4(),
download_url="http://www.example.com/certificates/download", download_url="http://www.example.com/certificates/download",
grade="0.95", grade="0.95",
...@@ -164,11 +164,9 @@ class CertificatesViewsTests(ModuleStoreTestCase, EventTrackingTestCase): ...@@ -164,11 +164,9 @@ class CertificatesViewsTests(ModuleStoreTestCase, EventTrackingTestCase):
Test: LinkedIn share URL. Test: LinkedIn share URL.
""" """
self._add_course_certificates(count=1, signatory_count=1, is_active=True) self._add_course_certificates(count=1, signatory_count=1, is_active=True)
test_url = get_certificate_url( test_url = get_certificate_url(uuid=self.cert.verify_uuid)
user_id=self.user.id,
course_id=unicode(self.course.id)
)
response = self.client.get(test_url) response = self.client.get(test_url)
self.assertEqual(response.status_code, 200)
self.assertIn(urllib.quote_plus(self.request.build_absolute_uri(test_url)), response.content) self.assertIn(urllib.quote_plus(self.request.build_absolute_uri(test_url)), response.content)
@override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED) @override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
...@@ -178,12 +176,9 @@ class CertificatesViewsTests(ModuleStoreTestCase, EventTrackingTestCase): ...@@ -178,12 +176,9 @@ class CertificatesViewsTests(ModuleStoreTestCase, EventTrackingTestCase):
Test: LinkedIn share URL should not be visible when called from within a microsite (for now) Test: LinkedIn share URL should not be visible when called from within a microsite (for now)
""" """
self._add_course_certificates(count=1, signatory_count=1, is_active=True) self._add_course_certificates(count=1, signatory_count=1, is_active=True)
test_url = get_certificate_url( test_url = get_certificate_url(uuid=self.cert.verify_uuid)
user_id=self.user.id,
course_id=unicode(self.course.id)
)
response = self.client.get(test_url) response = self.client.get(test_url)
self.assertEqual(response.status_code, 200)
# the URL should not be present # the URL should not be present
self.assertNotIn(urllib.quote_plus(self.request.build_absolute_uri(test_url)), response.content) self.assertNotIn(urllib.quote_plus(self.request.build_absolute_uri(test_url)), response.content)
......
...@@ -10,13 +10,20 @@ from certificates import views ...@@ -10,13 +10,20 @@ from certificates import views
urlpatterns = patterns( urlpatterns = patterns(
'', '',
# Certificates HTML view # Certificates HTML view end point to render web certs by user and course
url( url(
r'^user/(?P<user_id>[^/]*)/course/{course_id}'.format(course_id=settings.COURSE_ID_PATTERN), r'^user/(?P<user_id>[^/]*)/course/{course_id}'.format(course_id=settings.COURSE_ID_PATTERN),
views.render_html_view, views.render_html_view,
name='html_view' name='html_view'
), ),
# Certificates HTML view end point to render web certs by certificate_uuid
url(
r'^(?P<certificate_uuid>[0-9a-f]{32})$',
views.render_cert_by_uuid,
name='render_cert_by_uuid'
),
# End-points used by student support # End-points used by student support
# The views in the lms/djangoapps/support use these end-points # The views in the lms/djangoapps/support use these end-points
# to retrieve certificate information and regenerate certificates. # to retrieve certificate information and regenerate certificates.
......
...@@ -9,7 +9,7 @@ import urllib ...@@ -9,7 +9,7 @@ import urllib
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.http import HttpResponse from django.http import HttpResponse, Http404
from django.template import RequestContext from django.template import RequestContext
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.utils.encoding import smart_str from django.utils.encoding import smart_str
...@@ -271,12 +271,7 @@ def _update_social_context(request, context, course, user, user_certificate, pla ...@@ -271,12 +271,7 @@ def _update_social_context(request, context, course, user, user_certificate, pla
) )
) )
share_url = request.build_absolute_uri( share_url = request.build_absolute_uri(get_certificate_url(uuid=user_certificate.verify_uuid))
reverse(
'certificates:html_view',
kwargs=dict(user_id=str(user.id), course_id=unicode(course.id))
)
)
context['share_url'] = share_url context['share_url'] = share_url
twitter_url = '' twitter_url = ''
if context.get('twitter_share_enabled', False): if context.get('twitter_share_enabled', False):
...@@ -298,10 +293,7 @@ def _update_social_context(request, context, course, user, user_certificate, pla ...@@ -298,10 +293,7 @@ def _update_social_context(request, context, course, user, user_certificate, pla
course.id, course.id,
course.display_name, course.display_name,
user_certificate.mode, user_certificate.mode,
smart_str(request.build_absolute_uri(get_certificate_url( smart_str(share_url)
user_id=user.id,
course_id=unicode(course.id)
)))
) )
...@@ -341,34 +333,25 @@ def _get_user_certificate(request, user, course_key, course, preview_mode=None): ...@@ -341,34 +333,25 @@ def _get_user_certificate(request, user, course_key, course, preview_mode=None):
Returns None if there is no certificate generated for given user Returns None if there is no certificate generated for given user
otherwise returns `GeneratedCertificate` instance. otherwise returns `GeneratedCertificate` instance.
""" """
try: user_certificate = None
# Attempt to load the user's generated certificate data if preview_mode:
if preview_mode: # certificate is being previewed from studio
user_certificate = GeneratedCertificate.objects.get( if has_access(request.user, 'instructor', course) or has_access(request.user, 'staff', course):
user=user, user_certificate = GeneratedCertificate(
course_id=course_key, mode=preview_mode,
mode=preview_mode verify_uuid=unicode(uuid4().hex),
modified_date=datetime.now().date()
) )
else: else:
# certificate is being viewed by learner or public
try:
user_certificate = GeneratedCertificate.objects.get( user_certificate = GeneratedCertificate.objects.get(
user=user, user=user,
course_id=course_key, course_id=course_key,
status=CertificateStatuses.downloadable status=CertificateStatuses.downloadable
) )
except GeneratedCertificate.DoesNotExist:
# If there's no generated certificate data for this user, we need to see if we're in 'preview' mode... pass
# If we are, we'll need to create a mock version of the user_certificate container for previewing
except GeneratedCertificate.DoesNotExist:
if preview_mode and (
has_access(request.user, 'instructor', course) or
has_access(request.user, 'staff', course)):
user_certificate = GeneratedCertificate(
mode=preview_mode,
verify_uuid=unicode(uuid4().hex),
modified_date=datetime.now().date()
)
else:
return None
return user_certificate return user_certificate
...@@ -475,13 +458,27 @@ def _update_organization_context(context, course): ...@@ -475,13 +458,27 @@ def _update_organization_context(context, course):
context['organization_logo'] = organization_logo context['organization_logo'] = organization_logo
def render_cert_by_uuid(request, certificate_uuid):
"""
This public view generates an HTML representation of the specified certificate
"""
try:
certificate = GeneratedCertificate.objects.get(
verify_uuid=certificate_uuid,
status=CertificateStatuses.downloadable
)
return render_html_view(request, certificate.user.id, unicode(certificate.course_id))
except GeneratedCertificate.DoesNotExist:
raise Http404
@handle_500( @handle_500(
template_path="certificates/server-error.html", template_path="certificates/server-error.html",
test_func=lambda request: request.GET.get('preview', None) test_func=lambda request: request.GET.get('preview', None)
) )
def render_html_view(request, user_id, course_id): def render_html_view(request, user_id, course_id):
""" """
This public view generates an HTML representation of the specified student's certificate This public view generates an HTML representation of the specified user and course
If a certificate is not available, we display a "Sorry!" screen instead If a certificate is not available, we display a "Sorry!" screen instead
""" """
preview_mode = request.GET.get('preview', None) preview_mode = request.GET.get('preview', None)
......
...@@ -908,10 +908,7 @@ class ProgressPageTests(ModuleStoreTestCase): ...@@ -908,10 +908,7 @@ class ProgressPageTests(ModuleStoreTestCase):
self.assertContains(resp, u"View Certificate") self.assertContains(resp, u"View Certificate")
self.assertContains(resp, u"You can keep working for a higher grade") self.assertContains(resp, u"You can keep working for a higher grade")
cert_url = certs_api.get_certificate_url( cert_url = certs_api.get_certificate_url(uuid=certificate.verify_uuid)
user_id=self.user.id,
course_id=self.course.id
)
self.assertContains(resp, cert_url) self.assertContains(resp, cert_url)
# when course certificate is not active # when course certificate is not active
......
...@@ -966,18 +966,14 @@ def _progress(request, course_key, student_id): ...@@ -966,18 +966,14 @@ def _progress(request, course_key, student_id):
} }
if show_generate_cert_btn: if show_generate_cert_btn:
context.update(certs_api.certificate_downloadable_status(student, course_key)) cert_status = certs_api.certificate_downloadable_status(student, course_key)
context.update(cert_status)
# showing the certificate web view button if feature flags are enabled. # showing the certificate web view button if feature flags are enabled.
if certs_api.has_html_certificates_enabled(course_key, course): if certs_api.has_html_certificates_enabled(course_key, course):
if certs_api.get_active_web_certificate(course) is not None: if certs_api.get_active_web_certificate(course) is not None:
context.update({ context.update({
'show_cert_web_view': True, 'show_cert_web_view': True,
'cert_web_view_url': u'{url}'.format( 'cert_web_view_url': certs_api.get_certificate_url(uuid=cert_status['uuid']),
url=certs_api.get_certificate_url(
user_id=student.id,
course_id=unicode(course.id)
)
)
}) })
else: else:
context.update({ context.update({
......
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