AA-4: Extreme defensiveness over any fields accessed from modulestore

This commit is contained in:
Dillon Dumesnil
2020-02-11 11:07:47 -05:00
parent fe91d63a0b
commit 5853cddfc1
6 changed files with 61 additions and 13 deletions

View File

@@ -3,7 +3,7 @@
from django.test import TestCase
from django.urls import reverse
from six import unichr # pylint: disable=W0622
from six import unichr
from contentstore.views.helpers import event as cms_user_track
@@ -20,7 +20,7 @@ class CMSLogTest(TestCase):
"""
requests = [
{"event": "my_event", "event_type": "my_event_type", "page": "my_page"},
{"event": "{'json': 'object'}", "event_type": unichr(512), "page": "my_page"} # pylint: disable=unicode-format-string
{"event": "{'json': 'object'}", "event_type": unichr(512), "page": "my_page"}
]
for request_params in requests:
response = self.client.post(reverse(cms_user_track), request_params)

View File

@@ -15,6 +15,7 @@ from django.conf import settings
from django.db.models import Prefetch
from django.http import Http404, QueryDict
from django.urls import reverse
from django.utils.translation import ugettext as _
from edx_django_utils.monitoring import function_trace
from edx_when.api import get_dates_for_course
from fs.errors import ResourceNotFound
@@ -442,11 +443,12 @@ def get_course_assignment_due_dates(course, user, request, num_return=None, incl
block_url = None
now = datetime.now().replace(tzinfo=pytz.UTC)
assignment_released = item.start < now
assignment_released = item.start < now if item.start else None
if assignment_released:
block_url = reverse('jump_to', args=[course.id, block_key])
block_url = request.build_absolute_uri(block_url) if request else None
date_block.set_title(item.display_name, block_url)
assignment_title = item.display_name if item.display_name else _('Assignment')
date_block.set_title(assignment_title, block_url)
date_blocks.append(date_block)
date_blocks = sorted((b for b in date_blocks if b.is_enabled or include_past_dates), key=date_block_key_fn)

View File

@@ -62,6 +62,11 @@ class DateSummary(object):
"""The title of this summary."""
return ''
@property
def title_html(self):
"""The title as html for this summary."""
return ''
@property
def description(self):
"""The detail text displayed by this summary."""
@@ -340,6 +345,7 @@ class CourseAssignmentDate(DateSummary):
super().__init__(*args, **kwargs)
self.assignment_date = None
self.assignment_title = None
self.assignment_title_html = None
@property
def date(self):
@@ -353,13 +359,17 @@ class CourseAssignmentDate(DateSummary):
def title(self):
return self.assignment_title
@property
def title_html(self):
return self.assignment_title_html
def set_title(self, title, link=None):
""" Used to set the title_html and title properties for the assignment date block """
if link:
self.assignment_title = HTML(
self.assignment_title_html = HTML(
'<a href="{assignment_link}">{assignment_title}</a>'
).format(assignment_link=link, assignment_title=title)
else:
self.assignment_title = title
self.assignment_title = title
class CourseExpiredDate(DateSummary):

View File

@@ -132,7 +132,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase):
CourseEnrollmentFactory(course_id=course.id, user=user, mode=CourseMode.VERIFIED)
self.assert_block_types(course, user, expected_blocks)
def test_enabled_block_types_with_assignments(self):
def test_enabled_block_types_with_assignments(self): # pylint: disable=too-many-statements
"""
Creates a course with multiple subsections to test all of the different
cases for assignment dates showing up. Mocks out calling the edx-when
@@ -187,6 +187,24 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase):
due=now - timedelta(days=7),
graded=False,
)
subsection_6 = ItemFactory.create(
category='sequential',
display_name='No start date',
parent_location=section.location,
start=None,
due=now + timedelta(days=9),
graded=True,
)
subsection_7 = ItemFactory.create(
category='sequential',
# Setting display name to None should set the assignment title to 'Assignment'
display_name=None,
parent_location=section.location,
start=now - timedelta(days=14),
due=now + timedelta(days=10),
graded=True,
)
dummy_subsection = ItemFactory.create(category='sequential')
with patch('lms.djangoapps.courseware.courses.get_dates_for_course') as mock_get_dates:
mock_get_dates.return_value = {
@@ -200,6 +218,12 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase):
(subsection_4.location, 'start'): subsection_4.start,
(subsection_5.location, 'due'): subsection_5.due,
(subsection_5.location, 'start'): subsection_5.start,
(subsection_6.location, 'due'): subsection_6.due,
(subsection_7.location, 'due'): subsection_7.due,
(subsection_7.location, 'start'): subsection_7.start,
# Adding this in for the case where we return a block that
# doesn't actually exist as part of the course. Should just be ignored.
(dummy_subsection.location, 'due'): dummy_subsection.due,
}
# Standard widget case where we restrict the number of assignments.
expected_blocks = (
@@ -210,7 +234,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase):
self.assertEqual(set(type(b) for b in blocks), set(expected_blocks))
assignment_blocks = filter(lambda b: isinstance(b, CourseAssignmentDate), blocks)
for assignment in assignment_blocks:
assignment_title = str(assignment.title)
assignment_title = str(assignment.title_html) or str(assignment.title)
self.assertNotEqual(assignment_title, 'Third nearest assignment')
self.assertNotEqual(assignment_title, 'Past due date')
self.assertNotEqual(assignment_title, 'Not returned since we do not get non-graded subsections')
@@ -226,14 +250,15 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase):
# No restrictions on number of assignments to return
expected_blocks = (
CourseStartDate, TodaysDate, CourseAssignmentDate, CourseAssignmentDate, CourseAssignmentDate,
CourseAssignmentDate, CourseEndDate, VerificationDeadlineDate
CourseAssignmentDate, CourseAssignmentDate, CourseAssignmentDate, CourseEndDate,
VerificationDeadlineDate
)
blocks = get_course_date_blocks(course, user, request, include_past_dates=True)
self.assertEqual(len(blocks), len(expected_blocks))
self.assertEqual(set(type(b) for b in blocks), set(expected_blocks))
assignment_blocks = filter(lambda b: isinstance(b, CourseAssignmentDate), blocks)
for assignment in assignment_blocks:
assignment_title = str(assignment.title)
assignment_title = str(assignment.title_html) or str(assignment.title)
self.assertNotEqual(assignment_title, 'Not returned since we do not get non-graded subsections')
# checking if it is _in_ the title instead of being the title since released assignments
# are actually links. Unreleased assignments are just the string of the title.
@@ -251,6 +276,15 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase):
self.assertGreater(now, assignment.date)
for html_tag in assignment_title_html:
self.assertIn(html_tag, assignment_title)
elif 'No start date' == assignment_title:
# Can't determine if it is released so it does not get a link
for html_tag in assignment_title_html:
self.assertNotIn(html_tag, assignment_title)
# This is the item with no display name where we set one ourselves.
elif 'Assignment' in assignment_title:
# Can't determine if it is released so it does not get a link
for html_tag in assignment_title_html:
self.assertIn(html_tag, assignment_title)
def test_enabled_block_types_with_expired_course(self):
course = create_course_run(days_till_start=-100)

View File

@@ -10,7 +10,9 @@ from django.utils.translation import ugettext as _
% if course_date.date:
<p class="hd hd-6 date localized-datetime" data-format="shortDate" data-datetime="${course_date.date}" data-timezone="${user_timezone}" data-language="${user_language}"></p>
% endif
% if course_date.title:
% if course_date.title_html:
<div class="hd hd-6 heading">${course_date.title_html}</div>
% elif course_date.title:
<div class="hd hd-6 heading">${course_date.title}</div>
% endif
% if course_date.description:

View File

@@ -2,6 +2,6 @@
set -e
export LOWER_PYLINT_THRESHOLD=1000
export UPPER_PYLINT_THRESHOLD=2005
export UPPER_PYLINT_THRESHOLD=1993
export ESLINT_THRESHOLD=5530
export STYLELINT_THRESHOLD=880