Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lms/djangoapps/courseware/access.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
MilestoneAccessError,
MobileAvailabilityError,
NoAllowedPartitionGroupsError,
OldMongoAccessError,
VisibilityError
)
from lms.djangoapps.courseware.access_utils import (
Expand Down Expand Up @@ -329,6 +330,9 @@ def can_load():
# ).or(
# _has_staff_access_to_descriptor, user, courselike, courselike.id
# )
if courselike.id.deprecated: # we no longer support accessing Old Mongo courses
return OldMongoAccessError(courselike)

visible_to_nonstaff = _visible_to_nonstaff_users(courselike)
if not visible_to_nonstaff:
staff_access = _has_staff_access_to_descriptor(user, courselike, courselike.id)
Expand Down
13 changes: 13 additions & 0 deletions lms/djangoapps/courseware/access_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,16 @@ def __init__(self):
developer_message = "User must be authenticated to view the course"
user_message = _("You must be logged in to see this course")
super().__init__(error_code, developer_message, user_message)


class OldMongoAccessError(AccessError):
"""
Access denied because the course is in Old Mongo and we no longer support them. See DEPR-58.
"""
def __init__(self, courselike):
error_code = 'old_mongo'
developer_message = 'Access to Old Mongo courses is unsupported'
user_message = _('{course_name} is no longer available.').format(
course_name=courselike.display_name_with_default,
)
super().__init__(error_code, developer_message, user_message)
10 changes: 10 additions & 0 deletions lms/djangoapps/courseware/courses.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
AuthenticationRequiredAccessError,
EnrollmentRequiredAccessError,
MilestoneAccessError,
OldMongoAccessError,
StartDateError,
)
from lms.djangoapps.courseware.date_summary import (
Expand Down Expand Up @@ -213,6 +214,15 @@ def check_course_access_with_redirect(course, user, action, check_if_enrolled=Fa
params=params.urlencode()
), access_response)

# Redirect if trying to access an Old Mongo course
if isinstance(access_response, OldMongoAccessError):
params = QueryDict(mutable=True)
params['access_response_error'] = access_response.user_message
raise CourseAccessRedirect('{dashboard_url}?{params}'.format(
dashboard_url=reverse('dashboard'),
params=params.urlencode(),
), access_response)

# Redirect if the user must answer a survey before entering the course.
if isinstance(access_response, MilestoneAccessError):
raise CourseAccessRedirect('{dashboard_url}'.format(
Expand Down
13 changes: 13 additions & 0 deletions lms/djangoapps/courseware/tests/test_courses.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
get_courses,
get_current_child
)
from lms.djangoapps.courseware.exceptions import CourseAccessRedirect
from lms.djangoapps.courseware.model_data import FieldDataCache
from lms.djangoapps.courseware.module_render import get_module_for_descriptor
from lms.djangoapps.courseware.courseware_access_exception import CoursewareAccessException
Expand Down Expand Up @@ -88,6 +89,18 @@ def test_get_course_func_with_access_error(self, course_access_func_name):
assert error.value.access_response.error_code == 'not_visible_to_user'
assert not error.value.access_response.has_access

@ddt.data(GET_COURSE_WITH_ACCESS, GET_COURSE_OVERVIEW_WITH_ACCESS)
def test_old_mongo_access_error(self, course_access_func_name):
course_access_func = self.COURSE_ACCESS_FUNCS[course_access_func_name]
user = UserFactory.create()
with self.store.default_store(ModuleStoreEnum.Type.mongo):
course = CourseFactory.create()

with pytest.raises(CourseAccessRedirect) as error:
course_access_func(user, 'load', course.id)
assert error.value.access_error.error_code == 'old_mongo'
assert not error.value.access_error.has_access

@ddt.data(
(GET_COURSE_WITH_ACCESS, 3),
(GET_COURSE_OVERVIEW_WITH_ACCESS, 0),
Expand Down
19 changes: 19 additions & 0 deletions openedx/features/course_experience/tests/views/test_course_home.py
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,25 @@ def test_expired_course(self):
)
self.assertRedirects(response, expected_url)

def test_old_mongo_access_error(self):
"""
Ensure that a user accessing an Old Mongo course sees a redirect to
the student dashboard, not a 404.
"""
course = CourseFactory.create(default_store=ModuleStoreEnum.Type.mongo)
user = UserFactory(password=self.TEST_PASSWORD)
self.client.login(username=user.username, password=self.TEST_PASSWORD)

response = self.client.get(course_home_url(course))

expected_params = QueryDict(mutable=True)
expected_params['access_response_error'] = f'{course.display_name_with_default} is no longer available.'
expected_url = '{url}?{params}'.format(
url=reverse('dashboard'),
params=expected_params.urlencode(),
)
self.assertRedirects(response, expected_url)

@mock.patch.dict(settings.FEATURES, {'DISABLE_START_DATES': False})
def test_expiration_banner_with_expired_upgrade_deadline(self):
"""
Expand Down