Merge pull request #19260 from open-craft/xblock-view-oauth

Allow calling xblock_view API with OAuth creds
This commit is contained in:
David Ormsbee
2018-11-28 13:01:54 -05:00
committed by GitHub
3 changed files with 57 additions and 19 deletions

View File

@@ -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:

View File

@@ -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)

View File

@@ -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