Commit 6834376b by Don Mitchell

Don't fetch the course just to find out if the user has access to it.

parent d466132a
...@@ -23,6 +23,7 @@ from student.roles import ( ...@@ -23,6 +23,7 @@ from student.roles import (
GlobalStaff, CourseStaffRole, CourseInstructorRole, GlobalStaff, CourseStaffRole, CourseInstructorRole,
OrgStaffRole, OrgInstructorRole, CourseBetaTesterRole OrgStaffRole, OrgInstructorRole, CourseBetaTesterRole
) )
from xmodule.modulestore.keys import CourseKey
DEBUG_ACCESS = False DEBUG_ACCESS = False
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
...@@ -81,6 +82,9 @@ def has_access(user, action, obj, course_key=None): ...@@ -81,6 +82,9 @@ def has_access(user, action, obj, course_key=None):
if isinstance(obj, XBlock): if isinstance(obj, XBlock):
return _has_access_descriptor(user, action, obj, course_key) return _has_access_descriptor(user, action, obj, course_key)
if isinstance(obj, CourseKey):
return _has_access_course_key(user, action, obj)
if isinstance(obj, Location): if isinstance(obj, Location):
return _has_access_location(user, action, obj, course_key) return _has_access_location(user, action, obj, course_key)
...@@ -297,8 +301,6 @@ def _has_access_location(user, action, location, course_key): ...@@ -297,8 +301,6 @@ def _has_access_location(user, action, location, course_key):
NOTE: if you add other actions, make sure that NOTE: if you add other actions, make sure that
has_access(user, location, action) == has_access(user, get_item(location), action) has_access(user, location, action) == has_access(user, get_item(location), action)
And in general, prefer checking access on loaded items, rather than locations.
""" """
checkers = { checkers = {
'staff': lambda: _has_staff_access_to_location(user, location, course_key) 'staff': lambda: _has_staff_access_to_location(user, location, course_key)
...@@ -307,6 +309,22 @@ def _has_access_location(user, action, location, course_key): ...@@ -307,6 +309,22 @@ def _has_access_location(user, action, location, course_key):
return _dispatch(checkers, action, user, location) return _dispatch(checkers, action, user, location)
def _has_access_course_key(user, action, course_key):
"""
Check if user has access to the course with this course_key
Valid actions:
'staff' : True if the user has staff access to this location
'instructor' : True if the user has staff access to this location
"""
checkers = {
'staff': lambda: _has_staff_access_to_location(user, None, course_key),
'instructor': lambda: _has_instructor_access_to_location(user, None, course_key),
}
return _dispatch(checkers, action, user, course_key)
def _has_access_string(user, action, perm, course_key): def _has_access_string(user, action, perm, course_key):
""" """
Check if user has certain special access, specified as string. Valid strings: Check if user has certain special access, specified as string. Valid strings:
...@@ -388,27 +406,25 @@ def _adjust_start_date_for_beta_testers(user, descriptor, course_key=None): # p ...@@ -388,27 +406,25 @@ def _adjust_start_date_for_beta_testers(user, descriptor, course_key=None): # p
return descriptor.start return descriptor.start
def _has_instructor_access_to_location(user, location, course_key=None): # pylint: disable=invalid-name def _has_instructor_access_to_location(user, location, course_key=None):
return _has_access_to_location(user, 'instructor', location, course_key) if course_key is None:
course_key = location.course_key
return _has_access_to_course(user, 'instructor', course_key)
def _has_staff_access_to_location(user, location, course_key=None): def _has_staff_access_to_location(user, location, course_key=None):
return _has_access_to_location(user, 'staff', location, course_key) if course_key is None:
course_key = location.course_key
return _has_access_to_course(user, 'staff', course_key)
def _has_access_to_location(user, access_level, location, course_key): def _has_access_to_course(user, access_level, course_key):
''' '''
Returns True if the given user has access_level (= staff or Returns True if the given user has access_level (= staff or
instructor) access to a location. For now this is equivalent to instructor) access to the course with the given course_key.
having staff / instructor access to the course location.course. This ensures the user is authenticated and checks if global staff or has
staff / instructor access.
This means that user is in the staff_* group or instructor_* group, or is an overall admin.
TODO (vshnayder): this needs to be changed to allow per-course_key permissions, not per-course
(e.g. staff in 2012 is different from 2013, but maybe some people always have access)
course is a string: the course field of the location being accessed.
location = location
access_level = string, either "staff" or "instructor" access_level = string, either "staff" or "instructor"
''' '''
if user is None or (not user.is_authenticated()): if user is None or (not user.is_authenticated()):
...@@ -423,7 +439,7 @@ def _has_access_to_location(user, access_level, location, course_key): ...@@ -423,7 +439,7 @@ def _has_access_to_location(user, access_level, location, course_key):
return True return True
if access_level not in ('staff', 'instructor'): if access_level not in ('staff', 'instructor'):
log.debug("Error in access._has_access_to_location access_level=%s unknown", access_level) log.debug("Error in access._has_access_to_course access_level=%s unknown", access_level)
debug("Deny: unknown access level") debug("Deny: unknown access level")
return False return False
...@@ -449,13 +465,6 @@ def _has_access_to_location(user, access_level, location, course_key): ...@@ -449,13 +465,6 @@ def _has_access_to_location(user, access_level, location, course_key):
return False return False
# TODO Please change this function signature to _has_staff_access_to_course_key at next opportunity!
def _has_staff_access_to_course_id(user, course_key):
"""Helper method that takes a course_key instead of a course name"""
loc = CourseDescriptor.id_to_location(course_key)
return _has_staff_access_to_location(user, loc, course_key)
def _has_instructor_access_to_descriptor(user, descriptor, course_key): # pylint: disable=invalid-name def _has_instructor_access_to_descriptor(user, descriptor, course_key): # pylint: disable=invalid-name
"""Helper method that checks whether the user has staff access to """Helper method that checks whether the user has staff access to
the course of the location. the course of the location.
...@@ -479,13 +488,11 @@ def get_user_role(user, course_key): ...@@ -479,13 +488,11 @@ def get_user_role(user, course_key):
Return corresponding string if user has staff, instructor or student Return corresponding string if user has staff, instructor or student
course role in LMS. course role in LMS.
""" """
from courseware.courses import get_course
course = get_course(course_key)
if is_masquerading_as_student(user): if is_masquerading_as_student(user):
return 'student' return 'student'
elif has_access(user, 'instructor', course): elif has_access(user, 'instructor', course_key):
return 'instructor' return 'instructor'
elif has_access(user, 'staff', course): elif has_access(user, 'staff', course_key):
return 'staff' return 'staff'
else: else:
return 'student' return 'student'
...@@ -8,7 +8,6 @@ from django.test.utils import override_settings ...@@ -8,7 +8,6 @@ from django.test.utils import override_settings
from courseware.tests.factories import UserFactory, StaffFactory, InstructorFactory from courseware.tests.factories import UserFactory, StaffFactory, InstructorFactory
from student.tests.factories import AnonymousUserFactory, CourseEnrollmentAllowedFactory from student.tests.factories import AnonymousUserFactory, CourseEnrollmentAllowedFactory
from xmodule.modulestore import Location
from courseware.tests.tests import TEST_DATA_MIXED_MODULESTORE from courseware.tests.tests import TEST_DATA_MIXED_MODULESTORE
import pytz import pytz
from xmodule.modulestore.locations import SlashSeparatedCourseKey from xmodule.modulestore.locations import SlashSeparatedCourseKey
...@@ -31,48 +30,48 @@ class AccessTestCase(TestCase): ...@@ -31,48 +30,48 @@ class AccessTestCase(TestCase):
self.course_staff = StaffFactory(course=self.course.course_key) self.course_staff = StaffFactory(course=self.course.course_key)
self.course_instructor = InstructorFactory(course=self.course.course_key) self.course_instructor = InstructorFactory(course=self.course.course_key)
def test__has_access_to_location(self): def test_has_access_to_course(self):
self.assertFalse(access._has_access_to_location( self.assertFalse(access._has_access_to_course(
None, 'staff', self.course, self.course.course_key None, 'staff', self.course.course_key
)) ))
self.assertFalse(access._has_access_to_location( self.assertFalse(access._has_access_to_course(
self.anonymous_user, 'staff', self.course, self.course.course_key self.anonymous_user, 'staff', self.course.course_key
)) ))
self.assertFalse(access._has_access_to_location( self.assertFalse(access._has_access_to_course(
self.anonymous_user, 'instructor', self.course, self.course.course_key self.anonymous_user, 'instructor', self.course.course_key
)) ))
self.assertTrue(access._has_access_to_location( self.assertTrue(access._has_access_to_course(
self.global_staff, 'staff', self.course, self.course.course_key self.global_staff, 'staff', self.course.course_key
)) ))
self.assertTrue(access._has_access_to_location( self.assertTrue(access._has_access_to_course(
self.global_staff, 'instructor', self.course, self.course.course_key self.global_staff, 'instructor', self.course.course_key
)) ))
# A user has staff access if they are in the staff group # A user has staff access if they are in the staff group
self.assertTrue(access._has_access_to_location( self.assertTrue(access._has_access_to_course(
self.course_staff, 'staff', self.course, self.course.course_key self.course_staff, 'staff', self.course.course_key
)) ))
self.assertFalse(access._has_access_to_location( self.assertFalse(access._has_access_to_course(
self.course_staff, 'instructor', self.course, self.course.course_key self.course_staff, 'instructor', self.course.course_key
)) ))
# A user has staff and instructor access if they are in the instructor group # A user has staff and instructor access if they are in the instructor group
self.assertTrue(access._has_access_to_location( self.assertTrue(access._has_access_to_course(
self.course_instructor, 'staff', self.course, self.course.course_key self.course_instructor, 'staff', self.course.course_key
)) ))
self.assertTrue(access._has_access_to_location( self.assertTrue(access._has_access_to_course(
self.course_instructor, 'instructor', self.course, self.course.course_key self.course_instructor, 'instructor', self.course.course_key
)) ))
# A user does not have staff or instructor access if they are # A user does not have staff or instructor access if they are
# not in either the staff or the the instructor group # not in either the staff or the the instructor group
self.assertFalse(access._has_access_to_location( self.assertFalse(access._has_access_to_course(
self.student, 'staff', self.course, self.course.course_key self.student, 'staff', self.course.course_key
)) ))
self.assertFalse(access._has_access_to_location( self.assertFalse(access._has_access_to_course(
self.student, 'instructor', self.course, self.course.course_key self.student, 'instructor', self.course.course_key
)) ))
def test__has_access_string(self): def test__has_access_string(self):
......
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