diff --git a/cms/djangoapps/contentstore/tests/test_clone_course.py b/cms/djangoapps/contentstore/tests/test_clone_course.py index 25ea5eb6e8..7fe8e10bd2 100644 --- a/cms/djangoapps/contentstore/tests/test_clone_course.py +++ b/cms/djangoapps/contentstore/tests/test_clone_course.py @@ -6,7 +6,7 @@ from opaque_keys.edx.locator import CourseLocator from xmodule.modulestore import ModuleStoreEnum, EdxJSONEncoder from contentstore.tests.utils import CourseTestCase from contentstore.tasks import rerun_course -from contentstore.views.access import has_course_access +from student.auth import has_course_access from course_action_state.models import CourseRerunState from course_action_state.managers import CourseRerunUIStateManager from mock import patch, Mock diff --git a/cms/djangoapps/contentstore/tests/test_permissions.py b/cms/djangoapps/contentstore/tests/test_permissions.py index 6e71d1a418..29c8df9249 100644 --- a/cms/djangoapps/contentstore/tests/test_permissions.py +++ b/cms/djangoapps/contentstore/tests/test_permissions.py @@ -10,7 +10,6 @@ from contentstore.tests.utils import AjaxEnabledTestClient from opaque_keys.edx.locations import SlashSeparatedCourseKey from contentstore.utils import reverse_url, reverse_course_url from student.roles import CourseInstructorRole, CourseStaffRole, OrgStaffRole, OrgInstructorRole -from contentstore.views.access import has_course_access from student import auth @@ -93,7 +92,7 @@ class TestCourseAccess(ModuleStoreTestCase): user = users.pop() group.add_users(user) user_by_role[role].append(user) - self.assertTrue(has_course_access(user, self.course_key), "{} does not have access".format(user)) + self.assertTrue(auth.has_course_access(user, self.course_key), "{} does not have access".format(user)) course_team_url = reverse_course_url('course_team_handler', self.course_key) response = self.client.get_html(course_team_url) @@ -126,9 +125,9 @@ class TestCourseAccess(ModuleStoreTestCase): if hasattr(user, '_roles'): del user._roles - self.assertTrue(has_course_access(user, copy_course_key), "{} no copy access".format(user)) + self.assertTrue(auth.has_course_access(user, copy_course_key), "{} no copy access".format(user)) if (role is OrgStaffRole) or (role is OrgInstructorRole): auth.remove_users(self.user, role(self.course_key.org), user) else: auth.remove_users(self.user, role(self.course_key), user) - self.assertFalse(has_course_access(user, self.course_key), "{} remove didn't work".format(user)) + self.assertFalse(auth.has_course_access(user, self.course_key), "{} remove didn't work".format(user)) diff --git a/cms/djangoapps/contentstore/views/access.py b/cms/djangoapps/contentstore/views/access.py index 6e9eab48b6..bafb5000e1 100644 --- a/cms/djangoapps/contentstore/views/access.py +++ b/cms/djangoapps/contentstore/views/access.py @@ -1,29 +1,9 @@ """ Helper methods for determining user access permissions in Studio """ -from student.roles import CourseStaffRole, GlobalStaff, CourseInstructorRole, OrgStaffRole, OrgInstructorRole +from student.roles import CourseInstructorRole from student import auth -def has_course_access(user, course_key, role=CourseStaffRole): - """ - Return True if user allowed to access this course_id - Note that the CMS permissions model is with respect to courses - There is a super-admin permissions if user.is_staff is set - Also, since we're unifying the user database between LMS and CAS, - I'm presuming that the course instructor (formally known as admin) - will not be in both INSTRUCTOR and STAFF groups, so we have to cascade our - queries here as INSTRUCTOR has all the rights that STAFF do - """ - 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 - # temporary to ensure we give universal access given a course until we impl branch specific perms - return auth.has_access(user, role(course_key.for_branch(None))) - - def get_user_role(user, course_id): """ What type of access: staff or instructor does this user have in Studio? diff --git a/cms/djangoapps/contentstore/views/assets.py b/cms/djangoapps/contentstore/views/assets.py index 95baa62747..63e96046b5 100644 --- a/cms/djangoapps/contentstore/views/assets.py +++ b/cms/djangoapps/contentstore/views/assets.py @@ -26,7 +26,7 @@ from util.json_request import JsonResponse from django.http import HttpResponseNotFound from django.utils.translation import ugettext as _ from pymongo import ASCENDING, DESCENDING -from .access import has_course_access +from student.auth import has_course_access from xmodule.modulestore.exceptions import ItemNotFoundError __all__ = ['assets_handler'] diff --git a/cms/djangoapps/contentstore/views/checklist.py b/cms/djangoapps/contentstore/views/checklist.py index 0d58ee8a36..18d332bd67 100644 --- a/cms/djangoapps/contentstore/views/checklist.py +++ b/cms/djangoapps/contentstore/views/checklist.py @@ -13,7 +13,7 @@ from opaque_keys.edx.keys import CourseKey from xmodule.modulestore.django import modulestore from contentstore.utils import reverse_course_url -from .access import has_course_access +from student.auth import has_course_access from xmodule.course_module import CourseDescriptor from django.utils.translation import ugettext diff --git a/cms/djangoapps/contentstore/views/component.py b/cms/djangoapps/contentstore/views/component.py index 40209bf37d..8c9cbebe70 100644 --- a/cms/djangoapps/contentstore/views/component.py +++ b/cms/djangoapps/contentstore/views/component.py @@ -25,7 +25,7 @@ from contentstore.views.item import create_xblock_info from opaque_keys.edx.keys import UsageKey -from .access import has_course_access +from student.auth import has_course_access from django.utils.translation import ugettext as _ from models.settings.course_grading import CourseGradingModel diff --git a/cms/djangoapps/contentstore/views/course.py b/cms/djangoapps/contentstore/views/course.py index 7f62d1ac42..e0fbd6ffbc 100644 --- a/cms/djangoapps/contentstore/views/course.py +++ b/cms/djangoapps/contentstore/views/course.py @@ -47,7 +47,7 @@ from models.settings.course_grading import CourseGradingModel from models.settings.course_metadata import CourseMetadata from util.json_request import expect_json from util.string_utils import _has_non_ascii_characters -from .access import has_course_access +from student.auth import has_course_access from .component import ( OPEN_ENDED_COMPONENT_TYPES, NOTE_COMPONENT_TYPES, diff --git a/cms/djangoapps/contentstore/views/export_git.py b/cms/djangoapps/contentstore/views/export_git.py index 94edd13018..b7678305a8 100644 --- a/cms/djangoapps/contentstore/views/export_git.py +++ b/cms/djangoapps/contentstore/views/export_git.py @@ -10,7 +10,7 @@ from django.core.exceptions import PermissionDenied from django_future.csrf import ensure_csrf_cookie from django.utils.translation import ugettext as _ -from .access import has_course_access +from student.auth import has_course_access import contentstore.git_export_utils as git_export_utils from edxmako.shortcuts import render_to_response from xmodule.modulestore.django import modulestore diff --git a/cms/djangoapps/contentstore/views/import_export.py b/cms/djangoapps/contentstore/views/import_export.py index 91dc1f8d3c..18010468af 100644 --- a/cms/djangoapps/contentstore/views/import_export.py +++ b/cms/djangoapps/contentstore/views/import_export.py @@ -28,7 +28,7 @@ from opaque_keys.edx.keys import CourseKey from xmodule.modulestore.xml_importer import import_from_xml from xmodule.modulestore.xml_exporter import export_to_xml -from .access import has_course_access +from student.auth import has_course_access from extract_tar import safetar_extractall from util.json_request import JsonResponse diff --git a/cms/djangoapps/contentstore/views/item.py b/cms/djangoapps/contentstore/views/item.py index e09db7a4e4..60f9f59ae4 100644 --- a/cms/djangoapps/contentstore/views/item.py +++ b/cms/djangoapps/contentstore/views/item.py @@ -37,7 +37,7 @@ from util.date_utils import get_default_time_display from util.json_request import expect_json, JsonResponse -from .access import has_course_access +from student.auth import has_course_access from contentstore.utils import find_release_date_source, find_staff_lock_source, is_currently_visible_to_students, \ ancestor_has_staff_lock from contentstore.views.helpers import is_unit, xblock_studio_url, xblock_primary_child_category, \ diff --git a/cms/djangoapps/contentstore/views/tabs.py b/cms/djangoapps/contentstore/views/tabs.py index d374e64343..7d15cd3b89 100644 --- a/cms/djangoapps/contentstore/views/tabs.py +++ b/cms/djangoapps/contentstore/views/tabs.py @@ -1,7 +1,7 @@ """ Views related to course tabs """ -from access import has_course_access +from student.auth import has_course_access from util.json_request import expect_json, JsonResponse from django.http import HttpResponseNotFound diff --git a/cms/djangoapps/contentstore/views/tests/test_course_index.py b/cms/djangoapps/contentstore/views/tests/test_course_index.py index eb8adc5ea7..9bc6e3aacc 100644 --- a/cms/djangoapps/contentstore/views/tests/test_course_index.py +++ b/cms/djangoapps/contentstore/views/tests/test_course_index.py @@ -7,7 +7,7 @@ import datetime from contentstore.tests.utils import CourseTestCase from contentstore.utils import reverse_course_url, add_instructor -from contentstore.views.access import has_course_access +from student.auth import has_course_access from contentstore.views.course import course_outline_initial_state from contentstore.views.item import create_xblock_info, VisibilityState from course_action_state.models import CourseRerunState diff --git a/cms/djangoapps/contentstore/views/transcripts_ajax.py b/cms/djangoapps/contentstore/views/transcripts_ajax.py index d404a6d9dc..ae68509b97 100644 --- a/cms/djangoapps/contentstore/views/transcripts_ajax.py +++ b/cms/djangoapps/contentstore/views/transcripts_ajax.py @@ -38,7 +38,7 @@ from xmodule.video_module.transcripts_utils import ( TranscriptsRequestValidationException ) -from .access import has_course_access +from student.auth import has_course_access __all__ = [ 'upload_transcripts', diff --git a/cms/djangoapps/contentstore/views/user.py b/cms/djangoapps/contentstore/views/user.py index 7e3b720e2b..b1e7029a12 100644 --- a/cms/djangoapps/contentstore/views/user.py +++ b/cms/djangoapps/contentstore/views/user.py @@ -13,7 +13,7 @@ from util.json_request import JsonResponse, expect_json from student.roles import CourseInstructorRole, CourseStaffRole from course_creators.views import user_requested_access -from .access import has_course_access +from student.auth import has_course_access from student.models import CourseEnrollment from django.http import HttpResponseNotFound diff --git a/common/djangoapps/student/auth.py b/common/djangoapps/student/auth.py index 7fa22b9d58..b68055696c 100644 --- a/common/djangoapps/student/auth.py +++ b/common/djangoapps/student/auth.py @@ -8,7 +8,7 @@ from django.core.exceptions import PermissionDenied from django.conf import settings from student.roles import GlobalStaff, CourseCreatorRole, CourseStaffRole, CourseInstructorRole, CourseRole, \ - CourseBetaTesterRole + CourseBetaTesterRole, OrgInstructorRole, OrgStaffRole def has_access(user, role): @@ -40,6 +40,30 @@ def has_access(user, role): return False +def has_course_access(user, course_key, role=CourseStaffRole): + """ + Return True if user allowed to access this course_id + Note that the CMS permissions model is with respect to courses + There is a super-admin permissions if user.is_staff is set + Also, since we're unifying the user database between LMS and CAS, + I'm presuming that the course instructor (formally known as admin) + will not be in both INSTRUCTOR and STAFF groups, so we have to cascade our + queries here as INSTRUCTOR has all the rights that STAFF do. + + :param user: + :param course_key: A course key + :param role: an AccessRole + """ + 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 + # temporary to ensure we give universal access given a course until we impl branch specific perms + return has_access(user, role(course_key.for_branch(None))) + + def add_users(caller, role, *users): """ The caller requests adding the given users to the role. Checks that the caller