diff --git a/lms/djangoapps/course_api/blocks/api.py b/lms/djangoapps/course_api/blocks/api.py index a99fc4121d..905e1bd9d7 100644 --- a/lms/djangoapps/course_api/blocks/api.py +++ b/lms/djangoapps/course_api/blocks/api.py @@ -26,7 +26,7 @@ def get_blocks( student_view_data=None, return_type='dict', block_types_filter=None, - hide_access_denials=False, + hide_access_denials=True, ): """ Return a serialized representation of the course blocks. diff --git a/openedx/features/content_type_gating/tests/test_access.py b/openedx/features/content_type_gating/tests/test_access.py index 980bd59b8f..60c3d464e1 100644 --- a/openedx/features/content_type_gating/tests/test_access.py +++ b/openedx/features/content_type_gating/tests/test_access.py @@ -11,7 +11,6 @@ from django.urls import reverse from django.utils import timezone from mock import patch -from course_api.blocks.api import get_blocks from django_comment_common.models import ( FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, @@ -62,13 +61,6 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedMo from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory -METADATA = { - 'group_access': { - CONTENT_GATING_PARTITION_ID: [CONTENT_TYPE_GATE_GROUP_IDS['full_access']] - } -} - - @patch("crum.get_current_request") def _get_fragment_from_block(block, user_id, course, request_factory, mock_get_current_request): """ @@ -93,23 +85,24 @@ def _get_fragment_from_block(block, user_id, course, request_factory, mock_get_c # This method of fetching the block from the descriptor bypassess access checks problem_block = runtime.get_module(block) + # Attempt to render the block, this should return different fragments if the content is gated or not. frag = runtime.render(problem_block, 'student_view') return frag -def _assert_block_is_gated(block, is_gated, user, course, request_factory, has_upgrade_link=True): +def _assert_block_is_gated(block, is_gated, user_id, course, request_factory, has_upgrade_link=True): """ Asserts that a block in a specific course is gated for a specific user Arguments: block: some sort of xblock descriptor, must implement .scope_ids.usage_id is_gated (bool): if True, this user is expected to be gated from this block - user (int): user + user_id (int): id of user course_id (CourseLocator): id of course """ checkout_link = '#' if has_upgrade_link else None with patch.object(ContentTypeGatingPartition, '_get_checkout_link', return_value=checkout_link): - frag = _get_fragment_from_block(block, user.id, course, request_factory) + frag = _get_fragment_from_block(block, user_id, course, request_factory) if is_gated: assert 'content-paywall' in frag.content if has_upgrade_link: @@ -119,15 +112,6 @@ def _assert_block_is_gated(block, is_gated, user, course, request_factory, has_u else: assert 'content-paywall' not in frag.content - fake_request = request_factory.get('') - with patch('lms.djangoapps.course_api.blocks.api.is_request_from_mobile_app', return_value=True): - blocks = get_blocks(fake_request, course.location, user=user) - course_api_block = blocks['blocks'][str(block.location)] - if is_gated: - assert 'authorization_denial_reason' in course_api_block - else: - assert 'authorization_denial_reason' not in course_api_block - def _assert_block_is_empty(block, user_id, course, request_factory): """ @@ -199,7 +183,6 @@ class TestProblemTypeAccess(SharedModuleStoreTestCase): display_name=case_name, graded=graded, weight=weight, - metadata=METADATA if (graded and has_score and weight) else {}, ) cls.graded_score_weight_blocks[(graded, has_score, weight)] = block @@ -210,7 +193,6 @@ class TestProblemTypeAccess(SharedModuleStoreTestCase): display_name='lti_consumer', has_score=True, graded=True, - metadata=METADATA, ) cls.blocks_dict['lti_block_not_scored'] = ItemFactory.create( parent=cls.blocks_dict['vertical'], @@ -225,7 +207,6 @@ class TestProblemTypeAccess(SharedModuleStoreTestCase): category='problem', display_name='graded_problem', graded=True, - metadata=METADATA, ) cls.blocks_dict['ungraded_problem'] = ItemFactory.create( parent=cls.blocks_dict['vertical'], @@ -341,22 +322,22 @@ class TestProblemTypeAccess(SharedModuleStoreTestCase): blocks_dict = {} chapter = ItemFactory.create( parent=course, - display_name='Overview', + display_name='Overview' ) blocks_dict['chapter'] = ItemFactory.create( parent=course, category='chapter', - display_name='Week 1', + display_name='Week 1' ) blocks_dict['sequential'] = ItemFactory.create( parent=chapter, category='sequential', - display_name='Lesson 1', + display_name='Lesson 1' ) blocks_dict['vertical'] = ItemFactory.create( parent=blocks_dict['sequential'], category='vertical', - display_name='Lesson 1 Vertical - Unit 1', + display_name='Lesson 1 Vertical - Unit 1' ) for component_type in component_types: @@ -365,7 +346,6 @@ class TestProblemTypeAccess(SharedModuleStoreTestCase): category=component_type, display_name=component_type, graded=True, - metadata={} if component_type == 'html' else METADATA ) blocks_dict[component_type] = block @@ -389,14 +369,14 @@ class TestProblemTypeAccess(SharedModuleStoreTestCase): def test_access_to_problems(self, prob_type, is_gated): _assert_block_is_gated( block=self.blocks_dict[prob_type], - user=self.users['audit'], + user_id=self.users['audit'].id, course=self.course, is_gated=is_gated, request_factory=self.factory, ) _assert_block_is_gated( block=self.blocks_dict[prob_type], - user=self.users['verified'], + user_id=self.users['verified'].id, course=self.course, is_gated=False, request_factory=self.factory, @@ -411,7 +391,7 @@ class TestProblemTypeAccess(SharedModuleStoreTestCase): block = self.graded_score_weight_blocks[(graded, has_score, weight)] _assert_block_is_gated( block=block, - user=self.audit_user, + user_id=self.audit_user.id, course=self.course, is_gated=is_gated, request_factory=self.factory, @@ -446,7 +426,7 @@ class TestProblemTypeAccess(SharedModuleStoreTestCase): """ _assert_block_is_gated( block=self.courses[course]['blocks'][component_type], - user=self.users[user_track], + user_id=self.users[user_track].id, course=self.courses[course]['course'], is_gated=is_gated, request_factory=self.factory, @@ -459,7 +439,7 @@ class TestProblemTypeAccess(SharedModuleStoreTestCase): """ _assert_block_is_gated( block=self.courses['default']['blocks']['problem'], - user=self.users['audit'], + user_id=self.users['audit'].id, course=self.courses['default']['course'], is_gated=True, request_factory=self.factory, @@ -516,7 +496,7 @@ class TestProblemTypeAccess(SharedModuleStoreTestCase): # assert that course team members have access to graded content _assert_block_is_gated( block=self.blocks_dict['problem'], - user=user, + user_id=user.id, course=self.course, is_gated=False, request_factory=self.factory, @@ -538,7 +518,7 @@ class TestProblemTypeAccess(SharedModuleStoreTestCase): _assert_block_is_gated( block=self.blocks_dict['problem'], - user=user, + user_id=user.id, course=self.course, is_gated=False, request_factory=self.factory, @@ -568,7 +548,7 @@ class TestProblemTypeAccess(SharedModuleStoreTestCase): block = self.graded_score_weight_blocks[(graded, has_score, weight)] _assert_block_is_gated( block=block, - user=user, + user_id=user.id, course=self.course, is_gated=is_gated, request_factory=self.factory, @@ -691,7 +671,7 @@ class TestProblemTypeAccess(SharedModuleStoreTestCase): _assert_block_is_gated( block=self.blocks_dict['problem'], - user=user, + user_id=user.id, course=self.course, is_gated=False, request_factory=self.factory, @@ -734,26 +714,24 @@ class TestConditionalContentAccess(TestConditionalContent): user=self.student_verified_a, course_id=self.course.id, key='xblock.partition_service.partition_{0}'.format(self.partition.id), - value=str('0'), + value=str('user_course_tag_a'), ) UserCourseTagFactory( user=self.student_verified_b, course_id=self.course.id, key='xblock.partition_service.partition_{0}'.format(self.partition.id), - value=str('1'), + value=str('user_course_tag_b'), ) # Create blocks to go into the verticals self.block_a = ItemFactory.create( category='problem', parent=self.vertical_a, display_name='problem_a', - metadata=METADATA, ) self.block_b = ItemFactory.create( category='problem', parent=self.vertical_b, display_name='problem_b', - metadata=METADATA, ) def test_access_based_on_conditional_content(self): @@ -765,14 +743,14 @@ class TestConditionalContentAccess(TestConditionalContent): # Make sure that all audit enrollments are gated regardless of if they see vertical a or vertical b _assert_block_is_gated( block=self.block_a, - user=self.student_audit_a, + user_id=self.student_audit_a.id, course=self.course, is_gated=True, request_factory=self.factory, ) _assert_block_is_gated( block=self.block_b, - user=self.student_audit_b, + user_id=self.student_audit_b.id, course=self.course, is_gated=True, request_factory=self.factory, @@ -781,14 +759,14 @@ class TestConditionalContentAccess(TestConditionalContent): # Make sure that all verified enrollments are not gated regardless of if they see vertical a or vertical b _assert_block_is_gated( block=self.block_a, - user=self.student_verified_a, + user_id=self.student_verified_a.id, course=self.course, is_gated=False, request_factory=self.factory, ) _assert_block_is_gated( block=self.block_b, - user=self.student_verified_b, + user_id=self.student_verified_b.id, course=self.course, is_gated=False, request_factory=self.factory, @@ -858,11 +836,10 @@ class TestMessageDeduplication(ModuleStoreTestCase): category='problem', display_name='graded_problem', graded=True, - metadata=METADATA, ) _assert_block_is_gated( block=blocks_dict['graded_1'], - user=self.user, + user_id=self.user.id, course=course['course'], is_gated=True, request_factory=self.request_factory, @@ -877,14 +854,12 @@ class TestMessageDeduplication(ModuleStoreTestCase): category='problem', display_name='graded_problem', graded=True, - metadata=METADATA, ) blocks_dict['graded_2'] = ItemFactory.create( parent=blocks_dict['vertical'], category='problem', display_name='graded_problem', graded=True, - metadata=METADATA, ) CourseEnrollmentFactory.create( user=self.user, @@ -893,7 +868,7 @@ class TestMessageDeduplication(ModuleStoreTestCase): ) _assert_block_is_gated( block=blocks_dict['graded_1'], - user=self.user, + user_id=self.user.id, course=course['course'], is_gated=True, request_factory=self.request_factory, @@ -914,28 +889,24 @@ class TestMessageDeduplication(ModuleStoreTestCase): category='problem', display_name='graded_problem', graded=True, - metadata=METADATA, ) blocks_dict['graded_2'] = ItemFactory.create( parent=blocks_dict['vertical'], category='problem', display_name='graded_problem', graded=True, - metadata=METADATA, ) blocks_dict['graded_3'] = ItemFactory.create( parent=blocks_dict['vertical'], category='problem', display_name='graded_problem', graded=True, - metadata=METADATA, ) blocks_dict['graded_4'] = ItemFactory.create( parent=blocks_dict['vertical'], category='problem', display_name='graded_problem', graded=True, - metadata=METADATA, ) CourseEnrollmentFactory.create( user=self.user, @@ -944,7 +915,7 @@ class TestMessageDeduplication(ModuleStoreTestCase): ) _assert_block_is_gated( block=blocks_dict['graded_1'], - user=self.user, + user_id=self.user.id, course=course['course'], is_gated=True, request_factory=self.request_factory, @@ -977,7 +948,6 @@ class TestMessageDeduplication(ModuleStoreTestCase): category='problem', display_name='graded_problem', graded=True, - metadata=METADATA, ) blocks_dict['ungraded_2'] = ItemFactory.create( parent=blocks_dict['vertical'], @@ -990,7 +960,6 @@ class TestMessageDeduplication(ModuleStoreTestCase): category='problem', display_name='graded_problem', graded=True, - metadata=METADATA, ) CourseEnrollmentFactory.create( user=self.user, @@ -999,21 +968,21 @@ class TestMessageDeduplication(ModuleStoreTestCase): ) _assert_block_is_gated( block=blocks_dict['graded_1'], - user=self.user, + user_id=self.user.id, course=course['course'], is_gated=True, request_factory=self.request_factory, ) _assert_block_is_gated( block=blocks_dict['ungraded_2'], - user=self.user, + user_id=self.user.id, course=course['course'], is_gated=False, request_factory=self.request_factory, ) _assert_block_is_gated( block=blocks_dict['graded_3'], - user=self.user, + user_id=self.user.id, course=course['course'], is_gated=True, request_factory=self.request_factory, diff --git a/openedx/features/course_experience/utils.py b/openedx/features/course_experience/utils.py index 3637b4731b..8b74b01e30 100644 --- a/openedx/features/course_experience/utils.py +++ b/openedx/features/course_experience/utils.py @@ -90,12 +90,13 @@ def get_course_outline_block_tree(request, course_id, user=None): latest_completion, block=block['children'][idx] ) - if block['children'][idx].get('resume_block') is True: + if block['children'][idx]['resume_block'] is True: block['resume_block'] = True completable_blocks = [child for child in block['children'] - if child.get('type') != 'discussion'] - if all(child.get('complete') for child in completable_blocks): + if child['type'] != 'discussion'] + if len([child['complete'] for child in block['children'] + if child['complete']]) == len(completable_blocks): block['complete'] = True def mark_last_accessed(user, course_key, block): @@ -172,7 +173,7 @@ def get_resume_block(block): Gets the deepest block marked as 'resume_block'. """ - if block.get('authorization_denial_reason') or not block['resume_block']: + if not block['resume_block']: return None if not block.get('children'): return block diff --git a/openedx/features/course_experience/views/course_outline.py b/openedx/features/course_experience/views/course_outline.py index d63ce19411..3b895c13dc 100644 --- a/openedx/features/course_experience/views/course_outline.py +++ b/openedx/features/course_experience/views/course_outline.py @@ -76,13 +76,12 @@ class CourseOutlineFragmentView(EdxFragmentView): if xblock_display_names is None: xblock_display_names = {} - if not course_block_tree.get('authorization_denial_reason'): - if course_block_tree.get('id'): - xblock_display_names[course_block_tree['id']] = course_block_tree['display_name'] + if course_block_tree.get('id'): + xblock_display_names[course_block_tree['id']] = course_block_tree['display_name'] - if course_block_tree.get('children'): - for child in course_block_tree['children']: - self.create_xblock_id_and_name_dict(child, xblock_display_names) + if course_block_tree.get('children'): + for child in course_block_tree['children']: + self.create_xblock_id_and_name_dict(child, xblock_display_names) return xblock_display_names