Skip to content

Commit

Permalink
fix: bypass access checks when populating course blocks cache
Browse files Browse the repository at this point in the history
  • Loading branch information
asadali145 committed Oct 16, 2024
1 parent e28a01e commit b7cd161
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 4 deletions.
1 change: 1 addition & 0 deletions lms/djangoapps/course_blocks/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,5 @@ def get_course_blocks(
transformers,
starting_block_usage_key,
collected_block_structure,
user,
)
23 changes: 19 additions & 4 deletions openedx/core/djangoapps/content/block_structure/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def __init__(self, root_block_usage_key, modulestore, cache):
self.modulestore = modulestore
self.store = BlockStructureStore(cache)

def get_transformed(self, transformers, starting_block_usage_key=None, collected_block_structure=None):
def get_transformed(self, transformers, starting_block_usage_key=None, collected_block_structure=None, user=None):
"""
Returns the transformed Block Structure for the root_block_usage_key,
starting at starting_block_usage_key, getting block data from the cache
Expand All @@ -57,11 +57,14 @@ def get_transformed(self, transformers, starting_block_usage_key=None, collected
get_collected. Can be optionally provided if already available,
for optimization.
user (django.contrib.auth.models.User) - User object for
which the block structure is to be transformed.
Returns:
BlockStructureBlockData - A transformed block structure,
starting at starting_block_usage_key.
"""
block_structure = collected_block_structure.copy() if collected_block_structure else self.get_collected()
block_structure = collected_block_structure.copy() if collected_block_structure else self.get_collected(user)

if starting_block_usage_key:
# Override the root_block_usage_key so traversals start at the
Expand All @@ -77,7 +80,7 @@ def get_transformed(self, transformers, starting_block_usage_key=None, collected
transformers.transform(block_structure)
return block_structure

def get_collected(self):
def get_collected(self, user=None):
"""
Returns the collected Block Structure for the root_block_usage_key,
getting block data from the cache and modulestore, as needed.
Expand All @@ -86,6 +89,10 @@ def get_collected(self):
the modulestore is accessed if needed (at cache miss), and the
transformers data is collected if needed.
In the case of a cache miss, the function bypasses runtime access checks for the current
user. This is done to prevent inconsistencies in the data, which can occur when
certain blocks are inaccessible due to access restrictions.
Returns:
BlockStructureBlockData - A collected block structure,
starting at root_block_usage_key, with collected data
Expand All @@ -99,7 +106,15 @@ def get_collected(self):
BlockStructureTransformers.verify_versions(block_structure)

except (BlockStructureNotFound, TransformerDataIncompatible):
block_structure = self._update_collected()
if user:
# This bypasses the runtime access checks. When we are populating the course blocks cache,
# we do not want to perform access checks. Access checks result in inconsistent blocks where
# inaccessible blocks are missing from the cache. Cached course blocks are then used for all the users.
user.known = False
block_structure = self._update_collected()
user.known = True
else:
block_structure = self._update_collected()

return block_structure

Expand Down

0 comments on commit b7cd161

Please sign in to comment.