Commit 7655a177 by Sanford Student

Revert "moving milestones check to access.py"

This reverts commit 5db58c00.
parent 5ba8cf83
...@@ -345,19 +345,14 @@ def add_course_content_milestone(course_id, content_id, relationship, milestone) ...@@ -345,19 +345,14 @@ def add_course_content_milestone(course_id, content_id, relationship, milestone)
return milestones_api.add_course_content_milestone(course_id, content_id, relationship, milestone) return milestones_api.add_course_content_milestone(course_id, content_id, relationship, milestone)
def get_course_content_milestones(course_id, content_id, relationship, user_id=None): def get_course_content_milestones(course_id, content_id, relationship):
""" """
Client API operation adapter/wrapper Client API operation adapter/wrapper
""" """
if not settings.FEATURES.get('MILESTONES_APP', False): if not settings.FEATURES.get('MILESTONES_APP', False):
return [] return []
from milestones import api as milestones_api from milestones import api as milestones_api
return milestones_api.get_course_content_milestones( return milestones_api.get_course_content_milestones(course_id, content_id, relationship)
course_id,
content_id,
relationship,
{'id': user_id} if user_id else None
)
def remove_course_content_user_milestones(course_key, content_key, user, relationship): def remove_course_content_user_milestones(course_key, content_key, user, relationship):
......
...@@ -20,7 +20,6 @@ from django.utils.timezone import UTC ...@@ -20,7 +20,6 @@ from django.utils.timezone import UTC
from opaque_keys.edx.keys import CourseKey, UsageKey from opaque_keys.edx.keys import CourseKey, UsageKey
from util import milestones_helpers as milestones_helpers
from xblock.core import XBlock from xblock.core import XBlock
from xmodule.course_module import ( from xmodule.course_module import (
...@@ -553,20 +552,21 @@ def _has_access_descriptor(user, action, descriptor, course_key=None): ...@@ -553,20 +552,21 @@ def _has_access_descriptor(user, action, descriptor, course_key=None):
students to see modules. If not, views should check the course, so we students to see modules. If not, views should check the course, so we
don't have to hit the enrollments table on every module load. don't have to hit the enrollments table on every module load.
""" """
if _has_staff_access_to_descriptor(user, descriptor, course_key): response = (
return ACCESS_GRANTED _visible_to_nonstaff_users(descriptor)
and _has_group_access(descriptor, user, course_key)
# if the user has staff access, they can load the module so this code doesn't need to run and
return (
_visible_to_nonstaff_users(descriptor) and
_can_access_descriptor_with_milestones(user, descriptor, course_key) and
_has_group_access(descriptor, user, course_key) and
( (
_has_detached_class_tag(descriptor) or _has_detached_class_tag(descriptor)
_can_access_descriptor_with_start_date(user, descriptor, course_key) or _can_access_descriptor_with_start_date(user, descriptor, course_key)
) )
) )
return (
ACCESS_GRANTED if (response or _has_staff_access_to_descriptor(user, descriptor, course_key))
else response
)
checkers = { checkers = {
'load': can_load, 'load': can_load,
'staff': lambda: _has_staff_access_to_descriptor(user, descriptor, course_key), 'staff': lambda: _has_staff_access_to_descriptor(user, descriptor, course_key),
...@@ -801,22 +801,6 @@ def _visible_to_nonstaff_users(descriptor): ...@@ -801,22 +801,6 @@ def _visible_to_nonstaff_users(descriptor):
return VisibilityError() if descriptor.visible_to_staff_only else ACCESS_GRANTED return VisibilityError() if descriptor.visible_to_staff_only else ACCESS_GRANTED
def _can_access_descriptor_with_milestones(user, descriptor, course_key):
"""
Returns if the object is blocked by an unfulfilled milestone.
Args:
user: the user trying to access this content
descriptor: the object being accessed
course_key: key for the course for this descriptor
"""
if milestones_helpers.get_course_content_milestones(course_key, descriptor.location, 'requires', user.id):
debug("Deny: user has not completed all milestones for content")
return ACCESS_DENIED
else:
return ACCESS_GRANTED
def _has_detached_class_tag(descriptor): def _has_detached_class_tag(descriptor):
""" """
Returns if the given descriptor's type is marked as detached. Returns if the given descriptor's type is marked as detached.
......
...@@ -17,6 +17,7 @@ from opaque_keys.edx.keys import CourseKey ...@@ -17,6 +17,7 @@ from opaque_keys.edx.keys import CourseKey
from opaque_keys.edx.locator import BlockUsageLocator from opaque_keys.edx.locator import BlockUsageLocator
from openedx.core.djangoapps.content.block_structure.api import get_course_in_cache from openedx.core.djangoapps.content.block_structure.api import get_course_in_cache
from openedx.core.lib.cache_utils import memoized from openedx.core.lib.cache_utils import memoized
from openedx.core.lib.gating import api as gating_api
from courseware.model_data import FieldDataCache, ScoresClient from courseware.model_data import FieldDataCache, ScoresClient
from openedx.core.djangoapps.signals.signals import GRADES_UPDATED from openedx.core.djangoapps.signals.signals import GRADES_UPDATED
from student.models import anonymous_id_for_user from student.models import anonymous_id_for_user
...@@ -512,6 +513,9 @@ def _progress_summary(student, course, course_structure=None): ...@@ -512,6 +513,9 @@ def _progress_summary(student, course, course_structure=None):
unicode(course.id), anonymous_id_for_user(student, course.id) unicode(course.id), anonymous_id_for_user(student, course.id)
) )
# Check for gated content
gated_content = gating_api.get_gated_content(course, student)
chapters = [] chapters = []
locations_to_weighted_scores = {} locations_to_weighted_scores = {}
...@@ -519,6 +523,9 @@ def _progress_summary(student, course, course_structure=None): ...@@ -519,6 +523,9 @@ def _progress_summary(student, course, course_structure=None):
chapter = course_structure[chapter_key] chapter = course_structure[chapter_key]
sections = [] sections = []
for section_key in course_structure.get_children(chapter_key): for section_key in course_structure.get_children(chapter_key):
if unicode(section_key) in gated_content:
continue
section = course_structure[section_key] section = course_structure[section_key]
graded = getattr(section, 'graded', False) graded = getattr(section, 'graded', False)
......
...@@ -32,6 +32,7 @@ from xblock.exceptions import NoSuchHandlerError, NoSuchViewError ...@@ -32,6 +32,7 @@ from xblock.exceptions import NoSuchHandlerError, NoSuchViewError
from xblock.reference.plugins import FSService from xblock.reference.plugins import FSService
import static_replace import static_replace
from openedx.core.lib.gating import api as gating_api
from courseware.access import has_access, get_user_role from courseware.access import has_access, get_user_role
from courseware.entrance_exams import ( from courseware.entrance_exams import (
get_entrance_exam_score, get_entrance_exam_score,
...@@ -163,6 +164,9 @@ def toc_for_course(user, request, course, active_chapter, active_section, field_ ...@@ -163,6 +164,9 @@ def toc_for_course(user, request, course, active_chapter, active_section, field_
# before the rest of the content is made available # before the rest of the content is made available
required_content = milestones_helpers.get_required_content(course, user) required_content = milestones_helpers.get_required_content(course, user)
# Check for gated content
gated_content = gating_api.get_gated_content(course, user)
# The user may not actually have to complete the entrance exam, if one is required # The user may not actually have to complete the entrance exam, if one is required
if not user_must_complete_entrance_exam(request, user, course): if not user_must_complete_entrance_exam(request, user, course):
required_content = [content for content in required_content if not content == course.entrance_exam_id] required_content = [content for content in required_content if not content == course.entrance_exam_id]
...@@ -185,7 +189,9 @@ def toc_for_course(user, request, course, active_chapter, active_section, field_ ...@@ -185,7 +189,9 @@ def toc_for_course(user, request, course, active_chapter, active_section, field_
sections = list() sections = list()
for section in chapter.get_display_items(): for section in chapter.get_display_items():
# skip the section if it is hidden from the user # skip the section if it is gated/hidden from the user
if gated_content and unicode(section.location) in gated_content:
continue
if section.hide_from_toc: if section.hide_from_toc:
continue continue
......
...@@ -1112,7 +1112,6 @@ class TestGatedSubsectionRendering(SharedModuleStoreTestCase, MilestonesTestCase ...@@ -1112,7 +1112,6 @@ class TestGatedSubsectionRendering(SharedModuleStoreTestCase, MilestonesTestCase
return None return None
@patch.dict(settings.FEATURES, {'MILESTONES_APP': True})
def test_toc_with_gated_sequential(self): def test_toc_with_gated_sequential(self):
""" """
Test generation of TOC for a course with a gated subsection Test generation of TOC for a course with a gated subsection
......
...@@ -1878,7 +1878,7 @@ class TestIndexView(ModuleStoreTestCase): ...@@ -1878,7 +1878,7 @@ class TestIndexView(ModuleStoreTestCase):
@ddt.ddt @ddt.ddt
class TestIndexViewWithVerticalPositions(ModuleStoreTestCase): class TestIndewViewWithVerticalPositions(ModuleStoreTestCase):
""" """
Test the index view to handle vertical positions. Confirms that first position is loaded Test the index view to handle vertical positions. Confirms that first position is loaded
if input position is non-positive or greater than number of positions available. if input position is non-positive or greater than number of positions available.
...@@ -1888,7 +1888,7 @@ class TestIndexViewWithVerticalPositions(ModuleStoreTestCase): ...@@ -1888,7 +1888,7 @@ class TestIndexViewWithVerticalPositions(ModuleStoreTestCase):
""" """
Set up initial test data Set up initial test data
""" """
super(TestIndexViewWithVerticalPositions, self).setUp() super(TestIndewViewWithVerticalPositions, self).setUp()
self.user = UserFactory() self.user = UserFactory()
...@@ -1966,7 +1966,6 @@ class TestIndexViewWithGating(ModuleStoreTestCase, MilestonesTestCaseMixin): ...@@ -1966,7 +1966,6 @@ class TestIndexViewWithGating(ModuleStoreTestCase, MilestonesTestCaseMixin):
CourseEnrollmentFactory(user=self.user, course_id=self.course.id) CourseEnrollmentFactory(user=self.user, course_id=self.course.id)
@patch.dict(settings.FEATURES, {'MILESTONES_APP': True})
def test_index_with_gated_sequential(self): def test_index_with_gated_sequential(self):
""" """
Test index view with a gated sequential raises Http404 Test index view with a gated sequential raises Http404
......
...@@ -25,6 +25,7 @@ import urllib ...@@ -25,6 +25,7 @@ import urllib
from lang_pref import LANGUAGE_KEY from lang_pref import LANGUAGE_KEY
from xblock.fragment import Fragment from xblock.fragment import Fragment
from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.keys import CourseKey
from openedx.core.lib.gating import api as gating_api
from openedx.core.lib.time_zone_utils import get_user_time_zone from openedx.core.lib.time_zone_utils import get_user_time_zone
from openedx.core.djangoapps.user_api.preferences.api import get_user_preference from openedx.core.djangoapps.user_api.preferences.api import get_user_preference
from shoppingcart.models import CourseRegistrationCode from shoppingcart.models import CourseRegistrationCode
...@@ -142,6 +143,7 @@ class CoursewareIndex(View): ...@@ -142,6 +143,7 @@ class CoursewareIndex(View):
if self.chapter and self.section: if self.chapter and self.section:
self._redirect_if_not_requested_section() self._redirect_if_not_requested_section()
self._verify_section_not_gated()
self._save_positions() self._save_positions()
self._prefetch_and_bind_section() self._prefetch_and_bind_section()
...@@ -270,6 +272,15 @@ class CoursewareIndex(View): ...@@ -270,6 +272,15 @@ class CoursewareIndex(View):
self.chapter_url_name = exam_chapter.url_name self.chapter_url_name = exam_chapter.url_name
self.section_url_name = exam_section.url_name self.section_url_name = exam_section.url_name
def _verify_section_not_gated(self):
"""
Verify whether the section is gated and accessible to the user.
"""
gated_content = gating_api.get_gated_content(self.course, self.effective_user)
if gated_content:
if unicode(self.section.location) in gated_content:
raise Http404
def _get_language_preference(self): def _get_language_preference(self):
""" """
Returns the preferred language for the actual user making the request. Returns the preferred language for the actual user making the request.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment