fix: CourseLimitedStaffRole should not be able to access studio.
We previously fixed this when the CourseLimitedStaffRole was applied to a course but did not handle the case where the role is applied to a user for a whole org. The underlying issue is that the CourseLimitedStaffRole is a subclass of the CourseStaffRole and much of the system assumes that subclesses are for giving more access not less access. To prevent that from happening for the case of the CourseLimitedStaffRole, when we do CourseStaffRole access checks, we use the strict_role_checking context manager to ensure that we're not accidentally granting the limited_staff role too much access.
This commit is contained in:
@@ -21,8 +21,10 @@ from cms.djangoapps.contentstore.views.course import (
|
||||
get_courses_accessible_to_user
|
||||
)
|
||||
from common.djangoapps.course_action_state.models import CourseRerunState
|
||||
from common.djangoapps.student.models.user import CourseAccessRole
|
||||
from common.djangoapps.student.roles import (
|
||||
CourseInstructorRole,
|
||||
CourseLimitedStaffRole,
|
||||
CourseStaffRole,
|
||||
GlobalStaff,
|
||||
OrgInstructorRole,
|
||||
@@ -176,6 +178,48 @@ class TestCourseListing(ModuleStoreTestCase):
|
||||
with self.assertNumQueries(2):
|
||||
list(_accessible_courses_summary_iter(self.request))
|
||||
|
||||
def test_course_limited_staff_course_listing(self):
|
||||
# Setup a new course
|
||||
course_location = self.store.make_course_key('Org', 'CreatedCourse', 'Run')
|
||||
CourseFactory.create(
|
||||
org=course_location.org,
|
||||
number=course_location.course,
|
||||
run=course_location.run
|
||||
)
|
||||
course = CourseOverviewFactory.create(id=course_location, org=course_location.org)
|
||||
|
||||
# Add the user as a course_limited_staff on the course
|
||||
CourseLimitedStaffRole(course.id).add_users(self.user)
|
||||
self.assertTrue(CourseLimitedStaffRole(course.id).has_user(self.user))
|
||||
|
||||
# Fetch accessible courses list & verify their count
|
||||
courses_list_by_staff, __ = get_courses_accessible_to_user(self.request)
|
||||
|
||||
# Limited Course Staff should not be able to list courses in Studio
|
||||
assert len(list(courses_list_by_staff)) == 0
|
||||
|
||||
def test_org_limited_staff_course_listing(self):
|
||||
|
||||
# Setup a new course
|
||||
course_location = self.store.make_course_key('Org', 'CreatedCourse', 'Run')
|
||||
CourseFactory.create(
|
||||
org=course_location.org,
|
||||
number=course_location.course,
|
||||
run=course_location.run
|
||||
)
|
||||
course = CourseOverviewFactory.create(id=course_location, org=course_location.org)
|
||||
|
||||
# Add a user as course_limited_staff on the org
|
||||
# This is not possible using the course roles classes but is possible via Django admin so we
|
||||
# insert a row into the model directly to test that scenario.
|
||||
CourseAccessRole.objects.create(user=self.user, org=course_location.org, role=CourseLimitedStaffRole.ROLE)
|
||||
|
||||
# Fetch accessible courses list & verify their count
|
||||
courses_list_by_staff, __ = get_courses_accessible_to_user(self.request)
|
||||
|
||||
# Limited Course Staff should not be able to list courses in Studio
|
||||
assert len(list(courses_list_by_staff)) == 0
|
||||
|
||||
def test_get_course_list_with_invalid_course_location(self):
|
||||
"""
|
||||
Test getting courses with invalid course location (course deleted from modulestore).
|
||||
|
||||
@@ -61,6 +61,7 @@ from common.djangoapps.student.roles import (
|
||||
GlobalStaff,
|
||||
UserBasedRole,
|
||||
OrgStaffRole,
|
||||
strict_role_checking,
|
||||
)
|
||||
from common.djangoapps.util.json_request import JsonResponse, JsonResponseBadRequest, expect_json
|
||||
from common.djangoapps.util.string_utils import _has_non_ascii_characters
|
||||
@@ -532,7 +533,9 @@ def _accessible_courses_list_from_groups(request):
|
||||
return not isinstance(course_access.course_id, CCXLocator)
|
||||
|
||||
instructor_courses = UserBasedRole(request.user, CourseInstructorRole.ROLE).courses_with_role()
|
||||
staff_courses = UserBasedRole(request.user, CourseStaffRole.ROLE).courses_with_role()
|
||||
with strict_role_checking():
|
||||
staff_courses = UserBasedRole(request.user, CourseStaffRole.ROLE).courses_with_role()
|
||||
|
||||
all_courses = list(filter(filter_ccx, instructor_courses | staff_courses))
|
||||
courses_list = []
|
||||
course_keys = {}
|
||||
|
||||
Reference in New Issue
Block a user