def _get_user_certificate(request, user, course_key, course, preview_mode=None): """ Retrieves user's certificate from db. Creates one in case of preview mode. Returns None if there is no certificate generated for given user otherwise returns `GeneratedCertificate` instance. """ try: # Attempt to load the user's generated certificate data if preview_mode: user_certificate = GeneratedCertificate.objects.get( user=user, course_id=course_key, mode=preview_mode) else: user_certificate = GeneratedCertificate.objects.get( user=user, course_id=course_key, status=CertificateStatuses.downloadable) # If there's no generated certificate data for this user, we need to see if we're in 'preview' mode... # If we are, we'll need to create a mock version of the user_certificate container for previewing except GeneratedCertificate.DoesNotExist: if preview_mode and (has_access(request.user, 'instructor', course) or has_access(request.user, 'staff', course)): user_certificate = GeneratedCertificate( mode=preview_mode, verify_uuid=unicode(uuid4().hex), modified_date=datetime.now().date()) else: return None return user_certificate
def _get_user_certificate(request, user, course_key, course, preview_mode=None): """ Retrieves user's certificate from db. Creates one in case of preview mode. Returns None if there is no certificate generated for given user otherwise returns `GeneratedCertificate` instance. """ user_certificate = None if preview_mode: # certificate is being previewed from studio if has_access(request.user, 'instructor', course) or has_access( request.user, 'staff', course): user_certificate = GeneratedCertificate( mode=preview_mode, verify_uuid=unicode(uuid4().hex), modified_date=datetime.now().date()) else: # certificate is being viewed by learner or public try: user_certificate = GeneratedCertificate.eligible_certificates.get( user=user, course_id=course_key, status=CertificateStatuses.downloadable) except GeneratedCertificate.DoesNotExist: pass return user_certificate
def test_no_match(self): """ Make sure a badge isn't created before a user's reached any checkpoint. """ user = UserFactory() course = CourseFactory() GeneratedCertificate( # pylint: disable=no-member user=user, course_id=course.location.course_key, status=CertificateStatuses.downloadable).save() # pylint: disable=no-member self.assertFalse(user.badgeassertion_set.all())
def test_checkpoint_matches(self, checkpoint, required_badges): """ Make sure the proper badges are awarded at the right checkpoints. """ user = UserFactory() courses = [CourseFactory() for _i in range(required_badges)] for course in courses: GeneratedCertificate( # pylint: disable=no-member user=user, course_id=course.location.course_key, status=CertificateStatuses.downloadable).save() # pylint: disable=no-member assertions = user.badgeassertion_set.all().order_by('id') # pylint: disable=no-member self.assertEqual(user.badgeassertion_set.all().count(), checkpoint) self.assertEqual(assertions[checkpoint - 1].badge_class, self.badge_classes[checkpoint - 1])
def test_group_matches(self): """ Make sure the proper badges are awarded when groups are completed. """ user = UserFactory() items = list(self.config_map.items()) for badge_class, course_keys in items: for i, key in enumerate(course_keys): GeneratedCertificate( user=user, course_id=key, status=CertificateStatuses.downloadable).save() # We don't award badges until all three are set. if i + 1 == len(course_keys): self.assertTrue(badge_class.get_for_user(user)) else: self.assertFalse(badge_class.get_for_user(user)) # pylint: disable=no-member classes = [ badge.badge_class.id for badge in user.badgeassertion_set.all() ] source_classes = [badge.id for badge in self.badge_classes] self.assertEqual(classes, source_classes)
def render_html_view(request, user_id, course_id): """ This public view generates an HTML representation of the specified student's certificate If a certificate is not available, we display a "Sorry!" screen instead """ # Create the initial view context, bootstrapping with Django settings and passed-in values context = {} context['platform_name'] = microsite.get_value("platform_name", settings.PLATFORM_NAME) context['course_id'] = course_id # Update the view context with the default ConfigurationModel settings configuration = CertificateHtmlViewConfiguration.get_config() # if we are in a microsite, then let's first see if there is an override # section in our config config_key = microsite.get_value('microsite_config_key', 'default') # if there is no special microsite override, then let's use default if config_key not in configuration: config_key = 'default' context.update(configuration.get(config_key, {})) # Translators: 'All rights reserved' is a legal term used in copyrighting to protect published content reserved = _("All rights reserved") context[ 'copyright_text'] = '© {year} {platform_name}. {reserved}.'.format( year=settings.COPYRIGHT_YEAR, platform_name=context.get('platform_name'), reserved=reserved) # Translators: This text is bound to the HTML 'title' element of the page and appears # in the browser title bar when a requested certificate is not found or recognized context['document_title'] = _("Invalid Certificate") # Translators: The & characters represent an ampersand character and can be ignored context['company_tos_urltext'] = _("Terms of Service & Honor Code") # Translators: A 'Privacy Policy' is a legal document/statement describing a website's use of personal information context['company_privacy_urltext'] = _("Privacy Policy") # Translators: This line appears as a byline to a header image and describes the purpose of the page context['logo_subtitle'] = _("Certificate Validation") invalid_template_path = 'certificates/invalid.html' # Kick the user back to the "Invalid" screen if the feature is disabled if not settings.FEATURES.get('CERTIFICATES_HTML_VIEW', False): return render_to_response(invalid_template_path, context) # Load the core building blocks for the view context try: course_key = CourseKey.from_string(course_id) user = User.objects.get(id=user_id) course = modulestore().get_course(course_key) if not course: raise CourseDoesNotExist # Attempt to load the user's generated certificate data user_certificate = GeneratedCertificate.objects.get( user=user, course_id=course_key) # If there's no generated certificate data for this user, we need to see if we're in 'preview' mode... # If we are, we'll need to create a mock version of the user_certificate container for previewing except GeneratedCertificate.DoesNotExist: if request.GET.get('preview', None): user_certificate = GeneratedCertificate( mode=request.GET.get('preview'), verify_uuid=unicode(uuid4().hex), modified_date=datetime.now().date()) else: return render_to_response(invalid_template_path, context) # For any other expected exceptions, kick the user back to the "Invalid" screen except (InvalidKeyError, CourseDoesNotExist, User.DoesNotExist): return render_to_response(invalid_template_path, context) # Badge Request Event Tracking Logic if 'evidence_visit' in request.GET: try: badge = BadgeAssertion.objects.get(user=user, course_id=course_key) tracker.emit( 'edx.badge.assertion.evidence_visited', { 'user_id': user.id, 'course_id': unicode(course_key), 'enrollment_mode': badge.mode, 'assertion_id': badge.id, 'assertion_image_url': badge.data['image'], 'assertion_json_url': badge.data['json']['id'], 'issuer': badge.data['issuer'], }) except BadgeAssertion.DoesNotExist: logger.warn( "Could not find badge for %s on course %s.", user.id, course_key, ) # Okay, now we have all of the pieces, time to put everything together # Get the active certificate configuration for this course # If we do not have an active certificate, we'll need to send the user to the "Invalid" screen # Passing in the 'preview' parameter, if specified, will return a configuration, if defined active_configuration = get_active_web_certificate( course, request.GET.get('preview')) if active_configuration is None: return render_to_response(invalid_template_path, context) else: context['certificate_data'] = active_configuration # Append/Override the existing view context values with any mode-specific ConfigurationModel values context.update(configuration.get(user_certificate.mode, {})) # Append/Override the existing view context values with request-time values _update_certificate_context(context, course, user, user_certificate) # Microsites will need to be able to override any hard coded # content that was put into the context in the # _update_certificate_context() call above. For example the # 'company_about_description' talks about edX, which we most likely # do not want to keep in a microsite # # So we need to re-apply any configuration/content that # we are sourceing from the database. This is somewhat duplicative of # the code at the beginning of this method, but we # need the configuration at the top as some error code paths # require that to be set up early on in the pipeline # microsite_config_key = microsite.get_value('microsite_config_key') if microsite_config_key: context.update(configuration.get(microsite_config_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, course_id, course, { 'certificate_id': user_certificate.verify_uuid, 'enrollment_mode': user_certificate.mode, 'social_network': CertificateSocialNetworks.linkedin }) # Append/Override the existing view context values with any course-specific static values from Advanced Settings context.update(course.cert_html_view_overrides) # FINALLY, generate and send the output the client return render_to_response("certificates/valid.html", context)
def setUp(self): CourseFactory.create(org='TESTX', number='1', display_name='TEST1', start=datetime.datetime(2010, 5, 12, 2, 42, tzinfo=utc), end=datetime.datetime(2011, 5, 12, 2, 42, tzinfo=utc)) CourseFactory.create(org='TESTX', number='2', display_name='TEST2', start=datetime.datetime(2010, 5, 12, 2, 42, tzinfo=utc), end=datetime.datetime(2011, 5, 12, 2, 42, tzinfo=utc)) CourseFactory.create(org='TESTX', number='3', display_name='TEST3', start=datetime.datetime(2010, 5, 12, 2, 42, tzinfo=utc), end=datetime.datetime(2011, 5, 12, 2, 42, tzinfo=utc)) self.fred = fred = User(username='******', email='*****@*****.**') fred.save() UserProfile(user=fred, name='Fred Flintstone').save() LinkedIn(user=fred, has_linkedin_account=True).save() self.barney = barney = User(username='******', email='*****@*****.**') barney.save() LinkedIn(user=barney, has_linkedin_account=True).save() UserProfile(user=barney, name='Barney Rubble').save() self.adam = adam = User(username='******', email='*****@*****.**') adam.save() LinkedIn(user=adam, has_linkedin_account=True).save() UserProfile(user=adam, name='Adam (חיים פּלי)').save() self.cert1 = cert1 = GeneratedCertificate( status='downloadable', user=fred, course_id='TESTX/1/TEST1', name='TestX/Intro101', download_url='http://test.foo/test') cert1.save() cert2 = GeneratedCertificate(status='downloadable', user=fred, course_id='TESTX/2/TEST2') cert2.save() cert3 = GeneratedCertificate(status='downloadable', user=barney, course_id='TESTX/3/TEST3') cert3.save() cert5 = GeneratedCertificate(status='downloadable', user=adam, course_id='TESTX/3/TEST3') cert5.save()