diff --git a/cms/templates/js/maintenance/force-published-course-response.underscore b/cms/templates/js/maintenance/force-published-course-response.underscore
index d77059ca5311..7441413dd47c 100644
--- a/cms/templates/js/maintenance/force-published-course-response.underscore
+++ b/cms/templates/js/maintenance/force-published-course-response.underscore
@@ -3,7 +3,7 @@
<%- gettext('You have done a dry run of force publishing the course. Nothing has changed. Had you run it, the following course versions would have been change.') %>
- <%= StringUtils.interpolate(
+ <%- StringUtils.interpolate(
gettext('The published branch version, {published}, was reset to the draft branch version, {draft}.'),
{
published: current_versions['published-branch'],
diff --git a/cms/templates/js/mock/mock-xmodule-editor.underscore b/cms/templates/js/mock/mock-xmodule-editor.underscore
index db0771e482a5..d06fcb49d88e 100644
--- a/cms/templates/js/mock/mock-xmodule-editor.underscore
+++ b/cms/templates/js/mock/mock-xmodule-editor.underscore
@@ -16,13 +16,13 @@
diff --git a/cms/templates/js/publish-editor.underscore b/cms/templates/js/publish-editor.underscore
index 27c4ce290274..519564f72198 100644
--- a/cms/templates/js/publish-editor.underscore
+++ b/cms/templates/js/publish-editor.underscore
@@ -6,13 +6,13 @@
<% _.each(xblockInfo.get('child_info').children, function(subsection) { %>
<% if (subsection.isPublishable()) { %>
-
<%= subsection.get('display_name') %>
+
<%- subsection.get('display_name') %>
<% _.each(subsection.get('child_info').children, function(unit) { %>
<% if (unit.isPublishable()) { %>
<%- summaryMessage.text %>
<% if (summaryMessage.action_class) { %>
@@ -25,7 +25,7 @@ var aggregateValidationClass = aggregateMessageType === "error"? "has-errors" :
var messageType = message.type
var messageTypeDisplayName = getDisplayName(messageType)
%>
-
+
<% if (messageTypeDisplayName) { %>
<%- messageTypeDisplayName %>:
diff --git a/lms/djangoapps/badges/events/course_complete.py b/lms/djangoapps/badges/events/course_complete.py
index 38ff2f1782c5..b85b4102fa91 100644
--- a/lms/djangoapps/badges/events/course_complete.py
+++ b/lms/djangoapps/badges/events/course_complete.py
@@ -57,8 +57,12 @@ def evidence_url(user_id, course_key):
Generates a URL to the user's Certificate HTML view, along with a GET variable that will signal the evidence visit
event.
"""
+ course_id = unicode(course_key)
+ # avoid circular import problems
+ from lms.djangoapps.certificates.models import GeneratedCertificate
+ cert = GeneratedCertificate.eligible_certificates.get(user__id=int(user_id), course_id=course_id)
return site_prefix() + reverse(
- 'certificates:html_view', kwargs={'user_id': user_id, 'course_id': unicode(course_key)}) + '?evidence_visit=1'
+ 'certificates:render_cert_by_uuid', kwargs={'certificate_uuid': cert.verify_uuid}) + '?evidence_visit=1'
def criteria(course_key):
diff --git a/lms/djangoapps/certificates/api.py b/lms/djangoapps/certificates/api.py
index e54501b2e0e7..79437c3db24b 100644
--- a/lms/djangoapps/certificates/api.py
+++ b/lms/djangoapps/certificates/api.py
@@ -416,13 +416,13 @@ def _course_from_key(course_key):
return CourseOverview.get_from_id(_safe_course_key(course_key))
-def _certificate_html_url(user_id, course_id, uuid):
- if uuid:
- return reverse('certificates:render_cert_by_uuid', kwargs={'certificate_uuid': uuid})
- elif user_id and course_id:
- kwargs = {"user_id": str(user_id), "course_id": unicode(course_id)}
- return reverse('certificates:html_view', kwargs=kwargs)
- return ''
+def _certificate_html_url(uuid):
+ """
+ Returns uuid based certificate URL.
+ """
+ return reverse(
+ 'certificates:render_cert_by_uuid', kwargs={'certificate_uuid': uuid}
+ ) if uuid else ''
def _certificate_download_url(user_id, course_id):
@@ -455,7 +455,7 @@ def get_certificate_url(user_id=None, course_id=None, uuid=None):
return url
if has_html_certificates_enabled(course):
- url = _certificate_html_url(user_id, course_id, uuid)
+ url = _certificate_html_url(uuid)
else:
url = _certificate_download_url(user_id, course_id)
return url
@@ -568,10 +568,11 @@ def emit_certificate_event(event_name, user, course_id, course=None, event_data=
'org_id': course.org,
'course_id': unicode(course_id)
}
+
data = {
'user_id': user.id,
'course_id': unicode(course_id),
- 'certificate_url': get_certificate_url(user.id, course_id)
+ 'certificate_url': get_certificate_url(user.id, course_id, uuid=event_data['certificate_id'])
}
event_data = event_data or {}
event_data.update(data)
diff --git a/lms/djangoapps/certificates/urls.py b/lms/djangoapps/certificates/urls.py
index 9954a2c39d15..e0a08a12bd75 100644
--- a/lms/djangoapps/certificates/urls.py
+++ b/lms/djangoapps/certificates/urls.py
@@ -11,8 +11,14 @@
# Certificates HTML view end point to render web certs by user and course
url(
r'^user/(?P[^/]*)/course/{course_id}'.format(course_id=settings.COURSE_ID_PATTERN),
- views.render_html_view,
- name='html_view'
+ views.unsupported_url,
+ name='unsupported_url'
+ ),
+
+ url(
+ r'^course/{course_id}'.format(course_id=settings.COURSE_ID_PATTERN),
+ views.render_preview_certificate,
+ name='preview_cert'
),
# Certificates HTML view end point to render web certs by certificate_uuid
diff --git a/lms/djangoapps/certificates/views/webview.py b/lms/djangoapps/certificates/views/webview.py
index 0ef11992a657..c4fadfb3822e 100644
--- a/lms/djangoapps/certificates/views/webview.py
+++ b/lms/djangoapps/certificates/views/webview.py
@@ -9,7 +9,6 @@
import pytz
from django.conf import settings
-from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from django.http import Http404, HttpResponse
from django.template import RequestContext
@@ -43,7 +42,6 @@
from openedx.core.djangoapps.catalog.utils import get_course_run_details
from openedx.core.djangoapps.lang_pref.api import get_closest_released_language
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
-from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag, WaffleFlagNamespace
from openedx.core.lib.courses import course_image_url
from openedx.core.djangoapps.certificates.api import display_date_for_certificate, certificates_viewable_for_course
from student.models import LinkedInAddToProfileConfiguration
@@ -57,21 +55,6 @@
INVALID_CERTIFICATE_TEMPLATE_PATH = 'certificates/invalid.html'
-WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace(name='certificates')
-LOGIN_REQUIRED_FLAG = CourseWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'require_login')
-
-
-def certs_login_required(view):
- """
- Require login when the 'certificates.require_login' is enabled
- """
- def wrap(request, user_id, course_id, *args, **kwargs):
- course_key = CourseKey.from_string(course_id)
- if LOGIN_REQUIRED_FLAG.is_enabled(course_key):
- return login_required(view)(request, user_id, course_id, *args, **kwargs)
- else:
- return view(request, user_id, course_id, *args, **kwargs)
- return wrap
def get_certificate_description(mode, certificate_type, platform_name):
@@ -481,6 +464,26 @@ def _update_organization_context(context, course):
context['organization_logo'] = organization_logo
+def unsupported_url(request, user_id, course_id):
+ """
+ This view returns the un-supported url page aimed to let the user aware that
+ url is no longer supported
+ """
+ platform_name = configuration_helpers.get_value("platform_name", settings.PLATFORM_NAME)
+ configuration = CertificateHtmlViewConfiguration.get_config()
+ return _render_invalid_certificate(
+ course_id, platform_name, configuration, cert_path='certificates/url_unsupported.html'
+ )
+
+
+@login_required
+def render_preview_certificate(request, course_id):
+ """
+ This view renders the course certificate in preview mode
+ """
+ return render_html_view(request, unicode(course_id))
+
+
def render_cert_by_uuid(request, certificate_uuid):
"""
This public view generates an HTML representation of the specified certificate
@@ -490,7 +493,7 @@ def render_cert_by_uuid(request, certificate_uuid):
verify_uuid=certificate_uuid,
status=CertificateStatuses.downloadable
)
- return render_html_view(request, certificate.user.id, unicode(certificate.course_id))
+ return render_html_view(request, unicode(certificate.course_id), certificate)
except GeneratedCertificate.DoesNotExist:
raise Http404
@@ -499,17 +502,13 @@ def render_cert_by_uuid(request, certificate_uuid):
template_path="certificates/server-error.html",
test_func=lambda request: request.GET.get('preview', None)
)
-@certs_login_required
-def render_html_view(request, user_id, course_id):
+def render_html_view(request, course_id, certificate=None):
"""
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
"""
- try:
- user_id = int(user_id)
- except ValueError:
- raise Http404
-
+ user = certificate.user if certificate else request.user
+ user_id = user.id
preview_mode = request.GET.get('preview', None)
platform_name = configuration_helpers.get_value("platform_name", settings.PLATFORM_NAME)
configuration = CertificateHtmlViewConfiguration.get_config()
@@ -521,16 +520,15 @@ def render_html_view(request, user_id, course_id):
# Load the course and user objects
try:
course_key = CourseKey.from_string(course_id)
- user = User.objects.get(id=user_id)
course = get_course_by_id(course_key)
# For any course or user exceptions, kick the user back to the "Invalid" screen
- except (InvalidKeyError, User.DoesNotExist, Http404) as exception:
+ except (InvalidKeyError, Http404) as exception:
error_str = (
- "Invalid cert: error finding course %s or user with id "
- "%d. Specific error: %s"
+ "Invalid cert: error finding course %s "
+ "Specific error: %s"
)
- log.info(error_str, course_id, user_id, str(exception))
+ log.info(error_str, course_id, str(exception))
return _render_invalid_certificate(course_id, platform_name, configuration)
# Kick the user back to the "Invalid" screen if the feature is disabled for the course
@@ -677,10 +675,11 @@ def _get_custom_template_and_language(course_id, course_mode, course_language):
return (None, None)
-def _render_invalid_certificate(course_id, platform_name, configuration):
+def _render_invalid_certificate(course_id, platform_name, configuration,
+ cert_path=INVALID_CERTIFICATE_TEMPLATE_PATH):
context = {}
_update_context_with_basic_info(context, course_id, platform_name, configuration)
- return render_to_response(INVALID_CERTIFICATE_TEMPLATE_PATH, context)
+ return render_to_response(cert_path, context)
def _render_valid_certificate(request, context, custom_template=None):
diff --git a/lms/templates/certificates/url_unsupported.html b/lms/templates/certificates/url_unsupported.html
new file mode 100644
index 000000000000..f4f50b2f9c57
--- /dev/null
+++ b/lms/templates/certificates/url_unsupported.html
@@ -0,0 +1,18 @@
+<%page expression_filter="h"/>
+<%inherit file="accomplishment-base.html" />
+<%! from django.utils.translation import gettext as _ %>
+
+
+
+
+
+
${_("URL Not Supported")}
+
+
${_("This link is no longer valid. But don’t worry—this Verified Certificate is still valid and available to share. If this is your certificate, please visit your dashboard to get a new shareable link. If you're viewing someone else's certificate, please contact them to get an updated link.")}