Merge pull request #25987 from edx/ormsbee/tnl-7636-xblock-access

Check sequence-level gating in render_xblock (TNL-7636)
This commit is contained in:
David Ormsbee
2021-01-13 09:35:56 -05:00
committed by GitHub
5 changed files with 170 additions and 1 deletions

View File

@@ -560,6 +560,50 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule):
return None
def descendants_are_gated(self):
"""
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.
Ideally, this information would be passed down to all descendants so
that they would know if it's safe to render themselves, but the least
invasive patch to this is to make a method that rendering Django views
can use to verify before rendering descendants.
This does _NOT_ check for the content types of children because the
performing that traversal undoes a lot of the performance gains made in
large sequences when hitting the render_xblock endpoint directly. This
method is here mostly to help render_xblock figure out if it's okay to
render a descendant of a sequence to guard against malicious actors. So
the "let's check all descendants to not let people start an exam they
can't finish" reasoning of doing the full traversal does not apply.
Returns:
True if this sequence and its descendants are gated by what are
currently sequence-level checks.
False if the sequence is and its decendants are not gated.
Note that this gating logic is only a part of the equation when it
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:
return False
# We're not allowed to see it because of pre-reqs that haven't been
# fullfilled.
if self._required_prereq():
prereq_met, _prereq_meta_info = self._compute_is_prereq_met(True)
if not prereq_met:
return True
# Are we a time limited test that hasn't started yet?
if self.is_time_limited:
if self._time_limited_student_view() or self._hidden_content_student_view({}):
return True
# Otherwise, nothing is blocking us.
return False
def _compute_is_prereq_met(self, recalc_on_unmet):
"""
Evaluate if the user has completed the prerequisite