MICROBA-1055 Require a valid enrollment mode, even on the allowlist (#27012)

This commit is contained in:
Christie Rice
2021-03-16 09:37:27 -04:00
committed by GitHub
parent 6f7e6bca87
commit 90f5e42dbd
6 changed files with 47 additions and 7 deletions

View File

@@ -15,3 +15,15 @@ def get_paid_modes_for_course(course_run_id):
A list of paid modes (strings) that the course has attached to it.
"""
return _CourseMode.paid_modes_for_course(course_run_id)
def is_eligible_for_certificate(mode_slug, status=None):
"""
Returns whether or not the given mode_slug is eligible for a
certificate. Currently all modes other than 'audit' grant a
certificate. Note that audit enrollments which existed prior
to December 2015 *were* given certificates, so there will be
GeneratedCertificate records with mode='audit' which are
eligible.
"""
return _CourseMode.is_eligible_for_certificate(mode_slug, status)

View File

@@ -22,12 +22,15 @@ won't necessarily have a course certificate available to them. To receive a
downloadable allowlist course certificate, the following things must be true at
the time the certificate is generated:
* The user must be enrolled in the course
* The user must have an enrollment in the course
* The enrollment mode must be eligible for a certificate
* The enrollment does not need to be active
* The user must have an approved, unexpired, ID verification
* The user must be on the allowlist for the course run (see the CertificateWhitelist model)
* The user must not have an invalidated certificate for the course run (see the CertificateInvalidation model)
* Certificate generation must be enabled for the course run
* Automatic certificate generation must be enabled
* The user must be on the allowlist for the course run (see the *CertificateWhitelist* model)
* The user must not have an invalidated certificate for the course run (see the *CertificateInvalidation* model)
* Automatic certificate generation must be globally enabled
Note: the above requirements were written for the allowlist, which assumes the
CourseWaffleFlag *certificates_revamp.use_allowlist* has been enabled for the

View File

@@ -10,6 +10,7 @@ import logging
from edx_toggles.toggles import LegacyWaffleFlagNamespace
from common.djangoapps.course_modes import api as modes_api
from common.djangoapps.student.models import CourseEnrollment
from lms.djangoapps.certificates.models import (
CertificateInvalidation,
@@ -164,6 +165,11 @@ def _can_generate_allowlist_certificate(user, course_key):
log.info(f'{user.id} : {course_key} does not have an enrollment. Certificate cannot be generated.')
return False
if not modes_api.is_eligible_for_certificate(enrollment_mode):
log.info(f'{user.id} : {course_key} has an enrollment mode of {enrollment_mode}, which is not eligible for an '
f'allowlist certificate. Certificate cannot be generated.')
return False
if not IDVerificationService.user_is_verified(user):
log.info(f'{user.id} does not have a verified id. Certificate cannot be generated.')
return False

View File

@@ -15,6 +15,7 @@ from lxml.etree import ParserError, XMLSyntaxError
from requests.auth import HTTPBasicAuth
from capa.xqueue_interface import XQueueInterface, make_hashkey, make_xheader
from common.djangoapps.course_modes import api as modes_api
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
@@ -289,7 +290,7 @@ class XQueueCertInterface:
user_is_verified = IDVerificationService.user_is_verified(student)
cert_mode = enrollment_mode
is_eligible_for_certificate = CourseMode.is_eligible_for_certificate(enrollment_mode, cert_status)
is_eligible_for_certificate = modes_api.is_eligible_for_certificate(enrollment_mode, cert_status)
if is_whitelisted and not is_eligible_for_certificate:
# check if audit certificates are enabled for audit mode
is_eligible_for_certificate = enrollment_mode != CourseMode.AUDIT or \

View File

@@ -195,6 +195,23 @@ class AllowlistTests(ModuleStoreTestCase):
CertificateWhitelistFactory.create(course_id=key, user=u)
assert not _can_generate_allowlist_certificate(u, key)
def test_can_generate_audit(self):
"""
Test handling when user is enrolled in audit mode
"""
u = UserFactory()
cr = CourseFactory()
key = cr.id # pylint: disable=no-member
CourseEnrollmentFactory(
user=u,
course_id=key,
is_active=True,
mode="audit",
)
CertificateWhitelistFactory.create(course_id=key, user=u)
assert not _can_generate_allowlist_certificate(u, key)
def test_can_generate_not_whitelisted(self):
"""
Test handling when user is not whitelisted

View File

@@ -21,6 +21,7 @@ from testfixtures import LogCapture
# and verify that items are being correctly added to the queue
# in our `XQueueCertInterface` implementation.
from capa.xqueue_interface import XQueueInterface
from common.djangoapps.course_modes import api as modes_api
from common.djangoapps.course_modes.models import CourseMode
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory
from lms.djangoapps.certificates.models import (
@@ -91,7 +92,7 @@ class XQueueCertInterfaceAddCertificateTest(ModuleStoreTestCase):
id=self.course.id
)
mock_send = self.add_cert_to_queue(mode)
if CourseMode.is_eligible_for_certificate(mode):
if modes_api.is_eligible_for_certificate(mode):
self.assert_certificate_generated(mock_send, mode, template_name)
else:
self.assert_ineligible_certificate_generated(mock_send, mode)