示例#1
0
def load_block_as_anonymous_user(location):
    """
    Load a block as anonymous user.

    This uses a few internal courseware methods to retrieve the descriptor
    and bind an AnonymousUser to it, in a similar fashion as a `noauth` XBlock
    handler.
    """
    # pylint: disable=import-error,import-outside-toplevel
    from django.contrib.auth.models import AnonymousUser
    from xmodule.modulestore.django import modulestore
    from lms.djangoapps.courseware.module_render import get_module_for_descriptor_internal

    # Retrieve descriptor from modulestore
    descriptor = modulestore().get_item(location)

    # Load block, attaching it to AnonymousUser
    get_module_for_descriptor_internal(
        user=AnonymousUser(),
        descriptor=descriptor,
        student_data=None,
        course_id=location.course_key,
        track_function=None,
        xqueue_callback_url_prefix="",
        request_token="",
    )

    return descriptor
示例#2
0
def load_block_as_anonymous_user(location):
    """
    Load a block as anonymous user.

    This uses a few internal courseware methods to retrieve the descriptor
    and bind an AnonymousUser to it, in a similar fashion as a `noauth` XBlock
    handler.
    """
    # pylint: disable=import-error,import-outside-toplevel
    from crum import impersonate
    from django.contrib.auth.models import AnonymousUser
    from xmodule.modulestore.django import modulestore
    from lms.djangoapps.courseware.module_render import get_module_for_descriptor_internal

    # Retrieve descriptor from modulestore
    descriptor = modulestore().get_item(location)

    # ensure `crum.get_current_user` returns AnonymousUser. It returns None when outside
    # of request scope which causes error during block loading.
    user = AnonymousUser()
    with impersonate(user):
        # Load block, attaching it to AnonymousUser
        get_module_for_descriptor_internal(
            user=user,
            descriptor=descriptor,
            student_data=None,
            course_id=location.course_key,
            track_function=None,
            request_token="",
        )

        return descriptor
    def test_embed_mfe_in_course(self):
        """
        Test that the xblock embeds the MFE UI when the flag is enabled
        """
        discussion_xblock = get_module_for_descriptor_internal(
            user=self.user,
            descriptor=self.discussion,
            student_data=mock.Mock(name='student_data'),
            course_id=self.course.id,
            track_function=mock.Mock(name='track_function'),
            request_token='request_token',
        )

        fragment = discussion_xblock.render('student_view')
        html = fragment.content
        self.assertInHTML(
            """
            <iframe
                id='discussions-mfe-tab-embed'
                title='Discussions'
                src='http://test.url/edX/toy/2012_Fall/topics/test_discussion_xblock_id'
            />
            """,
            html,
        )
示例#4
0
def _get_module_instance_for_task(course_id,
                                  student,
                                  module_descriptor,
                                  xmodule_instance_args=None,
                                  grade_bucket_type=None,
                                  course=None):
    """
    Fetches a StudentModule instance for a given `course_id`, `student` object, and `module_descriptor`.

    `xmodule_instance_args` is used to provide information for creating a track function and an XQueue callback.
    These are passed, along with `grade_bucket_type`, to get_module_for_descriptor_internal, which sidesteps
    the need for a Request object when instantiating an xmodule instance.
    """
    # reconstitute the problem's corresponding XModule:
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course_id, student, module_descriptor)
    student_data = KvsFieldData(DjangoKeyValueStore(field_data_cache))

    # get request-related tracking information from args passthrough, and supplement with task-specific
    # information:
    request_info = xmodule_instance_args.get(
        'request_info', {}) if xmodule_instance_args is not None else {}
    task_info = {
        "student": student.username,
        "task_id": _get_task_id_from_xmodule_args(xmodule_instance_args)
    }

    def make_track_function():
        '''
        Make a tracking function that logs what happened.

        For insertion into ModuleSystem, and used by CapaModule, which will
        provide the event_type (as string) and event (as dict) as arguments.
        The request_info and task_info (and page) are provided here.
        '''
        return lambda event_type, event: task_track(
            request_info, task_info, event_type, event, page='x_module_task')

    xqueue_callback_url_prefix = xmodule_instance_args.get('xqueue_callback_url_prefix', '') \
        if xmodule_instance_args is not None else ''

    return get_module_for_descriptor_internal(
        user=student,
        descriptor=module_descriptor,
        student_data=student_data,
        course_id=course_id,
        track_function=make_track_function(),
        xqueue_callback_url_prefix=xqueue_callback_url_prefix,
        grade_bucket_type=grade_bucket_type,
        # This module isn't being used for front-end rendering
        request_token=None,
        # pass in a loaded course for override enabling
        course=course)
示例#5
0
    def test_discussion_render_successfully_with_orphan_parent(
            self, default_store):
        """
        Test that discussion xblock render successfully
        if discussion xblock is child of an orphan.
        """
        with self.store.default_store(default_store):
            orphan_sequential = self.store.create_item(self.user.id,
                                                       self.course.id,
                                                       'sequential')

            vertical = self.store.create_child(
                self.user.id,
                orphan_sequential.location,
                'vertical',
                block_id=self.course.location.block_id)

            discussion = self.store.create_child(
                self.user.id,
                vertical.location,
                'discussion',
                block_id=self.course.location.block_id)

            discussion = self.store.get_item(discussion.location)

            root = self.get_root(discussion)
            # Assert that orphan sequential is root of the discussion xblock.
            self.assertEqual(orphan_sequential.location.block_type,
                             root.location.block_type)
            self.assertEqual(orphan_sequential.location.block_id,
                             root.location.block_id)

            # Get xblock bound to a user and a descriptor.
            discussion_xblock = get_module_for_descriptor_internal(
                user=self.user,
                descriptor=discussion,
                student_data=mock.Mock(name='student_data'),
                course_id=self.course.id,
                track_function=mock.Mock(name='track_function'),
                xqueue_callback_url_prefix=mock.Mock(
                    name='xqueue_callback_url_prefix'),
                request_token='request_token',
            )

            fragment = discussion_xblock.render('student_view')
            html = fragment.content

            self.assertIsInstance(discussion_xblock, DiscussionXBlock)
            self.assertIn('data-user-create-comment="false"', html)
            self.assertIn('data-user-create-subcomment="false"', html)
    def test_permissions_query_load(self):
        """
        Tests that the permissions queries are cached when rendering numerous discussion XBlocks.
        """
        user = UserFactory()
        course = ToyCourseFactory()
        course_key = course.id
        course_usage_key = self.store.make_course_usage_key(course_key)
        discussions = []

        for counter in range(5):
            discussion_id = f'test_discussion_{counter}'
            discussions.append(
                ItemFactory.create(
                    parent_location=course_usage_key,
                    category='discussion',
                    discussion_id=discussion_id,
                    discussion_category='Category discussion',
                    discussion_target='Target Discussion',
                ))

        # 7 queries are required to do first discussion xblock render:
        # * split_modulestore_django_splitmodulestorecourseindex x2
        # * waffle_utils_wafflecourseoverridemodel
        # * waffle_utils_waffleorgoverridemodel
        # * waffle_flag
        # * django_comment_client_role
        # * lms_xblock_xblockasidesconfig
        num_queries = 7
        for discussion in discussions:
            discussion_xblock = get_module_for_descriptor_internal(
                user=user,
                descriptor=discussion,
                student_data=mock.Mock(name='student_data'),
                course_id=course.id,
                track_function=mock.Mock(name='track_function'),
                request_token='request_token',
            )
            with self.assertNumQueries(num_queries):
                fragment = discussion_xblock.render('student_view')

            # Permissions are cached, so only 1  query required for subsequent renders
            # to check the waffle flag
            num_queries = 1

            html = fragment.content
            assert 'data-user-create-comment="false"' in html
            assert 'data-user-create-subcomment="false"' in html
    def test_html_with_user(self):
        """
        Test rendered DiscussionXBlock permissions.
        """
        discussion_xblock = get_module_for_descriptor_internal(
            user=self.user,
            descriptor=self.discussion,
            student_data=mock.Mock(name='student_data'),
            course_id=self.course.id,
            track_function=mock.Mock(name='track_function'),
            request_token='request_token',
        )

        fragment = discussion_xblock.render('student_view')
        html = fragment.content
        assert 'data-user-create-comment="false"' in html
        assert 'data-user-create-subcomment="false"' in html
示例#8
0
    def test_permissions_query_load(self):
        """
        Tests that the permissions queries are cached when rendering numerous discussion XBlocks.
        """
        user = UserFactory()
        course = ToyCourseFactory()
        course_key = course.id
        course_usage_key = self.store.make_course_usage_key(course_key)
        discussions = []

        for counter in range(5):
            discussion_id = 'test_discussion_{}'.format(counter)
            discussions.append(
                ItemFactory.create(
                    parent_location=course_usage_key,
                    category='discussion',
                    discussion_id=discussion_id,
                    discussion_category='Category discussion',
                    discussion_target='Target Discussion',
                ))

        # 3 queries are required to do first discussion xblock render:
        # * django_comment_client_role
        # * django_comment_client_permission
        # * lms_xblock_xblockasidesconfig
        num_queries = 2
        for discussion in discussions:
            discussion_xblock = get_module_for_descriptor_internal(
                user=user,
                descriptor=discussion,
                student_data=mock.Mock(name='student_data'),
                course_id=course.id,
                track_function=mock.Mock(name='track_function'),
                xqueue_callback_url_prefix=mock.Mock(
                    name='xqueue_callback_url_prefix'),
                request_token='request_token',
            )
            with self.assertNumQueries(num_queries):
                fragment = discussion_xblock.render('student_view')

            # Permissions are cached, so no queries required for subsequent renders
            num_queries = 0

            html = fragment.content
            self.assertIn('data-user-create-comment="false"', html)
            self.assertIn('data-user-create-subcomment="false"', html)