def test_generation_uuid_persists_through_revocation(self): """ Test that the `verify_uuid` value of a certificate does not change when it is revoked and re-awarded. """ generated_cert = generate_course_certificate(self.u, self.key, self.gen_mode) assert generated_cert.status, CertificateStatuses.downloadable verify_uuid = generated_cert.verify_uuid generated_cert.invalidate() assert generated_cert.status, CertificateStatuses.unavailable assert generated_cert.verify_uuid, verify_uuid generated_cert = generate_course_certificate(self.u, self.key, self.gen_mode) assert generated_cert.status, CertificateStatuses.downloadable assert generated_cert.verify_uuid, verify_uuid generated_cert.mark_notpassing(50.00) assert generated_cert.status, CertificateStatuses.notpassing assert generated_cert.verify_uuid, verify_uuid generated_cert = generate_course_certificate(self.u, self.key, self.gen_mode) assert generated_cert.status, CertificateStatuses.downloadable assert generated_cert.verify_uuid, verify_uuid
def test_generation_verified_name(self, should_use_verified_name_for_certs, status): """ Test that if verified name functionality is enabled and the user has their preference set to use verified name for certificates, their verified name will appear on the certificate rather than their profile name. """ verified_name = 'Jonathan Doe' create_verified_name(self.u, verified_name, self.name, status=status) create_verified_name_config( self.u, use_verified_name_for_certs=should_use_verified_name_for_certs) GeneratedCertificateFactory(user=self.u, course_id=self.key, mode=CourseMode.AUDIT, status=CertificateStatuses.unverified) generate_course_certificate( self.u, self.key, CertificateStatuses.downloadable, self.enrollment_mode, self.grade, self.gen_mode, ) cert = GeneratedCertificate.objects.get(user=self.u, course_id=self.key) if should_use_verified_name_for_certs and status == VerifiedNameStatus.APPROVED: assert cert.name == verified_name else: assert cert.name == self.name
def test_generation_existing_unverified(self): """ Test certificate generation when a certificate already exists and we want to mark it as unverified """ error_reason = 'Some PDF error' GeneratedCertificateFactory(user=self.u, course_id=self.key, mode=CourseMode.AUDIT, status=CertificateStatuses.error, error_reason=error_reason) cert = GeneratedCertificate.objects.get(user=self.u, course_id=self.key) assert cert.error_reason == error_reason assert cert.mode == CourseMode.AUDIT assert cert.status == CertificateStatuses.error generate_course_certificate(self.u, self.key, CertificateStatuses.unverified, self.enrollment_mode, self.grade, self.gen_mode) cert = GeneratedCertificate.objects.get(user=self.u, course_id=self.key) assert cert.error_reason == '' assert cert.status == CertificateStatuses.unverified assert cert.mode == self.enrollment_mode assert cert.grade == ''
def generate_certificate(self, **kwargs): """ Generates a certificate for a single user. kwargs: - student: The student for whom to generate a certificate. - course_key: The course key for the course that the student is receiving a certificate in. - expected_verification_status: The expected verification status for the user. When the status has changed, we double check that the actual verification status is as expected before generating a certificate, in the off chance that the database has not yet updated with the user's new verification status. - v2_certificate: A flag indicating whether to generate a v2 course certificate - generation_mode: Only used when emitting an event for V2 certificates. Options are "self" (implying the user generated the cert themself) and "batch" for everything else. """ original_kwargs = kwargs.copy() student = User.objects.get(id=kwargs.pop('student')) course_key = CourseKey.from_string(kwargs.pop('course_key')) expected_verification_status = kwargs.pop('expected_verification_status', None) v2_certificate = kwargs.pop('v2_certificate', False) status = kwargs.pop('status', CertificateStatuses.downloadable) generation_mode = kwargs.pop('generation_mode', 'batch') if v2_certificate: generate_course_certificate(user=student, course_key=course_key, status=status, generation_mode=generation_mode) return if expected_verification_status: actual_verification_status = IDVerificationService.user_status(student) actual_verification_status = actual_verification_status['status'] if expected_verification_status != actual_verification_status: log.warning('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, course=course_key)) raise self.retry(kwargs=original_kwargs) generate_user_certificates(student=student, course_key=course_key, **kwargs)
def generate_certificate(self, **kwargs): """ Generates a certificate for a single user. kwargs: - student: The student for whom to generate a certificate. - course_key: The course key for the course that the student is receiving a certificate in. - expected_verification_status: The expected verification status for the user. When the status has changed, we double check that the actual verification status is as expected before generating a certificate, in the off chance that the database has not yet updated with the user's new verification status. - allowlist_certificate: A flag indicating whether to generate an allowlist certificate (which is V2 of whitelisted certificates) - v2_certificate: A flag indicating whether to generate a v2 course certificate """ original_kwargs = kwargs.copy() student = User.objects.get(id=kwargs.pop('student')) course_key = CourseKey.from_string(kwargs.pop('course_key')) expected_verification_status = kwargs.pop('expected_verification_status', None) allowlist_certificate = kwargs.pop('allowlist_certificate', False) v2_certificate = kwargs.pop('v2_certificate', False) if allowlist_certificate: generate_allowlist_certificate(user=student, course_key=course_key) return if v2_certificate: generate_course_certificate(user=student, course_key=course_key) return if expected_verification_status: actual_verification_status = IDVerificationService.user_status(student) actual_verification_status = actual_verification_status['status'] if expected_verification_status != actual_verification_status: log.warning('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, course=course_key)) raise self.retry(kwargs=original_kwargs) generate_user_certificates(student=student, course_key=course_key, **kwargs)
def test_generation(self): """ Test certificate generation """ certs = GeneratedCertificate.objects.filter(user=self.u, course_id=self.key) assert len(certs) == 0 generated_cert = generate_course_certificate( self.u, self.key, CertificateStatuses.downloadable, self.enrollment_mode, self.grade, self.gen_mode) self.assert_event_emitted('edx.certificate.created', user_id=self.u.id, course_id=str(self.key), certificate_id=generated_cert.verify_uuid, enrollment_mode=generated_cert.mode, certificate_url='', generation_mode=self.gen_mode) certs = GeneratedCertificate.objects.filter(user=self.u, course_id=self.key) assert len(certs) == 1 cert = GeneratedCertificate.objects.get(user=self.u, course_id=self.key) assert cert.status == CertificateStatuses.downloadable assert cert.mode == self.enrollment_mode assert cert.grade == self.grade assert cert.name == self.name
def test_generation(self): """ Test certificate generation """ # Create user, a course run, and an enrollment u = UserFactory() cr = CourseFactory() key = cr.id # pylint: disable=no-member CourseEnrollmentFactory( user=u, course_id=key, is_active=True, mode="verified", ) gen_mode = 'batch' certs = GeneratedCertificate.objects.filter(user=u, course_id=key) assert len(certs) == 0 generated_cert = generate_course_certificate(u, key, gen_mode) assert generated_cert.status, CertificateStatuses.downloadable certs = GeneratedCertificate.objects.filter(user=u, course_id=key) assert len(certs) == 1 self.assert_event_emitted('edx.certificate.created', user_id=u.id, course_id=str(key), certificate_id=generated_cert.verify_uuid, enrollment_mode=generated_cert.mode, certificate_url='', generation_mode=gen_mode)
def test_generation_existing(self): """ Test certificate generation when a certificate already exists """ # Create user, a course run, and an enrollment u = UserFactory() cr = CourseFactory() key = cr.id # pylint: disable=no-member CourseEnrollmentFactory( user=u, course_id=key, is_active=True, mode='verified', ) error_reason = 'Some PDF error' GeneratedCertificateFactory( user=u, course_id=key, mode='verified', status=CertificateStatuses.error, error_reason=error_reason ) gen_mode = 'batch' cert = GeneratedCertificate.objects.get(user=u, course_id=key) assert cert.error_reason == error_reason generated_cert = generate_course_certificate(u, key, gen_mode) assert generated_cert.status, CertificateStatuses.downloadable cert = GeneratedCertificate.objects.get(user=u, course_id=key) assert cert.error_reason == ''
def test_generation_missing_profile(self): """ Test certificate generation when the user profile is missing """ GeneratedCertificateFactory( user=self.u, course_id=self.key, mode=CourseMode.AUDIT, status=CertificateStatuses.unverified ) with mock.patch(PROFILE_NAME_METHOD, return_value=None): generate_course_certificate(self.u, self.key, CertificateStatuses.downloadable, self.enrollment_mode, self.grade, self.gen_mode) cert = GeneratedCertificate.objects.get(user=self.u, course_id=self.key) assert cert.status == CertificateStatuses.downloadable assert cert.mode == self.enrollment_mode assert cert.grade == self.grade assert cert.name == ''
def test_generation_creates_verify_uuid_when_needed(self): """ Test that ensures we will create a verify_uuid when needed. """ GeneratedCertificateFactory(user=self.u, course_id=self.key, mode='verified', status=CertificateStatuses.unverified, verify_uuid='') generated_cert = generate_course_certificate(self.u, self.key, self.gen_mode) assert generated_cert.status, CertificateStatuses.downloadable assert generated_cert.verify_uuid != ''
def generate_certificate(self, **kwargs): # pylint: disable=unused-argument """ Generates a certificate for a single user. kwargs: - student: The student for whom to generate a certificate. Required. - course_key: The course key for the course that the student is receiving a certificate in. Required. - status: Certificate status (value from the CertificateStatuses model). Defaults to 'downloadable'. - enrollment_mode: User's enrollment mode (ex. verified). Required. - course_grade: User's course grade. Defaults to ''. - generation_mode: Used when emitting an event. Options are "self" (implying the user generated the cert themself) and "batch" for everything else. Defaults to 'batch'. """ student = User.objects.get(id=kwargs.pop('student')) course_key = CourseKey.from_string(kwargs.pop('course_key')) status = kwargs.pop('status', CertificateStatuses.downloadable) enrollment_mode = kwargs.pop('enrollment_mode') course_grade = kwargs.pop('course_grade', '') generation_mode = kwargs.pop('generation_mode', 'batch') generate_course_certificate(user=student, course_key=course_key, status=status, enrollment_mode=enrollment_mode, course_grade=course_grade, generation_mode=generation_mode)
def test_generation_existing(self): """ Test certificate generation when a certificate already exists """ error_reason = 'Some PDF error' GeneratedCertificateFactory( user=self.u, course_id=self.key, mode='verified', status=CertificateStatuses.error, error_reason=error_reason ) cert = GeneratedCertificate.objects.get(user=self.u, course_id=self.key) assert cert.error_reason == error_reason generated_cert = generate_course_certificate(self.u, self.key, self.gen_mode) assert generated_cert.status, CertificateStatuses.downloadable cert = GeneratedCertificate.objects.get(user=self.u, course_id=self.key) assert cert.error_reason == ''