feat: new unstable URL to render a v2 library xblock in an iframe (#35473)

This commit is contained in:
Rômulo Penido
2024-09-13 15:45:33 -03:00
committed by GitHub
parent 4e5a3b2db9
commit bb6ac5a898
4 changed files with 60 additions and 3 deletions

View File

@@ -6,7 +6,12 @@
<base target="_blank">
<meta charset="UTF-8">
<!-- gettext & XBlock JS i18n code -->
<script type="text/javascript" src="{{ lms_root_url }}/static/js/i18n/en/djangojs.js"></script>
{% if is_development %}
<!-- in development, the djangojs file isn't available so use fallback-->
<script type="text/javascript" src="{{ lms_root_url }}/static/js/src/gettext_fallback.js"></script>
{% else %}
<script type="text/javascript" src="{{ lms_root_url }}/static/js/i18n/en/djangojs.js"></script>
{% endif %}
<!-- Most XBlocks require jQuery: -->
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<!-- The Video XBlock requires "ajaxWithPrefix" -->

View File

@@ -0,0 +1 @@
../../../cms/templates/content_libraries/xblock_iframe.html

View File

@@ -29,4 +29,9 @@ urlpatterns = [
),
])),
])),
path('xblocks/v2/<str:usage_key_str>/', include([
# render one of this XBlock's views (e.g. student_view) for embedding in an iframe
# NOTE: this endpoint is **unstable** and subject to changes after Sumac
re_path(r'^embed/(?P<view_name>[\w\-]+)/$', views.embed_block_view),
])),
]

View File

@@ -1,12 +1,16 @@
"""
Views that implement a RESTful API for interacting with XBlocks.
"""
import itertools
import json
from common.djangoapps.util.json_request import JsonResponse
from corsheaders.signals import check_request_enabled
from django.conf import settings
from django.contrib.auth import get_user_model
from django.db.transaction import atomic
from django.http import Http404
from django.shortcuts import render
from django.utils.translation import gettext as _
from django.views.decorators.clickjacking import xframe_options_exempt
from django.views.decorators.csrf import csrf_exempt
@@ -21,6 +25,7 @@ from xblock.fields import Scope
from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import UsageKey
import openedx.core.djangoapps.site_configuration.helpers as configuration_helpers
from openedx.core.djangoapps.xblock.learning_context.manager import get_learning_context_impl
from openedx.core.lib.api.view_utils import view_auth_classes
from ..api import (
@@ -87,6 +92,47 @@ def render_block_view(request, usage_key_str, view_name):
return Response(response_data)
@api_view(['GET'])
@view_auth_classes(is_authenticated=False)
@permission_classes((permissions.AllowAny, )) # Permissions are handled at a lower level, by the learning context
@xframe_options_exempt
def embed_block_view(request, usage_key_str, view_name):
"""
Render the given XBlock in an <iframe>
Unstable - may change after Sumac
"""
try:
usage_key = UsageKey.from_string(usage_key_str)
except InvalidKeyError as e:
raise NotFound(invalid_not_found_fmt.format(usage_key=usage_key_str)) from e
try:
block = load_block(usage_key, request.user)
except NoSuchUsage as exc:
raise NotFound(f"{usage_key} not found") from exc
fragment = _render_block_view(block, view_name, request.user)
handler_urls = {
str(key): _get_handler_url(key, 'handler_name', request.user)
for key in itertools.chain([block.scope_ids.usage_id], getattr(block, 'children', []))
}
lms_root_url = configuration_helpers.get_value('LMS_ROOT_URL', settings.LMS_ROOT_URL)
context = {
'fragment': fragment,
'handler_urls_json': json.dumps(handler_urls),
'lms_root_url': lms_root_url,
'is_development': settings.DEBUG,
}
response = render(request, 'xblock_v2/xblock_iframe.html', context, content_type='text/html')
# Only allow this iframe be embedded if the parent is in the CORS_ORIGIN_WHITELIST
cors_origin_whitelist = configuration_helpers.get_value('CORS_ORIGIN_WHITELIST', settings.CORS_ORIGIN_WHITELIST)
response["Content-Security-Policy"] = f"frame-ancestors 'self' {' '.join(cors_origin_whitelist)};"
return response
@api_view(['GET'])
@view_auth_classes(is_authenticated=False)
def get_handler_url(request, usage_key_str, handler_name):
@@ -185,8 +231,8 @@ class BlockFieldsView(APIView):
View to get/edit the field values of an XBlock as JSON (in the v2 runtime)
This class mimics the functionality of xblock_handler in block.py (for v1 xblocks), but for v2 xblocks.
However, it only implements the exact subset of functionality needed to support the v2 editors (from
the frontend-lib-content-components project). As such, it only supports GET and POST, and only the
However, it only implements the exact subset of functionality needed to support the v2 editors (in
the Course Authoring MFE). As such, it only supports GET and POST, and only the
POSTing of data/metadata fields.
"""