Merge pull request #19260 from open-craft/xblock-view-oauth
Allow calling xblock_view API with OAuth creds
This commit is contained in:
@@ -15,7 +15,6 @@ from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.cache import cache
|
||||
from django.template.context_processors import csrf
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.urls import reverse
|
||||
from django.http import Http404, HttpResponse, HttpResponseForbidden
|
||||
from django.utils.text import slugify
|
||||
@@ -27,6 +26,7 @@ from edx_proctoring.services import ProctoringService
|
||||
from opaque_keys import InvalidKeyError
|
||||
from opaque_keys.edx.keys import CourseKey, UsageKey
|
||||
from requests.auth import HTTPBasicAuth
|
||||
from rest_framework.decorators import api_view
|
||||
from six import text_type
|
||||
from xblock.core import XBlock
|
||||
from xblock.django.request import django_to_webob_request, webob_to_django_response
|
||||
@@ -59,6 +59,7 @@ from openedx.core.djangoapps.crawlers.models import CrawlersConfig
|
||||
from openedx.core.djangoapps.credit.services import CreditService
|
||||
from openedx.core.djangoapps.util.user_utils import SystemUser
|
||||
from openedx.core.djangolib.markup import HTML
|
||||
from openedx.core.lib.api.view_utils import view_auth_classes
|
||||
from openedx.core.lib.gating.services import GatingService
|
||||
from openedx.core.lib.license import wrap_with_license
|
||||
from openedx.core.lib.url_utils import quote_slashes, unquote_slashes
|
||||
@@ -1169,6 +1170,8 @@ def hash_resource(resource):
|
||||
return md5.hexdigest()
|
||||
|
||||
|
||||
@api_view(['GET'])
|
||||
@view_auth_classes(is_authenticated=True)
|
||||
def xblock_view(request, course_id, usage_id, view_name):
|
||||
"""
|
||||
Returns the rendered view of a given XBlock, with related resources
|
||||
@@ -1183,9 +1186,6 @@ def xblock_view(request, course_id, usage_id, view_name):
|
||||
" see FEATURES['ENABLE_XBLOCK_VIEW_ENDPOINT']")
|
||||
raise Http404
|
||||
|
||||
if not request.user.is_authenticated:
|
||||
raise PermissionDenied
|
||||
|
||||
try:
|
||||
course_key = CourseKey.from_string(course_id)
|
||||
except InvalidKeyError:
|
||||
|
||||
@@ -743,21 +743,33 @@ class TestHandleXBlockCallback(SharedModuleStoreTestCase, LoginEnrollmentTestCas
|
||||
with self.assertRaises(BlockCompletion.DoesNotExist):
|
||||
BlockCompletion.objects.get(block_key=block.scope_ids.usage_id)
|
||||
|
||||
@patch.dict('django.conf.settings.FEATURES', {'ENABLE_XBLOCK_VIEW_ENDPOINT': True})
|
||||
def test_xblock_view_handler(self):
|
||||
args = [
|
||||
'edX/toy/2012_Fall',
|
||||
quote_slashes('i4x://edX/toy/videosequence/Toy_Videos'),
|
||||
'student_view'
|
||||
]
|
||||
xblock_view_url = reverse(
|
||||
'xblock_view',
|
||||
args=args
|
||||
)
|
||||
|
||||
request = self.request_factory.get(xblock_view_url)
|
||||
request.user = self.mock_user
|
||||
response = render.xblock_view(request, *args)
|
||||
@attr(shard=1)
|
||||
@ddt.ddt
|
||||
@patch.dict('django.conf.settings.FEATURES', {'ENABLE_XBLOCK_VIEW_ENDPOINT': True})
|
||||
class TestXBlockView(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
"""
|
||||
Test the handle_xblock_callback function
|
||||
"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestXBlockView, cls).setUpClass()
|
||||
cls.course_key = ToyCourseFactory.create().id
|
||||
cls.toy_course = modulestore().get_course(cls.course_key)
|
||||
|
||||
def setUp(self):
|
||||
super(TestXBlockView, self).setUp()
|
||||
|
||||
self.location = unicode(self.course_key.make_usage_key('html', 'toyhtml'))
|
||||
self.request_factory = RequestFactory()
|
||||
|
||||
self.view_args = [unicode(self.course_key), quote_slashes(self.location), 'student_view']
|
||||
self.xblock_view_url = reverse('xblock_view', args=self.view_args)
|
||||
|
||||
def test_xblock_view_handler(self):
|
||||
request = self.request_factory.get(self.xblock_view_url)
|
||||
request.user = UserFactory.create()
|
||||
response = render.xblock_view(request, *self.view_args)
|
||||
self.assertEquals(200, response.status_code)
|
||||
|
||||
expected = ['csrf_token', 'html', 'resources']
|
||||
@@ -765,7 +777,30 @@ class TestHandleXBlockCallback(SharedModuleStoreTestCase, LoginEnrollmentTestCas
|
||||
for section in expected:
|
||||
self.assertIn(section, content)
|
||||
doc = PyQuery(content['html'])
|
||||
self.assertEquals(len(doc('div.xblock-student_view-videosequence')), 1)
|
||||
self.assertEquals(len(doc('div.xblock-student_view-html')), 1)
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test_hide_staff_markup(self, hide):
|
||||
"""
|
||||
When xblock_view gets 'hide_staff_markup' in its context, the staff markup
|
||||
should not be included. See 'add_staff_markup' in xblock_utils/__init__.py
|
||||
"""
|
||||
request = self.request_factory.get(self.xblock_view_url)
|
||||
request.user = GlobalStaffFactory.create()
|
||||
request.session = {}
|
||||
if hide:
|
||||
request.GET = {'hide_staff_markup': 'true'}
|
||||
response = render.xblock_view(request, *self.view_args)
|
||||
self.assertEquals(200, response.status_code)
|
||||
|
||||
html = json.loads(response.content)['html']
|
||||
self.assertEqual('Staff Debug Info' in html, not hide)
|
||||
|
||||
def test_xblock_view_handler_not_authenticated(self):
|
||||
request = self.request_factory.get(self.xblock_view_url)
|
||||
request.user = AnonymousUser()
|
||||
response = render.xblock_view(request, *self.view_args)
|
||||
self.assertEquals(401, response.status_code)
|
||||
|
||||
|
||||
@attr(shard=1)
|
||||
|
||||
@@ -309,6 +309,9 @@ def add_staff_markup(user, disable_staff_debug_info, block, view, frag, context)
|
||||
|
||||
Does nothing if module is a SequenceModule.
|
||||
"""
|
||||
if context and context.get('hide_staff_markup', False):
|
||||
# If hide_staff_markup is passed, don't add the markup
|
||||
return frag
|
||||
# TODO: make this more general, eg use an XModule attribute instead
|
||||
if isinstance(block, VerticalBlock) and (not context or not context.get('child_of_vertical', False)):
|
||||
# check that the course is a mongo backed Studio course before doing work
|
||||
|
||||
Reference in New Issue
Block a user