Commit 3f3e9724 by Julia Hansbrough Committed by Sarina Canelake

Add fallback for org based roles

parent 29bb179a
......@@ -6,14 +6,15 @@ import random
from chrono import Timer
from mock import patch, Mock
import ddt
from django.test import RequestFactory
from contentstore.views.course import _accessible_courses_list, _accessible_courses_list_from_groups
from contentstore.views.course import _accessible_courses_list, _accessible_courses_list_from_groups, AccessListFallback
from contentstore.utils import delete_course_and_groups, reverse_course_url
from contentstore.tests.utils import AjaxEnabledTestClient
from student.tests.factories import UserFactory
from student.roles import CourseInstructorRole, CourseStaffRole, GlobalStaff
from student.roles import CourseInstructorRole, CourseStaffRole, GlobalStaff, OrgStaffRole, OrgInstructorRole
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.locations import SlashSeparatedCourseKey
......@@ -24,6 +25,7 @@ TOTAL_COURSES_COUNT = 500
USER_COURSES_COUNT = 50
@ddt.ddt
class TestCourseListing(ModuleStoreTestCase):
"""
Unit tests for getting the list of courses for a logged in user
......@@ -271,3 +273,31 @@ class TestCourseListing(ModuleStoreTestCase):
courses_list = _accessible_courses_list_from_groups(self.request)
self.assertEqual(len(courses_list), 1, courses_list)
@ddt.data(OrgStaffRole('AwesomeOrg'), OrgInstructorRole('AwesomeOrg'))
def test_course_listing_org_permissions(self, role):
"""
Create multiple courses within the same org. Verify that someone with org-wide permissions can access
all of them.
"""
org_course_one = SlashSeparatedCourseKey('AwesomeOrg', 'Course1', 'RunBabyRun')
CourseFactory.create(
org=org_course_one.org,
number=org_course_one.course,
run=org_course_one.run
)
org_course_two = SlashSeparatedCourseKey('AwesomeOrg', 'Course2', 'RunRunRun')
CourseFactory.create(
org=org_course_two.org,
number=org_course_two.course,
run=org_course_two.run
)
# Two types of org-wide roles have edit permissions: staff and instructor. We test both
role.add_users(self.user)
with self.assertRaises(AccessListFallback):
_accessible_courses_list_from_groups(self.request)
courses_list = _accessible_courses_list(self.request)
self.assertEqual(len(courses_list), 2)
from student.roles import CourseStaffRole, GlobalStaff, CourseInstructorRole
""" Helper methods for determining user access permissions in Studio """
from student.roles import CourseStaffRole, GlobalStaff, CourseInstructorRole, OrgStaffRole, OrgInstructorRole
from student import auth
......@@ -14,6 +16,10 @@ def has_course_access(user, course_key, role=CourseStaffRole):
"""
if GlobalStaff().has_user(user):
return True
if OrgInstructorRole(org=course_key.org).has_user(user):
return True
if OrgStaffRole(org=course_key.org).has_user(user):
return True
return auth.has_access(user, role(course_key))
......
......@@ -68,6 +68,14 @@ __all__ = ['course_info_handler', 'course_handler', 'course_info_update_handler'
'textbooks_list_handler', 'textbooks_detail_handler']
class AccessListFallback(Exception):
"""
An exception that is raised whenever we need to `fall back` to fetching *all* courses
available to a user, rather than using a shorter method (i.e. fetching by group)
"""
pass
def _get_course_module(course_key, user, depth=0):
"""
Internal method used to calculate and return the locator and course module
......@@ -190,8 +198,13 @@ def _accessible_courses_list_from_groups(request):
for course_access in all_courses:
course_key = course_access.course_id
if course_key not in courses_list:
if course_key is None:
# If the course_access does not have a course_id, it's an org-based role, so we fall back
raise AccessListFallback
try:
course = modulestore('direct').get_course(course_key)
except ItemNotFoundError:
raise ItemNotFoundError
if course is not None and not isinstance(course, ErrorDescriptor):
# ignore deleted or errored courses
courses_list[course_key] = course
......@@ -213,7 +226,7 @@ def course_listing(request):
else:
try:
courses = _accessible_courses_list_from_groups(request)
except ItemNotFoundError:
except AccessListFallback:
# user have some old groups or there was some error getting courses from django groups
# so fallback to iterating through all courses
courses = _accessible_courses_list(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