Commit 7dbb4c05 by Clinton Blackburn

Corrected Cache Key Encoding Issues

- Using Unicode when formatting strings that might have Unicode values
- Properly encoding cache keys before hashing to MD5
parent cc27a6b1
...@@ -18,4 +18,4 @@ def sanitize_cache_key(key): ...@@ -18,4 +18,4 @@ def sanitize_cache_key(key):
""" """
Returns a memcached-safe (no spaces or control characters) key. Returns a memcached-safe (no spaces or control characters) key.
""" """
return md5(key).hexdigest() return md5(key.encode("utf-8")).hexdigest()
...@@ -165,7 +165,7 @@ class CoursePerformancePresenter(BasePresenter): ...@@ -165,7 +165,7 @@ class CoursePerformancePresenter(BasePresenter):
return answer_distributions return answer_distributions
def get_cache_key(self, name): def get_cache_key(self, name):
return sanitize_cache_key('{}_{}'.format(self.course_id, name)) return sanitize_cache_key(u'{}_{}'.format(self.course_id, name))
@property @property
def last_updated(self): def last_updated(self):
...@@ -298,11 +298,11 @@ class CoursePerformancePresenter(BasePresenter): ...@@ -298,11 +298,11 @@ class CoursePerformancePresenter(BasePresenter):
def assignments(self, assignment_type=None): def assignments(self, assignment_type=None):
""" Returns the assignments (and problems) for the represented course. """ """ Returns the assignments (and problems) for the represented course. """
assignment_type_key = self.get_cache_key('assignments_{}'.format(assignment_type)) assignment_type_key = self.get_cache_key(u'assignments_{}'.format(assignment_type))
assignments = cache.get(assignment_type_key) assignments = cache.get(assignment_type_key)
if not assignments: if not assignments:
all_assignments_key = '{}_assignments'.format(self.course_id) all_assignments_key = self.get_cache_key(u'assignments')
assignments = cache.get(all_assignments_key) assignments = cache.get(all_assignments_key)
if not assignments: if not assignments:
......
...@@ -56,7 +56,7 @@ class CourseAPIMixin(object): ...@@ -56,7 +56,7 @@ class CourseAPIMixin(object):
return super(CourseAPIMixin, self).dispatch(request, *args, **kwargs) return super(CourseAPIMixin, self).dispatch(request, *args, **kwargs)
def _course_detail_cache_key(self, course_id): def _course_detail_cache_key(self, course_id):
return sanitize_cache_key('course_{}_details'.format(course_id)) return sanitize_cache_key(u'course_{}_details'.format(course_id))
def get_course_info(self, course_id): def get_course_info(self, course_id):
""" """
...@@ -83,7 +83,7 @@ class CourseAPIMixin(object): ...@@ -83,7 +83,7 @@ class CourseAPIMixin(object):
def get_courses(self): def get_courses(self):
# Check the cache for the user's courses # Check the cache for the user's courses
key = sanitize_cache_key('user_{}_courses'.format(self.request.user.pk)) key = sanitize_cache_key(u'user_{}_courses'.format(self.request.user.pk))
courses = cache.get(key) courses = cache.get(key)
# If no cached courses, iterate over the data from the course API. # If no cached courses, iterate over the data from the course API.
......
...@@ -20,7 +20,7 @@ class CSVResponseMixin(object): ...@@ -20,7 +20,7 @@ class CSVResponseMixin(object):
# pylint: disable=unused-argument # pylint: disable=unused-argument
def render_to_response(self, context, **response_kwargs): def render_to_response(self, context, **response_kwargs):
response = HttpResponse(self.get_data(), content_type='text/csv', **response_kwargs) response = HttpResponse(self.get_data(), content_type='text/csv', **response_kwargs)
response['Content-Disposition'] = 'attachment; filename="{0}"'.format(self._get_filename()) response['Content-Disposition'] = u'attachment; filename="{0}"'.format(self._get_filename())
return response return response
def get_data(self): def get_data(self):
...@@ -29,7 +29,7 @@ class CSVResponseMixin(object): ...@@ -29,7 +29,7 @@ class CSVResponseMixin(object):
def _get_filename(self): def _get_filename(self):
course_key = self.course_key course_key = self.course_key
course_id = '-'.join([course_key.org, course_key.course, course_key.run]) course_id = '-'.join([course_key.org, course_key.course, course_key.run])
filename = '{0}--{1}.csv'.format(course_id, self.csv_filename_suffix) filename = u'{0}--{1}.csv'.format(course_id, self.csv_filename_suffix)
return urllib.quote(filename) return urllib.quote(filename)
......
...@@ -106,8 +106,8 @@ class PerformanceAnswerDistributionView(PerformanceTemplateView): ...@@ -106,8 +106,8 @@ class PerformanceAnswerDistributionView(PerformanceTemplateView):
view_live_url = None view_live_url = None
if settings.LMS_COURSE_SHORTCUT_BASE_URL: if settings.LMS_COURSE_SHORTCUT_BASE_URL:
view_live_url = '{0}/{1}/jump_to/{2}'.format(settings.LMS_COURSE_SHORTCUT_BASE_URL, self.course_id, view_live_url = u'{0}/{1}/jump_to/{2}'.format(settings.LMS_COURSE_SHORTCUT_BASE_URL, self.course_id,
problem_id) problem_id)
answer_distribution_entry = presenter.get_answer_distribution(problem_id, part_id) answer_distribution_entry = presenter.get_answer_distribution(problem_id, part_id)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment