def generate_user_certificates(student, course_key, insecure=False, generation_mode='batch', forced_grade=None):
    """
    It will add the add-cert request into the xqueue.

    A new record will be created to track the certificate
    generation task.  If an error occurs while adding the certificate
    to the queue, the task will have status 'error'. It also emits
    `edx.certificate.created` event for analytics.

    This method has not yet been updated (it predates the certificates revamp). If modifying this method,
    see also generate_user_certificates() in generation_handler.py (which is very similar but is not called from a
    celery task). In the future these methods will be unified.

   Args:
        student (User)
        course_key (CourseKey)

    Keyword Arguments:
        insecure - (Boolean)
        generation_mode - who has requested certificate generation. Its value should `batch`
        in case of django command and `self` if student initiated the request.
        forced_grade - a string indicating to replace grade parameter. if present grading
                       will be skipped.
    """
    beta_testers_queryset = list_with_level(course_key, 'beta')
    if beta_testers_queryset.filter(username=student.username):
        log.info(f"Canceling Certificate Generation task for user {student.id} : {course_key}. User is a Beta Tester.")
        return

    xqueue = XQueueCertInterface()
    if insecure:
        xqueue.use_https = False

    course_overview = get_course_overview(course_key)
    generate_pdf = not has_html_certificates_enabled(course_overview)

    cert = xqueue.add_cert(
        student,
        course_key,
        generate_pdf=generate_pdf,
        forced_grade=forced_grade
    )

    log.info(f"Queued Certificate Generation task for {student.id} : {course_key}")

    # If cert_status is not present in certificate valid_statuses (for example unverified) then
    # add_cert returns None and raises AttributeError while accessing cert attributes.
    if cert is None:
        return

    if CertificateStatuses.is_passing_status(cert.status):
        emit_certificate_event('created', student, course_key, course_overview, {
            'user_id': student.id,
            'course_id': str(course_key),
            'certificate_id': cert.verify_uuid,
            'enrollment_mode': cert.mode,
            'generation_mode': generation_mode
        })
    return cert.status
def _can_generate_certificate_common(user, course_key, enrollment_mode):
    """
    Check if a course certificate can be generated (created if it doesn't already exist, or updated if it does
    exist) for this user, in this course run.

    This method contains checks that are common to both allowlist and regular course certificates.
    """
    if CertificateInvalidation.has_certificate_invalidation(user, course_key):
        # The invalidation list prevents certificate generation
        log.info(
            f'{user.id} : {course_key} is on the certificate invalidation list. Certificate cannot be generated.'
        )
        return False

    if enrollment_mode is None:
        log.info(
            f'{user.id} : {course_key} does not have an enrollment. Certificate cannot be generated.'
        )
        return False

    is_eligible_for_cert = modes_api.is_eligible_for_certificate(
        enrollment_mode)
    if not is_eligible_for_cert:
        log.info(
            f'{user.id} : {course_key} has an enrollment mode of {enrollment_mode}, which is not eligible for a '
            f'certificate. Certificate cannot be generated.')
        return False

    # If the IDV check fails we then check if the course-run requires ID verification. Honor and Professional-No-ID
    # modes do not require IDV for certificate generation.
    if _required_verification_missing(user):
        if enrollment_mode not in CourseMode.NON_VERIFIED_MODES:
            log.info(
                f'{user.id} does not have a verified id. Certificate cannot be generated for {course_key}.'
            )
            return False

        log.info(
            f'{user.id} : {course_key} is eligible for a certificate without requiring a verified ID. '
            'Skipping results of the ID verification check.')

    if not _can_generate_certificate_for_status(user, course_key,
                                                enrollment_mode):
        return False

    course_overview = get_course_overview_or_none(course_key)
    if not course_overview:
        log.info(
            f'{course_key} does not a course overview. Certificate cannot be generated for {user.id}.'
        )
        return False

    if not has_html_certificates_enabled(course_overview):
        log.info(
            f'{course_key} does not have HTML certificates enabled. Certificate cannot be generated for '
            f'{user.id}.')
        return False

    return True
Exemple #3
0
    def test_has_html_certificates_enabled_from_course_overview_disabled(self):
        """
        Test to ensure we return the correct value when the HTML certificates are disabled in a course-run.
        """
        self.course_overview.cert_html_view_enabled = False
        self.course_overview.save()

        assert not has_html_certificates_enabled(self.course_overview)
def regenerate_user_certificates(student,
                                 course_key,
                                 course=None,
                                 forced_grade=None,
                                 template_file=None,
                                 insecure=False):
    """
    Add the regen-cert request into the xqueue.

    A new record will be created to track the certificate
    generation task.  If an error occurs while adding the certificate
    to the queue, the task will have status 'error'.

    This method has not yet been updated (it predates the certificates revamp).

    Args:
        student (User)
        course_key (CourseKey)

    Keyword Arguments:
        course (Course): Optionally provide the course object; if not provided
            it will be loaded.
        grade_value - The grade string, such as "Distinction"
        template_file - The template file used to render this certificate
        insecure - (Boolean)
    """
    if is_using_certificate_allowlist_and_is_on_allowlist(student, course_key):
        log.info(
            f'{course_key} is using allowlist certificates, and the user {student.id} is on its allowlist. '
            f'Attempt will be made to regenerate an allowlist certificate.')
        return generate_allowlist_certificate_task(student, course_key)

    xqueue = XQueueCertInterface()
    if insecure:
        xqueue.use_https = False

    if not course:
        course = modulestore().get_course(course_key, depth=0)

    generate_pdf = not has_html_certificates_enabled(course)
    log.info(
        "Started regenerating certificates for user %s in course %s with generate_pdf status: %s",
        student.username, str(course_key), generate_pdf)

    xqueue.regen_cert(student,
                      course_key,
                      course=course,
                      forced_grade=forced_grade,
                      template_file=template_file,
                      generate_pdf=generate_pdf)
    return True
Exemple #5
0
def regenerate_user_certificates(student,
                                 course_key,
                                 forced_grade=None,
                                 template_file=None,
                                 insecure=False):
    """
    Add the regen-cert request into the xqueue.

    A new record will be created to track the certificate
    generation task.  If an error occurs while adding the certificate
    to the queue, the task will have status 'error'.

    This method has not yet been updated (it predates the certificates revamp).

    Args:
        student (User)
        course_key (CourseKey)

    Keyword Arguments:
        grade_value - The grade string, such as "Distinction"
        template_file - The template file used to render this certificate
        insecure - (Boolean)
    """
    if can_generate_certificate_task(student, course_key):
        log.info(
            f"{course_key} is using V2 certificates. Attempt will be made to regenerate a V2 certificate for "
            f"user {student.id}.")
        return generate_certificate_task(student, course_key)

    xqueue = XQueueCertInterface()
    if insecure:
        xqueue.use_https = False

    course_overview = get_course_overview_or_none(course_key)
    if not course_overview:
        log.info(
            f"Canceling certificate generation for user {student.id} : {course_key} due to a missing course "
            f"overview.")
        return False

    generate_pdf = not has_html_certificates_enabled(course_overview)
    log.info(
        f"Started regenerating certificates for user {student.id} in course {course_key} with generate_pdf "
        f"status: {generate_pdf}.")

    xqueue.regen_cert(student,
                      course_key,
                      forced_grade=forced_grade,
                      template_file=template_file,
                      generate_pdf=generate_pdf)
    return True
Exemple #6
0
def _can_generate_certificate_common(user, course_key):
    """
    Check if a course certificate can be generated (created if it doesn't already exist, or updated if it does
    exist) for this user, in this course run.

    This method contains checks that are common to both allowlist and V2 regular course certificates.
    """
    if CertificateInvalidation.has_certificate_invalidation(user, course_key):
        # The invalidation list prevents certificate generation
        log.info(
            f'{user.id} : {course_key} is on the certificate invalidation list. Certificate cannot be generated.'
        )
        return False

    enrollment_mode, __ = CourseEnrollment.enrollment_mode_for_user(
        user, course_key)
    if enrollment_mode is None:
        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 a '
            f'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 for {course_key}.'
        )
        return False

    if not _can_generate_certificate_for_status(user, course_key):
        return False

    course_overview = get_course_overview_or_none(course_key)
    if not course_overview:
        log.info(
            f'{course_key} does not a course overview. Certificate cannot be generated for {user.id}.'
        )
        return False

    if not has_html_certificates_enabled(course_overview):
        log.info(
            f'{course_key} does not have HTML certificates enabled. Certificate cannot be generated for '
            f'{user.id}.')
        return False

    return True
def _can_set_cert_status_common(user, course_key, course):
    """
    Determine whether we can set a custom (non-downloadable) cert status
    """
    if _is_cert_downloadable(user, course_key):
        return False

    enrollment_mode, __ = CourseEnrollment.enrollment_mode_for_user(
        user, course_key)
    if enrollment_mode is None:
        return False

    if not modes_api.is_eligible_for_certificate(enrollment_mode):
        return False

    if not has_html_certificates_enabled(course):
        return False

    return True
def generate_user_certificates(student,
                               course_key,
                               course=None,
                               insecure=False,
                               generation_mode='batch',
                               forced_grade=None):
    """
    It will add the add-cert request into the xqueue.

    A new record will be created to track the certificate
    generation task.  If an error occurs while adding the certificate
    to the queue, the task will have status 'error'. It also emits
    `edx.certificate.created` event for analytics.

    This method has not yet been updated (it predates the certificates revamp). If modifying this method,
    see also generate_user_certificates() in generation.py (which is very similar but is called from a celery task).
    In the future these methods will be unified.

    Args:
        student (User)
        course_key (CourseKey)

    Keyword Arguments:
        course (Course): Optionally provide the course object; if not provided
            it will be loaded.
        insecure - (Boolean)
        generation_mode - who has requested certificate generation. Its value should `batch`
        in case of django command and `self` if student initiated the request.
        forced_grade - a string indicating to replace grade parameter. if present grading
                       will be skipped.
    """
    if is_using_certificate_allowlist_and_is_on_allowlist(student, course_key):
        # Note that this will launch an asynchronous task, and so cannot return the certificate status. This is a
        # change from the older certificate code that tries to immediately create a cert.
        log.info(
            f'{course_key} is using allowlist certificates, and the user {student.id} is on its allowlist. '
            f'Attempt will be made to regenerate an allowlist certificate.')
        return generate_allowlist_certificate_task(student, course_key)

    if not course:
        course = modulestore().get_course(course_key, depth=0)

    beta_testers_queryset = list_with_level(course, 'beta')

    if beta_testers_queryset.filter(username=student.username):
        message = 'Cancelling course certificate generation for user [{}] against course [{}], user is a Beta Tester.'
        log.info(message.format(student.username, course_key))
        return

    xqueue = XQueueCertInterface()
    if insecure:
        xqueue.use_https = False

    generate_pdf = not has_html_certificates_enabled(course)

    cert = xqueue.add_cert(student,
                           course_key,
                           course=course,
                           generate_pdf=generate_pdf,
                           forced_grade=forced_grade)

    message = 'Queued Certificate Generation task for {user} : {course}'
    log.info(message.format(user=student.id, course=course_key))

    # If cert_status is not present in certificate valid_statuses (for example unverified) then
    # add_cert returns None and raises AttributeError while accessing cert attributes.
    if cert is None:
        return

    if CertificateStatuses.is_passing_status(cert.status):
        emit_certificate_event(
            'created', student, course_key, course, {
                'user_id': student.id,
                'course_id': str(course_key),
                'certificate_id': cert.verify_uuid,
                'enrollment_mode': cert.mode,
                'generation_mode': generation_mode
            })
    return cert.status
def _can_generate_v2_certificate(user, course_key):
    """
    Check if a v2 course certificate can be generated (created if it doesn't already exist, or updated if it does
    exist) for this user, in this course run.
    """
    if not _is_using_v2_course_certificates(course_key):
        # This course run is not using the v2 course certificate feature
        log.info(
            f'{course_key} is not using v2 course certificates. Certificate cannot be generated.'
        )
        return False

    if not auto_certificate_generation_enabled():
        # Automatic certificate generation is globally disabled
        log.info(
            f'Automatic certificate generation is globally disabled. Certificate cannot be generated for '
            f'{user.id} : {course_key}.')
        return False

    if CertificateInvalidation.has_certificate_invalidation(user, course_key):
        # The invalidation list prevents certificate generation
        log.info(
            f'{user.id} : {course_key} is on the certificate invalidation list. Certificate cannot be generated.'
        )
        return False

    enrollment_mode, __ = CourseEnrollment.enrollment_mode_for_user(
        user, course_key)
    if enrollment_mode is None:
        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 for {course_key}.'
        )
        return False

    if _is_ccx_course(course_key):
        log.info(
            f'{course_key} is a CCX course. Certificate cannot be generated for {user.id}.'
        )
        return False

    course = _get_course(course_key)
    if _is_beta_tester(user, course):
        log.info(
            f'{user.id} is a beta tester in {course_key}. Certificate cannot be generated.'
        )
        return False

    if not _has_passing_grade(user, course):
        log.info(
            f'{user.id} does not have a passing grade in {course_key}. Certificate cannot be generated.'
        )
        return False

    if not _can_generate_certificate_for_status(user, course_key):
        return False

    course = _get_course(course_key)
    if not has_html_certificates_enabled(course):
        log.info(
            f'{course_key} does not have HTML certificates enabled. Certificate cannot be generated for '
            f'{user.id}.')
        return False

    log.info(f'V2 certificate can be generated for {user.id} : {course_key}')
    return True
def _can_generate_allowlist_certificate(user, course_key):
    """
    Check if an allowlist certificate can be generated (created if it doesn't already exist, or updated if it does
    exist) for this user, in this course run.
    """
    if not is_using_certificate_allowlist(course_key):
        # This course run is not using the allowlist feature
        log.info(
            f'{course_key} is not using the certificate allowlist. Allowlist certificate cannot be generated'
            f'for {user.id}.')
        return False

    if not _is_on_certificate_allowlist(user, course_key):
        log.info(
            f'{user.id} : {course_key} is not on the certificate allowlist. Allowlist certificate cannot be '
            f'generated.')
        return False

    if not auto_certificate_generation_enabled():
        # Automatic certificate generation is globally disabled
        log.info(
            f'Automatic certificate generation is globally disabled. Allowlist certificate cannot be generated'
            f'for {user.id} : {course_key}.')
        return False

    if CertificateInvalidation.has_certificate_invalidation(user, course_key):
        # The invalidation list overrides the allowlist
        log.info(
            f'{user.id} : {course_key} is on the certificate invalidation list. Allowlist certificate cannot be '
            f'generated.')
        return False

    enrollment_mode, __ = CourseEnrollment.enrollment_mode_for_user(
        user, course_key)
    if enrollment_mode is None:
        log.info(
            f'{user.id} : {course_key} does not have an enrollment. Allowlist 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. Allowlist certificate cannot be generated for {course_key}.'
        )
        return False

    course = _get_course(course_key)
    if not has_html_certificates_enabled(course):
        log.info(
            f'{course_key} does not have HTML certificates enabled. Allowlist certificate cannot be generated for '
            f'{user.id}.')
        return False

    log.info(f'{user.id} : {course_key} is on the certificate allowlist')
    return _can_generate_allowlist_certificate_for_status(user, course_key)
Exemple #11
0
 def test_has_html_certificates_enabled_from_course_overview_cert_html_view_disabled(self):
     """
     Test to ensure we return the correct value when the `CERTIFICATES_HTML_VIEW` setting is disabled.
     """
     assert not has_html_certificates_enabled(self.course_overview)