Merge pull request #6189 from edx/andya/fix-masquerade
Fix Mako templates to always use updated request context
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distribuetd under the License is distributed on an "AS IS" BASIS,
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
@@ -22,10 +22,24 @@ REQUEST_CONTEXT = threading.local()
|
||||
class MakoMiddleware(object):
|
||||
|
||||
def process_request(self, request):
|
||||
REQUEST_CONTEXT.context = RequestContext(request)
|
||||
REQUEST_CONTEXT.context['is_secure'] = request.is_secure()
|
||||
REQUEST_CONTEXT.context['site'] = safe_get_host(request)
|
||||
""" Process the middleware request. """
|
||||
REQUEST_CONTEXT.request = request
|
||||
|
||||
def process_response(self, request, response):
|
||||
REQUEST_CONTEXT.context = None
|
||||
def process_response(self, __, response):
|
||||
""" Process the middleware response. """
|
||||
REQUEST_CONTEXT.request = None
|
||||
return response
|
||||
|
||||
|
||||
def get_template_request_context():
|
||||
"""
|
||||
Returns the template processing context to use for the current request,
|
||||
or returns None if there is not a current request.
|
||||
"""
|
||||
request = getattr(REQUEST_CONTEXT, "request", None)
|
||||
if not request:
|
||||
return None
|
||||
context = RequestContext(request)
|
||||
context['is_secure'] = request.is_secure()
|
||||
context['site'] = safe_get_host(request)
|
||||
return context
|
||||
|
||||
@@ -19,7 +19,7 @@ import logging
|
||||
from microsite_configuration import microsite
|
||||
|
||||
from edxmako import lookup_template
|
||||
import edxmako.middleware
|
||||
from edxmako.middleware import get_template_request_context
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -114,11 +114,12 @@ def render_to_string(template_name, dictionary, context=None, namespace='main'):
|
||||
context_instance['marketing_link'] = marketing_link
|
||||
|
||||
# In various testing contexts, there might not be a current request context.
|
||||
if getattr(edxmako.middleware.REQUEST_CONTEXT, "context", None):
|
||||
for d in edxmako.middleware.REQUEST_CONTEXT.context:
|
||||
context_dictionary.update(d)
|
||||
for d in context_instance:
|
||||
context_dictionary.update(d)
|
||||
request_context = get_template_request_context()
|
||||
if request_context:
|
||||
for item in request_context:
|
||||
context_dictionary.update(item)
|
||||
for item in context_instance:
|
||||
context_dictionary.update(item)
|
||||
if context:
|
||||
context_dictionary.update(context)
|
||||
# fetch and render template
|
||||
|
||||
@@ -12,12 +12,12 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from django.conf import settings
|
||||
from mako.template import Template as MakoTemplate
|
||||
from edxmako.shortcuts import marketing_link
|
||||
|
||||
import edxmako
|
||||
import edxmako.middleware
|
||||
|
||||
from django.conf import settings
|
||||
from edxmako.middleware import get_template_request_context
|
||||
from edxmako.shortcuts import marketing_link
|
||||
from mako.template import Template as MakoTemplate
|
||||
|
||||
DJANGO_VARIABLES = ['output_encoding', 'encoding_errors']
|
||||
|
||||
@@ -48,11 +48,12 @@ class Template(MakoTemplate):
|
||||
context_dictionary = {}
|
||||
|
||||
# In various testing contexts, there might not be a current request context.
|
||||
if getattr(edxmako.middleware.REQUEST_CONTEXT, "context", None):
|
||||
for d in edxmako.middleware.REQUEST_CONTEXT.context:
|
||||
context_dictionary.update(d)
|
||||
for d in context_instance:
|
||||
context_dictionary.update(d)
|
||||
request_context = get_template_request_context()
|
||||
if request_context:
|
||||
for item in request_context:
|
||||
context_dictionary.update(item)
|
||||
for item in context_instance:
|
||||
context_dictionary.update(item)
|
||||
context_dictionary['settings'] = settings
|
||||
context_dictionary['EDX_ROOT_URL'] = settings.EDX_ROOT_URL
|
||||
context_dictionary['django_context'] = context_instance
|
||||
|
||||
@@ -10,6 +10,7 @@ from django.test.utils import override_settings
|
||||
from django.test.client import RequestFactory
|
||||
from django.core.urlresolvers import reverse
|
||||
import edxmako.middleware
|
||||
from edxmako.middleware import get_template_request_context
|
||||
from edxmako import add_lookup, LOOKUP
|
||||
from edxmako.shortcuts import (
|
||||
marketing_link,
|
||||
@@ -83,11 +84,11 @@ class MakoMiddlewareTest(TestCase):
|
||||
|
||||
self.middleware.process_request(self.request)
|
||||
# requestcontext should not be None.
|
||||
self.assertIsNotNone(edxmako.middleware.REQUEST_CONTEXT.context)
|
||||
self.assertIsNotNone(get_template_request_context())
|
||||
|
||||
self.middleware.process_response(self.request, self.response)
|
||||
# requestcontext should be None.
|
||||
self.assertIsNone(edxmako.middleware.REQUEST_CONTEXT.context)
|
||||
self.assertIsNone(get_template_request_context())
|
||||
|
||||
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
|
||||
@patch("edxmako.middleware.REQUEST_CONTEXT")
|
||||
|
||||
@@ -4,6 +4,7 @@ Base class for pages in courseware.
|
||||
|
||||
from bok_choy.page_object import PageObject
|
||||
from . import BASE_URL
|
||||
from .tab_nav import TabNavPage
|
||||
|
||||
|
||||
class CoursePage(PageObject):
|
||||
@@ -29,3 +30,11 @@ class CoursePage(PageObject):
|
||||
Construct a URL to the page within the course.
|
||||
"""
|
||||
return BASE_URL + "/courses/" + self.course_id + "/" + self.url_path
|
||||
|
||||
def has_tab(self, tab_name):
|
||||
"""
|
||||
Returns true if the current page is showing a tab with the given name.
|
||||
:return:
|
||||
"""
|
||||
tab_nav = TabNavPage(self.browser)
|
||||
return tab_name in tab_nav.tab_names
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
Staff view of courseware
|
||||
"""
|
||||
from bok_choy.page_object import PageObject
|
||||
from .courseware import CoursewarePage
|
||||
|
||||
|
||||
class StaffPage(PageObject):
|
||||
class StaffPage(CoursewarePage):
|
||||
"""
|
||||
View of courseware pages while logged in as course staff
|
||||
"""
|
||||
@@ -13,6 +14,8 @@ class StaffPage(PageObject):
|
||||
STAFF_STATUS_CSS = '#staffstatus'
|
||||
|
||||
def is_browser_on_page(self):
|
||||
if not super(StaffPage, self).is_browser_on_page():
|
||||
return False
|
||||
return self.q(css=self.STAFF_STATUS_CSS).present
|
||||
|
||||
@property
|
||||
|
||||
@@ -48,7 +48,7 @@ class TabNavPage(PageObject):
|
||||
Return the CSS to click for `tab_name`.
|
||||
If no tabs exist for that name, return `None`.
|
||||
"""
|
||||
all_tabs = self._tab_names
|
||||
all_tabs = self.tab_names
|
||||
|
||||
try:
|
||||
tab_index = all_tabs.index(tab_name)
|
||||
@@ -58,7 +58,7 @@ class TabNavPage(PageObject):
|
||||
return 'ol.course-tabs li:nth-of-type({0}) a'.format(tab_index + 1)
|
||||
|
||||
@property
|
||||
def _tab_names(self):
|
||||
def tab_names(self):
|
||||
"""
|
||||
Return the list of available tab names. If no tab names
|
||||
are available, wait for them to load. Raises a `BrokenPromiseError`
|
||||
|
||||
@@ -11,15 +11,15 @@ from ...fixtures.course import CourseFixture, XBlockFixtureDesc
|
||||
from textwrap import dedent
|
||||
|
||||
|
||||
class StaffDebugTest(UniqueCourseTest):
|
||||
class StaffViewTest(UniqueCourseTest):
|
||||
"""
|
||||
Tests that verify the staff debug info.
|
||||
Tests that verify the staff view.
|
||||
"""
|
||||
USERNAME = "STAFF_TESTER"
|
||||
EMAIL = "johndoe@example.com"
|
||||
|
||||
def setUp(self):
|
||||
super(StaffDebugTest, self).setUp()
|
||||
super(StaffViewTest, self).setUp()
|
||||
|
||||
self.courseware_page = CoursewarePage(self.browser, self.course_id)
|
||||
|
||||
@@ -59,10 +59,31 @@ class StaffDebugTest(UniqueCourseTest):
|
||||
Open staff page with assertion
|
||||
"""
|
||||
self.courseware_page.visit()
|
||||
staff_page = StaffPage(self.browser)
|
||||
staff_page = StaffPage(self.browser, self.course_id)
|
||||
self.assertEqual(staff_page.staff_status, 'Staff view')
|
||||
return staff_page
|
||||
|
||||
|
||||
class StaffViewToggleTest(StaffViewTest):
|
||||
"""
|
||||
Tests for the staff view toggle button.
|
||||
"""
|
||||
def test_instructor_tab_visibility(self):
|
||||
"""
|
||||
Test that the instructor tab is hidden when viewing as a student.
|
||||
"""
|
||||
|
||||
course_page = self._goto_staff_page()
|
||||
self.assertTrue(course_page.has_tab('Instructor'))
|
||||
course_page.toggle_staff_view()
|
||||
self.assertEqual(course_page.staff_status, 'Student view')
|
||||
self.assertFalse(course_page.has_tab('Instructor'))
|
||||
|
||||
|
||||
class StaffDebugTest(StaffViewTest):
|
||||
"""
|
||||
Tests that verify the staff debug info.
|
||||
"""
|
||||
def test_reset_attempts_empty(self):
|
||||
"""
|
||||
Test that we reset even when there is no student state
|
||||
|
||||
@@ -678,7 +678,7 @@ class UnitPublishingTest(ContainerBase):
|
||||
"""
|
||||
Verifies that the browser is on the staff page and returns a StaffPage.
|
||||
"""
|
||||
page = StaffPage(self.browser)
|
||||
page = StaffPage(self.browser, self.course_id)
|
||||
EmptyPromise(page.is_browser_on_page, 'Browser is on staff page in LMS').fulfill()
|
||||
return page
|
||||
|
||||
|
||||
@@ -718,7 +718,7 @@ class StaffLockTest(CourseOutlineTest):
|
||||
courseware = CoursewarePage(self.browser, self.course_id)
|
||||
courseware.wait_for_page()
|
||||
self.assertEqual(courseware.num_sections, 2)
|
||||
StaffPage(self.browser).toggle_staff_view()
|
||||
StaffPage(self.browser, self.course_id).toggle_staff_view()
|
||||
self.assertEqual(courseware.num_sections, 1)
|
||||
|
||||
def test_locked_subsections_do_not_appear_in_lms(self):
|
||||
@@ -737,7 +737,7 @@ class StaffLockTest(CourseOutlineTest):
|
||||
courseware = CoursewarePage(self.browser, self.course_id)
|
||||
courseware.wait_for_page()
|
||||
self.assertEqual(courseware.num_subsections, 2)
|
||||
StaffPage(self.browser).toggle_staff_view()
|
||||
StaffPage(self.browser, self.course_id).toggle_staff_view()
|
||||
self.assertEqual(courseware.num_subsections, 1)
|
||||
|
||||
def test_toggling_staff_lock_on_section_does_not_publish_draft_units(self):
|
||||
|
||||
@@ -92,7 +92,7 @@ def make_track_function(request):
|
||||
return function
|
||||
|
||||
|
||||
def toc_for_course(user, request, course, active_chapter, active_section, field_data_cache):
|
||||
def toc_for_course(request, course, active_chapter, active_section, field_data_cache):
|
||||
'''
|
||||
Create a table of contents from the module store
|
||||
|
||||
@@ -117,7 +117,7 @@ def toc_for_course(user, request, course, active_chapter, active_section, field_
|
||||
'''
|
||||
|
||||
with modulestore().bulk_operations(course.id):
|
||||
course_module = get_module_for_descriptor(user, request, course, field_data_cache, course.id)
|
||||
course_module = get_module_for_descriptor(request.user, request, course, field_data_cache, course.id)
|
||||
if course_module is None:
|
||||
return None
|
||||
|
||||
|
||||
@@ -394,7 +394,7 @@ class TestTOC(ModuleStoreTestCase):
|
||||
|
||||
with check_mongo_calls(toc_finds):
|
||||
actual = render.toc_for_course(
|
||||
self.request.user, self.request, self.toy_course, self.chapter, None, self.field_data_cache
|
||||
self.request, self.toy_course, self.chapter, None, self.field_data_cache
|
||||
)
|
||||
for toc_section in expected:
|
||||
self.assertIn(toc_section, actual)
|
||||
@@ -432,7 +432,9 @@ class TestTOC(ModuleStoreTestCase):
|
||||
'url_name': 'secret:magic', 'display_name': 'secret:magic'}])
|
||||
|
||||
with check_mongo_calls(toc_finds):
|
||||
actual = render.toc_for_course(self.request.user, self.request, self.toy_course, self.chapter, section, self.field_data_cache)
|
||||
actual = render.toc_for_course(
|
||||
self.request, self.toy_course, self.chapter, section, self.field_data_cache
|
||||
)
|
||||
for toc_section in expected:
|
||||
self.assertIn(toc_section, actual)
|
||||
|
||||
|
||||
@@ -555,7 +555,8 @@ class TestAccordionDueDate(BaseDueDateTests):
|
||||
def get_text(self, course):
|
||||
""" Returns the HTML for the accordion """
|
||||
return views.render_accordion(
|
||||
self.request, course, course.get_children()[0].scope_ids.usage_id.to_deprecated_string(), None, None
|
||||
self.request, course, course.get_children()[0].scope_ids.usage_id.to_deprecated_string(),
|
||||
None, None
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -118,9 +118,7 @@ def render_accordion(request, course, chapter, section, field_data_cache):
|
||||
Returns the html string
|
||||
"""
|
||||
# grab the table of contents
|
||||
user = User.objects.prefetch_related("groups").get(id=request.user.id)
|
||||
request.user = user # keep just one instance of User
|
||||
toc = toc_for_course(user, request, course, chapter, section, field_data_cache)
|
||||
toc = toc_for_course(request, course, chapter, section, field_data_cache)
|
||||
|
||||
context = dict([
|
||||
('toc', toc),
|
||||
@@ -325,10 +323,15 @@ def index(request, course_id, chapter=None, section=None,
|
||||
|
||||
request.user = user # keep just one instance of User
|
||||
with modulestore().bulk_operations(course_key):
|
||||
return _index_bulk_op(request, user, course_key, chapter, section, position)
|
||||
return _index_bulk_op(request, course_key, chapter, section, position)
|
||||
|
||||
|
||||
def _index_bulk_op(request, user, course_key, chapter, section, position):
|
||||
# pylint: disable=too-many-statements
|
||||
def _index_bulk_op(request, course_key, chapter, section, position):
|
||||
"""
|
||||
Render the index page for the specified course.
|
||||
"""
|
||||
user = request.user
|
||||
course = get_course_with_access(user, 'load', course_key, depth=2)
|
||||
|
||||
staff_access = has_access(user, 'staff', course)
|
||||
|
||||
Reference in New Issue
Block a user