fix: Allow masquerading users to see content (#28458)
If a user with staff access is masquerading as a specific student, they should be able to see content that would normally be gated for that student.
This commit is contained in:
@@ -638,7 +638,7 @@ class SequenceBlock(
|
||||
|
||||
return None
|
||||
|
||||
def descendants_are_gated(self):
|
||||
def descendants_are_gated(self, context):
|
||||
"""
|
||||
Sequences do their own access gating logic as to whether their content
|
||||
should be viewable, based on things like pre-reqs and time exam starts.
|
||||
@@ -664,7 +664,7 @@ class SequenceBlock(
|
||||
comes to determining whether a student is allowed to access this,
|
||||
with other checks being done in has_access calls.
|
||||
"""
|
||||
if self.runtime.user_is_staff:
|
||||
if self.runtime.user_is_staff or context.get('specific_masquerade', False):
|
||||
return False
|
||||
|
||||
# We're not allowed to see it because of pre-reqs that haven't been
|
||||
|
||||
@@ -3134,6 +3134,47 @@ class TestRenderXBlock(RenderXBlockTestMixin, ModuleStoreTestCase, CompletionWaf
|
||||
# The Sequence itself 200s (or we risk infinite redirect loops).
|
||||
assert self.get_response(usage_key=self.sequence.location).status_code == 200
|
||||
|
||||
def test_rendering_descendant_of_gated_sequence_with_masquerade(self):
|
||||
"""
|
||||
Test that if we are masquerading as a specific student, we do not redirect if content is gated
|
||||
"""
|
||||
with self.store.default_store(ModuleStoreEnum.Type.split):
|
||||
# pylint:disable=attribute-defined-outside-init
|
||||
self.course = CourseFactory.create(**self.course_options())
|
||||
self.chapter = ItemFactory.create(parent=self.course, category='chapter')
|
||||
self.sequence = ItemFactory.create(
|
||||
parent=self.chapter,
|
||||
category='sequential',
|
||||
display_name='Sequence',
|
||||
is_time_limited=True,
|
||||
)
|
||||
self.vertical_block = ItemFactory.create(
|
||||
parent=self.sequence,
|
||||
category='vertical',
|
||||
display_name="Vertical",
|
||||
)
|
||||
self.html_block = ItemFactory.create(
|
||||
parent=self.vertical_block,
|
||||
category='html',
|
||||
data="<p>Test HTML Content<p>"
|
||||
)
|
||||
self.problem_block = ItemFactory.create(
|
||||
parent=self.vertical_block,
|
||||
category='problem',
|
||||
display_name='Problem'
|
||||
)
|
||||
CourseOverview.load_from_module_store(self.course.id)
|
||||
self.setup_user(admin=True, enroll=True, login=True)
|
||||
|
||||
student = UserFactory()
|
||||
CourseEnrollment.enroll(student, self.course.id)
|
||||
self.update_masquerade(role='student', username=student.username)
|
||||
|
||||
# Problem and Vertical response should both render successfully
|
||||
for block in [self.problem_block, self.vertical_block]:
|
||||
response = self.get_response(usage_key=block.location)
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
class TestRenderXBlockSelfPaced(TestRenderXBlock): # lint-amnesty, pylint: disable=test-inherits-tests
|
||||
"""
|
||||
|
||||
@@ -77,7 +77,7 @@ from lms.djangoapps.courseware.courses import (
|
||||
)
|
||||
from lms.djangoapps.courseware.date_summary import verified_upgrade_deadline_link
|
||||
from lms.djangoapps.courseware.exceptions import CourseAccessRedirect, Redirect
|
||||
from lms.djangoapps.courseware.masquerade import setup_masquerade
|
||||
from lms.djangoapps.courseware.masquerade import setup_masquerade, is_masquerading_as_specific_student
|
||||
from lms.djangoapps.courseware.model_data import FieldDataCache
|
||||
from lms.djangoapps.courseware.models import BaseStudentModuleHistory, StudentModule
|
||||
from lms.djangoapps.courseware.permissions import ( # lint-amnesty, pylint: disable=unused-import
|
||||
@@ -1763,9 +1763,10 @@ def render_xblock(request, usage_key_string, check_if_enrolled=True):
|
||||
# timed exam started?").
|
||||
ancestor_sequence_block = enclosing_sequence_for_gating_checks(block)
|
||||
if ancestor_sequence_block:
|
||||
context = {'specific_masquerade': is_masquerading_as_specific_student(request.user, course_key)}
|
||||
# If the SequenceModule feels that gating is necessary, redirect
|
||||
# there so we can have some kind of error message at any rate.
|
||||
if ancestor_sequence_block.descendants_are_gated():
|
||||
if ancestor_sequence_block.descendants_are_gated(context):
|
||||
return redirect(
|
||||
reverse(
|
||||
'render_xblock',
|
||||
|
||||
Reference in New Issue
Block a user