Пример #1
0
def _listen_for_id_verification_status_changed(sender, user, **kwargs):  # pylint: disable=unused-argument
    """
    Catches a track change signal, determines user status,
    calls _fire_ungenerated_certificate_task for passing grades
    """
    if not auto_certificate_generation_enabled():
        return

    user_enrollments = CourseEnrollment.enrollments_for_user(user=user)

    grade_factory = CourseGradeFactory()
    expected_verification_status = IDVerificationService.user_status(user)
    expected_verification_status = expected_verification_status['status']
    for enrollment in user_enrollments:
        if is_using_certificate_allowlist_and_is_on_allowlist(
                user, enrollment.course_id):
            log.info(
                f'{enrollment.course_id} is using allowlist certificates, and the user {user.id} is on its '
                f'allowlist. Attempt will be made to generate an allowlist certificate. Id verification status '
                f'is {expected_verification_status}')
            generate_allowlist_certificate_task(user, enrollment.course_id)
        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}')
                log.info(
                    message.format(user=user.id,
                                   course=enrollment.course_id,
                                   status=expected_verification_status))
Пример #2
0
    def invalidate_certificate(self, user_id, course_key_or_id):
        """
        Invalidate the user certificate in a given course if it exists and the user is not on the allowlist for this
        course run.
        """
        course_key = _get_key(course_key_or_id, CourseKey)
        if is_using_certificate_allowlist_and_is_on_allowlist(user_id, course_key):
            log.info('{course_key} is using allowlist certificates, and the user {user_id} is on its allowlist. The '
                     'certificate will not be invalidated.'.format(course_key=course_key, user_id=user_id))
            return False

        try:
            generated_certificate = GeneratedCertificate.objects.get(
                user=user_id,
                course_id=course_key
            )
            generated_certificate.invalidate()
            log.info(
                'Certificate invalidated for user %d in course %s',
                user_id,
                course_key
            )
        except ObjectDoesNotExist:
            log.warning(
                'Invalidation failed because a certificate for user %d in course %s does not exist.',
                user_id,
                course_key
            )
            return False

        return True
Пример #3
0
 def test_is_using_allowlist_and_is_on_list_true(self):
     """
     Test the allowlist flag and the presence of the user on the list when the user is not on the list
     """
     u = UserFactory()
     CourseEnrollmentFactory(
         user=u,
         course_id=self.course_run_key,
         is_active=True,
         mode="verified",
     )
     CertificateWhitelistFactory.create(course_id=self.course_run_key, user=u, whitelist=False)
     self.assertFalse(is_using_certificate_allowlist_and_is_on_allowlist(u, self.course_run_key))
Пример #4
0
def _listen_for_enrollment_mode_change(sender, user, course_key, mode,
                                       **kwargs):  # pylint: disable=unused-argument
    """
    Listen for the signal indicating that a user's enrollment mode has changed.

    If possible, grant the user a course certificate. Note that we intentionally do not revoke certificates here, even
    if the user has moved to the audit track.
    """
    if modes_api.is_eligible_for_certificate(mode):
        if is_using_certificate_allowlist_and_is_on_allowlist(
                user, course_key):
            log.info(
                f'{course_key} is using allowlist certificates, and the user {user.id} is on its allowlist. '
                f'Attempt will be made to generate an allowlist certificate since the enrollment mode is now '
                f'{mode}.')
            generate_allowlist_certificate_task(user, course_key)
Пример #5
0
def _listen_for_certificate_whitelist_append(sender, instance, **kwargs):  # pylint: disable=unused-argument
    """
    Listen for a user being added to or modified on the whitelist (allowlist)
    """
    if not auto_certificate_generation_enabled():
        return

    if is_using_certificate_allowlist_and_is_on_allowlist(instance.user, instance.course_id):
        log.info(f'{instance.course_id} is using allowlist certificates, and the user {instance.user.id} is now on '
                 f'its allowlist. Attempt will be made to generate an allowlist certificate.')
        return generate_allowlist_certificate_task(instance.user, instance.course_id)

    if _fire_ungenerated_certificate_task(instance.user, instance.course_id):
        log.info('Certificate generation task initiated for {user} : {course} via whitelist'.format(
            user=instance.user.id,
            course=instance.course_id
        ))
Пример #6
0
def listen_for_passing_grade(sender, user, course_id, **kwargs):  # pylint: disable=unused-argument
    """
    Listen for a learner passing a course, send cert generation task,
    downstream signal from COURSE_GRADE_CHANGED
    """
    if is_using_certificate_allowlist_and_is_on_allowlist(user, course_id):
        log.info(
            f'{course_id} is using allowlist certificates, and the user {user.id} is on its allowlist. Attempt '
            f'will be made to generate an allowlist certificate as a passing grade was received.'
        )
        return generate_allowlist_certificate_task(user, course_id)

    if not auto_certificate_generation_enabled():
        return

    if _fire_ungenerated_certificate_task(user, course_id):
        log.info(
            u'Certificate generation task initiated for {user} : {course} via passing grade'
            .format(user=user.id, course=course_id))
Пример #7
0
def _listen_for_failing_grade(sender, user, course_id, grade, **kwargs):  # pylint: disable=unused-argument
    """
    Listen for a learner failing a course, mark the cert as notpassing
    if it is currently passing,
    downstream signal from COURSE_GRADE_CHANGED
    """
    if is_using_certificate_allowlist_and_is_on_allowlist(user, course_id):
        log.info('{course_id} is using allowlist certificates, and the user {user_id} is on its allowlist. The '
                 'failing grade will not affect the certificate.'.format(course_id=course_id, user_id=user.id))
        return

    cert = GeneratedCertificate.certificate_for_student(user, course_id)
    if cert is not None:
        if CertificateStatuses.is_passing_status(cert.status):
            cert.mark_notpassing(grade.percent)
            log.info('Certificate marked not passing for {user} : {course} via failing grade: {grade}'.format(
                user=user.id,
                course=course_id,
                grade=grade
            ))
Пример #8
0
def _listen_for_failing_grade(sender, user, course_id, grade, **kwargs):  # pylint: disable=unused-argument
    """
    Listen for a signal indicating that the user has failed a course run.

    If needed, mark the certificate as notpassing.
    """
    if is_using_certificate_allowlist_and_is_on_allowlist(user, course_id):
        log.info(
            '{course_id} is using allowlist certificates, and the user {user_id} is on its allowlist. The '
            'failing grade will not affect the certificate.'.format(
                course_id=course_id, user_id=user.id))
        return

    cert = GeneratedCertificate.certificate_for_student(user, course_id)
    if cert is not None:
        if CertificateStatuses.is_passing_status(cert.status):
            cert.mark_notpassing(grade.percent)
            log.info(
                'Certificate marked not passing for {user} : {course} via failing grade: {grade}'
                .format(user=user.id, course=course_id, grade=grade))
Пример #9
0
 def test_is_using_allowlist_and_is_on_list_with_flag_off(self):
     """
     Test the allowlist flag and the presence of the user on the list when the flag is off
     """
     assert not is_using_certificate_allowlist_and_is_on_allowlist(
         self.user, self.course_run_key)
Пример #10
0
 def test_is_using_allowlist_and_is_on_list(self):
     """
     Test the allowlist flag and the presence of the user on the list
     """
     assert is_using_certificate_allowlist_and_is_on_allowlist(
         self.user, self.course_run_key)
Пример #11
0
def fire_ungenerated_certificate_task(user,
                                      course_key,
                                      expected_verification_status=None):
    """
    Helper function to fire certificate generation task.
    Auto-generation of certificates is available for following course modes:
        1- VERIFIED
        2- CREDIT_MODE
        3- PROFESSIONAL
        4- NO_ID_PROFESSIONAL_MODE

    Certificate generation task is fired to either generate a certificate
    when there is no generated certificate for user in a particular course or
    update a certificate if it has 'unverified' status.

    Task is fired to attempt an update to a certificate
    with 'unverified' status as this method is called when a user is
    successfully verified, any certificate associated
    with such user can now be verified.

    NOTE: Purpose of restricting other course modes (HONOR and AUDIT) from auto-generation is to reduce
    traffic to workers.
    """

    message = u'Entered into Ungenerated Certificate task for {user} : {course}'
    log.info(message.format(user=user.id, course=course_key))

    if is_using_certificate_allowlist_and_is_on_allowlist(user, course_key):
        log.info(
            '{course} is using allowlist certificates, and the user {user} is on its allowlist. Attempt will be '
            'made to generate an allowlist certificate.'.format(
                course=course_key, user=user.id))
        generate_allowlist_certificate_task(user, course_key)
        return True

    log.info(
        '{course} is not using allowlist certificates (or user {user} is not on its allowlist). The normal '
        'generation logic will be followed.'.format(course=course_key,
                                                    user=user.id))

    allowed_enrollment_modes_list = [
        CourseMode.VERIFIED,
        CourseMode.CREDIT_MODE,
        CourseMode.PROFESSIONAL,
        CourseMode.NO_ID_PROFESSIONAL_MODE,
        CourseMode.MASTERS,
        CourseMode.EXECUTIVE_EDUCATION,
    ]
    enrollment_mode, __ = CourseEnrollment.enrollment_mode_for_user(
        user, course_key)
    cert = GeneratedCertificate.certificate_for_student(user, course_key)

    generate_learner_certificate = (
        enrollment_mode in allowed_enrollment_modes_list
        and (cert is None or cert.status == 'unverified'))

    if generate_learner_certificate:
        kwargs = {
            'student': six.text_type(user.id),
            'course_key': six.text_type(course_key)
        }
        if expected_verification_status:
            kwargs['expected_verification_status'] = six.text_type(
                expected_verification_status)
        generate_certificate.apply_async(countdown=CERTIFICATE_DELAY_SECONDS,
                                         kwargs=kwargs)
        return True

    message = u'Certificate Generation task failed for {user} : {course}'
    log.info(message.format(user=user.id, course=course_key))
    return False