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:
alangsto
2021-08-24 09:14:01 -04:00
committed by GitHub
parent de0f42c93e
commit 6fa89e610a
3 changed files with 46 additions and 4 deletions

View File

@@ -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

View File

@@ -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
"""

View File

@@ -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',