def test_generate_enrollment_status_hash(self): """ Verify the method returns a hash of a user's current enrollments. """ # Return None for anonymous users self.assertIsNone( CourseEnrollment.generate_enrollment_status_hash(AnonymousUser())) # No enrollments expected = hashlib.md5(self.user.username.encode('utf-8')).hexdigest() self.assertEqual( CourseEnrollment.generate_enrollment_status_hash(self.user), expected) self.assert_enrollment_status_hash_cached(self.user, expected) # No active enrollments enrollment_mode = 'verified' course_id = self.course.id # pylint: disable=no-member enrollment = CourseEnrollmentFactory.create(user=self.user, course_id=course_id, mode=enrollment_mode, is_active=False) self.assertEqual( CourseEnrollment.generate_enrollment_status_hash(self.user), expected) self.assert_enrollment_status_hash_cached(self.user, expected) # One active enrollment enrollment.is_active = True enrollment.save() expected = '{username}&{course_id}={mode}'.format( username=self.user.username, course_id=str(course_id).lower(), mode=enrollment_mode.lower()) expected = hashlib.md5(expected.encode('utf-8')).hexdigest() self.assertEqual( CourseEnrollment.generate_enrollment_status_hash(self.user), expected) self.assert_enrollment_status_hash_cached(self.user, expected) # Multiple enrollments CourseEnrollmentFactory.create(user=self.user) enrollments = CourseEnrollment.enrollments_for_user( self.user).order_by(Lower('course_id')) hash_elements = [self.user.username] hash_elements += [ '{course_id}={mode}'.format( course_id=str(enrollment.course_id).lower(), mode=enrollment.mode.lower()) for enrollment in enrollments ] expected = hashlib.md5( '&'.join(hash_elements).encode('utf-8')).hexdigest() self.assertEqual( CourseEnrollment.generate_enrollment_status_hash(self.user), expected) self.assert_enrollment_status_hash_cached(self.user, expected)
def get_user_info_cookie_data(request): """ Returns information that wil populate the user info cookie. """ user = request.user # Set a cookie with user info. This can be used by external sites # to customize content based on user information. Currently, # we include information that's used to customize the "account" # links in the header of subdomain sites (such as the marketing site). header_urls = {'logout': reverse('logout')} # Unfortunately, this app is currently used by both the LMS and Studio login pages. # If we're in Studio, we won't be able to reverse the account/profile URLs. # To handle this, we don't add the URLs if we can't reverse them. # External sites will need to have fallback mechanisms to handle this case # (most likely just hiding the links). try: header_urls['account_settings'] = reverse('account_settings') header_urls['learner_profile'] = reverse('learner_profile', kwargs={'username': user.username}) except NoReverseMatch: pass # Convert relative URL paths to absolute URIs for url_name, url_path in six.iteritems(header_urls): header_urls[url_name] = request.build_absolute_uri(url_path) user_info = { 'version': settings.EDXMKTG_USER_INFO_COOKIE_VERSION, 'username': user.username, 'header_urls': header_urls, 'enrollmentStatusHash': CourseEnrollment.generate_enrollment_status_hash(user) } return user_info
def test_get_user_info_cookie_data(self): actual = cookies_api._get_user_info_cookie_data(self.request, self.user) # pylint: disable=protected-access expected = { 'version': settings.EDXMKTG_USER_INFO_COOKIE_VERSION, 'username': self.user.username, 'header_urls': self._get_expected_header_urls(), 'enrollmentStatusHash': CourseEnrollment.generate_enrollment_status_hash(self.user) } self.assertDictEqual(actual, expected)
def test_save_deletes_cached_enrollment_status_hash(self): """ Verify the method deletes the cached enrollment status hash for the user. """ # There should be no cached value for a new user with no enrollments. self.assertIsNone(cache.get(CourseEnrollment.enrollment_status_hash_cache_key(self.user))) # Generating a status hash should cache the generated value. status_hash = CourseEnrollment.generate_enrollment_status_hash(self.user) self.assert_enrollment_status_hash_cached(self.user, status_hash) # Modifying enrollments should delete the cached value. CourseEnrollmentFactory.create(user=self.user) self.assertIsNone(cache.get(CourseEnrollment.enrollment_status_hash_cache_key(self.user)))
def test_generate_enrollment_status_hash(self): """ Verify the method returns a hash of a user's current enrollments. """ # Return None for anonymous users self.assertIsNone(CourseEnrollment.generate_enrollment_status_hash(AnonymousUser())) # No enrollments expected = hashlib.md5(self.user.username).hexdigest() self.assertEqual(CourseEnrollment.generate_enrollment_status_hash(self.user), expected) self.assert_enrollment_status_hash_cached(self.user, expected) # No active enrollments enrollment_mode = 'verified' course_id = self.course.id # pylint: disable=no-member enrollment = CourseEnrollmentFactory.create(user=self.user, course_id=course_id, mode=enrollment_mode, is_active=False) self.assertEqual(CourseEnrollment.generate_enrollment_status_hash(self.user), expected) self.assert_enrollment_status_hash_cached(self.user, expected) # One active enrollment enrollment.is_active = True enrollment.save() expected = '{username}&{course_id}={mode}'.format( username=self.user.username, course_id=str(course_id).lower(), mode=enrollment_mode.lower() ) expected = hashlib.md5(expected).hexdigest() self.assertEqual(CourseEnrollment.generate_enrollment_status_hash(self.user), expected) self.assert_enrollment_status_hash_cached(self.user, expected) # Multiple enrollments CourseEnrollmentFactory.create(user=self.user) enrollments = CourseEnrollment.enrollments_for_user(self.user).order_by(Lower('course_id')) hash_elements = [self.user.username] hash_elements += [ '{course_id}={mode}'.format(course_id=str(enrollment.course_id).lower(), mode=enrollment.mode.lower()) for enrollment in enrollments] expected = hashlib.md5('&'.join(hash_elements)).hexdigest() self.assertEqual(CourseEnrollment.generate_enrollment_status_hash(self.user), expected) self.assert_enrollment_status_hash_cached(self.user, expected)
def test_get_user_info_cookie_data(self): request = RequestFactory().get('/') request.user = self.user actual = _get_user_info_cookie_data(request, self.user) expected = { 'version': settings.EDXMKTG_USER_INFO_COOKIE_VERSION, 'username': self.user.username, 'header_urls': self._get_expected_header_urls(request), 'enrollmentStatusHash': CourseEnrollment.generate_enrollment_status_hash(self.user) } self.assertDictEqual(actual, expected)
def test_get_user_info_cookie_data(self): request = RequestFactory().get('/') request.user = self.user actual = get_user_info_cookie_data(request) expected = { 'version': settings.EDXMKTG_USER_INFO_COOKIE_VERSION, 'username': self.user.username, 'header_urls': self._get_expected_header_urls(request), 'enrollmentStatusHash': CourseEnrollment.generate_enrollment_status_hash(self.user) } self.assertDictEqual(actual, expected)
def _get_user_info_cookie_data(request, user): """ Returns information that will populate the user info cookie. """ # Set a cookie with user info. This can be used by external sites # to customize content based on user information. Currently, # we include information that's used to customize the "account" # links in the header of subdomain sites (such as the marketing site). header_urls = {'logout': reverse('logout')} # Unfortunately, this app is currently used by both the LMS and Studio login pages. # If we're in Studio, we won't be able to reverse the account/profile URLs. # To handle this, we don't add the URLs if we can't reverse them. # External sites will need to have fallback mechanisms to handle this case # (most likely just hiding the links). try: header_urls['account_settings'] = reverse('account_settings') header_urls['learner_profile'] = reverse( 'learner_profile', kwargs={'username': user.username}) except NoReverseMatch: pass # Add 'resume course' last completed block try: header_urls['resume_block'] = retrieve_last_sitewide_block_completed( user) except User.DoesNotExist: pass # Convert relative URL paths to absolute URIs for url_name, url_path in six.iteritems(header_urls): header_urls[url_name] = request.build_absolute_uri(url_path) profile_image_url = get_profile_image_urls_for_user(user)['medium'] user_info = { 'version': settings.EDXMKTG_USER_INFO_COOKIE_VERSION, 'username': user.username, 'header_urls': header_urls, 'enrollmentStatusHash': CourseEnrollment.generate_enrollment_status_hash(user), 'profile_image_url': profile_image_url } return user_info