refactor: ran pyupgrade on lms/djangoapps/certificates
This commit is contained in:
@@ -42,7 +42,7 @@ class CertificateTemplateForm(forms.ModelForm):
|
||||
choices=lang_choices, required=False
|
||||
)
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = CertificateTemplate
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ certificates models or any other certificates modules.
|
||||
|
||||
import logging
|
||||
|
||||
import six
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.db.models import Q
|
||||
from eventtracking import tracker
|
||||
@@ -18,13 +17,16 @@ from opaque_keys.edx.django.models import CourseKeyField
|
||||
from organizations.api import get_course_organization_id
|
||||
|
||||
from lms.djangoapps.branding import api as branding_api
|
||||
from lms.djangoapps.certificates.generation_handler import (
|
||||
is_using_certificate_allowlist as _is_using_certificate_allowlist,
|
||||
is_using_certificate_allowlist_and_is_on_allowlist as _is_using_certificate_allowlist_and_is_on_allowlist,
|
||||
generate_allowlist_certificate_task as _generate_allowlist_certificate_task,
|
||||
generate_user_certificates as _generate_user_certificates,
|
||||
from lms.djangoapps.certificates.generation_handler import \
|
||||
generate_user_certificates as _generate_user_certificates
|
||||
from lms.djangoapps.certificates.generation_handler import \
|
||||
is_using_certificate_allowlist as _is_using_certificate_allowlist
|
||||
from lms.djangoapps.certificates.generation_handler import \
|
||||
is_using_certificate_allowlist_and_is_on_allowlist as _is_using_certificate_allowlist_and_is_on_allowlist
|
||||
from lms.djangoapps.certificates.generation_handler import \
|
||||
generate_allowlist_certificate_task as _generate_allowlist_certificate_task
|
||||
from lms.djangoapps.certificates.generation_handler import \
|
||||
regenerate_user_certificates as _regenerate_user_certificates
|
||||
)
|
||||
from lms.djangoapps.certificates.models import (
|
||||
CertificateGenerationConfiguration,
|
||||
CertificateGenerationCourseSetting,
|
||||
@@ -273,12 +275,12 @@ def set_cert_generation_enabled(course_key, is_enabled):
|
||||
cert_event_type = 'enabled' if is_enabled else 'disabled'
|
||||
event_name = '.'.join(['edx', 'certificate', 'generation', cert_event_type])
|
||||
tracker.emit(event_name, {
|
||||
'course_id': six.text_type(course_key),
|
||||
'course_id': str(course_key),
|
||||
})
|
||||
if is_enabled:
|
||||
log.info(u"Enabled self-generated certificates for course '%s'.", six.text_type(course_key))
|
||||
log.info("Enabled self-generated certificates for course '%s'.", str(course_key))
|
||||
else:
|
||||
log.info(u"Disabled self-generated certificates for course '%s'.", six.text_type(course_key))
|
||||
log.info("Disabled self-generated certificates for course '%s'.", str(course_key))
|
||||
|
||||
|
||||
def is_certificate_invalid(student, course_key):
|
||||
|
||||
@@ -3,17 +3,15 @@ Tests for the Certificate REST APIs.
|
||||
"""
|
||||
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
import ddt
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from freezegun import freeze_time
|
||||
from mock import patch
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
@@ -23,6 +21,8 @@ from lms.djangoapps.certificates.tests.factories import GeneratedCertificateFact
|
||||
from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
|
||||
from openedx.core.djangoapps.user_api.tests.factories import UserPreferenceFactory
|
||||
from openedx.core.djangoapps.user_authn.tests.utils import JWT_AUTH_TYPES, AuthAndScopesTestMixin, AuthType
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -35,7 +35,7 @@ class CertificatesDetailRestApiTest(AuthAndScopesTestMixin, SharedModuleStoreTes
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(CertificatesDetailRestApiTest, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.course = CourseFactory.create(
|
||||
org='edx',
|
||||
number='verified',
|
||||
@@ -86,7 +86,7 @@ class CertificatesDetailRestApiTest(AuthAndScopesTestMixin, SharedModuleStoreTes
|
||||
'grade': '0.88',
|
||||
'download_url': 'www.google.com',
|
||||
'certificate_type': CourseMode.VERIFIED,
|
||||
'course_id': six.text_type(self.course.id),
|
||||
'course_id': str(self.course.id),
|
||||
'created_date': self.now}
|
||||
|
||||
def test_no_certificate(self):
|
||||
@@ -127,7 +127,7 @@ class CertificatesListRestApiTest(AuthAndScopesTestMixin, SharedModuleStoreTestC
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(CertificatesListRestApiTest, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.course = CourseFactory.create(
|
||||
org='edx',
|
||||
number='verified',
|
||||
@@ -174,7 +174,7 @@ class CertificatesListRestApiTest(AuthAndScopesTestMixin, SharedModuleStoreTestC
|
||||
""" This method is required by AuthAndScopesTestMixin. """
|
||||
assert response.data ==\
|
||||
[{'username': self.student.username,
|
||||
'course_id': six.text_type(self.course.id),
|
||||
'course_id': str(self.course.id),
|
||||
'course_display_name': self.course.display_name,
|
||||
'course_organization': self.course.org,
|
||||
'certificate_type': CourseMode.VERIFIED,
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
import logging
|
||||
|
||||
import edx_api_doc_tools as apidocs
|
||||
import six
|
||||
from django.contrib.auth import get_user_model
|
||||
from edx_rest_framework_extensions import permissions
|
||||
from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication
|
||||
@@ -108,7 +107,7 @@ class CertificatesDetailView(APIView):
|
||||
try:
|
||||
course_key = CourseKey.from_string(course_id)
|
||||
except InvalidKeyError:
|
||||
log.warning(u'Course ID string "%s" is not valid', course_id)
|
||||
log.warning('Course ID string "%s" is not valid', course_id)
|
||||
return Response(
|
||||
status=404,
|
||||
data={'error_code': 'course_id_not_valid'}
|
||||
@@ -132,7 +131,7 @@ class CertificatesDetailView(APIView):
|
||||
return Response(
|
||||
{
|
||||
"username": user_cert.get('username'),
|
||||
"course_id": six.text_type(user_cert.get('course_key')),
|
||||
"course_id": str(user_cert.get('course_key')),
|
||||
"certificate_type": user_cert.get('type'),
|
||||
"created_date": user_cert.get('created'),
|
||||
"status": user_cert.get('status'),
|
||||
@@ -228,7 +227,7 @@ class CertificatesListView(APIView):
|
||||
for user_cert in self._get_certificates_for_user(username):
|
||||
user_certs.append({
|
||||
'username': user_cert.get('username'),
|
||||
'course_id': six.text_type(user_cert.get('course_key')),
|
||||
'course_id': str(user_cert.get('course_key')),
|
||||
'course_display_name': user_cert.get('course_display_name'),
|
||||
'course_organization': user_cert.get('course_organization'),
|
||||
'certificate_type': user_cert.get('type'),
|
||||
|
||||
@@ -14,7 +14,7 @@ class CertificatesConfig(AppConfig):
|
||||
"""
|
||||
Application Configuration for Certificates.
|
||||
"""
|
||||
name = u'lms.djangoapps.certificates'
|
||||
name = 'lms.djangoapps.certificates'
|
||||
|
||||
def ready(self):
|
||||
"""
|
||||
|
||||
@@ -14,15 +14,13 @@ import random
|
||||
from uuid import uuid4
|
||||
|
||||
from capa.xqueue_interface import make_hashkey
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
from common.djangoapps.student.models import CourseEnrollment, UserProfile
|
||||
from lms.djangoapps.certificates.models import CertificateStatuses, GeneratedCertificate
|
||||
from lms.djangoapps.certificates.queue import XQueueCertInterface
|
||||
from lms.djangoapps.certificates.utils import emit_certificate_event
|
||||
from lms.djangoapps.certificates.utils import has_html_certificates_enabled
|
||||
from lms.djangoapps.certificates.utils import emit_certificate_event, has_html_certificates_enabled
|
||||
from lms.djangoapps.grades.api import CourseGradeFactory
|
||||
from lms.djangoapps.instructor.access import list_with_level
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -9,12 +9,11 @@ cannot be generated, a message is logged and no further action is taken.
|
||||
import logging
|
||||
|
||||
from edx_toggles.toggles import LegacyWaffleFlagNamespace
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
from common.djangoapps.student.models import CourseEnrollment
|
||||
from lms.djangoapps.certificates.models import (
|
||||
CertificateStatuses,
|
||||
CertificateInvalidation,
|
||||
CertificateStatuses,
|
||||
CertificateWhitelist,
|
||||
GeneratedCertificate
|
||||
)
|
||||
@@ -25,6 +24,7 @@ from lms.djangoapps.instructor.access import list_with_level
|
||||
from lms.djangoapps.verify_student.services import IDVerificationService
|
||||
from openedx.core.djangoapps.certificates.api import auto_certificate_generation_enabled
|
||||
from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -52,11 +52,11 @@ def generate_allowlist_certificate_task(user, course_key):
|
||||
"""
|
||||
if not can_generate_allowlist_certificate(user, course_key):
|
||||
log.info(
|
||||
'Cannot generate an allowlist certificate for {user} : {course}'.format(user=user.id, course=course_key))
|
||||
f'Cannot generate an allowlist certificate for {user.id} : {course_key}')
|
||||
return False
|
||||
|
||||
log.info(
|
||||
'About to create an allowlist certificate task for {user} : {course}'.format(user=user.id, course=course_key))
|
||||
f'About to create an allowlist certificate task for {user.id} : {course_key}')
|
||||
|
||||
kwargs = {
|
||||
'student': str(user.id),
|
||||
|
||||
@@ -108,7 +108,7 @@ class Command(BaseCommand):
|
||||
|
||||
whitelist = CertificateWhitelist.objects.filter(course_id=course)
|
||||
wl_users = '\n'.join(
|
||||
u"{u.user.username} {u.user.email} {u.whitelist}".format(u=u)
|
||||
"{u.user.username} {u.user.email} {u.whitelist}".format(u=u)
|
||||
for u in whitelist
|
||||
)
|
||||
print(u"User whitelist for course {0}:\n{1}".format(course_id, wl_users))
|
||||
print(f"User whitelist for course {course_id}:\n{wl_users}")
|
||||
|
||||
@@ -17,7 +17,6 @@ from textwrap import dedent
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.management.base import BaseCommand
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from six import text_type
|
||||
|
||||
from lms.djangoapps.certificates.models import CertificateStatuses, GeneratedCertificate
|
||||
|
||||
@@ -104,18 +103,18 @@ class Command(BaseCommand):
|
||||
|
||||
if created:
|
||||
LOGGER.info(
|
||||
u"Created certificate for user %s in course %s "
|
||||
u"with mode %s, status %s, "
|
||||
u"and grade %s",
|
||||
user.id, text_type(course_key),
|
||||
"Created certificate for user %s in course %s "
|
||||
"with mode %s, status %s, "
|
||||
"and grade %s",
|
||||
user.id, str(course_key),
|
||||
cert_mode, status, grade
|
||||
)
|
||||
|
||||
else:
|
||||
LOGGER.info(
|
||||
u"Updated certificate for user %s in course %s "
|
||||
u"with mode %s, status %s, "
|
||||
u"and grade %s",
|
||||
user.id, text_type(course_key),
|
||||
"Updated certificate for user %s in course %s "
|
||||
"with mode %s, status %s, "
|
||||
"and grade %s",
|
||||
user.id, str(course_key),
|
||||
cert_mode, status, grade
|
||||
)
|
||||
|
||||
@@ -44,7 +44,7 @@ class Command(BaseCommand):
|
||||
|
||||
def handle(self, *args, **options):
|
||||
course_id = options['course']
|
||||
log.info(u'Fetching ungraded students for %s.', course_id)
|
||||
log.info('Fetching ungraded students for %s.', course_id)
|
||||
ungraded = GeneratedCertificate.objects.filter(
|
||||
course_id__exact=course_id
|
||||
).filter(grade__exact='')
|
||||
@@ -52,7 +52,7 @@ class Command(BaseCommand):
|
||||
for cert in ungraded:
|
||||
# grade the student
|
||||
grade = CourseGradeFactory().read(cert.user, course)
|
||||
log.info(u'grading %s - %s', cert.user, grade.percent)
|
||||
log.info('grading %s - %s', cert.user, grade.percent)
|
||||
cert.grade = grade.percent
|
||||
if not options['noop']:
|
||||
cert.save()
|
||||
|
||||
@@ -7,7 +7,6 @@ from django.contrib.auth import get_user_model
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.db.models import Count
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from six import text_type
|
||||
|
||||
from lms.djangoapps.certificates.models import GeneratedCertificate
|
||||
|
||||
@@ -59,7 +58,7 @@ class Command(BaseCommand):
|
||||
|
||||
# find students who are active
|
||||
# number of enrolled students = downloadable + notpassing
|
||||
print(u"Looking up certificate states for {0}".format(options['course']))
|
||||
print("Looking up certificate states for {}".format(options['course']))
|
||||
enrolled_current = User.objects.filter(
|
||||
courseenrollment__course_id=course_id,
|
||||
courseenrollment__is_active=True
|
||||
@@ -112,15 +111,15 @@ class Command(BaseCommand):
|
||||
|
||||
# all states we have seen far all courses
|
||||
status_headings = sorted(
|
||||
set([status for course in cert_data for status in cert_data[course]]) # pylint: disable=consider-using-set-comprehension
|
||||
{status for course in cert_data for status in cert_data[course]} # pylint: disable=consider-using-set-comprehension
|
||||
)
|
||||
|
||||
# print the heading for the report
|
||||
print("{:>26}".format("course ID"), end=' ')
|
||||
print(' '.join(["{:>16}".format(heading) for heading in status_headings]))
|
||||
print(' '.join([f"{heading:>16}" for heading in status_headings]))
|
||||
|
||||
# print the report
|
||||
print("{0:>26}".format(text_type(course_id)), end=' ')
|
||||
print("{:>26}".format(str(course_id)), end=' ')
|
||||
for heading in status_headings:
|
||||
if heading in cert_data[course_id]:
|
||||
print("{:>16}".format(cert_data[course_id][heading]), end=' ')
|
||||
|
||||
@@ -7,12 +7,11 @@ import logging
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.management.base import BaseCommand
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from six import text_type
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
from lms.djangoapps.badges.events.course_complete import get_completion_badge
|
||||
from lms.djangoapps.badges.utils import badges_enabled
|
||||
from lms.djangoapps.certificates.api import regenerate_user_certificates
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
User = get_user_model()
|
||||
@@ -65,11 +64,11 @@ class Command(BaseCommand):
|
||||
cleaned_options['username'] = '<USERNAME>'
|
||||
LOGGER.info(
|
||||
(
|
||||
u"Starting to create tasks to regenerate certificates "
|
||||
u"with arguments %s and options %s"
|
||||
"Starting to create tasks to regenerate certificates "
|
||||
"with arguments %s and options %s"
|
||||
),
|
||||
text_type(args),
|
||||
text_type(cleaned_options)
|
||||
str(args),
|
||||
str(cleaned_options)
|
||||
)
|
||||
|
||||
# try to parse out the course from the serialized form
|
||||
@@ -86,8 +85,8 @@ class Command(BaseCommand):
|
||||
if not options['noop']:
|
||||
LOGGER.info(
|
||||
(
|
||||
u"Adding task to the XQueue to generate a certificate "
|
||||
u"for student %s in course '%s'."
|
||||
"Adding task to the XQueue to generate a certificate "
|
||||
"for student %s in course '%s'."
|
||||
),
|
||||
student.id,
|
||||
course_id
|
||||
@@ -99,7 +98,7 @@ class Command(BaseCommand):
|
||||
|
||||
if badge:
|
||||
badge.delete()
|
||||
LOGGER.info(u"Cleared badge for student %s.", student.id)
|
||||
LOGGER.info("Cleared badge for student %s.", student.id)
|
||||
|
||||
# Add the certificate request to the queue
|
||||
regenerate_user_certificates(
|
||||
@@ -111,29 +110,29 @@ class Command(BaseCommand):
|
||||
|
||||
LOGGER.info(
|
||||
(
|
||||
u"Added a certificate regeneration task to the XQueue "
|
||||
u"for student %s in course '%s'."
|
||||
"Added a certificate regeneration task to the XQueue "
|
||||
"for student %s in course '%s'."
|
||||
),
|
||||
student.id,
|
||||
text_type(course_id)
|
||||
str(course_id)
|
||||
)
|
||||
|
||||
else:
|
||||
LOGGER.info(
|
||||
(
|
||||
u"Skipping certificate generation for "
|
||||
u"student %s in course '%s' "
|
||||
u"because the noop flag is set."
|
||||
"Skipping certificate generation for "
|
||||
"student %s in course '%s' "
|
||||
"because the noop flag is set."
|
||||
),
|
||||
student.id,
|
||||
text_type(course_id)
|
||||
str(course_id)
|
||||
)
|
||||
|
||||
LOGGER.info(
|
||||
(
|
||||
u"Finished regenerating certificates command for "
|
||||
u"user %s and course '%s'."
|
||||
"Finished regenerating certificates command for "
|
||||
"user %s and course '%s'."
|
||||
),
|
||||
student.id,
|
||||
text_type(course_id)
|
||||
str(course_id)
|
||||
)
|
||||
|
||||
@@ -24,11 +24,10 @@ from textwrap import dedent
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from opaque_keys import InvalidKeyError
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from six import text_type
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
from lms.djangoapps.certificates.api import generate_user_certificates
|
||||
from lms.djangoapps.certificates.models import CertificateStatuses, GeneratedCertificate
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -66,7 +65,7 @@ class Command(BaseCommand):
|
||||
only_course_keys.append(CourseKey.from_string(course_key_str))
|
||||
except InvalidKeyError as e:
|
||||
raise CommandError(
|
||||
u'"{course_key_str}" is not a valid course key.'.format(
|
||||
'"{course_key_str}" is not a valid course key.'.format(
|
||||
course_key_str=course_key_str
|
||||
)
|
||||
) from e
|
||||
@@ -74,12 +73,12 @@ class Command(BaseCommand):
|
||||
if only_course_keys:
|
||||
LOGGER.info(
|
||||
(
|
||||
u'Starting to re-submit certificates with status "error" '
|
||||
u'in these courses: %s'
|
||||
), ", ".join([text_type(key) for key in only_course_keys])
|
||||
'Starting to re-submit certificates with status "error" '
|
||||
'in these courses: %s'
|
||||
), ", ".join([str(key) for key in only_course_keys])
|
||||
)
|
||||
else:
|
||||
LOGGER.info(u'Starting to re-submit certificates with status "error".')
|
||||
LOGGER.info('Starting to re-submit certificates with status "error".')
|
||||
|
||||
# Retrieve the IDs of generated certificates with
|
||||
# error status in the set of courses we're considering.
|
||||
@@ -100,19 +99,19 @@ class Command(BaseCommand):
|
||||
resubmit_count += 1
|
||||
LOGGER.info(
|
||||
(
|
||||
u"Re-submitted certificate for user %s "
|
||||
u"in course '%s'"
|
||||
"Re-submitted certificate for user %s "
|
||||
"in course '%s'"
|
||||
), user.id, course_key
|
||||
)
|
||||
else:
|
||||
LOGGER.error(
|
||||
(
|
||||
u"Could not find course for course key '%s'. "
|
||||
u"Certificate for user %s will not be resubmitted."
|
||||
"Could not find course for course key '%s'. "
|
||||
"Certificate for user %s will not be resubmitted."
|
||||
), course_key, user.id
|
||||
)
|
||||
|
||||
LOGGER.info(u"Finished resubmitting %s certificate tasks", resubmit_count)
|
||||
LOGGER.info("Finished resubmitting %s certificate tasks", resubmit_count)
|
||||
|
||||
def _load_course_with_cache(self, course_key, course_cache):
|
||||
"""Retrieve the course, then cache it to avoid Mongo queries. """
|
||||
|
||||
@@ -11,11 +11,10 @@ from django.contrib.auth import get_user_model
|
||||
from django.core.management.base import BaseCommand
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from pytz import UTC
|
||||
from six import text_type
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
from lms.djangoapps.certificates.api import generate_user_certificates
|
||||
from lms.djangoapps.certificates.models import CertificateStatuses, certificate_status_for_student
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
User = get_user_model()
|
||||
@@ -69,11 +68,11 @@ class Command(BaseCommand):
|
||||
def handle(self, *args, **options):
|
||||
LOGGER.info(
|
||||
(
|
||||
u"Starting to create tasks for ungenerated certificates "
|
||||
u"with arguments %s and options %s"
|
||||
"Starting to create tasks for ungenerated certificates "
|
||||
"with arguments %s and options %s"
|
||||
),
|
||||
text_type(args),
|
||||
text_type(options)
|
||||
str(args),
|
||||
str(options)
|
||||
)
|
||||
|
||||
# Will only generate a certificate if the current
|
||||
@@ -113,18 +112,18 @@ class Command(BaseCommand):
|
||||
timeleft = diff * (total - count) / status_interval
|
||||
hours, remainder = divmod(timeleft.seconds, 3600)
|
||||
minutes, _seconds = divmod(remainder, 60)
|
||||
print(u"{0}/{1} completed ~{2:02}:{3:02}m remaining".format(count, total, hours, minutes))
|
||||
print(f"{count}/{total} completed ~{hours:02}:{minutes:02}m remaining")
|
||||
start = datetime.datetime.now(UTC)
|
||||
|
||||
cert_status = certificate_status_for_student(student, course_key)['status']
|
||||
LOGGER.info(
|
||||
(
|
||||
u"Student %s has certificate status '%s' "
|
||||
u"in course '%s'"
|
||||
"Student %s has certificate status '%s' "
|
||||
"in course '%s'"
|
||||
),
|
||||
student.id,
|
||||
cert_status,
|
||||
text_type(course_key)
|
||||
str(course_key)
|
||||
)
|
||||
|
||||
if cert_status in valid_statuses:
|
||||
@@ -144,29 +143,29 @@ class Command(BaseCommand):
|
||||
else:
|
||||
LOGGER.info(
|
||||
(
|
||||
u"Skipping certificate generation for "
|
||||
u"student %s in course '%s' "
|
||||
u"because the noop flag is set."
|
||||
"Skipping certificate generation for "
|
||||
"student %s in course '%s' "
|
||||
"because the noop flag is set."
|
||||
),
|
||||
student.id,
|
||||
text_type(course_key)
|
||||
str(course_key)
|
||||
)
|
||||
|
||||
else:
|
||||
LOGGER.info(
|
||||
(
|
||||
u"Skipped student %s because "
|
||||
u"certificate status '%s' is not in %s"
|
||||
"Skipped student %s because "
|
||||
"certificate status '%s' is not in %s"
|
||||
),
|
||||
student.id,
|
||||
cert_status,
|
||||
text_type(valid_statuses)
|
||||
str(valid_statuses)
|
||||
)
|
||||
|
||||
LOGGER.info(
|
||||
(
|
||||
u"Completed ungenerated certificates command "
|
||||
u"for course '%s'"
|
||||
"Completed ungenerated certificates command "
|
||||
"for course '%s'"
|
||||
),
|
||||
text_type(course_key)
|
||||
str(course_key)
|
||||
)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Certificates are created for a student and an offering of a course.
|
||||
|
||||
@@ -52,7 +51,6 @@ import logging
|
||||
import os
|
||||
import uuid
|
||||
|
||||
import six
|
||||
from config_models.models import ConfigurationModel
|
||||
from django.apps import apps
|
||||
from django.conf import settings
|
||||
@@ -82,7 +80,7 @@ log = logging.getLogger(__name__)
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class CertificateStatuses(object):
|
||||
class CertificateStatuses:
|
||||
"""
|
||||
Enum for certificate statuses
|
||||
"""
|
||||
@@ -121,7 +119,7 @@ class CertificateStatuses(object):
|
||||
return status in cls.PASSED_STATUSES
|
||||
|
||||
|
||||
class CertificateSocialNetworks(object):
|
||||
class CertificateSocialNetworks:
|
||||
"""
|
||||
Enum for certificate social networks
|
||||
"""
|
||||
@@ -140,7 +138,7 @@ class CertificateWhitelist(models.Model):
|
||||
|
||||
.. no_pii:
|
||||
"""
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
app_label = "certificates"
|
||||
|
||||
objects = NoneToEmptyManager()
|
||||
@@ -187,12 +185,12 @@ class CertificateWhitelist(models.Model):
|
||||
result.append({
|
||||
'id': item.id,
|
||||
'user_id': item.user.id,
|
||||
'user_name': six.text_type(item.user.username),
|
||||
'user_email': six.text_type(item.user.email),
|
||||
'course_id': six.text_type(item.course_id),
|
||||
'created': item.created.strftime(u"%B %d, %Y"),
|
||||
'certificate_generated': certificate_generated and certificate_generated.strftime(u"%B %d, %Y"),
|
||||
'notes': six.text_type(item.notes or ''),
|
||||
'user_name': str(item.user.username),
|
||||
'user_email': str(item.user.email),
|
||||
'course_id': str(item.course_id),
|
||||
'created': item.created.strftime("%B %d, %Y"),
|
||||
'certificate_generated': certificate_generated and certificate_generated.strftime("%B %d, %Y"),
|
||||
'notes': str(item.notes or ''),
|
||||
})
|
||||
return result
|
||||
|
||||
@@ -284,7 +282,7 @@ class GeneratedCertificate(models.Model):
|
||||
grade = models.CharField(max_length=5, blank=True, default='')
|
||||
key = models.CharField(max_length=32, blank=True, default='')
|
||||
distinction = models.BooleanField(default=False)
|
||||
status = models.CharField(max_length=32, default=u'unavailable')
|
||||
status = models.CharField(max_length=32, default='unavailable')
|
||||
mode = models.CharField(max_length=32, choices=MODES, default=MODES.honor)
|
||||
name = models.CharField(blank=True, max_length=255)
|
||||
created_date = models.DateTimeField(auto_now_add=True)
|
||||
@@ -297,7 +295,7 @@ class GeneratedCertificate(models.Model):
|
||||
if 'certificates' in apps.app_configs:
|
||||
history = HistoricalRecords()
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
unique_together = (('user', 'course_id'),)
|
||||
app_label = "certificates"
|
||||
|
||||
@@ -495,11 +493,11 @@ class CertificateGenerationHistory(TimeStampedModel):
|
||||
else:
|
||||
return _("All learners")
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
app_label = "certificates"
|
||||
|
||||
def __str__(self):
|
||||
return u"certificates %s by %s on %s for %s" % \
|
||||
return "certificates %s by %s on %s for %s" % \
|
||||
("regenerated" if self.is_regeneration else "generated", self.generated_by, self.created, self.course_id)
|
||||
|
||||
|
||||
@@ -522,11 +520,11 @@ class CertificateInvalidation(TimeStampedModel):
|
||||
if 'certificates' in apps.app_configs:
|
||||
history = HistoricalRecords()
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
app_label = "certificates"
|
||||
|
||||
def __str__(self):
|
||||
return u"Certificate %s, invalidated by %s on %s." % \
|
||||
return "Certificate %s, invalidated by %s on %s." % \
|
||||
(self.generated_certificate, self.invalidated_by, self.created)
|
||||
|
||||
def deactivate(self):
|
||||
@@ -560,7 +558,7 @@ class CertificateInvalidation(TimeStampedModel):
|
||||
'id': certificate_invalidation.id,
|
||||
'user': certificate_invalidation.generated_certificate.user.username,
|
||||
'invalidated_by': certificate_invalidation.invalidated_by.username,
|
||||
u'created': certificate_invalidation.created.strftime(u"%B %d, %Y"),
|
||||
'created': certificate_invalidation.created.strftime("%B %d, %Y"),
|
||||
'notes': certificate_invalidation.notes,
|
||||
})
|
||||
return data
|
||||
@@ -704,7 +702,7 @@ class ExampleCertificateSet(TimeStampedModel):
|
||||
"""
|
||||
course_key = CourseKeyField(max_length=255, db_index=True)
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
get_latest_by = 'created'
|
||||
app_label = "certificates"
|
||||
|
||||
@@ -764,16 +762,15 @@ class ExampleCertificateSet(TimeStampedModel):
|
||||
|
||||
"""
|
||||
queryset = (ExampleCertificate.objects).select_related('example_cert_set').filter(example_cert_set=self)
|
||||
for cert in queryset:
|
||||
yield cert
|
||||
yield from queryset
|
||||
|
||||
@staticmethod
|
||||
def _template_for_mode(mode_slug, course_key):
|
||||
"""Calculate the template PDF based on the course mode. """
|
||||
return (
|
||||
u"certificate-template-{key.org}-{key.course}-verified.pdf".format(key=course_key)
|
||||
"certificate-template-{key.org}-{key.course}-verified.pdf".format(key=course_key)
|
||||
if mode_slug == 'verified'
|
||||
else u"certificate-template-{key.org}-{key.course}.pdf".format(key=course_key)
|
||||
else "certificate-template-{key.org}-{key.course}.pdf".format(key=course_key)
|
||||
)
|
||||
|
||||
|
||||
@@ -802,25 +799,25 @@ class ExampleCertificate(TimeStampedModel):
|
||||
|
||||
.. no_pii:
|
||||
"""
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
app_label = "certificates"
|
||||
|
||||
# Statuses
|
||||
STATUS_STARTED = u'started'
|
||||
STATUS_SUCCESS = u'success'
|
||||
STATUS_ERROR = u'error'
|
||||
STATUS_STARTED = 'started'
|
||||
STATUS_SUCCESS = 'success'
|
||||
STATUS_ERROR = 'error'
|
||||
|
||||
# Dummy full name for the generated certificate
|
||||
EXAMPLE_FULL_NAME = u'John Doë'
|
||||
EXAMPLE_FULL_NAME = 'John Doë'
|
||||
|
||||
example_cert_set = models.ForeignKey(ExampleCertificateSet, on_delete=models.CASCADE)
|
||||
|
||||
description = models.CharField(
|
||||
max_length=255,
|
||||
help_text=_(
|
||||
u"A human-readable description of the example certificate. "
|
||||
u"For example, 'verified' or 'honor' to differentiate between "
|
||||
u"two types of certificates."
|
||||
"A human-readable description of the example certificate. "
|
||||
"For example, 'verified' or 'honor' to differentiate between "
|
||||
"two types of certificates."
|
||||
)
|
||||
)
|
||||
|
||||
@@ -833,9 +830,9 @@ class ExampleCertificate(TimeStampedModel):
|
||||
db_index=True,
|
||||
unique=True,
|
||||
help_text=_(
|
||||
u"A unique identifier for the example certificate. "
|
||||
u"This is used when we receive a response from the queue "
|
||||
u"to determine which example certificate was processed."
|
||||
"A unique identifier for the example certificate. "
|
||||
"This is used when we receive a response from the queue "
|
||||
"to determine which example certificate was processed."
|
||||
)
|
||||
)
|
||||
|
||||
@@ -844,22 +841,22 @@ class ExampleCertificate(TimeStampedModel):
|
||||
default=_make_uuid,
|
||||
db_index=True,
|
||||
help_text=_(
|
||||
u"An access key for the example certificate. "
|
||||
u"This is used when we receive a response from the queue "
|
||||
u"to validate that the sender is the same entity we asked "
|
||||
u"to generate the certificate."
|
||||
"An access key for the example certificate. "
|
||||
"This is used when we receive a response from the queue "
|
||||
"to validate that the sender is the same entity we asked "
|
||||
"to generate the certificate."
|
||||
)
|
||||
)
|
||||
|
||||
full_name = models.CharField(
|
||||
max_length=255,
|
||||
default=EXAMPLE_FULL_NAME,
|
||||
help_text=_(u"The full name that will appear on the certificate.")
|
||||
help_text=_("The full name that will appear on the certificate.")
|
||||
)
|
||||
|
||||
template = models.CharField(
|
||||
max_length=255,
|
||||
help_text=_(u"The template file to use when generating the certificate.")
|
||||
help_text=_("The template file to use when generating the certificate.")
|
||||
)
|
||||
|
||||
# Outputs from certificate generation
|
||||
@@ -867,24 +864,24 @@ class ExampleCertificate(TimeStampedModel):
|
||||
max_length=255,
|
||||
default=STATUS_STARTED,
|
||||
choices=(
|
||||
(STATUS_STARTED, u'Started'),
|
||||
(STATUS_SUCCESS, u'Success'),
|
||||
(STATUS_ERROR, u'Error')
|
||||
(STATUS_STARTED, 'Started'),
|
||||
(STATUS_SUCCESS, 'Success'),
|
||||
(STATUS_ERROR, 'Error')
|
||||
),
|
||||
help_text=_(u"The status of the example certificate.")
|
||||
help_text=_("The status of the example certificate.")
|
||||
)
|
||||
|
||||
error_reason = models.TextField(
|
||||
null=True,
|
||||
default=None,
|
||||
help_text=_(u"The reason an error occurred during certificate generation.")
|
||||
help_text=_("The reason an error occurred during certificate generation.")
|
||||
)
|
||||
|
||||
download_url = models.CharField(
|
||||
max_length=255,
|
||||
null=True,
|
||||
default=None,
|
||||
help_text=_(u"The download URL for the generated certificate.")
|
||||
help_text=_("The download URL for the generated certificate.")
|
||||
)
|
||||
|
||||
def update_status(self, status, error_reason=None, download_url=None):
|
||||
@@ -910,7 +907,7 @@ class ExampleCertificate(TimeStampedModel):
|
||||
|
||||
"""
|
||||
if status not in [self.STATUS_SUCCESS, self.STATUS_ERROR]:
|
||||
msg = u"Invalid status: must be either '{success}' or '{error}'.".format(
|
||||
msg = "Invalid status: must be either '{success}' or '{error}'.".format(
|
||||
success=self.STATUS_SUCCESS,
|
||||
error=self.STATUS_ERROR
|
||||
)
|
||||
@@ -969,30 +966,30 @@ class CertificateGenerationCourseSetting(TimeStampedModel):
|
||||
self_generation_enabled = models.BooleanField(
|
||||
default=False,
|
||||
help_text=(
|
||||
u"Allow students to generate their own certificates for the course. "
|
||||
u"Enabling this does NOT affect usage of the management command used "
|
||||
u"for batch certificate generation."
|
||||
"Allow students to generate their own certificates for the course. "
|
||||
"Enabling this does NOT affect usage of the management command used "
|
||||
"for batch certificate generation."
|
||||
)
|
||||
)
|
||||
language_specific_templates_enabled = models.BooleanField(
|
||||
default=False,
|
||||
help_text=(
|
||||
u"Render translated certificates rather than using the platform's "
|
||||
u"default language. Available translations are controlled by the "
|
||||
u"certificate template."
|
||||
"Render translated certificates rather than using the platform's "
|
||||
"default language. Available translations are controlled by the "
|
||||
"certificate template."
|
||||
)
|
||||
)
|
||||
include_hours_of_effort = models.NullBooleanField(
|
||||
default=None,
|
||||
help_text=(
|
||||
u"Display estimated time to complete the course, which is equal to the maximum hours of effort per week "
|
||||
u"times the length of the course in weeks. This attribute will only be displayed in a certificate when the "
|
||||
u"attributes 'Weeks to complete' and 'Max effort' have been provided for the course run and its "
|
||||
u"certificate template includes Hours of Effort."
|
||||
"Display estimated time to complete the course, which is equal to the maximum hours of effort per week "
|
||||
"times the length of the course in weeks. This attribute will only be displayed in a certificate when the "
|
||||
"attributes 'Weeks to complete' and 'Max effort' have been provided for the course run and its "
|
||||
"certificate template includes Hours of Effort."
|
||||
)
|
||||
)
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
get_latest_by = 'created'
|
||||
app_label = "certificates"
|
||||
|
||||
@@ -1088,7 +1085,7 @@ class CertificateHtmlViewConfiguration(ConfigurationModel):
|
||||
app_label = "certificates"
|
||||
|
||||
configuration = models.TextField(
|
||||
help_text=u"Certificate HTML View Parameters (JSON)"
|
||||
help_text="Certificate HTML View Parameters (JSON)"
|
||||
)
|
||||
|
||||
def clean(self):
|
||||
@@ -1124,22 +1121,22 @@ class CertificateTemplate(TimeStampedModel):
|
||||
"""
|
||||
name = models.CharField(
|
||||
max_length=255,
|
||||
help_text=_(u'Name of template.'),
|
||||
help_text=_('Name of template.'),
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=255,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text=_(u'Description and/or admin notes.'),
|
||||
help_text=_('Description and/or admin notes.'),
|
||||
)
|
||||
template = models.TextField(
|
||||
help_text=_(u'Django template HTML.'),
|
||||
help_text=_('Django template HTML.'),
|
||||
)
|
||||
organization_id = models.IntegerField(
|
||||
null=True,
|
||||
blank=True,
|
||||
db_index=True,
|
||||
help_text=_(u'Organization of template.'),
|
||||
help_text=_('Organization of template.'),
|
||||
)
|
||||
course_key = CourseKeyField(
|
||||
max_length=255,
|
||||
@@ -1153,24 +1150,24 @@ class CertificateTemplate(TimeStampedModel):
|
||||
default=GeneratedCertificate.MODES.honor,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text=_(u'The course mode for this template.'),
|
||||
help_text=_('The course mode for this template.'),
|
||||
)
|
||||
is_active = models.BooleanField(
|
||||
help_text=_(u'On/Off switch.'),
|
||||
help_text=_('On/Off switch.'),
|
||||
default=False,
|
||||
)
|
||||
language = models.CharField(
|
||||
max_length=2,
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text=u'Only certificates for courses in the selected language will be rendered using this template. '
|
||||
u'Course language is determined by the first two letters of the language code.'
|
||||
help_text='Only certificates for courses in the selected language will be rendered using this template. '
|
||||
'Course language is determined by the first two letters of the language code.'
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return u'%s' % (self.name, )
|
||||
return f'{self.name}'
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
get_latest_by = 'created'
|
||||
unique_together = (('organization_id', 'course_key', 'mode', 'language'),)
|
||||
app_label = "certificates"
|
||||
@@ -1204,18 +1201,18 @@ class CertificateTemplateAsset(TimeStampedModel):
|
||||
max_length=255,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text=_(u'Description of the asset.'),
|
||||
help_text=_('Description of the asset.'),
|
||||
)
|
||||
asset = models.FileField(
|
||||
max_length=255,
|
||||
upload_to=template_assets_path,
|
||||
help_text=_(u'Asset file. It could be an image or css file.'),
|
||||
help_text=_('Asset file. It could be an image or css file.'),
|
||||
)
|
||||
asset_slug = models.SlugField(
|
||||
max_length=255,
|
||||
unique=True,
|
||||
null=True,
|
||||
help_text=_(u'Asset\'s unique slug. We can reference the asset in templates using this value.'),
|
||||
help_text=_('Asset\'s unique slug. We can reference the asset in templates using this value.'),
|
||||
)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
@@ -1229,9 +1226,9 @@ class CertificateTemplateAsset(TimeStampedModel):
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
def __str__(self):
|
||||
return u'%s' % (self.asset.url, )
|
||||
return f'{self.asset.url}'
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
get_latest_by = 'created'
|
||||
app_label = "certificates"
|
||||
|
||||
|
||||
@@ -7,16 +7,14 @@ import random
|
||||
from uuid import uuid4
|
||||
|
||||
import lxml.html
|
||||
import six
|
||||
from capa.xqueue_interface import XQueueInterface, make_hashkey, make_xheader
|
||||
from django.conf import settings
|
||||
from django.test.client import RequestFactory
|
||||
from django.urls import reverse
|
||||
from django.utils.encoding import python_2_unicode_compatible
|
||||
from lxml.etree import ParserError, XMLSyntaxError
|
||||
from requests.auth import HTTPBasicAuth
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
from capa.xqueue_interface import XQueueInterface, make_hashkey, make_xheader
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
from common.djangoapps.student.models import CourseEnrollment, UserProfile
|
||||
from lms.djangoapps.certificates.models import CertificateStatuses as status
|
||||
@@ -28,6 +26,7 @@ from lms.djangoapps.certificates.models import (
|
||||
)
|
||||
from lms.djangoapps.grades.api import CourseGradeFactory
|
||||
from lms.djangoapps.verify_student.services import IDVerificationService
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -39,19 +38,19 @@ class XQueueAddToQueueError(Exception):
|
||||
def __init__(self, error_code, error_msg):
|
||||
self.error_code = error_code
|
||||
self.error_msg = error_msg
|
||||
super().__init__(six.text_type(self))
|
||||
super().__init__(str(self))
|
||||
|
||||
def __str__(self):
|
||||
return (
|
||||
u"Could not add certificate to the XQueue. "
|
||||
u"The error code was '{code}' and the message was '{msg}'."
|
||||
"Could not add certificate to the XQueue. "
|
||||
"The error code was '{code}' and the message was '{msg}'."
|
||||
).format(
|
||||
code=self.error_code,
|
||||
msg=self.error_msg
|
||||
)
|
||||
|
||||
|
||||
class XQueueCertInterface(object):
|
||||
class XQueueCertInterface:
|
||||
"""
|
||||
XQueueCertificateInterface provides an
|
||||
interface to the xqueue server for
|
||||
@@ -133,12 +132,12 @@ class XQueueCertInterface(object):
|
||||
|
||||
LOGGER.info(
|
||||
(
|
||||
u"Found an existing certificate entry for student %s "
|
||||
u"in course '%s' "
|
||||
u"with status '%s' while regenerating certificates. "
|
||||
"Found an existing certificate entry for student %s "
|
||||
"in course '%s' "
|
||||
"with status '%s' while regenerating certificates. "
|
||||
),
|
||||
student.id,
|
||||
six.text_type(course_id),
|
||||
str(course_id),
|
||||
certificate.status
|
||||
)
|
||||
|
||||
@@ -153,11 +152,11 @@ class XQueueCertInterface(object):
|
||||
|
||||
LOGGER.info(
|
||||
(
|
||||
u"The certificate status for student %s "
|
||||
u"in course '%s' has been changed to '%s'."
|
||||
"The certificate status for student %s "
|
||||
"in course '%s' has been changed to '%s'."
|
||||
),
|
||||
student.id,
|
||||
six.text_type(course_id),
|
||||
str(course_id),
|
||||
certificate.status
|
||||
)
|
||||
|
||||
@@ -225,12 +224,12 @@ class XQueueCertInterface(object):
|
||||
if hasattr(course_id, 'ccx'):
|
||||
LOGGER.warning(
|
||||
(
|
||||
u"Cannot create certificate generation task for user %s "
|
||||
u"in the course '%s'; "
|
||||
u"certificates are not allowed for CCX courses."
|
||||
"Cannot create certificate generation task for user %s "
|
||||
"in the course '%s'; "
|
||||
"certificates are not allowed for CCX courses."
|
||||
),
|
||||
student.id,
|
||||
six.text_type(course_id)
|
||||
str(course_id)
|
||||
)
|
||||
return None
|
||||
|
||||
@@ -260,14 +259,14 @@ class XQueueCertInterface(object):
|
||||
if cert_status not in valid_statuses:
|
||||
LOGGER.warning(
|
||||
(
|
||||
u"Cannot create certificate generation task for user %s "
|
||||
u"in the course '%s'; "
|
||||
u"the certificate status '%s' is not one of %s."
|
||||
"Cannot create certificate generation task for user %s "
|
||||
"in the course '%s'; "
|
||||
"the certificate status '%s' is not one of %s."
|
||||
),
|
||||
student.id,
|
||||
six.text_type(course_id),
|
||||
str(course_id),
|
||||
cert_status,
|
||||
six.text_type(valid_statuses)
|
||||
str(valid_statuses)
|
||||
)
|
||||
return None
|
||||
|
||||
@@ -318,14 +317,14 @@ class XQueueCertInterface(object):
|
||||
|
||||
LOGGER.info(
|
||||
(
|
||||
u"Certificate generated for student %s in the course: %s with template: %s. "
|
||||
u"given template: %s, "
|
||||
u"user is verified: %s, "
|
||||
u"mode is verified: %s,"
|
||||
u"generate_pdf is: %s"
|
||||
"Certificate generated for student %s in the course: %s with template: %s. "
|
||||
"given template: %s, "
|
||||
"user is verified: %s, "
|
||||
"mode is verified: %s,"
|
||||
"generate_pdf is: %s"
|
||||
),
|
||||
student.username,
|
||||
six.text_type(course_id),
|
||||
str(course_id),
|
||||
template_pdf,
|
||||
template_file,
|
||||
user_is_verified,
|
||||
@@ -350,24 +349,24 @@ class XQueueCertInterface(object):
|
||||
except (TypeError, XMLSyntaxError, ParserError) as exc:
|
||||
LOGGER.info(
|
||||
(
|
||||
u"Could not retrieve grade for student %s "
|
||||
u"in the course '%s' "
|
||||
u"because an exception occurred while parsing the "
|
||||
u"grade contents '%s' as HTML. "
|
||||
u"The exception was: '%s'"
|
||||
"Could not retrieve grade for student %s "
|
||||
"in the course '%s' "
|
||||
"because an exception occurred while parsing the "
|
||||
"grade contents '%s' as HTML. "
|
||||
"The exception was: '%s'"
|
||||
),
|
||||
student.id,
|
||||
six.text_type(course_id),
|
||||
str(course_id),
|
||||
grade_contents,
|
||||
six.text_type(exc)
|
||||
str(exc)
|
||||
)
|
||||
|
||||
# Check if the student is whitelisted
|
||||
if is_whitelisted:
|
||||
LOGGER.info(
|
||||
u"Student %s is whitelisted in '%s'",
|
||||
"Student %s is whitelisted in '%s'",
|
||||
student.id,
|
||||
six.text_type(course_id)
|
||||
str(course_id)
|
||||
)
|
||||
passing = True
|
||||
|
||||
@@ -381,7 +380,7 @@ class XQueueCertInterface(object):
|
||||
cert.status = status.audit_passing if passing else status.audit_notpassing
|
||||
cert.save()
|
||||
LOGGER.info(
|
||||
u"Student %s with enrollment mode %s is not eligible for a certificate.",
|
||||
"Student %s with enrollment mode %s is not eligible for a certificate.",
|
||||
student.id,
|
||||
enrollment_mode
|
||||
)
|
||||
@@ -393,12 +392,12 @@ class XQueueCertInterface(object):
|
||||
|
||||
LOGGER.info(
|
||||
(
|
||||
u"Student %s does not have a grade for '%s', "
|
||||
u"so their certificate status has been set to '%s'. "
|
||||
u"No certificate generation task was sent to the XQueue."
|
||||
"Student %s does not have a grade for '%s', "
|
||||
"so their certificate status has been set to '%s'. "
|
||||
"No certificate generation task was sent to the XQueue."
|
||||
),
|
||||
student.id,
|
||||
six.text_type(course_id),
|
||||
str(course_id),
|
||||
cert.status
|
||||
)
|
||||
return cert
|
||||
@@ -412,14 +411,14 @@ class XQueueCertInterface(object):
|
||||
|
||||
LOGGER.info(
|
||||
(
|
||||
u"Student %s is in the embargoed country restricted "
|
||||
u"list, so their certificate status has been set to '%s' "
|
||||
u"for the course '%s'. "
|
||||
u"No certificate generation task was sent to the XQueue."
|
||||
"Student %s is in the embargoed country restricted "
|
||||
"list, so their certificate status has been set to '%s' "
|
||||
"for the course '%s'. "
|
||||
"No certificate generation task was sent to the XQueue."
|
||||
),
|
||||
student.id,
|
||||
cert.status,
|
||||
six.text_type(course_id)
|
||||
str(course_id)
|
||||
)
|
||||
return cert
|
||||
|
||||
@@ -428,12 +427,12 @@ class XQueueCertInterface(object):
|
||||
cert.save()
|
||||
LOGGER.info(
|
||||
(
|
||||
u"User %s has a verified enrollment in course %s "
|
||||
u"but is missing ID verification. "
|
||||
u"Certificate status has been set to unverified"
|
||||
"User %s has a verified enrollment in course %s "
|
||||
"but is missing ID verification. "
|
||||
"Certificate status has been set to unverified"
|
||||
),
|
||||
student.id,
|
||||
six.text_type(course_id),
|
||||
str(course_id),
|
||||
)
|
||||
return cert
|
||||
|
||||
@@ -445,7 +444,7 @@ class XQueueCertInterface(object):
|
||||
Generate a certificate for the student. If `generate_pdf` is True,
|
||||
sends a request to XQueue.
|
||||
"""
|
||||
course_id = six.text_type(course.id)
|
||||
course_id = str(course.id)
|
||||
|
||||
key = make_hashkey(random.random())
|
||||
cert.key = key
|
||||
@@ -465,7 +464,7 @@ class XQueueCertInterface(object):
|
||||
cert.verify_uuid = uuid4().hex
|
||||
|
||||
cert.save()
|
||||
logging.info(u'certificate generated for user: %s with generate_pdf status: %s',
|
||||
logging.info('certificate generated for user: %s with generate_pdf status: %s',
|
||||
student.username, generate_pdf)
|
||||
|
||||
if generate_pdf:
|
||||
@@ -473,22 +472,22 @@ class XQueueCertInterface(object):
|
||||
self._send_to_xqueue(contents, key)
|
||||
except XQueueAddToQueueError as exc:
|
||||
cert.status = ExampleCertificate.STATUS_ERROR
|
||||
cert.error_reason = six.text_type(exc)
|
||||
cert.error_reason = str(exc)
|
||||
cert.save()
|
||||
LOGGER.critical(
|
||||
(
|
||||
u"Could not add certificate task to XQueue. "
|
||||
u"The course was '%s' and the student was '%s'."
|
||||
u"The certificate task status has been marked as 'error' "
|
||||
u"and can be re-submitted with a management command."
|
||||
"Could not add certificate task to XQueue. "
|
||||
"The course was '%s' and the student was '%s'."
|
||||
"The certificate task status has been marked as 'error' "
|
||||
"and can be re-submitted with a management command."
|
||||
), course_id, student.id
|
||||
)
|
||||
else:
|
||||
LOGGER.info(
|
||||
(
|
||||
u"The certificate status has been set to '%s'. "
|
||||
u"Sent a certificate grading task to the XQueue "
|
||||
u"with the key '%s'. "
|
||||
"The certificate status has been set to '%s'. "
|
||||
"Sent a certificate grading task to the XQueue "
|
||||
"with the key '%s'. "
|
||||
),
|
||||
cert.status,
|
||||
key
|
||||
@@ -512,7 +511,7 @@ class XQueueCertInterface(object):
|
||||
"""
|
||||
contents = {
|
||||
'action': 'create',
|
||||
'course_id': six.text_type(example_cert.course_key),
|
||||
'course_id': str(example_cert.course_key),
|
||||
'name': example_cert.full_name,
|
||||
'template_pdf': example_cert.template,
|
||||
|
||||
@@ -543,18 +542,18 @@ class XQueueCertInterface(object):
|
||||
task_identifier=example_cert.uuid,
|
||||
callback_url_path=callback_url_path
|
||||
)
|
||||
LOGGER.info(u"Started generating example certificates for course '%s'.", example_cert.course_key)
|
||||
LOGGER.info("Started generating example certificates for course '%s'.", example_cert.course_key)
|
||||
except XQueueAddToQueueError as exc:
|
||||
example_cert.update_status(
|
||||
ExampleCertificate.STATUS_ERROR,
|
||||
error_reason=six.text_type(exc)
|
||||
error_reason=str(exc)
|
||||
)
|
||||
LOGGER.critical(
|
||||
(
|
||||
u"Could not add example certificate with uuid '%s' to XQueue. "
|
||||
u"The exception was %s. "
|
||||
u"The example certificate has been marked with status 'error'."
|
||||
), example_cert.uuid, six.text_type(exc)
|
||||
"Could not add example certificate with uuid '%s' to XQueue. "
|
||||
"The exception was %s. "
|
||||
"The example certificate has been marked with status 'error'."
|
||||
), example_cert.uuid, str(exc)
|
||||
)
|
||||
|
||||
def _send_to_xqueue(self, contents, key, task_identifier=None, callback_url_path='/update_certificate'):
|
||||
@@ -573,7 +572,7 @@ class XQueueCertInterface(object):
|
||||
certificates.
|
||||
|
||||
"""
|
||||
callback_url = u'{protocol}://{base_url}{path}'.format(
|
||||
callback_url = '{protocol}://{base_url}{path}'.format(
|
||||
protocol=("https" if self.use_https else "http"),
|
||||
base_url=settings.SITE_NAME,
|
||||
path=callback_url_path
|
||||
@@ -604,21 +603,21 @@ class XQueueCertInterface(object):
|
||||
header=xheader, body=json.dumps(contents))
|
||||
if error:
|
||||
exc = XQueueAddToQueueError(error, msg)
|
||||
LOGGER.critical(six.text_type(exc))
|
||||
LOGGER.critical(str(exc))
|
||||
raise exc
|
||||
|
||||
def _log_pdf_cert_generation_discontinued_warning(self, student_id, course_id, cert_status, download_url):
|
||||
"""Logs PDF certificate generation discontinued warning."""
|
||||
LOGGER.warning(
|
||||
(
|
||||
u"PDF certificate generation discontinued, canceling "
|
||||
u"PDF certificate generation for student %s "
|
||||
u"in course '%s' "
|
||||
u"with status '%s' "
|
||||
u"and download_url '%s'."
|
||||
"PDF certificate generation discontinued, canceling "
|
||||
"PDF certificate generation for student %s "
|
||||
"in course '%s' "
|
||||
"with status '%s' "
|
||||
"and download_url '%s'."
|
||||
),
|
||||
student_id,
|
||||
six.text_type(course_id),
|
||||
str(course_id),
|
||||
cert_status,
|
||||
download_url
|
||||
)
|
||||
|
||||
@@ -15,7 +15,7 @@ from lms.djangoapps.utils import _get_key
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CertificateService(object):
|
||||
class CertificateService:
|
||||
"""
|
||||
User Certificate service
|
||||
"""
|
||||
@@ -38,13 +38,13 @@ class CertificateService(object):
|
||||
)
|
||||
generated_certificate.invalidate()
|
||||
log.info(
|
||||
u'Certificate invalidated for user %d in course %s',
|
||||
'Certificate invalidated for user %d in course %s',
|
||||
user_id,
|
||||
course_key
|
||||
)
|
||||
except ObjectDoesNotExist:
|
||||
log.warning(
|
||||
u'Invalidation failed because a certificate for user %d in course %s does not exist.',
|
||||
'Invalidation failed because a certificate for user %d in course %s does not exist.',
|
||||
user_id,
|
||||
course_key
|
||||
)
|
||||
|
||||
@@ -4,7 +4,6 @@ Signal handler for enabling/disabling self-generated certificates based on the c
|
||||
|
||||
import logging
|
||||
|
||||
import six
|
||||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
|
||||
@@ -44,7 +43,7 @@ def _update_cert_settings_on_pacing_change(sender, updated_course_overview, **kw
|
||||
updated_course_overview.id,
|
||||
updated_course_overview.self_paced,
|
||||
)
|
||||
log.info(u'Certificate Generation Setting Toggled for {course_id} via pacing change'.format(
|
||||
log.info('Certificate Generation Setting Toggled for {course_id} via pacing change'.format(
|
||||
course_id=updated_course_overview.id
|
||||
))
|
||||
|
||||
@@ -63,7 +62,7 @@ def _listen_for_certificate_whitelist_append(sender, instance, **kwargs): # pyl
|
||||
return
|
||||
|
||||
if _fire_ungenerated_certificate_task(instance.user, instance.course_id):
|
||||
log.info(u'Certificate generation task initiated for {user} : {course} via whitelist'.format(
|
||||
log.info('Certificate generation task initiated for {user} : {course} via whitelist'.format(
|
||||
user=instance.user.id,
|
||||
course=instance.course_id
|
||||
))
|
||||
@@ -84,7 +83,7 @@ def listen_for_passing_grade(sender, user, course_id, **kwargs): # pylint: disa
|
||||
return
|
||||
|
||||
if _fire_ungenerated_certificate_task(user, course_id):
|
||||
log.info(u'Certificate generation task initiated for {user} : {course} via passing grade'.format(
|
||||
log.info('Certificate generation task initiated for {user} : {course} via passing grade'.format(
|
||||
user=user.id,
|
||||
course=course_id
|
||||
))
|
||||
@@ -106,7 +105,7 @@ def _listen_for_failing_grade(sender, user, course_id, grade, **kwargs): # pyli
|
||||
if cert is not None:
|
||||
if CertificateStatuses.is_passing_status(cert.status):
|
||||
cert.mark_notpassing(grade.percent)
|
||||
log.info(u'Certificate marked not passing for {user} : {course} via failing grade: {grade}'.format(
|
||||
log.info('Certificate marked not passing for {user} : {course} via failing grade: {grade}'.format(
|
||||
user=user.id,
|
||||
course=course_id,
|
||||
grade=grade
|
||||
@@ -136,8 +135,8 @@ def _listen_for_id_verification_status_changed(sender, user, **kwargs): # pylin
|
||||
elif grade_factory.read(user=user, course=enrollment.course_overview).passed:
|
||||
if _fire_ungenerated_certificate_task(user, enrollment.course_id, expected_verification_status):
|
||||
message = (
|
||||
u'Certificate generation task initiated for {user} : {course} via track change ' +
|
||||
u'with verification status of {status}'
|
||||
'Certificate generation task initiated for {user} : {course} via track change ' +
|
||||
'with verification status of {status}'
|
||||
)
|
||||
log.info(message.format(
|
||||
user=user.id,
|
||||
@@ -168,7 +167,7 @@ def _fire_ungenerated_certificate_task(user, course_key, expected_verification_s
|
||||
traffic to workers.
|
||||
"""
|
||||
|
||||
message = u'Entered into Ungenerated Certificate task for {user} : {course}'
|
||||
message = 'Entered into Ungenerated Certificate task for {user} : {course}'
|
||||
log.info(message.format(user=user.id, course=course_key))
|
||||
|
||||
allowed_enrollment_modes_list = [
|
||||
@@ -188,14 +187,14 @@ def _fire_ungenerated_certificate_task(user, course_key, expected_verification_s
|
||||
|
||||
if generate_learner_certificate:
|
||||
kwargs = {
|
||||
'student': six.text_type(user.id),
|
||||
'course_key': six.text_type(course_key)
|
||||
'student': str(user.id),
|
||||
'course_key': str(course_key)
|
||||
}
|
||||
if expected_verification_status:
|
||||
kwargs['expected_verification_status'] = six.text_type(expected_verification_status)
|
||||
kwargs['expected_verification_status'] = str(expected_verification_status)
|
||||
generate_certificate.apply_async(countdown=CERTIFICATE_DELAY_SECONDS, kwargs=kwargs)
|
||||
return True
|
||||
|
||||
message = u'Certificate Generation task failed for {user} : {course}'
|
||||
message = 'Certificate Generation task failed for {user} : {course}'
|
||||
log.info(message.format(user=user.id, course=course_key))
|
||||
return False
|
||||
|
||||
@@ -51,9 +51,9 @@ def generate_certificate(self, **kwargs):
|
||||
actual_verification_status = actual_verification_status['status']
|
||||
if expected_verification_status != actual_verification_status:
|
||||
logger.warning(
|
||||
u'Expected verification status {expected} '
|
||||
u'differs from actual verification status {actual} '
|
||||
u'for user {user} in course {course}'.format(
|
||||
'Expected verification status {expected} '
|
||||
'differs from actual verification status {actual} '
|
||||
'for user {user} in course {course}'.format(
|
||||
expected=expected_verification_status,
|
||||
actual=actual_verification_status,
|
||||
user=student.id,
|
||||
|
||||
@@ -12,13 +12,13 @@ app_name = 'certificates'
|
||||
urlpatterns = [
|
||||
# Certificates HTML view end point to render web certs by user and course
|
||||
url(
|
||||
r'^user/(?P<user_id>[^/]*)/course/{course_id}'.format(course_id=settings.COURSE_ID_PATTERN),
|
||||
fr'^user/(?P<user_id>[^/]*)/course/{settings.COURSE_ID_PATTERN}',
|
||||
views.unsupported_url,
|
||||
name='unsupported_url'
|
||||
),
|
||||
|
||||
url(
|
||||
r'^course/{course_id}'.format(course_id=settings.COURSE_ID_PATTERN),
|
||||
fr'^course/{settings.COURSE_ID_PATTERN}',
|
||||
views.render_preview_certificate,
|
||||
name='preview_cert'
|
||||
),
|
||||
|
||||
@@ -4,17 +4,14 @@ Certificates utilities
|
||||
|
||||
import logging
|
||||
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.urls import reverse
|
||||
from eventtracking import tracker
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
from lms.djangoapps.certificates.models import (
|
||||
GeneratedCertificate
|
||||
)
|
||||
from lms.djangoapps.certificates.models import GeneratedCertificate
|
||||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -31,12 +28,12 @@ def emit_certificate_event(event_name, user, course_id, course=None, event_data=
|
||||
course = modulestore().get_course(course_id, depth=0)
|
||||
context = {
|
||||
'org_id': course.org,
|
||||
'course_id': six.text_type(course_id)
|
||||
'course_id': str(course_id)
|
||||
}
|
||||
|
||||
data = {
|
||||
'user_id': user.id,
|
||||
'course_id': six.text_type(course_id),
|
||||
'course_id': str(course_id),
|
||||
'certificate_url': get_certificate_url(user.id, course_id, uuid=event_data['certificate_id'])
|
||||
}
|
||||
event_data = event_data or {}
|
||||
@@ -93,9 +90,9 @@ def _certificate_download_url(user_id, course_id, user_certificate=None):
|
||||
)
|
||||
except GeneratedCertificate.DoesNotExist:
|
||||
log.critical(
|
||||
u'Unable to lookup certificate\n'
|
||||
u'user id: %s\n'
|
||||
u'course: %s', six.text_type(user_id), six.text_type(course_id)
|
||||
'Unable to lookup certificate\n'
|
||||
'user id: %s\n'
|
||||
'course: %s', str(user_id), str(course_id)
|
||||
)
|
||||
|
||||
if user_certificate:
|
||||
|
||||
@@ -7,10 +7,10 @@ See lms/djangoapps/support for more details.
|
||||
|
||||
|
||||
import logging
|
||||
import urllib
|
||||
from functools import wraps
|
||||
|
||||
import bleach
|
||||
import six
|
||||
from django.db import transaction
|
||||
from django.db.models import Q
|
||||
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, HttpResponseServerError
|
||||
@@ -18,7 +18,6 @@ from django.utils.translation import ugettext as _
|
||||
from django.views.decorators.http import require_GET, require_POST
|
||||
from opaque_keys import InvalidKeyError
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
from common.djangoapps.student.models import CourseEnrollment, User
|
||||
from common.djangoapps.util.json_request import JsonResponse
|
||||
@@ -27,6 +26,7 @@ from lms.djangoapps.certificates.models import CertificateInvalidation
|
||||
from lms.djangoapps.certificates.permissions import GENERATE_ALL_CERTIFICATES, VIEW_ALL_CERTIFICATES
|
||||
from lms.djangoapps.instructor_task.api import generate_certificates_for_students
|
||||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -89,7 +89,7 @@ def search_certificates(request):
|
||||
]
|
||||
|
||||
"""
|
||||
unbleached_filter = six.moves.urllib.parse.unquote(six.moves.urllib.parse.quote_plus(request.GET.get("user", "")))
|
||||
unbleached_filter = urllib.parse.unquote(urllib.parse.quote_plus(request.GET.get("user", "")))
|
||||
user_filter = bleach.clean(unbleached_filter)
|
||||
if not user_filter:
|
||||
msg = _("user is not given.")
|
||||
@@ -98,21 +98,21 @@ def search_certificates(request):
|
||||
try:
|
||||
user = User.objects.get(Q(email=user_filter) | Q(username=user_filter))
|
||||
except User.DoesNotExist:
|
||||
return HttpResponseBadRequest(_(u"user '{user}' does not exist").format(user=user_filter))
|
||||
return HttpResponseBadRequest(_("user '{user}' does not exist").format(user=user_filter))
|
||||
|
||||
certificates = get_certificates_for_user(user.username)
|
||||
for cert in certificates:
|
||||
cert["course_key"] = six.text_type(cert["course_key"])
|
||||
cert["course_key"] = str(cert["course_key"])
|
||||
cert["created"] = cert["created"].isoformat()
|
||||
cert["modified"] = cert["modified"].isoformat()
|
||||
cert["regenerate"] = not cert['is_pdf_certificate']
|
||||
|
||||
course_id = six.moves.urllib.parse.quote_plus(request.GET.get("course_id", ""), safe=':/')
|
||||
course_id = urllib.parse.quote_plus(request.GET.get("course_id", ""), safe=':/')
|
||||
if course_id:
|
||||
try:
|
||||
course_key = CourseKey.from_string(course_id)
|
||||
except InvalidKeyError:
|
||||
return HttpResponseBadRequest(_(u"Course id '{course_id}' is not valid").format(course_id=course_id))
|
||||
return HttpResponseBadRequest(_("Course id '{course_id}' is not valid").format(course_id=course_id))
|
||||
else:
|
||||
try:
|
||||
if CourseOverview.get_from_id(course_key):
|
||||
@@ -121,7 +121,7 @@ def search_certificates(request):
|
||||
if not certificates:
|
||||
return JsonResponse([{'username': user.username, 'course_key': course_id, 'regenerate': False}])
|
||||
except CourseOverview.DoesNotExist:
|
||||
msg = _(u"The course does not exist against the given key '{course_key}'").format(course_key=course_key)
|
||||
msg = _("The course does not exist against the given key '{course_key}'").format(course_key=course_key)
|
||||
return HttpResponseBadRequest(msg)
|
||||
|
||||
return JsonResponse(certificates)
|
||||
@@ -142,14 +142,14 @@ def _validate_post_params(params):
|
||||
username = params.get("username")
|
||||
user = User.objects.get(username=username)
|
||||
except User.DoesNotExist:
|
||||
msg = _(u"User {username} does not exist").format(username=username)
|
||||
msg = _("User {username} does not exist").format(username=username)
|
||||
return None, HttpResponseBadRequest(msg)
|
||||
|
||||
# Validate the course key
|
||||
try:
|
||||
course_key = CourseKey.from_string(params.get("course_key"))
|
||||
except InvalidKeyError:
|
||||
msg = _(u"{course_key} is not a valid course key").format(course_key=params.get("course_key"))
|
||||
msg = _("{course_key} is not a valid course key").format(course_key=params.get("course_key"))
|
||||
return None, HttpResponseBadRequest(msg)
|
||||
|
||||
return {"user": user, "course_key": course_key}, None
|
||||
@@ -188,12 +188,12 @@ def regenerate_certificate_for_user(request):
|
||||
# Check that the course exists
|
||||
course = modulestore().get_course(params["course_key"])
|
||||
if course is None:
|
||||
msg = _(u"The course {course_key} does not exist").format(course_key=params["course_key"])
|
||||
msg = _("The course {course_key} does not exist").format(course_key=params["course_key"])
|
||||
return HttpResponseBadRequest(msg)
|
||||
|
||||
# Check that the user is enrolled in the course
|
||||
if not CourseEnrollment.is_enrolled(params["user"], params["course_key"]):
|
||||
msg = _(u"User {username} is not enrolled in the course {course_key}").format(
|
||||
msg = _("User {username} is not enrolled in the course {course_key}").format(
|
||||
username=params["user"].username,
|
||||
course_key=params["course_key"]
|
||||
)
|
||||
@@ -207,14 +207,14 @@ def regenerate_certificate_for_user(request):
|
||||
# certificates API. This may be overkill, but we're logging everything so we can
|
||||
# track down unexpected errors.
|
||||
log.exception(
|
||||
u"Could not regenerate certificates for user %s in course %s",
|
||||
"Could not regenerate certificates for user %s in course %s",
|
||||
params["user"].id,
|
||||
params["course_key"]
|
||||
)
|
||||
return HttpResponseServerError(_("An unexpected error occurred while regenerating certificates."))
|
||||
|
||||
log.info(
|
||||
u"Started regenerating certificates for user %s in course %s from the support page.",
|
||||
"Started regenerating certificates for user %s in course %s from the support page.",
|
||||
params["user"].id, params["course_key"]
|
||||
)
|
||||
return HttpResponse(200)
|
||||
@@ -253,12 +253,12 @@ def generate_certificate_for_user(request):
|
||||
# Check that the course exists
|
||||
CourseOverview.get_from_id(params["course_key"])
|
||||
except CourseOverview.DoesNotExist:
|
||||
msg = _(u"The course {course_key} does not exist").format(course_key=params["course_key"])
|
||||
msg = _("The course {course_key} does not exist").format(course_key=params["course_key"])
|
||||
return HttpResponseBadRequest(msg)
|
||||
else:
|
||||
# Check that the user is enrolled in the course
|
||||
if not CourseEnrollment.is_enrolled(params["user"], params["course_key"]):
|
||||
msg = _(u"User {username} is not enrolled in the course {course_key}").format(
|
||||
msg = _("User {username} is not enrolled in the course {course_key}").format(
|
||||
username=params["user"].username,
|
||||
course_key=params["course_key"]
|
||||
)
|
||||
|
||||
@@ -4,11 +4,11 @@ Certificate HTML webview.
|
||||
|
||||
|
||||
import logging
|
||||
import urllib
|
||||
from datetime import datetime
|
||||
from uuid import uuid4
|
||||
|
||||
import pytz
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import Http404, HttpResponse
|
||||
@@ -63,27 +63,27 @@ def get_certificate_description(mode, certificate_type, platform_name):
|
||||
certificate_type_description = None
|
||||
if mode == 'honor':
|
||||
# Translators: This text describes the 'Honor' course certificate type.
|
||||
certificate_type_description = _(u"An {cert_type} certificate signifies that a "
|
||||
u"learner has agreed to abide by the honor code established by "
|
||||
u"{platform_name} and has completed all of the required tasks for this course "
|
||||
u"under its guidelines.").format(cert_type=certificate_type,
|
||||
platform_name=platform_name)
|
||||
certificate_type_description = _("An {cert_type} certificate signifies that a "
|
||||
"learner has agreed to abide by the honor code established by "
|
||||
"{platform_name} and has completed all of the required tasks for this course "
|
||||
"under its guidelines.").format(cert_type=certificate_type,
|
||||
platform_name=platform_name)
|
||||
elif mode == 'verified':
|
||||
# Translators: This text describes the 'ID Verified' course certificate type, which is a higher level of
|
||||
# verification offered by edX. This type of verification is useful for professional education/certifications
|
||||
certificate_type_description = _(u"A {cert_type} certificate signifies that a "
|
||||
u"learner has agreed to abide by the honor code established by "
|
||||
u"{platform_name} and has completed all of the required tasks for this course "
|
||||
u"under its guidelines. A {cert_type} certificate also indicates that the "
|
||||
u"identity of the learner has been checked and "
|
||||
u"is valid.").format(cert_type=certificate_type,
|
||||
platform_name=platform_name)
|
||||
certificate_type_description = _("A {cert_type} certificate signifies that a "
|
||||
"learner has agreed to abide by the honor code established by "
|
||||
"{platform_name} and has completed all of the required tasks for this course "
|
||||
"under its guidelines. A {cert_type} certificate also indicates that the "
|
||||
"identity of the learner has been checked and "
|
||||
"is valid.").format(cert_type=certificate_type,
|
||||
platform_name=platform_name)
|
||||
elif mode == 'xseries':
|
||||
# Translators: This text describes the 'XSeries' course certificate type. An XSeries is a collection of
|
||||
# courses related to each other in a meaningful way, such as a specific topic or theme, or even an organization
|
||||
certificate_type_description = _(u"An {cert_type} certificate demonstrates a high level of "
|
||||
u"achievement in a program of study, and includes verification of "
|
||||
u"the student's identity.").format(cert_type=certificate_type)
|
||||
certificate_type_description = _("An {cert_type} certificate demonstrates a high level of "
|
||||
"achievement in a program of study, and includes verification of "
|
||||
"the student's identity.").format(cert_type=certificate_type)
|
||||
return certificate_type_description
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ def _update_certificate_context(context, course, user_certificate, platform_name
|
||||
|
||||
# Override the defaults with any mode-specific static values
|
||||
context['certificate_id_number'] = user_certificate.verify_uuid
|
||||
context['certificate_verify_url'] = u"{prefix}{uuid}{suffix}".format(
|
||||
context['certificate_verify_url'] = "{prefix}{uuid}{suffix}".format(
|
||||
prefix=context.get('certificate_verify_url_prefix'),
|
||||
uuid=user_certificate.verify_uuid,
|
||||
suffix=context.get('certificate_verify_url_suffix')
|
||||
@@ -108,8 +108,8 @@ def _update_certificate_context(context, course, user_certificate, platform_name
|
||||
context['certificate_date_issued'] = strftime_localized(date, settings.CERTIFICATE_DATE_FORMAT)
|
||||
|
||||
# Translators: This text represents the verification of the certificate
|
||||
context['document_meta_description'] = _(u'This is a valid {platform_name} certificate for {user_name}, '
|
||||
u'who participated in {partner_short_name} {course_number}').format(
|
||||
context['document_meta_description'] = _('This is a valid {platform_name} certificate for {user_name}, '
|
||||
'who participated in {partner_short_name} {course_number}').format(
|
||||
platform_name=platform_name,
|
||||
user_name=context['accomplishment_copy_name'],
|
||||
partner_short_name=context['organization_short_name'],
|
||||
@@ -117,7 +117,7 @@ def _update_certificate_context(context, course, user_certificate, platform_name
|
||||
)
|
||||
|
||||
# Translators: This text is bound to the HTML 'title' element of the page and appears in the browser title bar
|
||||
context['document_title'] = _(u"{partner_short_name} {course_number} Certificate | {platform_name}").format(
|
||||
context['document_title'] = _("{partner_short_name} {course_number} Certificate | {platform_name}").format(
|
||||
partner_short_name=context['organization_short_name'],
|
||||
course_number=context['course_number'],
|
||||
platform_name=platform_name
|
||||
@@ -125,9 +125,9 @@ def _update_certificate_context(context, course, user_certificate, platform_name
|
||||
|
||||
# Translators: This text fragment appears after the student's name (displayed in a large font) on the certificate
|
||||
# screen. The text describes the accomplishment represented by the certificate information displayed to the user
|
||||
context['accomplishment_copy_description_full'] = _(u"successfully completed, received a passing grade, and was "
|
||||
u"awarded this {platform_name} {certificate_type} "
|
||||
u"Certificate of Completion in ").format(
|
||||
context['accomplishment_copy_description_full'] = _("successfully completed, received a passing grade, and was "
|
||||
"awarded this {platform_name} {certificate_type} "
|
||||
"Certificate of Completion in ").format(
|
||||
platform_name=platform_name,
|
||||
certificate_type=context.get("certificate_type"))
|
||||
|
||||
@@ -136,9 +136,9 @@ def _update_certificate_context(context, course, user_certificate, platform_name
|
||||
context['certificate_type_description'] = certificate_type_description
|
||||
|
||||
# Translators: This text describes the purpose (and therefore, value) of a course certificate
|
||||
context['certificate_info_description'] = _(u"{platform_name} acknowledges achievements through "
|
||||
u"certificates, which are awarded for course activities "
|
||||
u"that {platform_name} students complete.").format(
|
||||
context['certificate_info_description'] = _("{platform_name} acknowledges achievements through "
|
||||
"certificates, which are awarded for course activities "
|
||||
"that {platform_name} students complete.").format(
|
||||
platform_name=platform_name,
|
||||
)
|
||||
|
||||
@@ -156,7 +156,7 @@ def _update_context_with_basic_info(context, course_id, platform_name, configura
|
||||
|
||||
# Translators: 'All rights reserved' is a legal term used in copyrighting to protect published content
|
||||
reserved = _("All rights reserved")
|
||||
context['copyright_text'] = u'© {year} {platform_name}. {reserved}.'.format(
|
||||
context['copyright_text'] = '© {year} {platform_name}. {reserved}.'.format(
|
||||
year=datetime.now(pytz.timezone(settings.TIME_ZONE)).year,
|
||||
platform_name=platform_name,
|
||||
reserved=reserved
|
||||
@@ -175,7 +175,7 @@ def _update_context_with_basic_info(context, course_id, platform_name, configura
|
||||
context['logo_subtitle'] = _("Certificate Validation")
|
||||
|
||||
# Translators: Accomplishments describe the awards/certifications obtained by students on this platform
|
||||
context['accomplishment_copy_about'] = _(u'About {platform_name} Accomplishments').format(
|
||||
context['accomplishment_copy_about'] = _('About {platform_name} Accomplishments').format(
|
||||
platform_name=platform_name
|
||||
)
|
||||
|
||||
@@ -185,39 +185,39 @@ def _update_context_with_basic_info(context, course_id, platform_name, configura
|
||||
# Translators: The Certificate ID Number is an alphanumeric value unique to each individual certificate
|
||||
context['certificate_id_number_title'] = _('Certificate ID Number')
|
||||
|
||||
context['certificate_info_title'] = _(u'About {platform_name} Certificates').format(
|
||||
context['certificate_info_title'] = _('About {platform_name} Certificates').format(
|
||||
platform_name=platform_name
|
||||
)
|
||||
|
||||
context['certificate_verify_title'] = _(u"How {platform_name} Validates Student Certificates").format(
|
||||
context['certificate_verify_title'] = _("How {platform_name} Validates Student Certificates").format(
|
||||
platform_name=platform_name
|
||||
)
|
||||
|
||||
# Translators: This text describes the validation mechanism for a certificate file (known as GPG security)
|
||||
context['certificate_verify_description'] = _(u'Certificates issued by {platform_name} are signed by a gpg key so '
|
||||
u'that they can be validated independently by anyone with the '
|
||||
u'{platform_name} public key. For independent verification, '
|
||||
u'{platform_name} uses what is called a '
|
||||
u'"detached signature""".').format(platform_name=platform_name)
|
||||
context['certificate_verify_description'] = _('Certificates issued by {platform_name} are signed by a gpg key so '
|
||||
'that they can be validated independently by anyone with the '
|
||||
'{platform_name} public key. For independent verification, '
|
||||
'{platform_name} uses what is called a '
|
||||
'"detached signature""".').format(platform_name=platform_name)
|
||||
|
||||
context['certificate_verify_urltext'] = _("Validate this certificate for yourself")
|
||||
|
||||
# Translators: This text describes (at a high level) the mission and charter the edX platform and organization
|
||||
context['company_about_description'] = _(u"{platform_name} offers interactive online classes and MOOCs.").format(
|
||||
context['company_about_description'] = _("{platform_name} offers interactive online classes and MOOCs.").format(
|
||||
platform_name=platform_name)
|
||||
|
||||
context['company_about_title'] = _(u"About {platform_name}").format(platform_name=platform_name)
|
||||
context['company_about_title'] = _("About {platform_name}").format(platform_name=platform_name)
|
||||
|
||||
context['company_about_urltext'] = _(u"Learn more about {platform_name}").format(platform_name=platform_name)
|
||||
context['company_about_urltext'] = _("Learn more about {platform_name}").format(platform_name=platform_name)
|
||||
|
||||
context['company_courselist_urltext'] = _(u"Learn with {platform_name}").format(platform_name=platform_name)
|
||||
context['company_courselist_urltext'] = _("Learn with {platform_name}").format(platform_name=platform_name)
|
||||
|
||||
context['company_careers_urltext'] = _(u"Work at {platform_name}").format(platform_name=platform_name)
|
||||
context['company_careers_urltext'] = _("Work at {platform_name}").format(platform_name=platform_name)
|
||||
|
||||
context['company_contact_urltext'] = _(u"Contact {platform_name}").format(platform_name=platform_name)
|
||||
context['company_contact_urltext'] = _("Contact {platform_name}").format(platform_name=platform_name)
|
||||
|
||||
# Translators: This text appears near the top of the certificate and describes the guarantee provided by edX
|
||||
context['document_banner'] = _(u"{platform_name} acknowledges the following student accomplishment").format(
|
||||
context['document_banner'] = _("{platform_name} acknowledges the following student accomplishment").format(
|
||||
platform_name=platform_name
|
||||
)
|
||||
|
||||
@@ -234,7 +234,7 @@ def _update_course_context(request, context, course, platform_name):
|
||||
context['course_number'] = course_number
|
||||
if context['organization_long_name']:
|
||||
# Translators: This text represents the description of course
|
||||
context['accomplishment_copy_course_description'] = _(u'a course of study offered by {partner_short_name}, '
|
||||
context['accomplishment_copy_course_description'] = _('a course of study offered by {partner_short_name}, '
|
||||
'an online learning initiative of '
|
||||
'{partner_long_name}.').format(
|
||||
partner_short_name=context['organization_short_name'],
|
||||
@@ -257,7 +257,7 @@ def _update_social_context(request, context, course, user_certificate, platform_
|
||||
context['facebook_app_id'] = configuration_helpers.get_value("FACEBOOK_APP_ID", settings.FACEBOOK_APP_ID)
|
||||
context['facebook_share_text'] = share_settings.get(
|
||||
'CERTIFICATE_FACEBOOK_TEXT',
|
||||
_(u"I completed the {course_title} course on {platform_name}.").format(
|
||||
_("I completed the {course_title} course on {platform_name}.").format(
|
||||
course_title=context['accomplishment_copy_course_name'],
|
||||
platform_name=platform_name
|
||||
)
|
||||
@@ -265,7 +265,7 @@ def _update_social_context(request, context, course, user_certificate, platform_
|
||||
context['twitter_share_enabled'] = share_settings.get('CERTIFICATE_TWITTER', False)
|
||||
context['twitter_share_text'] = share_settings.get(
|
||||
'CERTIFICATE_TWITTER_TEXT',
|
||||
_(u"I completed a course at {platform_name}. Take a look at my certificate.").format(
|
||||
_("I completed a course at {platform_name}. Take a look at my certificate.").format(
|
||||
platform_name=platform_name
|
||||
)
|
||||
)
|
||||
@@ -276,7 +276,7 @@ def _update_social_context(request, context, course, user_certificate, platform_
|
||||
if context.get('twitter_share_enabled', False):
|
||||
twitter_url = 'https://twitter.com/intent/tweet?text={twitter_share_text}&url={share_url}'.format(
|
||||
twitter_share_text=smart_str(context['twitter_share_text']),
|
||||
share_url=six.moves.urllib.parse.quote_plus(smart_str(share_url))
|
||||
share_url=urllib.parse.quote_plus(smart_str(share_url))
|
||||
)
|
||||
context['twitter_url'] = twitter_url
|
||||
context['linked_in_url'] = None
|
||||
@@ -301,11 +301,11 @@ def _update_context_with_user_info(context, user, user_certificate):
|
||||
context['accomplishment_copy_name'] = user_fullname
|
||||
context['accomplishment_copy_username'] = user.username
|
||||
|
||||
context['accomplishment_more_title'] = _(u"More Information About {user_name}'s Certificate:").format(
|
||||
context['accomplishment_more_title'] = _("More Information About {user_name}'s Certificate:").format(
|
||||
user_name=user_fullname
|
||||
)
|
||||
# Translators: This line is displayed to a user who has completed a course and achieved a certification
|
||||
context['accomplishment_banner_opening'] = _(u"{fullname}, you earned a certificate!").format(
|
||||
context['accomplishment_banner_opening'] = _("{fullname}, you earned a certificate!").format(
|
||||
fullname=user_fullname
|
||||
)
|
||||
|
||||
@@ -315,7 +315,7 @@ def _update_context_with_user_info(context, user, user_certificate):
|
||||
"in your social and professional networks.")
|
||||
|
||||
# Translators: This line leads the reader to understand more about the certificate that a student has been awarded
|
||||
context['accomplishment_copy_more_about'] = _(u"More about {fullname}'s accomplishment").format(
|
||||
context['accomplishment_copy_more_about'] = _("More about {fullname}'s accomplishment").format(
|
||||
fullname=user_fullname
|
||||
)
|
||||
|
||||
@@ -336,7 +336,7 @@ def _get_user_certificate(request, user, course_key, course, preview_mode=None):
|
||||
modified_date = datetime.now().date()
|
||||
user_certificate = GeneratedCertificate(
|
||||
mode=preview_mode,
|
||||
verify_uuid=six.text_type(uuid4().hex),
|
||||
verify_uuid=str(uuid4().hex),
|
||||
modified_date=modified_date,
|
||||
created_date=datetime.now().date(),
|
||||
)
|
||||
@@ -364,7 +364,7 @@ def _track_certificate_events(request, course, user, user_certificate):
|
||||
if 'evidence_visit' in request.GET:
|
||||
badge_class = get_completion_badge(course_key, user)
|
||||
if not badge_class:
|
||||
log.warning(u'Visit to evidence URL for badge, but badges not configured for course "%s"', course_key)
|
||||
log.warning('Visit to evidence URL for badge, but badges not configured for course "%s"', course_key)
|
||||
badges = []
|
||||
else:
|
||||
badges = badge_class.get_for_user(user)
|
||||
@@ -379,7 +379,7 @@ def _track_certificate_events(request, course, user, user_certificate):
|
||||
'badge_generator': badge.backend,
|
||||
'issuing_component': badge.badge_class.issuing_component,
|
||||
'user_id': user.id,
|
||||
'course_id': six.text_type(course_key),
|
||||
'course_id': str(course_key),
|
||||
'enrollment_mode': badge.badge_class.mode,
|
||||
'assertion_id': badge.id,
|
||||
'assertion_image_url': badge.image_url,
|
||||
@@ -389,14 +389,14 @@ def _track_certificate_events(request, course, user, user_certificate):
|
||||
)
|
||||
else:
|
||||
log.warning(
|
||||
u"Could not find badge for %s on course %s.",
|
||||
"Could not find badge for %s on course %s.",
|
||||
user.id,
|
||||
course_key,
|
||||
)
|
||||
|
||||
# track certificate evidence_visited event for analytics when certificate_user and accessing_user are different
|
||||
if request.user and request.user.id != user.id:
|
||||
emit_certificate_event('evidence_visited', user, six.text_type(course.id), course, {
|
||||
emit_certificate_event('evidence_visited', user, str(course.id), course, {
|
||||
'certificate_id': user_certificate.verify_uuid,
|
||||
'enrollment_mode': user_certificate.mode,
|
||||
'social_network': CertificateSocialNetworks.linkedin
|
||||
@@ -452,7 +452,7 @@ def render_preview_certificate(request, course_id):
|
||||
"""
|
||||
This view renders the course certificate in preview mode
|
||||
"""
|
||||
return render_html_view(request, six.text_type(course_id))
|
||||
return render_html_view(request, str(course_id))
|
||||
|
||||
|
||||
def render_cert_by_uuid(request, certificate_uuid):
|
||||
@@ -464,7 +464,7 @@ def render_cert_by_uuid(request, certificate_uuid):
|
||||
verify_uuid=certificate_uuid,
|
||||
status=CertificateStatuses.downloadable
|
||||
)
|
||||
return render_html_view(request, six.text_type(certificate.course_id), certificate)
|
||||
return render_html_view(request, str(certificate.course_id), certificate)
|
||||
except GeneratedCertificate.DoesNotExist as e:
|
||||
raise Http404 from e
|
||||
|
||||
@@ -496,8 +496,8 @@ def render_html_view(request, course_id, certificate=None):
|
||||
# For any course or user exceptions, kick the user back to the "Invalid" screen
|
||||
except (InvalidKeyError, Http404) as exception:
|
||||
error_str = (
|
||||
u"Invalid cert: error finding course %s "
|
||||
u"Specific error: %s"
|
||||
"Invalid cert: error finding course %s "
|
||||
"Specific error: %s"
|
||||
)
|
||||
log.info(error_str, course_id, str(exception))
|
||||
return _render_invalid_certificate(request, course_id, platform_name, configuration)
|
||||
@@ -505,7 +505,7 @@ def render_html_view(request, course_id, certificate=None):
|
||||
# Kick the user back to the "Invalid" screen if the feature is disabled for the course
|
||||
if not course.cert_html_view_enabled:
|
||||
log.info(
|
||||
u"Invalid cert: HTML certificates disabled for %s. User id: %d",
|
||||
"Invalid cert: HTML certificates disabled for %s. User id: %d",
|
||||
course_id,
|
||||
user_id,
|
||||
)
|
||||
@@ -515,7 +515,7 @@ def render_html_view(request, course_id, certificate=None):
|
||||
user_certificate = _get_user_certificate(request, user, course_key, course, preview_mode)
|
||||
if not user_certificate:
|
||||
log.info(
|
||||
u"Invalid cert: User %d does not have eligible cert for %s.",
|
||||
"Invalid cert: User %d does not have eligible cert for %s.",
|
||||
user_id,
|
||||
course_id,
|
||||
)
|
||||
@@ -527,7 +527,7 @@ def render_html_view(request, course_id, certificate=None):
|
||||
active_configuration = get_active_web_certificate(course, preview_mode)
|
||||
if active_configuration is None:
|
||||
log.info(
|
||||
u"Invalid cert: course %s does not have an active configuration. User id: %d",
|
||||
"Invalid cert: course %s does not have an active configuration. User id: %d",
|
||||
course_id,
|
||||
user_id,
|
||||
)
|
||||
@@ -540,7 +540,7 @@ def render_html_view(request, course_id, certificate=None):
|
||||
custom_template = None
|
||||
custom_template_language = None
|
||||
if settings.FEATURES.get('CUSTOM_CERTIFICATE_TEMPLATES_ENABLED', False):
|
||||
log.info(u"Custom certificate for course %s", course_id)
|
||||
log.info("Custom certificate for course %s", course_id)
|
||||
custom_template, custom_template_language = _get_custom_template_and_language(
|
||||
course.id,
|
||||
user_certificate.mode,
|
||||
@@ -554,7 +554,7 @@ def render_html_view(request, course_id, certificate=None):
|
||||
certificate_language = custom_template_language if custom_template else user_language
|
||||
|
||||
log.info(
|
||||
u"certificate language is: %s for the course: %s",
|
||||
"certificate language is: %s for the course: %s",
|
||||
certificate_language,
|
||||
course_key
|
||||
)
|
||||
@@ -631,7 +631,7 @@ def _get_catalog_data_for_course(course_key):
|
||||
log.exception('Error occurred while parsing course run details')
|
||||
catalog_data['content_language'] = course_run_data.get('content_language')
|
||||
log.info(
|
||||
u"catalog data received for course: %s is : %s",
|
||||
"catalog data received for course: %s is : %s",
|
||||
course_key,
|
||||
catalog_data,
|
||||
)
|
||||
@@ -645,7 +645,7 @@ def _get_custom_template_and_language(course_id, course_mode, course_language):
|
||||
"""
|
||||
closest_released_language = get_closest_released_language(course_language) if course_language else None
|
||||
log.info(
|
||||
u"closest released language for %s is %s and course language was: %s",
|
||||
"closest released language for %s is %s and course language was: %s",
|
||||
course_id,
|
||||
closest_released_language,
|
||||
course_language
|
||||
|
||||
@@ -12,7 +12,6 @@ from django.http import Http404, HttpResponse, HttpResponseForbidden
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from django.views.decorators.http import require_POST
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
from common.djangoapps.util.json_request import JsonResponse, JsonResponseBadRequest
|
||||
from common.djangoapps.util.request_rate_limiter import BadRequestRateLimiter
|
||||
@@ -27,6 +26,7 @@ from lms.djangoapps.certificates.models import (
|
||||
GeneratedCertificate,
|
||||
certificate_status_for_student
|
||||
)
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
User = get_user_model()
|
||||
@@ -56,7 +56,7 @@ def request_certificate(request):
|
||||
f'allowlist. Attempt will be made to generate an allowlist certificate.')
|
||||
generate_allowlist_certificate_task(student, course_key)
|
||||
elif status in [CertificateStatuses.unavailable, CertificateStatuses.notpassing, CertificateStatuses.error]:
|
||||
log_msg = u'Grading and certification requested for user %s in course %s via /request_certificate call'
|
||||
log_msg = 'Grading and certification requested for user %s in course %s via /request_certificate call'
|
||||
log.info(log_msg, username, course_key)
|
||||
status = generate_user_certificates(student, course_key, course=course)
|
||||
return HttpResponse(json.dumps({'add_status': status}), content_type='application/json') # pylint: disable=http-response-with-content-type-json, http-response-with-json-dumps
|
||||
@@ -91,8 +91,8 @@ def update_certificate(request):
|
||||
except GeneratedCertificate.DoesNotExist:
|
||||
log.critical(
|
||||
'Unable to lookup certificate\n'
|
||||
u'xqueue_body: %s\n'
|
||||
u'xqueue_header: %s',
|
||||
'xqueue_body: %s\n'
|
||||
'xqueue_header: %s',
|
||||
xqueue_body,
|
||||
xqueue_header
|
||||
)
|
||||
@@ -139,7 +139,7 @@ def update_certificate(request):
|
||||
cert.status = status.deleted
|
||||
else:
|
||||
log.critical(
|
||||
u'Invalid state for cert update: %s', cert.status
|
||||
'Invalid state for cert update: %s', cert.status
|
||||
)
|
||||
return HttpResponse( # pylint: disable=http-response-with-content-type-json, http-response-with-json-dumps
|
||||
json.dumps({
|
||||
@@ -179,23 +179,23 @@ def update_example_certificate(request):
|
||||
HttpResponse (404): Invalid certificate identifier or access key.
|
||||
|
||||
"""
|
||||
log.info(u"Received response for example certificate from XQueue.")
|
||||
log.info("Received response for example certificate from XQueue.")
|
||||
|
||||
rate_limiter = BadRequestRateLimiter()
|
||||
|
||||
# Check the parameters and rate limits
|
||||
# If these are invalid, return an error response.
|
||||
if rate_limiter.is_rate_limit_exceeded(request):
|
||||
log.info(u"Bad request rate limit exceeded for update example certificate end-point.")
|
||||
log.info("Bad request rate limit exceeded for update example certificate end-point.")
|
||||
return HttpResponseForbidden("Rate limit exceeded")
|
||||
|
||||
if 'xqueue_body' not in request.POST:
|
||||
log.info(u"Missing parameter 'xqueue_body' for update example certificate end-point")
|
||||
log.info("Missing parameter 'xqueue_body' for update example certificate end-point")
|
||||
rate_limiter.tick_request_counter(request)
|
||||
return JsonResponseBadRequest("Parameter 'xqueue_body' is required.")
|
||||
|
||||
if 'xqueue_header' not in request.POST:
|
||||
log.info(u"Missing parameter 'xqueue_header' for update example certificate end-point")
|
||||
log.info("Missing parameter 'xqueue_header' for update example certificate end-point")
|
||||
rate_limiter.tick_request_counter(request)
|
||||
return JsonResponseBadRequest("Parameter 'xqueue_header' is required.")
|
||||
|
||||
@@ -203,7 +203,7 @@ def update_example_certificate(request):
|
||||
xqueue_body = json.loads(request.POST['xqueue_body'])
|
||||
xqueue_header = json.loads(request.POST['xqueue_header'])
|
||||
except (ValueError, TypeError):
|
||||
log.info(u"Could not decode params to example certificate end-point as JSON.")
|
||||
log.info("Could not decode params to example certificate end-point as JSON.")
|
||||
rate_limiter.tick_request_counter(request)
|
||||
return JsonResponseBadRequest("Parameters must be JSON-serialized.")
|
||||
|
||||
@@ -218,7 +218,7 @@ def update_example_certificate(request):
|
||||
# were not valid. This most likely means that the request is NOT coming
|
||||
# from the XQueue. Return a 404 and increase the bad request counter
|
||||
# to protect against a DDOS attack.
|
||||
log.info(u"Could not find example certificate with uuid '%s' and access key '%s'", uuid, access_key)
|
||||
log.info("Could not find example certificate with uuid '%s' and access key '%s'", uuid, access_key)
|
||||
rate_limiter.tick_request_counter(request)
|
||||
raise Http404 from e
|
||||
|
||||
@@ -228,8 +228,8 @@ def update_example_certificate(request):
|
||||
cert.update_status(ExampleCertificate.STATUS_ERROR, error_reason=error_reason)
|
||||
log.warning(
|
||||
(
|
||||
u"Error occurred during example certificate generation for uuid '%s'. "
|
||||
u"The error response was '%s'."
|
||||
"Error occurred during example certificate generation for uuid '%s'. "
|
||||
"The error response was '%s'."
|
||||
), uuid, error_reason
|
||||
)
|
||||
else:
|
||||
@@ -238,13 +238,13 @@ def update_example_certificate(request):
|
||||
download_url = xqueue_body.get('url')
|
||||
if download_url is None:
|
||||
rate_limiter.tick_request_counter(request)
|
||||
log.warning(u"No download URL provided for example certificate with uuid '%s'.", uuid)
|
||||
log.warning("No download URL provided for example certificate with uuid '%s'.", uuid)
|
||||
return JsonResponseBadRequest(
|
||||
"Parameter 'download_url' is required for successfully generated certificates."
|
||||
)
|
||||
else:
|
||||
cert.update_status(ExampleCertificate.STATUS_SUCCESS, download_url=download_url)
|
||||
log.info(u"Successfully updated example certificate with uuid '%s'.", uuid)
|
||||
log.info("Successfully updated example certificate with uuid '%s'.", uuid)
|
||||
|
||||
# Let the XQueue know that we handled the response
|
||||
return JsonResponse({'return_code': 0})
|
||||
|
||||
Reference in New Issue
Block a user