Merge pull request #19609 from edx/fix_masquerade_banner
ensure content start date banner only shows for currently open sections
This commit is contained in:
@@ -13,14 +13,11 @@ from pytz import UTC
|
|||||||
from courseware.access_response import AccessResponse, StartDateError
|
from courseware.access_response import AccessResponse, StartDateError
|
||||||
from courseware.masquerade import (
|
from courseware.masquerade import (
|
||||||
get_course_masquerade,
|
get_course_masquerade,
|
||||||
is_masquerading_as_specific_student,
|
|
||||||
is_masquerading_as_student
|
is_masquerading_as_student
|
||||||
)
|
)
|
||||||
from crum import get_current_request
|
|
||||||
from openedx.core.djangoapps.util.user_messages import PageLevelMessages
|
from openedx.core.djangoapps.util.user_messages import PageLevelMessages
|
||||||
from openedx.core.djangolib.markup import HTML
|
from openedx.core.djangolib.markup import HTML
|
||||||
from openedx.features.course_experience import COURSE_PRE_START_ACCESS_FLAG
|
from openedx.features.course_experience import COURSE_PRE_START_ACCESS_FLAG
|
||||||
from student.role_helpers import has_staff_roles
|
|
||||||
from student.roles import CourseBetaTesterRole
|
from student.roles import CourseBetaTesterRole
|
||||||
from xmodule.util.xmodule_django import get_current_request_hostname
|
from xmodule.util.xmodule_django import get_current_request_hostname
|
||||||
|
|
||||||
@@ -71,29 +68,18 @@ def check_start_date(user, days_early_for_beta, start, course_key):
|
|||||||
"""
|
"""
|
||||||
start_dates_disabled = settings.FEATURES['DISABLE_START_DATES']
|
start_dates_disabled = settings.FEATURES['DISABLE_START_DATES']
|
||||||
masquerading_as_student = is_masquerading_as_student(user, course_key)
|
masquerading_as_student = is_masquerading_as_student(user, course_key)
|
||||||
masquerading_as_specific_student = is_masquerading_as_specific_student(user, course_key)
|
|
||||||
|
|
||||||
if start_dates_disabled and not masquerading_as_student:
|
if start_dates_disabled and not masquerading_as_student:
|
||||||
return ACCESS_GRANTED
|
return ACCESS_GRANTED
|
||||||
else:
|
else:
|
||||||
now = datetime.now(UTC)
|
now = datetime.now(UTC)
|
||||||
if start is None or in_preview_mode():
|
if start is None or in_preview_mode() or get_course_masquerade(user, course_key):
|
||||||
return ACCESS_GRANTED
|
return ACCESS_GRANTED
|
||||||
|
|
||||||
effective_start = adjust_start_date(user, days_early_for_beta, start, course_key)
|
effective_start = adjust_start_date(user, days_early_for_beta, start, course_key)
|
||||||
if now > effective_start:
|
if now > effective_start:
|
||||||
return ACCESS_GRANTED
|
return ACCESS_GRANTED
|
||||||
|
|
||||||
if get_course_masquerade(user, course_key):
|
|
||||||
if masquerading_as_student or (masquerading_as_specific_student and not has_staff_roles(user, course_key)):
|
|
||||||
request = get_current_request()
|
|
||||||
PageLevelMessages.register_warning_message(
|
|
||||||
request,
|
|
||||||
HTML(_('This user does not have access to this content due to the content start date')),
|
|
||||||
once_only=True
|
|
||||||
)
|
|
||||||
return ACCESS_GRANTED
|
|
||||||
|
|
||||||
return StartDateError(start)
|
return StartDateError(start)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ from datetime import datetime
|
|||||||
|
|
||||||
import branding
|
import branding
|
||||||
import pytz
|
import pytz
|
||||||
|
from crum import get_current_request
|
||||||
from openedx.features.course_duration_limits.access import AuditExpiredError
|
from openedx.features.course_duration_limits.access import AuditExpiredError
|
||||||
from courseware.access import has_access
|
from courseware.access import has_access
|
||||||
from courseware.access_response import StartDateError, MilestoneAccessError
|
from courseware.access_response import StartDateError, MilestoneAccessError
|
||||||
@@ -19,6 +20,7 @@ from courseware.date_summary import (
|
|||||||
VerifiedUpgradeDeadlineDate,
|
VerifiedUpgradeDeadlineDate,
|
||||||
CertificateAvailableDate
|
CertificateAvailableDate
|
||||||
)
|
)
|
||||||
|
from courseware.masquerade import check_content_start_date_for_masquerade_user
|
||||||
from courseware.model_data import FieldDataCache
|
from courseware.model_data import FieldDataCache
|
||||||
from courseware.module_render import get_module
|
from courseware.module_render import get_module
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@@ -132,6 +134,9 @@ def check_course_access(course, user, action, check_if_enrolled=False, check_sur
|
|||||||
if has_access(user, 'staff', course.id):
|
if has_access(user, 'staff', course.id):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
request = get_current_request()
|
||||||
|
check_content_start_date_for_masquerade_user(course.id, user, request, course.start)
|
||||||
|
|
||||||
access_response = has_access(user, action, course, course.id)
|
access_response = has_access(user, action, course, course.id)
|
||||||
if not access_response:
|
if not access_response:
|
||||||
# Redirect if StartDateError
|
# Redirect if StartDateError
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Which kind of view has been selected is stored in the session state.
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
@@ -13,10 +14,14 @@ from django.db.models import Q
|
|||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.views.decorators.http import require_POST
|
from django.views.decorators.http import require_POST
|
||||||
from opaque_keys.edx.keys import CourseKey
|
from opaque_keys.edx.keys import CourseKey
|
||||||
|
from pytz import utc
|
||||||
from web_fragments.fragment import Fragment
|
from web_fragments.fragment import Fragment
|
||||||
from xblock.runtime import KeyValueStore
|
from xblock.runtime import KeyValueStore
|
||||||
|
|
||||||
|
from openedx.core.djangoapps.util.user_messages import PageLevelMessages
|
||||||
|
from openedx.core.djangolib.markup import HTML
|
||||||
from student.models import CourseEnrollment
|
from student.models import CourseEnrollment
|
||||||
|
from student.role_helpers import has_staff_roles
|
||||||
from util.json_request import JsonResponse, expect_json
|
from util.json_request import JsonResponse, expect_json
|
||||||
from xmodule.partitions.partitions import NoSuchUserPartitionGroupError
|
from xmodule.partitions.partitions import NoSuchUserPartitionGroupError
|
||||||
|
|
||||||
@@ -186,6 +191,30 @@ def get_masquerading_user_group(course_key, user, user_partition):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def check_content_start_date_for_masquerade_user(course_key, user, request, course_start,
|
||||||
|
chapter_start=None, section_start=None):
|
||||||
|
"""
|
||||||
|
Add a warning message if the masquerade user would not have access to this content
|
||||||
|
due to the content start date being in the future.
|
||||||
|
"""
|
||||||
|
now = datetime.now(utc)
|
||||||
|
most_future_date = course_start
|
||||||
|
if chapter_start and section_start:
|
||||||
|
most_future_date = max(course_start, chapter_start, section_start)
|
||||||
|
is_masquerading = get_course_masquerade(user, course_key)
|
||||||
|
if now < most_future_date and is_masquerading:
|
||||||
|
group_masquerade = is_masquerading_as_student(user, course_key)
|
||||||
|
specific_student_masquerade = is_masquerading_as_specific_student(user, course_key)
|
||||||
|
is_staff = has_staff_roles(user, course_key)
|
||||||
|
if group_masquerade or (specific_student_masquerade and not is_staff):
|
||||||
|
PageLevelMessages.register_warning_message(
|
||||||
|
request,
|
||||||
|
HTML(_('This user does not have access to this content because \
|
||||||
|
the content start date is in the future')),
|
||||||
|
once_only=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Sentinel object to mark deleted objects in the session cache
|
# Sentinel object to mark deleted objects in the session cache
|
||||||
_DELETED_SENTINEL = object()
|
_DELETED_SENTINEL = object()
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,10 @@ from ..entrance_exams import (
|
|||||||
user_can_skip_entrance_exam,
|
user_can_skip_entrance_exam,
|
||||||
user_has_passed_entrance_exam
|
user_has_passed_entrance_exam
|
||||||
)
|
)
|
||||||
from ..masquerade import setup_masquerade
|
from ..masquerade import (
|
||||||
|
setup_masquerade,
|
||||||
|
check_content_start_date_for_masquerade_user
|
||||||
|
)
|
||||||
from ..model_data import FieldDataCache
|
from ..model_data import FieldDataCache
|
||||||
from ..module_render import get_module_for_descriptor, toc_for_course
|
from ..module_render import get_module_for_descriptor, toc_for_course
|
||||||
|
|
||||||
@@ -182,6 +185,9 @@ class CoursewareIndex(View):
|
|||||||
self._save_positions()
|
self._save_positions()
|
||||||
self._prefetch_and_bind_section()
|
self._prefetch_and_bind_section()
|
||||||
|
|
||||||
|
check_content_start_date_for_masquerade_user(self.course_key, self.effective_user, request,
|
||||||
|
self.course.start, self.chapter.start, self.section.start)
|
||||||
|
|
||||||
if not request.user.is_authenticated:
|
if not request.user.is_authenticated:
|
||||||
qs = urllib.urlencode({
|
qs = urllib.urlencode({
|
||||||
'course_id': self.course_key,
|
'course_id': self.course_key,
|
||||||
|
|||||||
Reference in New Issue
Block a user