Skip to content

Commit

Permalink
Merge branch 'master' into hu/ent-7413
Browse files Browse the repository at this point in the history
  • Loading branch information
brobro10000 authored Jul 13, 2023
2 parents 7361c0b + 472104a commit 93bdc02
Show file tree
Hide file tree
Showing 25 changed files with 300 additions and 257 deletions.
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ RUN apt-get update && \
libpython3.8 \
libpython3.8-stdlib \
libmysqlclient21 \
pkg-config \
libssl1.1 \
libxmlsec1-openssl \
# lynx: Required by https://github.com/openedx/edx-platform/blob/b489a4ecb122/openedx/core/lib/html_to_text.py#L16
Expand Down
2 changes: 1 addition & 1 deletion cms/djangoapps/contentstore/views/preview.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ def _prepare_runtime_for_preview(request, block):
# Set up functions to modify the fragment produced by student_view
block.runtime.wrappers = wrappers
block.runtime.wrappers_asides = wrappers_asides
block.runtime._services.update(services) # pylint: disable=protected-access
block.runtime._runtime_services.update(services) # lint-amnesty, pylint: disable=protected-access

# xmodules can check for this attribute during rendering to determine if
# they are being rendered for preview (i.e. in Studio)
Expand Down
1 change: 1 addition & 0 deletions cms/envs/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -2706,6 +2706,7 @@
WIKI_HELP_URL = "https://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/latest/course_assets/course_wiki.html"
CUSTOM_PAGES_HELP_URL = "https://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/latest/course_assets/pages.html#adding-custom-pages"
COURSE_LIVE_HELP_URL = "https://edx.readthedocs.io/projects/edx-partner-course-staff/en/latest/course_assets/course_live.html"
ORA_SETTINGS_HELP_URL = "https://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/latest/course_assets/ora_settings.html"

# keys for big blue button live provider
COURSE_LIVE_GLOBAL_CREDENTIALS = {}
Expand Down
282 changes: 142 additions & 140 deletions lms/djangoapps/courseware/block_render.py

Large diffs are not rendered by default.

45 changes: 45 additions & 0 deletions lms/djangoapps/courseware/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,3 +267,48 @@ def get_allowed_operations(cls, course_key: CourseKey, user: Optional[User] = No
@staticmethod
def legacy_link(course_key: CourseKey):
return urls.reverse('tabs_handler', kwargs={'course_key_string': course_key})


class ORASettingsApp(CourseApp):
"""
Course App config for ORA app.
"""

app_id = "ora_settings"
name = _("Open Response Assessment Settings")
description = _("Course level settings for Open Response Assessment.")
documentation_links = {
"learn_more_configuration": settings.ORA_SETTINGS_HELP_URL,
}

@classmethod
def is_available(cls, course_key: CourseKey) -> bool:
"""
Open response is available for course with at least one ORA.
"""
oras = modulestore().get_items(course_key, qualifiers={'category': 'openassessment'})
return len(oras) > 0

@classmethod
def is_enabled(cls, course_key: CourseKey) -> bool:
"""
Get open response enabled status from course overview model.
"""
return True

@classmethod
def set_enabled(cls, course_key: CourseKey, enabled: bool, user: 'User') -> bool:
"""
Update open response enabled status in modulestore. Always enable to avoid confusion that user can disable ora.
"""
return True

@classmethod
def get_allowed_operations(cls, course_key: CourseKey, user: Optional[User] = None) -> Dict[str, bool]:
"""
Get allowed operations for open response app.
"""
return {
"enable": False,
"configure": True,
}
29 changes: 14 additions & 15 deletions lms/djangoapps/courseware/tests/test_block_render.py
Original file line number Diff line number Diff line change
Expand Up @@ -949,7 +949,7 @@ def test_will_recheck_access_handler_attribute(self, handler, will_recheck_acces
request.user = self.mock_user

render.handle_xblock_callback(request, str(course.id), usage_id, handler)
assert mock_get_block.call_count == 2
assert mock_get_block.call_count == 1
assert mock_get_block.call_args[1]['will_recheck_access'] == will_recheck_access


Expand Down Expand Up @@ -1922,16 +1922,14 @@ def _get_anonymous_id(self, course_id, xblock_class, should_get_deprecated_id: b
if hasattr(xblock_class, 'module_class'):
block.module_class = xblock_class.module_class

rendered_block = render.get_block_for_descriptor(
rendered_block = render.get_block_for_descriptor_internal(
user=self.user,
block=block,
student_data=Mock(spec=FieldData, name='student_data'),
course_key=course_id,
course_id=course_id,
track_function=Mock(name='track_function'), # Track Function
request_token='request_token',
course=self.course,
request=None,
field_data_cache=None,
)
current_user = rendered_block.runtime.service(rendered_block, 'user').get_current_user()

Expand Down Expand Up @@ -2287,7 +2285,7 @@ def _prepare_runtime(self):
render.prepare_runtime_for_user(
self.user,
self.student_data,
self.block.runtime,
self.block,
self.course.id,
self.track_function,
self.request_token,
Expand Down Expand Up @@ -2441,6 +2439,7 @@ def test_no_service_exception_(self):
Test: NoSuchServiceError should be raised if i18n service is none.
"""
i18nService = self.block.runtime._services['i18n'] # pylint: disable=protected-access
self.block.runtime._runtime_services['i18n'] = None # pylint: disable=protected-access
self.block.runtime._services['i18n'] = None # pylint: disable=protected-access
with pytest.raises(NoSuchServiceError):
self.block.runtime.service(self.block, 'i18n')
Expand Down Expand Up @@ -2657,7 +2656,7 @@ def setUp(self):
render.prepare_runtime_for_user(
self.user,
self.student_data,
self.block.runtime,
self.block,
self.course.id,
self.track_function,
self.request_token,
Expand Down Expand Up @@ -2685,7 +2684,7 @@ def test_user_is_staff(self, is_staff, expected_role):
render.prepare_runtime_for_user(
self.user,
self.student_data,
self.block.runtime,
self.block,
self.course.id,
self.track_function,
self.request_token,
Expand All @@ -2707,7 +2706,7 @@ def test_user_is_admin(self, is_global_staff):
render.prepare_runtime_for_user(
self.user,
self.student_data,
self.block.runtime,
self.block,
self.course.id,
self.track_function,
self.request_token,
Expand All @@ -2727,7 +2726,7 @@ def test_user_is_beta_tester(self, is_beta_tester):
render.prepare_runtime_for_user(
self.user,
self.student_data,
self.block.runtime,
self.block,
self.course.id,
self.track_function,
self.request_token,
Expand All @@ -2748,7 +2747,7 @@ def test_get_user_role(self, is_instructor, expected_role):
render.prepare_runtime_for_user(
self.user,
self.student_data,
self.block.runtime,
self.block,
self.course.id,
self.track_function,
self.request_token,
Expand Down Expand Up @@ -2777,7 +2776,7 @@ def test_anonymous_student_id_bug(self):
render.prepare_runtime_for_user(
self.user,
self.student_data,
self.problem_block.runtime,
self.problem_block,
self.course.id,
self.track_function,
self.request_token,
Expand All @@ -2791,7 +2790,7 @@ def test_anonymous_student_id_bug(self):
render.prepare_runtime_for_user(
self.user,
self.student_data,
self.block.runtime,
self.block,
self.course.id,
self.track_function,
self.request_token,
Expand All @@ -2811,7 +2810,7 @@ def test_user_service_with_anonymous_user(self):
render.prepare_runtime_for_user(
AnonymousUser(),
self.student_data,
self.block.runtime,
self.block,
self.course.id,
self.track_function,
self.request_token,
Expand Down Expand Up @@ -2840,7 +2839,7 @@ def test_get_real_user(self):
render.prepare_runtime_for_user(
self.user,
self.student_data,
self.block.runtime,
self.block,
self.course.id,
self.track_function,
self.request_token,
Expand Down
26 changes: 9 additions & 17 deletions lms/djangoapps/courseware/tests/test_discussion_xblock.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from xmodule.modulestore.tests.factories import BlockFactory, ToyCourseFactory

from lms.djangoapps.course_api.blocks.tests.helpers import deserialize_usage_key
from lms.djangoapps.courseware.block_render import get_block_for_descriptor
from lms.djangoapps.courseware.block_render import get_block_for_descriptor_internal
from lms.djangoapps.courseware.tests.helpers import XModuleRenderingTestBase
from openedx.core.djangoapps.discussions.models import DiscussionsConfiguration, Provider
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory
Expand Down Expand Up @@ -293,15 +293,13 @@ def test_html_with_user(self):
"""
Test rendered DiscussionXBlock permissions.
"""
discussion_xblock = get_block_for_descriptor(
discussion_xblock = get_block_for_descriptor_internal(
user=self.user,
block=self.discussion,
student_data=mock.Mock(name='student_data'),
course_key=self.course.id,
course_id=self.course.id,
track_function=mock.Mock(name='track_function'),
request_token='request_token',
request=None,
field_data_cache=None,
)

fragment = discussion_xblock.render('student_view')
Expand Down Expand Up @@ -338,15 +336,13 @@ def test_discussion_render_successfully_with_orphan_parent(self):
assert orphan_sequential.location.block_id == root.location.block_id

# Get xblock bound to a user and a block.
discussion_xblock = get_block_for_descriptor(
discussion_xblock = get_block_for_descriptor_internal(
user=self.user,
block=discussion,
student_data=mock.Mock(name='student_data'),
course_key=self.course.id,
course_id=self.course.id,
track_function=mock.Mock(name='track_function'),
request_token='request_token',
request=None,
field_data_cache=None,
)

fragment = discussion_xblock.render('student_view')
Expand Down Expand Up @@ -390,15 +386,13 @@ def test_discussion_xblock_visibility(self):
provider_type=Provider.OPEN_EDX,
)

discussion_xblock = get_block_for_descriptor(
discussion_xblock = get_block_for_descriptor_internal(
user=self.user,
block=self.discussion,
student_data=mock.Mock(name='student_data'),
course_key=self.course.id,
course_id=self.course.id,
track_function=mock.Mock(name='track_function'),
request_token='request_token',
request=None,
field_data_cache=None,
)

fragment = discussion_xblock.render('student_view')
Expand Down Expand Up @@ -442,15 +436,13 @@ def test_permissions_query_load(self):
num_queries = 6

for discussion in discussions:
discussion_xblock = get_block_for_descriptor(
discussion_xblock = get_block_for_descriptor_internal(
user=user,
block=discussion,
student_data=mock.Mock(name='student_data'),
course_key=course.id,
course_id=course.id,
track_function=mock.Mock(name='track_function'),
request_token='request_token',
request=None,
field_data_cache=None,
)
with self.assertNumQueries(num_queries):
fragment = discussion_xblock.render('student_view')
Expand Down
18 changes: 9 additions & 9 deletions lms/djangoapps/courseware/testutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ class RenderXBlockTestMixin(MasqueradeMixin, metaclass=ABCMeta):
'<div class="container"',
]

# DOM elements that should only be present when viewing the XBlock as staff.
XBLOCK_STAFF_DEBUG_INFO = [
# DOM elements that appear in an xBlock,
# but are excluded from the xBlock-only rendering.
XBLOCK_REMOVED_HTML_ELEMENTS = [
'<div class="wrap-instructor-info"',
]

Expand Down Expand Up @@ -142,24 +143,23 @@ def setup_user(self, admin=False, enroll=False, login=False):
if login:
self.login()

def verify_response(self, expected_response_code=200, url_params=None, is_staff=False):
def verify_response(self, expected_response_code=200, url_params=None):
"""
Helper method that calls the endpoint, verifies the expected response code, and returns the response.
Arguments:
expected_response_code: The expected response code.
url_params: URL parameters that will be encoded and passed to the request.
is_staff: Whether the user has staff permissions in the course.
"""
if url_params:
url_params = urlencode(url_params)

response = self.get_response(self.block_to_be_tested.location, url_params)
if expected_response_code == 200:
self.assertContains(response, self.html_block.data, status_code=expected_response_code)
unexpected_elements = self.block_specific_chrome_html_elements + self.COURSEWARE_CHROME_HTML_ELEMENTS
if not is_staff:
unexpected_elements += self.XBLOCK_STAFF_DEBUG_INFO
unexpected_elements = self.block_specific_chrome_html_elements
unexpected_elements += self.COURSEWARE_CHROME_HTML_ELEMENTS + self.XBLOCK_REMOVED_HTML_ELEMENTS
for chrome_element in unexpected_elements:
self.assertNotContains(response, chrome_element)
else:
Expand Down Expand Up @@ -202,12 +202,12 @@ def test_success_enrolled_staff(self):
# (3) definition - HTML block
# (4) definition - edx_notes decorator (original_get_html)
with check_mongo_calls(4):
self.verify_response(is_staff=True)
self.verify_response()

def test_success_unenrolled_staff(self):
self.setup_course()
self.setup_user(admin=True, enroll=False, login=True)
self.verify_response(is_staff=True)
self.verify_response()

def test_success_unenrolled_staff_masquerading_as_student(self):
self.setup_course()
Expand Down
10 changes: 3 additions & 7 deletions lms/djangoapps/courseware/views/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1521,7 +1521,7 @@ def _check_sequence_exam_access(request, location):
@xframe_options_exempt
@transaction.non_atomic_requests
@ensure_csrf_cookie
def render_xblock(request, usage_key_string, check_if_enrolled=True, disable_staff_debug_info=False):
def render_xblock(request, usage_key_string, check_if_enrolled=True):
"""
Returns an HttpResponse with HTML content for the xBlock with the given usage_key.
The returned HTML is a chromeless rendering of the xBlock (excluding content of the containing courseware).
Expand Down Expand Up @@ -1571,12 +1571,8 @@ def render_xblock(request, usage_key_string, check_if_enrolled=True, disable_sta
# get the block, which verifies whether the user has access to the block.
recheck_access = request.GET.get('recheck_access') == '1'
block, _ = get_block_by_usage_id(
request,
str(course_key),
str(usage_key),
disable_staff_debug_info=disable_staff_debug_info,
course=course,
will_recheck_access=recheck_access,
request, str(course_key), str(usage_key), disable_staff_debug_info=True, course=course,
will_recheck_access=recheck_access
)

student_view_context = request.GET.dict()
Expand Down
Loading

0 comments on commit 93bdc02

Please sign in to comment.