diff --git a/common/djangoapps/student/auth.py b/common/djangoapps/student/auth.py index f2e7b7f914..efb93cde52 100644 --- a/common/djangoapps/student/auth.py +++ b/common/djangoapps/student/auth.py @@ -7,6 +7,7 @@ to decide whether to check course creator role, and other such functions. from django.core.exceptions import PermissionDenied from django.conf import settings from opaque_keys.edx.locator import LibraryLocator +from ccx_keys.locator import CCXLocator, CCXBlockUsageLocator from student.roles import GlobalStaff, CourseCreatorRole, CourseStaffRole, CourseInstructorRole, CourseRole, \ CourseBetaTesterRole, OrgInstructorRole, OrgStaffRole, LibraryUserRole, OrgLibraryUserRole @@ -17,9 +18,18 @@ STUDIO_EDIT_ROLES = 8 STUDIO_VIEW_USERS = 4 STUDIO_EDIT_CONTENT = 2 STUDIO_VIEW_CONTENT = 1 +STUDIO_NO_PERMISSIONS = 0 # In addition to the above, one is always allowed to "demote" oneself to a lower role within a course, or remove oneself +def is_ccx_course(course_key): + """ + Check whether the course locator maps to a CCX course; this is important + because we don't allow access to CCX courses in Studio. + """ + return isinstance(course_key, CCXLocator) or isinstance(course_key, CCXBlockUsageLocator) + + def user_has_role(user, role): """ Check whether this user has access to this role (either direct or implied) @@ -60,6 +70,9 @@ def get_user_permissions(user, course_key, org=None): course_key = course_key.for_branch(None) else: assert course_key is None + # No one has studio permissions for CCX courses + if is_ccx_course(course_key): + return STUDIO_NO_PERMISSIONS all_perms = STUDIO_EDIT_ROLES | STUDIO_VIEW_USERS | STUDIO_EDIT_CONTENT | STUDIO_VIEW_CONTENT # global staff, org instructors, and course instructors have all permissions: if GlobalStaff().has_user(user) or OrgInstructorRole(org=org).has_user(user): @@ -73,7 +86,7 @@ def get_user_permissions(user, course_key, org=None): if course_key and isinstance(course_key, LibraryLocator): if OrgLibraryUserRole(org=org).has_user(user) or user_has_role(user, LibraryUserRole(course_key)): return STUDIO_VIEW_USERS | STUDIO_VIEW_CONTENT - return 0 + return STUDIO_NO_PERMISSIONS def has_studio_write_access(user, course_key): diff --git a/common/djangoapps/student/tests/test_authz.py b/common/djangoapps/student/tests/test_authz.py index e66da9622b..bafa96ca9c 100644 --- a/common/djangoapps/student/tests/test_authz.py +++ b/common/djangoapps/student/tests/test_authz.py @@ -9,8 +9,9 @@ from django.core.exceptions import PermissionDenied from student.roles import CourseInstructorRole, CourseStaffRole, CourseCreatorRole from student.tests.factories import AdminFactory -from student.auth import user_has_role, add_users, remove_users +from student.auth import user_has_role, add_users, remove_users, has_studio_write_access, has_studio_read_access from opaque_keys.edx.locations import SlashSeparatedCourseKey +from ccx_keys.locator import CCXLocator class CreatorGroupTest(TestCase): @@ -132,6 +133,45 @@ class CreatorGroupTest(TestCase): remove_users(self.admin, CourseCreatorRole(), self.user) +class CCXCourseGroupTest(TestCase): + """ + Test that access to a CCX course in Studio is disallowed + """ + def setUp(self): + """ + Set up test variables + """ + super(CCXCourseGroupTest, self).setUp() + self.global_admin = AdminFactory() + self.staff = User.objects.create_user('teststaff', 'teststaff+courses@edx.org', 'foo') + self.ccx_course_key = CCXLocator.from_string('ccx-v1:edX+DemoX+Demo_Course+ccx@1') + add_users(self.global_admin, CourseStaffRole(self.ccx_course_key), self.staff) + + def test_no_global_admin_write_access(self): + """ + Test that global admins have no write access + """ + self.assertFalse(has_studio_write_access(self.global_admin, self.ccx_course_key)) + + def test_no_staff_write_access(self): + """ + Test that course staff have no write access + """ + self.assertFalse(has_studio_write_access(self.staff, self.ccx_course_key)) + + def test_no_global_admin_read_access(self): + """ + Test that global admins have no read access + """ + self.assertFalse(has_studio_read_access(self.global_admin, self.ccx_course_key)) + + def test_no_staff_read_access(self): + """ + Test that course staff have no read access + """ + self.assertFalse(has_studio_read_access(self.staff, self.ccx_course_key)) + + class CourseGroupTest(TestCase): """ Tests for instructor and staff groups for a particular course.