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:
Matthew Piatetsky
2019-01-17 13:12:42 -05:00
committed by GitHub
4 changed files with 42 additions and 16 deletions

View File

@@ -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)

View File

@@ -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

View File

@@ -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()

View File

@@ -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,