fix: render library v2 assets with whitespace (#35974)

Assets that contain whitespace fail to be rendered when uploaded to library v2
This commit is contained in:
Daniel Valenzuela
2024-12-24 10:51:03 -03:00
committed by GitHub
parent 81f825ff15
commit 85f412864f
3 changed files with 24 additions and 4 deletions

View File

@@ -63,6 +63,13 @@ class ContentLibrariesStaticAssetsTest(ContentLibrariesRestApiTest):
file_name = "a////////b"
self._set_library_block_asset(block_id, file_name, SVG_DATA, expect_response=400)
# Names with spaces are allowed but replaced with underscores
file_name_with_space = "o w o.svg"
self._set_library_block_asset(block_id, file_name_with_space, SVG_DATA)
file_name = "o_w_o.svg"
assert self._get_library_block_asset(block_id, file_name)['path'] == file_name
assert self._get_library_block_asset(block_id, file_name)['size'] == file_size
def test_video_transcripts(self):
"""
Test that video blocks can read transcript files out of learning core.

View File

@@ -799,6 +799,7 @@ class LibraryBlockAssetView(APIView):
"""
Replace a static asset file belonging to this block.
"""
file_path = file_path.replace(" ", "_") # Messes up url/name correspondence due to URL encoding.
usage_key = LibraryUsageLocatorV2.from_string(usage_key_str)
api.require_permission_for_library_key(
usage_key.lib_key, request.user, permissions.CAN_EDIT_THIS_CONTENT_LIBRARY,

View File

@@ -6,6 +6,7 @@ from __future__ import annotations
import logging
from collections import defaultdict
from datetime import datetime, timezone
from urllib.parse import unquote
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.db.transaction import atomic
@@ -446,9 +447,20 @@ class LearningCoreXBlockRuntime(XBlockRuntime):
.get(key=f"static/{asset_path}")
)
except ObjectDoesNotExist:
# This means we see a path that _looks_ like it should be a static
# asset for this Component, but that static asset doesn't really
# exist.
return None
try:
# Retry with unquoted path. We don't always unquote because it would not
# be backwards-compatible, but we need to try both.
asset_path = unquote(asset_path)
content = (
component_version
.componentversioncontent_set
.filter(content__has_file=True)
.get(key=f"static/{asset_path}")
)
except ObjectDoesNotExist:
# This means we see a path that _looks_ like it should be a static
# asset for this Component, but that static asset doesn't really
# exist.
return None
return self._absolute_url_for_asset(component_version, asset_path)