Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
4fc3ee47
Commit
4fc3ee47
authored
Jul 19, 2015
by
tlindaliu
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #8838 from edx/lliu/has-access-rebased
Changes to has_access
parents
4b4ce5f1
0c837adf
Show whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
500 additions
and
219 deletions
+500
-219
cms/djangoapps/contentstore/views/access.py
+1
-1
cms/djangoapps/contentstore/views/course.py
+1
-1
cms/djangoapps/contentstore/views/tests/test_user.py
+16
-16
cms/djangoapps/course_creators/tests/test_admin.py
+2
-2
cms/djangoapps/course_creators/tests/test_views.py
+5
-5
common/djangoapps/student/auth.py
+5
-5
common/djangoapps/student/tests/test_authz.py
+19
-19
lms/djangoapps/class_dashboard/tests/test_dashboard_data.py
+1
-1
lms/djangoapps/class_dashboard/views.py
+1
-1
lms/djangoapps/course_structure_api/v0/views.py
+4
-2
lms/djangoapps/courseware/access.py
+160
-59
lms/djangoapps/courseware/access_response.py
+126
-0
lms/djangoapps/courseware/module_render.py
+4
-4
lms/djangoapps/courseware/tabs.py
+1
-1
lms/djangoapps/courseware/tests/test_access.py
+127
-75
lms/djangoapps/courseware/tests/test_group_access.py
+1
-1
lms/djangoapps/courseware/views.py
+9
-9
lms/djangoapps/django_comment_client/base/views.py
+2
-2
lms/djangoapps/django_comment_client/forum/views.py
+3
-3
lms/djangoapps/instructor/paidcourse_enrollment_report.py
+1
-1
lms/djangoapps/instructor/views/api.py
+2
-2
lms/djangoapps/instructor/views/instructor_dashboard.py
+3
-3
lms/djangoapps/instructor/views/legacy.py
+1
-1
lms/djangoapps/open_ended_grading/open_ended_notifications.py
+1
-1
lms/djangoapps/staticbook/views.py
+3
-3
lms/lib/courseware_search/lms_search_initializer.py
+1
-1
No files found.
cms/djangoapps/contentstore/views/access.py
View file @
4fc3ee47
...
@@ -16,7 +16,7 @@ def get_user_role(user, course_id):
...
@@ -16,7 +16,7 @@ def get_user_role(user, course_id):
:param course_id: the course_id of the course we're interested in
:param course_id: the course_id of the course we're interested in
"""
"""
# afaik, this is only used in lti
# afaik, this is only used in lti
if
auth
.
has_access
(
user
,
CourseInstructorRole
(
course_id
)):
if
auth
.
user_has_role
(
user
,
CourseInstructorRole
(
course_id
)):
return
'instructor'
return
'instructor'
else
:
else
:
return
'staff'
return
'staff'
cms/djangoapps/contentstore/views/course.py
View file @
4fc3ee47
...
@@ -662,7 +662,7 @@ def _create_or_rerun_course(request):
...
@@ -662,7 +662,7 @@ def _create_or_rerun_course(request):
Returns the destination course_key and overriding fields for the new course.
Returns the destination course_key and overriding fields for the new course.
Raises DuplicateCourseError and InvalidKeyError
Raises DuplicateCourseError and InvalidKeyError
"""
"""
if
not
auth
.
has_access
(
request
.
user
,
CourseCreatorRole
()):
if
not
auth
.
user_has_role
(
request
.
user
,
CourseCreatorRole
()):
raise
PermissionDenied
()
raise
PermissionDenied
()
try
:
try
:
...
...
cms/djangoapps/contentstore/views/tests/test_user.py
View file @
4fc3ee47
...
@@ -76,8 +76,8 @@ class UsersTestCase(CourseTestCase):
...
@@ -76,8 +76,8 @@ class UsersTestCase(CourseTestCase):
# reload user from DB
# reload user from DB
ext_user
=
User
.
objects
.
get
(
email
=
self
.
ext_user
.
email
)
ext_user
=
User
.
objects
.
get
(
email
=
self
.
ext_user
.
email
)
# no content: should not be in any roles
# no content: should not be in any roles
self
.
assertFalse
(
auth
.
has_access
(
ext_user
,
CourseStaffRole
(
self
.
course
.
id
)))
self
.
assertFalse
(
auth
.
user_has_role
(
ext_user
,
CourseStaffRole
(
self
.
course
.
id
)))
self
.
assertFalse
(
auth
.
has_access
(
ext_user
,
CourseInstructorRole
(
self
.
course
.
id
)))
self
.
assertFalse
(
auth
.
user_has_role
(
ext_user
,
CourseInstructorRole
(
self
.
course
.
id
)))
self
.
assert_not_enrolled
()
self
.
assert_not_enrolled
()
def
test_detail_post_staff
(
self
):
def
test_detail_post_staff
(
self
):
...
@@ -90,8 +90,8 @@ class UsersTestCase(CourseTestCase):
...
@@ -90,8 +90,8 @@ class UsersTestCase(CourseTestCase):
self
.
assertEqual
(
resp
.
status_code
,
204
)
self
.
assertEqual
(
resp
.
status_code
,
204
)
# reload user from DB
# reload user from DB
ext_user
=
User
.
objects
.
get
(
email
=
self
.
ext_user
.
email
)
ext_user
=
User
.
objects
.
get
(
email
=
self
.
ext_user
.
email
)
self
.
assertTrue
(
auth
.
has_access
(
ext_user
,
CourseStaffRole
(
self
.
course
.
id
)))
self
.
assertTrue
(
auth
.
user_has_role
(
ext_user
,
CourseStaffRole
(
self
.
course
.
id
)))
self
.
assertFalse
(
auth
.
has_access
(
ext_user
,
CourseInstructorRole
(
self
.
course
.
id
)))
self
.
assertFalse
(
auth
.
user_has_role
(
ext_user
,
CourseInstructorRole
(
self
.
course
.
id
)))
self
.
assert_enrolled
()
self
.
assert_enrolled
()
def
test_detail_post_staff_other_inst
(
self
):
def
test_detail_post_staff_other_inst
(
self
):
...
@@ -106,12 +106,12 @@ class UsersTestCase(CourseTestCase):
...
@@ -106,12 +106,12 @@ class UsersTestCase(CourseTestCase):
self
.
assertEqual
(
resp
.
status_code
,
204
)
self
.
assertEqual
(
resp
.
status_code
,
204
)
# reload user from DB
# reload user from DB
ext_user
=
User
.
objects
.
get
(
email
=
self
.
ext_user
.
email
)
ext_user
=
User
.
objects
.
get
(
email
=
self
.
ext_user
.
email
)
self
.
assertTrue
(
auth
.
has_access
(
ext_user
,
CourseStaffRole
(
self
.
course
.
id
)))
self
.
assertTrue
(
auth
.
user_has_role
(
ext_user
,
CourseStaffRole
(
self
.
course
.
id
)))
self
.
assertFalse
(
auth
.
has_access
(
ext_user
,
CourseInstructorRole
(
self
.
course
.
id
)))
self
.
assertFalse
(
auth
.
user_has_role
(
ext_user
,
CourseInstructorRole
(
self
.
course
.
id
)))
self
.
assert_enrolled
()
self
.
assert_enrolled
()
# check that other user is unchanged
# check that other user is unchanged
user
=
User
.
objects
.
get
(
email
=
self
.
user
.
email
)
user
=
User
.
objects
.
get
(
email
=
self
.
user
.
email
)
self
.
assertTrue
(
auth
.
has_access
(
user
,
CourseInstructorRole
(
self
.
course
.
id
)))
self
.
assertTrue
(
auth
.
user_has_role
(
user
,
CourseInstructorRole
(
self
.
course
.
id
)))
self
.
assertFalse
(
CourseStaffRole
(
self
.
course
.
id
)
.
has_user
(
user
))
self
.
assertFalse
(
CourseStaffRole
(
self
.
course
.
id
)
.
has_user
(
user
))
def
test_detail_post_instructor
(
self
):
def
test_detail_post_instructor
(
self
):
...
@@ -124,7 +124,7 @@ class UsersTestCase(CourseTestCase):
...
@@ -124,7 +124,7 @@ class UsersTestCase(CourseTestCase):
self
.
assertEqual
(
resp
.
status_code
,
204
)
self
.
assertEqual
(
resp
.
status_code
,
204
)
# reload user from DB
# reload user from DB
ext_user
=
User
.
objects
.
get
(
email
=
self
.
ext_user
.
email
)
ext_user
=
User
.
objects
.
get
(
email
=
self
.
ext_user
.
email
)
self
.
assertTrue
(
auth
.
has_access
(
ext_user
,
CourseInstructorRole
(
self
.
course
.
id
)))
self
.
assertTrue
(
auth
.
user_has_role
(
ext_user
,
CourseInstructorRole
(
self
.
course
.
id
)))
self
.
assertFalse
(
CourseStaffRole
(
self
.
course
.
id
)
.
has_user
(
ext_user
))
self
.
assertFalse
(
CourseStaffRole
(
self
.
course
.
id
)
.
has_user
(
ext_user
))
self
.
assert_enrolled
()
self
.
assert_enrolled
()
...
@@ -149,8 +149,8 @@ class UsersTestCase(CourseTestCase):
...
@@ -149,8 +149,8 @@ class UsersTestCase(CourseTestCase):
self
.
assertEqual
(
resp
.
status_code
,
204
)
self
.
assertEqual
(
resp
.
status_code
,
204
)
# reload user from DB
# reload user from DB
ext_user
=
User
.
objects
.
get
(
email
=
self
.
ext_user
.
email
)
ext_user
=
User
.
objects
.
get
(
email
=
self
.
ext_user
.
email
)
self
.
assertTrue
(
auth
.
has_access
(
ext_user
,
CourseStaffRole
(
self
.
course
.
id
)))
self
.
assertTrue
(
auth
.
user_has_role
(
ext_user
,
CourseStaffRole
(
self
.
course
.
id
)))
self
.
assertFalse
(
auth
.
has_access
(
ext_user
,
CourseInstructorRole
(
self
.
course
.
id
)))
self
.
assertFalse
(
auth
.
user_has_role
(
ext_user
,
CourseInstructorRole
(
self
.
course
.
id
)))
self
.
assert_enrolled
()
self
.
assert_enrolled
()
def
test_detail_delete_staff
(
self
):
def
test_detail_delete_staff
(
self
):
...
@@ -163,7 +163,7 @@ class UsersTestCase(CourseTestCase):
...
@@ -163,7 +163,7 @@ class UsersTestCase(CourseTestCase):
self
.
assertEqual
(
resp
.
status_code
,
204
)
self
.
assertEqual
(
resp
.
status_code
,
204
)
# reload user from DB
# reload user from DB
ext_user
=
User
.
objects
.
get
(
email
=
self
.
ext_user
.
email
)
ext_user
=
User
.
objects
.
get
(
email
=
self
.
ext_user
.
email
)
self
.
assertFalse
(
auth
.
has_access
(
ext_user
,
CourseStaffRole
(
self
.
course
.
id
)))
self
.
assertFalse
(
auth
.
user_has_role
(
ext_user
,
CourseStaffRole
(
self
.
course
.
id
)))
def
test_detail_delete_instructor
(
self
):
def
test_detail_delete_instructor
(
self
):
auth
.
add_users
(
self
.
user
,
CourseInstructorRole
(
self
.
course
.
id
),
self
.
ext_user
,
self
.
user
)
auth
.
add_users
(
self
.
user
,
CourseInstructorRole
(
self
.
course
.
id
),
self
.
ext_user
,
self
.
user
)
...
@@ -175,7 +175,7 @@ class UsersTestCase(CourseTestCase):
...
@@ -175,7 +175,7 @@ class UsersTestCase(CourseTestCase):
self
.
assertEqual
(
resp
.
status_code
,
204
)
self
.
assertEqual
(
resp
.
status_code
,
204
)
# reload user from DB
# reload user from DB
ext_user
=
User
.
objects
.
get
(
email
=
self
.
ext_user
.
email
)
ext_user
=
User
.
objects
.
get
(
email
=
self
.
ext_user
.
email
)
self
.
assertFalse
(
auth
.
has_access
(
ext_user
,
CourseInstructorRole
(
self
.
course
.
id
)))
self
.
assertFalse
(
auth
.
user_has_role
(
ext_user
,
CourseInstructorRole
(
self
.
course
.
id
)))
def
test_delete_last_instructor
(
self
):
def
test_delete_last_instructor
(
self
):
auth
.
add_users
(
self
.
user
,
CourseInstructorRole
(
self
.
course
.
id
),
self
.
ext_user
)
auth
.
add_users
(
self
.
user
,
CourseInstructorRole
(
self
.
course
.
id
),
self
.
ext_user
)
...
@@ -189,7 +189,7 @@ class UsersTestCase(CourseTestCase):
...
@@ -189,7 +189,7 @@ class UsersTestCase(CourseTestCase):
self
.
assertIn
(
"error"
,
result
)
self
.
assertIn
(
"error"
,
result
)
# reload user from DB
# reload user from DB
ext_user
=
User
.
objects
.
get
(
email
=
self
.
ext_user
.
email
)
ext_user
=
User
.
objects
.
get
(
email
=
self
.
ext_user
.
email
)
self
.
assertTrue
(
auth
.
has_access
(
ext_user
,
CourseInstructorRole
(
self
.
course
.
id
)))
self
.
assertTrue
(
auth
.
user_has_role
(
ext_user
,
CourseInstructorRole
(
self
.
course
.
id
)))
def
test_post_last_instructor
(
self
):
def
test_post_last_instructor
(
self
):
auth
.
add_users
(
self
.
user
,
CourseInstructorRole
(
self
.
course
.
id
),
self
.
ext_user
)
auth
.
add_users
(
self
.
user
,
CourseInstructorRole
(
self
.
course
.
id
),
self
.
ext_user
)
...
@@ -204,7 +204,7 @@ class UsersTestCase(CourseTestCase):
...
@@ -204,7 +204,7 @@ class UsersTestCase(CourseTestCase):
self
.
assertIn
(
"error"
,
result
)
self
.
assertIn
(
"error"
,
result
)
# reload user from DB
# reload user from DB
ext_user
=
User
.
objects
.
get
(
email
=
self
.
ext_user
.
email
)
ext_user
=
User
.
objects
.
get
(
email
=
self
.
ext_user
.
email
)
self
.
assertTrue
(
auth
.
has_access
(
ext_user
,
CourseInstructorRole
(
self
.
course
.
id
)))
self
.
assertTrue
(
auth
.
user_has_role
(
ext_user
,
CourseInstructorRole
(
self
.
course
.
id
)))
def
test_permission_denied_self
(
self
):
def
test_permission_denied_self
(
self
):
auth
.
add_users
(
self
.
user
,
CourseStaffRole
(
self
.
course
.
id
),
self
.
user
)
auth
.
add_users
(
self
.
user
,
CourseStaffRole
(
self
.
course
.
id
),
self
.
user
)
...
@@ -247,7 +247,7 @@ class UsersTestCase(CourseTestCase):
...
@@ -247,7 +247,7 @@ class UsersTestCase(CourseTestCase):
self
.
assertEqual
(
resp
.
status_code
,
204
)
self
.
assertEqual
(
resp
.
status_code
,
204
)
# reload user from DB
# reload user from DB
user
=
User
.
objects
.
get
(
email
=
self
.
user
.
email
)
user
=
User
.
objects
.
get
(
email
=
self
.
user
.
email
)
self
.
assertFalse
(
auth
.
has_access
(
user
,
CourseStaffRole
(
self
.
course
.
id
)))
self
.
assertFalse
(
auth
.
user_has_role
(
user
,
CourseStaffRole
(
self
.
course
.
id
)))
def
test_staff_cannot_delete_other
(
self
):
def
test_staff_cannot_delete_other
(
self
):
auth
.
add_users
(
self
.
user
,
CourseStaffRole
(
self
.
course
.
id
),
self
.
user
,
self
.
ext_user
)
auth
.
add_users
(
self
.
user
,
CourseStaffRole
(
self
.
course
.
id
),
self
.
user
,
self
.
ext_user
)
...
@@ -260,7 +260,7 @@ class UsersTestCase(CourseTestCase):
...
@@ -260,7 +260,7 @@ class UsersTestCase(CourseTestCase):
self
.
assertIn
(
"error"
,
result
)
self
.
assertIn
(
"error"
,
result
)
# reload user from DB
# reload user from DB
ext_user
=
User
.
objects
.
get
(
email
=
self
.
ext_user
.
email
)
ext_user
=
User
.
objects
.
get
(
email
=
self
.
ext_user
.
email
)
self
.
assertTrue
(
auth
.
has_access
(
ext_user
,
CourseStaffRole
(
self
.
course
.
id
)))
self
.
assertTrue
(
auth
.
user_has_role
(
ext_user
,
CourseStaffRole
(
self
.
course
.
id
)))
def
test_user_not_initially_enrolled
(
self
):
def
test_user_not_initially_enrolled
(
self
):
# Verify that ext_user is not enrolled in the new course before being added as a staff member.
# Verify that ext_user is not enrolled in the new course before being added as a staff member.
...
...
cms/djangoapps/course_creators/tests/test_admin.py
View file @
4fc3ee47
...
@@ -56,7 +56,7 @@ class CourseCreatorAdminTest(TestCase):
...
@@ -56,7 +56,7 @@ class CourseCreatorAdminTest(TestCase):
def
change_state_and_verify_email
(
state
,
is_creator
):
def
change_state_and_verify_email
(
state
,
is_creator
):
""" Changes user state, verifies creator status, and verifies e-mail is sent based on transition """
""" Changes user state, verifies creator status, and verifies e-mail is sent based on transition """
self
.
_change_state
(
state
)
self
.
_change_state
(
state
)
self
.
assertEqual
(
is_creator
,
auth
.
has_access
(
self
.
user
,
CourseCreatorRole
()))
self
.
assertEqual
(
is_creator
,
auth
.
user_has_role
(
self
.
user
,
CourseCreatorRole
()))
context
=
{
'studio_request_email'
:
self
.
studio_request_email
}
context
=
{
'studio_request_email'
:
self
.
studio_request_email
}
if
state
==
CourseCreator
.
GRANTED
:
if
state
==
CourseCreator
.
GRANTED
:
...
@@ -74,7 +74,7 @@ class CourseCreatorAdminTest(TestCase):
...
@@ -74,7 +74,7 @@ class CourseCreatorAdminTest(TestCase):
with
mock
.
patch
.
dict
(
'django.conf.settings.FEATURES'
,
self
.
enable_creator_group_patch
):
with
mock
.
patch
.
dict
(
'django.conf.settings.FEATURES'
,
self
.
enable_creator_group_patch
):
# User is initially unrequested.
# User is initially unrequested.
self
.
assertFalse
(
auth
.
has_access
(
self
.
user
,
CourseCreatorRole
()))
self
.
assertFalse
(
auth
.
user_has_role
(
self
.
user
,
CourseCreatorRole
()))
change_state_and_verify_email
(
CourseCreator
.
GRANTED
,
True
)
change_state_and_verify_email
(
CourseCreator
.
GRANTED
,
True
)
...
...
cms/djangoapps/course_creators/tests/test_views.py
View file @
4fc3ee47
...
@@ -50,7 +50,7 @@ class CourseCreatorView(TestCase):
...
@@ -50,7 +50,7 @@ class CourseCreatorView(TestCase):
def
test_add_granted
(
self
):
def
test_add_granted
(
self
):
with
mock
.
patch
.
dict
(
'django.conf.settings.FEATURES'
,
{
"ENABLE_CREATOR_GROUP"
:
True
}):
with
mock
.
patch
.
dict
(
'django.conf.settings.FEATURES'
,
{
"ENABLE_CREATOR_GROUP"
:
True
}):
# Calling add_user_with_status_granted impacts is_user_in_course_group_role.
# Calling add_user_with_status_granted impacts is_user_in_course_group_role.
self
.
assertFalse
(
auth
.
has_access
(
self
.
user
,
CourseCreatorRole
()))
self
.
assertFalse
(
auth
.
user_has_role
(
self
.
user
,
CourseCreatorRole
()))
add_user_with_status_granted
(
self
.
admin
,
self
.
user
)
add_user_with_status_granted
(
self
.
admin
,
self
.
user
)
self
.
assertEqual
(
'granted'
,
get_course_creator_status
(
self
.
user
))
self
.
assertEqual
(
'granted'
,
get_course_creator_status
(
self
.
user
))
...
@@ -59,15 +59,15 @@ class CourseCreatorView(TestCase):
...
@@ -59,15 +59,15 @@ class CourseCreatorView(TestCase):
add_user_with_status_unrequested
(
self
.
user
)
add_user_with_status_unrequested
(
self
.
user
)
self
.
assertEqual
(
'granted'
,
get_course_creator_status
(
self
.
user
))
self
.
assertEqual
(
'granted'
,
get_course_creator_status
(
self
.
user
))
self
.
assertTrue
(
auth
.
has_access
(
self
.
user
,
CourseCreatorRole
()))
self
.
assertTrue
(
auth
.
user_has_role
(
self
.
user
,
CourseCreatorRole
()))
def
test_update_creator_group
(
self
):
def
test_update_creator_group
(
self
):
with
mock
.
patch
.
dict
(
'django.conf.settings.FEATURES'
,
{
"ENABLE_CREATOR_GROUP"
:
True
}):
with
mock
.
patch
.
dict
(
'django.conf.settings.FEATURES'
,
{
"ENABLE_CREATOR_GROUP"
:
True
}):
self
.
assertFalse
(
auth
.
has_access
(
self
.
user
,
CourseCreatorRole
()))
self
.
assertFalse
(
auth
.
user_has_role
(
self
.
user
,
CourseCreatorRole
()))
update_course_creator_group
(
self
.
admin
,
self
.
user
,
True
)
update_course_creator_group
(
self
.
admin
,
self
.
user
,
True
)
self
.
assertTrue
(
auth
.
has_access
(
self
.
user
,
CourseCreatorRole
()))
self
.
assertTrue
(
auth
.
user_has_role
(
self
.
user
,
CourseCreatorRole
()))
update_course_creator_group
(
self
.
admin
,
self
.
user
,
False
)
update_course_creator_group
(
self
.
admin
,
self
.
user
,
False
)
self
.
assertFalse
(
auth
.
has_access
(
self
.
user
,
CourseCreatorRole
()))
self
.
assertFalse
(
auth
.
user_has_role
(
self
.
user
,
CourseCreatorRole
()))
def
test_user_requested_access
(
self
):
def
test_user_requested_access
(
self
):
add_user_with_status_unrequested
(
self
.
user
)
add_user_with_status_unrequested
(
self
.
user
)
...
...
common/djangoapps/student/auth.py
View file @
4fc3ee47
...
@@ -20,7 +20,7 @@ STUDIO_VIEW_CONTENT = 1
...
@@ -20,7 +20,7 @@ STUDIO_VIEW_CONTENT = 1
# In addition to the above, one is always allowed to "demote" oneself to a lower role within a course, or remove oneself
# In addition to the above, one is always allowed to "demote" oneself to a lower role within a course, or remove oneself
def
has_access
(
user
,
role
):
def
user_has_role
(
user
,
role
):
"""
"""
Check whether this user has access to this role (either direct or implied)
Check whether this user has access to this role (either direct or implied)
:param user:
:param user:
...
@@ -64,14 +64,14 @@ def get_user_permissions(user, course_key, org=None):
...
@@ -64,14 +64,14 @@ def get_user_permissions(user, course_key, org=None):
# global staff, org instructors, and course instructors have all permissions:
# global staff, org instructors, and course instructors have all permissions:
if
GlobalStaff
()
.
has_user
(
user
)
or
OrgInstructorRole
(
org
=
org
)
.
has_user
(
user
):
if
GlobalStaff
()
.
has_user
(
user
)
or
OrgInstructorRole
(
org
=
org
)
.
has_user
(
user
):
return
all_perms
return
all_perms
if
course_key
and
has_access
(
user
,
CourseInstructorRole
(
course_key
)):
if
course_key
and
user_has_role
(
user
,
CourseInstructorRole
(
course_key
)):
return
all_perms
return
all_perms
# Staff have all permissions except EDIT_ROLES:
# Staff have all permissions except EDIT_ROLES:
if
OrgStaffRole
(
org
=
org
)
.
has_user
(
user
)
or
(
course_key
and
has_access
(
user
,
CourseStaffRole
(
course_key
))):
if
OrgStaffRole
(
org
=
org
)
.
has_user
(
user
)
or
(
course_key
and
user_has_role
(
user
,
CourseStaffRole
(
course_key
))):
return
STUDIO_VIEW_USERS
|
STUDIO_EDIT_CONTENT
|
STUDIO_VIEW_CONTENT
return
STUDIO_VIEW_USERS
|
STUDIO_EDIT_CONTENT
|
STUDIO_VIEW_CONTENT
# Otherwise, for libraries, users can view only:
# Otherwise, for libraries, users can view only:
if
course_key
and
isinstance
(
course_key
,
LibraryLocator
):
if
course_key
and
isinstance
(
course_key
,
LibraryLocator
):
if
OrgLibraryUserRole
(
org
=
org
)
.
has_user
(
user
)
or
has_access
(
user
,
LibraryUserRole
(
course_key
)):
if
OrgLibraryUserRole
(
org
=
org
)
.
has_user
(
user
)
or
user_has_role
(
user
,
LibraryUserRole
(
course_key
)):
return
STUDIO_VIEW_USERS
|
STUDIO_VIEW_CONTENT
return
STUDIO_VIEW_USERS
|
STUDIO_VIEW_CONTENT
return
0
return
0
...
@@ -151,5 +151,5 @@ def _check_caller_authority(caller, role):
...
@@ -151,5 +151,5 @@ def _check_caller_authority(caller, role):
if
isinstance
(
role
,
(
GlobalStaff
,
CourseCreatorRole
)):
if
isinstance
(
role
,
(
GlobalStaff
,
CourseCreatorRole
)):
raise
PermissionDenied
raise
PermissionDenied
elif
isinstance
(
role
,
CourseRole
):
# instructors can change the roles w/in their course
elif
isinstance
(
role
,
CourseRole
):
# instructors can change the roles w/in their course
if
not
has_access
(
caller
,
CourseInstructorRole
(
role
.
course_key
)):
if
not
user_has_role
(
caller
,
CourseInstructorRole
(
role
.
course_key
)):
raise
PermissionDenied
raise
PermissionDenied
common/djangoapps/student/tests/test_authz.py
View file @
4fc3ee47
...
@@ -9,7 +9,7 @@ from django.core.exceptions import PermissionDenied
...
@@ -9,7 +9,7 @@ from django.core.exceptions import PermissionDenied
from
student.roles
import
CourseInstructorRole
,
CourseStaffRole
,
CourseCreatorRole
from
student.roles
import
CourseInstructorRole
,
CourseStaffRole
,
CourseCreatorRole
from
student.tests.factories
import
AdminFactory
from
student.tests.factories
import
AdminFactory
from
student.auth
import
has_access
,
add_users
,
remove_users
from
student.auth
import
user_has_role
,
add_users
,
remove_users
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
...
@@ -30,30 +30,30 @@ class CreatorGroupTest(TestCase):
...
@@ -30,30 +30,30 @@ class CreatorGroupTest(TestCase):
Tests that CourseCreatorRole().has_user always returns True if ENABLE_CREATOR_GROUP
Tests that CourseCreatorRole().has_user always returns True if ENABLE_CREATOR_GROUP
and DISABLE_COURSE_CREATION are both not turned on.
and DISABLE_COURSE_CREATION are both not turned on.
"""
"""
self
.
assertTrue
(
has_access
(
self
.
user
,
CourseCreatorRole
()))
self
.
assertTrue
(
user_has_role
(
self
.
user
,
CourseCreatorRole
()))
def
test_creator_group_enabled_but_empty
(
self
):
def
test_creator_group_enabled_but_empty
(
self
):
""" Tests creator group feature on, but group empty. """
""" Tests creator group feature on, but group empty. """
with
mock
.
patch
.
dict
(
'django.conf.settings.FEATURES'
,
{
"ENABLE_CREATOR_GROUP"
:
True
}):
with
mock
.
patch
.
dict
(
'django.conf.settings.FEATURES'
,
{
"ENABLE_CREATOR_GROUP"
:
True
}):
self
.
assertFalse
(
has_access
(
self
.
user
,
CourseCreatorRole
()))
self
.
assertFalse
(
user_has_role
(
self
.
user
,
CourseCreatorRole
()))
# Make user staff. This will cause CourseCreatorRole().has_user to return True.
# Make user staff. This will cause CourseCreatorRole().has_user to return True.
self
.
user
.
is_staff
=
True
self
.
user
.
is_staff
=
True
self
.
assertTrue
(
has_access
(
self
.
user
,
CourseCreatorRole
()))
self
.
assertTrue
(
user_has_role
(
self
.
user
,
CourseCreatorRole
()))
def
test_creator_group_enabled_nonempty
(
self
):
def
test_creator_group_enabled_nonempty
(
self
):
""" Tests creator group feature on, user added. """
""" Tests creator group feature on, user added. """
with
mock
.
patch
.
dict
(
'django.conf.settings.FEATURES'
,
{
"ENABLE_CREATOR_GROUP"
:
True
}):
with
mock
.
patch
.
dict
(
'django.conf.settings.FEATURES'
,
{
"ENABLE_CREATOR_GROUP"
:
True
}):
add_users
(
self
.
admin
,
CourseCreatorRole
(),
self
.
user
)
add_users
(
self
.
admin
,
CourseCreatorRole
(),
self
.
user
)
self
.
assertTrue
(
has_access
(
self
.
user
,
CourseCreatorRole
()))
self
.
assertTrue
(
user_has_role
(
self
.
user
,
CourseCreatorRole
()))
# check that a user who has not been added to the group still returns false
# check that a user who has not been added to the group still returns false
user_not_added
=
User
.
objects
.
create_user
(
'testuser2'
,
'test+courses2@edx.org'
,
'foo2'
)
user_not_added
=
User
.
objects
.
create_user
(
'testuser2'
,
'test+courses2@edx.org'
,
'foo2'
)
self
.
assertFalse
(
has_access
(
user_not_added
,
CourseCreatorRole
()))
self
.
assertFalse
(
user_has_role
(
user_not_added
,
CourseCreatorRole
()))
# remove first user from the group and verify that CourseCreatorRole().has_user now returns false
# remove first user from the group and verify that CourseCreatorRole().has_user now returns false
remove_users
(
self
.
admin
,
CourseCreatorRole
(),
self
.
user
)
remove_users
(
self
.
admin
,
CourseCreatorRole
(),
self
.
user
)
self
.
assertFalse
(
has_access
(
self
.
user
,
CourseCreatorRole
()))
self
.
assertFalse
(
user_has_role
(
self
.
user
,
CourseCreatorRole
()))
def
test_course_creation_disabled
(
self
):
def
test_course_creation_disabled
(
self
):
""" Tests that the COURSE_CREATION_DISABLED flag overrides course creator group settings. """
""" Tests that the COURSE_CREATION_DISABLED flag overrides course creator group settings. """
...
@@ -63,15 +63,15 @@ class CreatorGroupTest(TestCase):
...
@@ -63,15 +63,15 @@ class CreatorGroupTest(TestCase):
add_users
(
self
.
admin
,
CourseCreatorRole
(),
self
.
user
)
add_users
(
self
.
admin
,
CourseCreatorRole
(),
self
.
user
)
# DISABLE_COURSE_CREATION overrides (user is not marked as staff).
# DISABLE_COURSE_CREATION overrides (user is not marked as staff).
self
.
assertFalse
(
has_access
(
self
.
user
,
CourseCreatorRole
()))
self
.
assertFalse
(
user_has_role
(
self
.
user
,
CourseCreatorRole
()))
# Mark as staff. Now CourseCreatorRole().has_user returns true.
# Mark as staff. Now CourseCreatorRole().has_user returns true.
self
.
user
.
is_staff
=
True
self
.
user
.
is_staff
=
True
self
.
assertTrue
(
has_access
(
self
.
user
,
CourseCreatorRole
()))
self
.
assertTrue
(
user_has_role
(
self
.
user
,
CourseCreatorRole
()))
# Remove user from creator group. CourseCreatorRole().has_user still returns true because is_staff=True
# Remove user from creator group. CourseCreatorRole().has_user still returns true because is_staff=True
remove_users
(
self
.
admin
,
CourseCreatorRole
(),
self
.
user
)
remove_users
(
self
.
admin
,
CourseCreatorRole
(),
self
.
user
)
self
.
assertTrue
(
has_access
(
self
.
user
,
CourseCreatorRole
()))
self
.
assertTrue
(
user_has_role
(
self
.
user
,
CourseCreatorRole
()))
def
test_add_user_not_authenticated
(
self
):
def
test_add_user_not_authenticated
(
self
):
"""
"""
...
@@ -84,7 +84,7 @@ class CreatorGroupTest(TestCase):
...
@@ -84,7 +84,7 @@ class CreatorGroupTest(TestCase):
anonymous_user
=
AnonymousUser
()
anonymous_user
=
AnonymousUser
()
role
=
CourseCreatorRole
()
role
=
CourseCreatorRole
()
add_users
(
self
.
admin
,
role
,
anonymous_user
)
add_users
(
self
.
admin
,
role
,
anonymous_user
)
self
.
assertFalse
(
has_access
(
anonymous_user
,
role
))
self
.
assertFalse
(
user_has_role
(
anonymous_user
,
role
))
def
test_add_user_not_active
(
self
):
def
test_add_user_not_active
(
self
):
"""
"""
...
@@ -96,7 +96,7 @@ class CreatorGroupTest(TestCase):
...
@@ -96,7 +96,7 @@ class CreatorGroupTest(TestCase):
):
):
self
.
user
.
is_active
=
False
self
.
user
.
is_active
=
False
add_users
(
self
.
admin
,
CourseCreatorRole
(),
self
.
user
)
add_users
(
self
.
admin
,
CourseCreatorRole
(),
self
.
user
)
self
.
assertFalse
(
has_access
(
self
.
user
,
CourseCreatorRole
()))
self
.
assertFalse
(
user_has_role
(
self
.
user
,
CourseCreatorRole
()))
def
test_add_user_to_group_requires_staff_access
(
self
):
def
test_add_user_to_group_requires_staff_access
(
self
):
with
self
.
assertRaises
(
PermissionDenied
):
with
self
.
assertRaises
(
PermissionDenied
):
...
@@ -150,15 +150,15 @@ class CourseGroupTest(TestCase):
...
@@ -150,15 +150,15 @@ class CourseGroupTest(TestCase):
Tests adding user to course group (happy path).
Tests adding user to course group (happy path).
"""
"""
# Create groups for a new course (and assign instructor role to the creator).
# Create groups for a new course (and assign instructor role to the creator).
self
.
assertFalse
(
has_access
(
self
.
creator
,
CourseInstructorRole
(
self
.
course_key
)))
self
.
assertFalse
(
user_has_role
(
self
.
creator
,
CourseInstructorRole
(
self
.
course_key
)))
add_users
(
self
.
global_admin
,
CourseInstructorRole
(
self
.
course_key
),
self
.
creator
)
add_users
(
self
.
global_admin
,
CourseInstructorRole
(
self
.
course_key
),
self
.
creator
)
add_users
(
self
.
global_admin
,
CourseStaffRole
(
self
.
course_key
),
self
.
creator
)
add_users
(
self
.
global_admin
,
CourseStaffRole
(
self
.
course_key
),
self
.
creator
)
self
.
assertTrue
(
has_access
(
self
.
creator
,
CourseInstructorRole
(
self
.
course_key
)))
self
.
assertTrue
(
user_has_role
(
self
.
creator
,
CourseInstructorRole
(
self
.
course_key
)))
# Add another user to the staff role.
# Add another user to the staff role.
self
.
assertFalse
(
has_access
(
self
.
staff
,
CourseStaffRole
(
self
.
course_key
)))
self
.
assertFalse
(
user_has_role
(
self
.
staff
,
CourseStaffRole
(
self
.
course_key
)))
add_users
(
self
.
creator
,
CourseStaffRole
(
self
.
course_key
),
self
.
staff
)
add_users
(
self
.
creator
,
CourseStaffRole
(
self
.
course_key
),
self
.
staff
)
self
.
assertTrue
(
has_access
(
self
.
staff
,
CourseStaffRole
(
self
.
course_key
)))
self
.
assertTrue
(
user_has_role
(
self
.
staff
,
CourseStaffRole
(
self
.
course_key
)))
def
test_add_user_to_course_group_permission_denied
(
self
):
def
test_add_user_to_course_group_permission_denied
(
self
):
"""
"""
...
@@ -177,13 +177,13 @@ class CourseGroupTest(TestCase):
...
@@ -177,13 +177,13 @@ class CourseGroupTest(TestCase):
add_users
(
self
.
global_admin
,
CourseStaffRole
(
self
.
course_key
),
self
.
creator
)
add_users
(
self
.
global_admin
,
CourseStaffRole
(
self
.
course_key
),
self
.
creator
)
add_users
(
self
.
creator
,
CourseStaffRole
(
self
.
course_key
),
self
.
staff
)
add_users
(
self
.
creator
,
CourseStaffRole
(
self
.
course_key
),
self
.
staff
)
self
.
assertTrue
(
has_access
(
self
.
staff
,
CourseStaffRole
(
self
.
course_key
)))
self
.
assertTrue
(
user_has_role
(
self
.
staff
,
CourseStaffRole
(
self
.
course_key
)))
remove_users
(
self
.
creator
,
CourseStaffRole
(
self
.
course_key
),
self
.
staff
)
remove_users
(
self
.
creator
,
CourseStaffRole
(
self
.
course_key
),
self
.
staff
)
self
.
assertFalse
(
has_access
(
self
.
staff
,
CourseStaffRole
(
self
.
course_key
)))
self
.
assertFalse
(
user_has_role
(
self
.
staff
,
CourseStaffRole
(
self
.
course_key
)))
remove_users
(
self
.
creator
,
CourseInstructorRole
(
self
.
course_key
),
self
.
creator
)
remove_users
(
self
.
creator
,
CourseInstructorRole
(
self
.
course_key
),
self
.
creator
)
self
.
assertFalse
(
has_access
(
self
.
creator
,
CourseInstructorRole
(
self
.
course_key
)))
self
.
assertFalse
(
user_has_role
(
self
.
creator
,
CourseInstructorRole
(
self
.
course_key
)))
def
test_remove_user_from_course_group_permission_denied
(
self
):
def
test_remove_user_from_course_group_permission_denied
(
self
):
"""
"""
...
...
lms/djangoapps/class_dashboard/tests/test_dashboard_data.py
View file @
4fc3ee47
...
@@ -316,5 +316,5 @@ class TestGetProblemGradeDistribution(ModuleStoreTestCase):
...
@@ -316,5 +316,5 @@ class TestGetProblemGradeDistribution(ModuleStoreTestCase):
"""
"""
Test for instructor access
Test for instructor access
"""
"""
ret_val
=
has_instructor_access_for_class
(
self
.
instructor
,
self
.
course
.
id
)
ret_val
=
bool
(
has_instructor_access_for_class
(
self
.
instructor
,
self
.
course
.
id
)
)
self
.
assertEquals
(
ret_val
,
True
)
self
.
assertEquals
(
ret_val
,
True
)
lms/djangoapps/class_dashboard/views.py
View file @
4fc3ee47
...
@@ -22,7 +22,7 @@ def has_instructor_access_for_class(user, course_id):
...
@@ -22,7 +22,7 @@ def has_instructor_access_for_class(user, course_id):
"""
"""
course
=
get_course_with_access
(
user
,
'staff'
,
course_id
,
depth
=
None
)
course
=
get_course_with_access
(
user
,
'staff'
,
course_id
,
depth
=
None
)
return
has_access
(
user
,
'staff'
,
course
)
return
bool
(
has_access
(
user
,
'staff'
,
course
)
)
def
all_sequential_open_distrib
(
request
,
course_id
):
def
all_sequential_open_distrib
(
request
,
course_id
):
...
...
lms/djangoapps/course_structure_api/v0/views.py
View file @
4fc3ee47
...
@@ -83,9 +83,11 @@ class CourseViewMixin(object):
...
@@ -83,9 +83,11 @@ class CourseViewMixin(object):
Determines if the user is staff or an instructor for the course.
Determines if the user is staff or an instructor for the course.
Always returns True if DEBUG mode is enabled.
Always returns True if DEBUG mode is enabled.
"""
"""
return
(
settings
.
DEBUG
return
bool
(
settings
.
DEBUG
or
has_access
(
user
,
CourseStaffRole
.
ROLE
,
course
)
or
has_access
(
user
,
CourseStaffRole
.
ROLE
,
course
)
or
has_access
(
user
,
CourseInstructorRole
.
ROLE
,
course
))
or
has_access
(
user
,
CourseInstructorRole
.
ROLE
,
course
)
)
def
check_course_permissions
(
self
,
user
,
course
):
def
check_course_permissions
(
self
,
user
,
course
):
"""
"""
...
...
lms/djangoapps/courseware/access.py
View file @
4fc3ee47
...
@@ -23,8 +23,10 @@ from opaque_keys.edx.keys import CourseKey, UsageKey
...
@@ -23,8 +23,10 @@ from opaque_keys.edx.keys import CourseKey, UsageKey
from
xblock.core
import
XBlock
from
xblock.core
import
XBlock
from
xmodule.course_module
import
(
from
xmodule.course_module
import
(
CourseDescriptor
,
CATALOG_VISIBILITY_CATALOG_AND_ABOUT
,
CourseDescriptor
,
CATALOG_VISIBILITY_ABOUT
)
CATALOG_VISIBILITY_CATALOG_AND_ABOUT
,
CATALOG_VISIBILITY_ABOUT
,
)
from
xmodule.error_module
import
ErrorDescriptor
from
xmodule.error_module
import
ErrorDescriptor
from
xmodule.x_module
import
XModule
,
DEPRECATION_VSCOMPAT_EVENT
from
xmodule.x_module
import
XModule
,
DEPRECATION_VSCOMPAT_EVENT
from
xmodule.split_test_module
import
get_split_user_partitions
from
xmodule.split_test_module
import
get_split_user_partitions
...
@@ -37,8 +39,12 @@ from openedx.core.djangoapps.content.course_overviews.models import CourseOvervi
...
@@ -37,8 +39,12 @@ from openedx.core.djangoapps.content.course_overviews.models import CourseOvervi
from
student
import
auth
from
student
import
auth
from
student.models
import
CourseEnrollmentAllowed
from
student.models
import
CourseEnrollmentAllowed
from
student.roles
import
(
from
student.roles
import
(
GlobalStaff
,
CourseStaffRole
,
CourseInstructorRole
,
CourseBetaTesterRole
,
OrgStaffRole
,
OrgInstructorRole
,
CourseBetaTesterRole
CourseInstructorRole
,
CourseStaffRole
,
GlobalStaff
,
OrgInstructorRole
,
OrgStaffRole
,
)
)
from
util.milestones_helpers
import
(
from
util.milestones_helpers
import
(
get_pre_requisite_courses_not_completed
,
get_pre_requisite_courses_not_completed
,
...
@@ -48,7 +54,17 @@ from ccx_keys.locator import CCXLocator
...
@@ -48,7 +54,17 @@ from ccx_keys.locator import CCXLocator
import
dogstats_wrapper
as
dog_stats_api
import
dogstats_wrapper
as
dog_stats_api
from
courseware.access_response
import
(
AccessResponse
,
MilestoneError
,
MobileAvailabilityError
,
StartDateError
,
VisibilityError
,
)
DEBUG_ACCESS
=
False
DEBUG_ACCESS
=
False
ACCESS_GRANTED
=
AccessResponse
(
True
)
ACCESS_DENIED
=
AccessResponse
(
False
)
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
...
@@ -86,8 +102,8 @@ def has_access(user, action, obj, course_key=None):
...
@@ -86,8 +102,8 @@ def has_access(user, action, obj, course_key=None):
Required when accessing anything other than a CourseDescriptor, 'global',
Required when accessing anything other than a CourseDescriptor, 'global',
or a location with category 'course'
or a location with category 'course'
Returns a
bool. It is up to the caller to actually deny access in a wa
y
Returns a
n AccessResponse object. It is up to the caller to actuall
y
that makes sense in context.
deny access in a way
that makes sense in context.
"""
"""
# Just in case user is passed in as None, make them anonymous
# Just in case user is passed in as None, make them anonymous
if
not
user
:
if
not
user
:
...
@@ -146,13 +162,18 @@ def _can_access_descriptor_with_start_date(user, descriptor, course_key): # pyl
...
@@ -146,13 +162,18 @@ def _can_access_descriptor_with_start_date(user, descriptor, course_key): # pyl
Arguments:
Arguments:
user (User): the user whose descriptor access we are checking.
user (User): the user whose descriptor access we are checking.
descriptor (AType): the descriptor for which we are checking access.
descriptor (AType): the descriptor for which we are checking access,
where AType is any descriptor that has the attributes .location and
where AType is CourseDescriptor, CourseOverview, or any other class
.days_early_for_beta
that represents a descriptor and has the attributes .location, .id,
.start, and .days_early_for_beta.
Returns:
AccessResponse: The result of this access check. Possible results are
ACCESS_GRANTED or a StartDateError.
"""
"""
start_dates_disabled
=
settings
.
FEATURES
[
'DISABLE_START_DATES'
]
start_dates_disabled
=
settings
.
FEATURES
[
'DISABLE_START_DATES'
]
if
start_dates_disabled
and
not
is_masquerading_as_student
(
user
,
course_key
):
if
start_dates_disabled
and
not
is_masquerading_as_student
(
user
,
course_key
):
return
True
return
ACCESS_GRANTED
else
:
else
:
now
=
datetime
.
now
(
UTC
())
now
=
datetime
.
now
(
UTC
())
effective_start
=
_adjust_start_date_for_beta_testers
(
effective_start
=
_adjust_start_date_for_beta_testers
(
...
@@ -160,11 +181,14 @@ def _can_access_descriptor_with_start_date(user, descriptor, course_key): # pyl
...
@@ -160,11 +181,14 @@ def _can_access_descriptor_with_start_date(user, descriptor, course_key): # pyl
descriptor
,
descriptor
,
course_key
=
course_key
course_key
=
course_key
)
)
return
(
if
(
descriptor
.
start
is
None
descriptor
.
start
is
None
or
now
>
effective_start
or
now
>
effective_start
or
in_preview_mode
()
or
in_preview_mode
()
)
):
return
ACCESS_GRANTED
return
StartDateError
(
descriptor
.
start
)
def
_can_view_courseware_with_prerequisites
(
user
,
course
):
# pylint: disable=invalid-name
def
_can_view_courseware_with_prerequisites
(
user
,
course
):
# pylint: disable=invalid-name
...
@@ -177,15 +201,22 @@ def _can_view_courseware_with_prerequisites(user, course): # pylint: disable=in
...
@@ -177,15 +201,22 @@ def _can_view_courseware_with_prerequisites(user, course): # pylint: disable=in
Arguments:
Arguments:
user (User): the user whose course access we are checking.
user (User): the user whose course access we are checking.
course (AType): the course for which we are checking access.
course (AType): the course for which we are checking access.
where AType is CourseDescriptor, CourseOverview, or any other class that
where AType is CourseDescriptor, CourseOverview, or any other
represents a course and has the attributes .location and .id.
class that represents a course and has the attributes .location
and .id.
"""
"""
def
_is_prerequisites_disabled
():
"""
Checks if prerequisites are disabled in the settings.
"""
return
ACCESS_DENIED
if
settings
.
FEATURES
[
'ENABLE_PREREQUISITE_COURSES'
]
else
ACCESS_GRANTED
return
(
return
(
not
settings
.
FEATURES
[
'ENABLE_PREREQUISITE_COURSES'
]
_is_prerequisites_disabled
()
or
_has_staff_access_to_descriptor
(
user
,
course
,
course
.
id
)
or
_has_staff_access_to_descriptor
(
user
,
course
,
course
.
id
)
or
not
course
.
pre_requisite_courses
or
user
.
is_anonymous
()
or
user
.
is_anonymous
()
or
not
get_pre_requisite_courses_not_completed
(
user
,
[
course
.
id
])
or
_has_fulfilled_prerequisites
(
user
,
[
course
.
id
])
)
)
...
@@ -209,7 +240,7 @@ def _can_load_course_on_mobile(user, course):
...
@@ -209,7 +240,7 @@ def _can_load_course_on_mobile(user, course):
is_mobile_available_for_user
(
user
,
course
)
and
is_mobile_available_for_user
(
user
,
course
)
and
(
(
_has_staff_access_to_descriptor
(
user
,
course
,
course
.
id
)
or
_has_staff_access_to_descriptor
(
user
,
course
,
course
.
id
)
or
not
any_unfulfilled_milestones
(
course
.
id
,
user
.
id
)
_has_fulfilled_all_milestones
(
user
,
course
.
id
)
)
)
)
)
...
@@ -275,19 +306,19 @@ def _has_access_course_desc(user, action, course):
...
@@ -275,19 +306,19 @@ def _has_access_course_desc(user, action, course):
# (sorry that it's confusing :( )
# (sorry that it's confusing :( )
if
user
is
not
None
and
user
.
is_authenticated
()
and
CourseEnrollmentAllowed
:
if
user
is
not
None
and
user
.
is_authenticated
()
and
CourseEnrollmentAllowed
:
if
CourseEnrollmentAllowed
.
objects
.
filter
(
email
=
user
.
email
,
course_id
=
course
.
id
):
if
CourseEnrollmentAllowed
.
objects
.
filter
(
email
=
user
.
email
,
course_id
=
course
.
id
):
return
True
return
ACCESS_GRANTED
if
_has_staff_access_to_descriptor
(
user
,
course
,
course
.
id
):
if
_has_staff_access_to_descriptor
(
user
,
course
,
course
.
id
):
return
True
return
ACCESS_GRANTED
# Invitation_only doesn't apply to CourseEnrollmentAllowed or has_staff_access_access
# Invitation_only doesn't apply to CourseEnrollmentAllowed or has_staff_access_access
if
course
.
invitation_only
:
if
course
.
invitation_only
:
debug
(
"Deny: invitation only"
)
debug
(
"Deny: invitation only"
)
return
False
return
ACCESS_DENIED
if
reg_method_ok
and
start
<
now
<
end
:
if
reg_method_ok
and
start
<
now
<
end
:
debug
(
"Allow: in enrollment period"
)
debug
(
"Allow: in enrollment period"
)
return
True
return
ACCESS_GRANTED
def
see_exists
():
def
see_exists
():
"""
"""
...
@@ -314,10 +345,10 @@ def _has_access_course_desc(user, action, course):
...
@@ -314,10 +345,10 @@ def _has_access_course_desc(user, action, course):
# seen by non-staff
# seen by non-staff
if
course
.
ispublic
:
if
course
.
ispublic
:
debug
(
"Allow: ACCESS_REQUIRE_STAFF_FOR_COURSE and ispublic"
)
debug
(
"Allow: ACCESS_REQUIRE_STAFF_FOR_COURSE and ispublic"
)
return
True
return
ACCESS_GRANTED
return
_has_staff_access_to_descriptor
(
user
,
course
,
course
.
id
)
return
_has_staff_access_to_descriptor
(
user
,
course
,
course
.
id
)
return
can_enroll
()
or
can_load
()
return
ACCESS_GRANTED
if
(
can_enroll
()
or
can_load
())
else
ACCESS_DENIED
def
can_see_in_catalog
():
def
can_see_in_catalog
():
"""
"""
...
@@ -326,8 +357,8 @@ def _has_access_course_desc(user, action, course):
...
@@ -326,8 +357,8 @@ def _has_access_course_desc(user, action, course):
but also allow course staff to see this.
but also allow course staff to see this.
"""
"""
return
(
return
(
course
.
catalog_visibility
==
CATALOG_VISIBILITY_CATALOG_AND_ABOUT
or
_has_catalog_visibility
(
course
,
CATALOG_VISIBILITY_CATALOG_AND_ABOUT
)
_has_staff_access_to_descriptor
(
user
,
course
,
course
.
id
)
or
_has_staff_access_to_descriptor
(
user
,
course
,
course
.
id
)
)
)
def
can_see_about_page
():
def
can_see_about_page
():
...
@@ -337,9 +368,9 @@ def _has_access_course_desc(user, action, course):
...
@@ -337,9 +368,9 @@ def _has_access_course_desc(user, action, course):
but also allow course staff to see this.
but also allow course staff to see this.
"""
"""
return
(
return
(
course
.
catalog_visibility
==
CATALOG_VISIBILITY_CATALOG_AND_ABOUT
or
_has_catalog_visibility
(
course
,
CATALOG_VISIBILITY_CATALOG_AND_ABOUT
)
course
.
catalog_visibility
==
CATALOG_VISIBILITY_ABOUT
or
or
_has_catalog_visibility
(
course
,
CATALOG_VISIBILITY_ABOUT
)
_has_staff_access_to_descriptor
(
user
,
course
,
course
.
id
)
or
_has_staff_access_to_descriptor
(
user
,
course
,
course
.
id
)
)
)
checkers
=
{
checkers
=
{
...
@@ -370,11 +401,15 @@ def _can_load_course_overview(user, course_overview):
...
@@ -370,11 +401,15 @@ def _can_load_course_overview(user, course_overview):
The user doesn't have to be enrolled in the course in order to have load
The user doesn't have to be enrolled in the course in order to have load
load access.
load access.
"""
"""
re
turn
(
re
sponse
=
(
not
course_overview
.
visible_to_staff_only
_visible_to_nonstaff_users
(
course_overview
)
and
_can_access_descriptor_with_start_date
(
user
,
course_overview
,
course_overview
.
id
)
and
_can_access_descriptor_with_start_date
(
user
,
course_overview
,
course_overview
.
id
)
)
or
_has_staff_access_to_descriptor
(
user
,
course_overview
,
course_overview
.
id
)
)
return
(
ACCESS_GRANTED
if
(
response
or
_has_staff_access_to_descriptor
(
user
,
course_overview
,
course_overview
.
id
))
else
response
)
_COURSE_OVERVIEW_CHECKERS
=
{
_COURSE_OVERVIEW_CHECKERS
=
{
'load'
:
_can_load_course_overview
,
'load'
:
_can_load_course_overview
,
...
@@ -432,7 +467,7 @@ def _has_group_access(descriptor, user, course_key):
...
@@ -432,7 +467,7 @@ def _has_group_access(descriptor, user, course_key):
# Short-circuit the process, since there are no defined user partitions that are not
# Short-circuit the process, since there are no defined user partitions that are not
# user_partitions used by the split_test module. The split_test module handles its own access
# user_partitions used by the split_test module. The split_test module handles its own access
# via updating the children of the split_test module.
# via updating the children of the split_test module.
return
True
return
ACCESS_GRANTED
# use merged_group_access which takes group access on the block's
# use merged_group_access which takes group access on the block's
# parents / ancestors into account
# parents / ancestors into account
...
@@ -441,20 +476,20 @@ def _has_group_access(descriptor, user, course_key):
...
@@ -441,20 +476,20 @@ def _has_group_access(descriptor, user, course_key):
# partition's group list excludes all students.
# partition's group list excludes all students.
if
False
in
merged_access
.
values
():
if
False
in
merged_access
.
values
():
log
.
warning
(
"Group access check excludes all students, access will be denied."
,
exc_info
=
True
)
log
.
warning
(
"Group access check excludes all students, access will be denied."
,
exc_info
=
True
)
return
False
return
ACCESS_DENIED
# resolve the partition IDs in group_access to actual
# resolve the partition IDs in group_access to actual
# partition objects, skipping those which contain empty group directives.
# partition objects, skipping those which contain empty group directives.
# if a referenced partition could not be found, access will be denied.
# if a referenced partition could not be found, access will be denied.
try
:
try
:
partitions
=
[
partitions
=
[
descriptor
.
_get_user_partition
(
partition_id
)
# pylint:disable=protected-access
descriptor
.
_get_user_partition
(
partition_id
)
# pylint:
disable=protected-access
for
partition_id
,
group_ids
in
merged_access
.
items
()
for
partition_id
,
group_ids
in
merged_access
.
items
()
if
group_ids
is
not
None
if
group_ids
is
not
None
]
]
except
NoSuchUserPartitionError
:
except
NoSuchUserPartitionError
:
log
.
warning
(
"Error looking up user partition, access will be denied."
,
exc_info
=
True
)
log
.
warning
(
"Error looking up user partition, access will be denied."
,
exc_info
=
True
)
return
False
return
ACCESS_DENIED
# next resolve the group IDs specified within each partition
# next resolve the group IDs specified within each partition
partition_groups
=
[]
partition_groups
=
[]
...
@@ -468,7 +503,7 @@ def _has_group_access(descriptor, user, course_key):
...
@@ -468,7 +503,7 @@ def _has_group_access(descriptor, user, course_key):
partition_groups
.
append
((
partition
,
groups
))
partition_groups
.
append
((
partition
,
groups
))
except
NoSuchUserPartitionGroupError
:
except
NoSuchUserPartitionGroupError
:
log
.
warning
(
"Error looking up referenced user partition group, access will be denied."
,
exc_info
=
True
)
log
.
warning
(
"Error looking up referenced user partition group, access will be denied."
,
exc_info
=
True
)
return
False
return
ACCESS_DENIED
# look up the user's group for each partition
# look up the user's group for each partition
user_groups
=
{}
user_groups
=
{}
...
@@ -482,10 +517,10 @@ def _has_group_access(descriptor, user, course_key):
...
@@ -482,10 +517,10 @@ def _has_group_access(descriptor, user, course_key):
# finally: check that the user has a satisfactory group assignment
# finally: check that the user has a satisfactory group assignment
# for each partition.
# for each partition.
if
not
all
(
user_groups
.
get
(
partition
.
id
)
in
groups
for
partition
,
groups
in
partition_groups
):
if
not
all
(
user_groups
.
get
(
partition
.
id
)
in
groups
for
partition
,
groups
in
partition_groups
):
return
False
return
ACCESS_DENIED
# all checks passed.
# all checks passed.
return
True
return
ACCESS_GRANTED
def
_has_access_descriptor
(
user
,
action
,
descriptor
,
course_key
=
None
):
def
_has_access_descriptor
(
user
,
action
,
descriptor
,
course_key
=
None
):
...
@@ -507,14 +542,20 @@ def _has_access_descriptor(user, action, descriptor, course_key=None):
...
@@ -507,14 +542,20 @@ def _has_access_descriptor(user, action, descriptor, course_key=None):
students to see modules. If not, views should check the course, so we
students to see modules. If not, views should check the course, so we
don't have to hit the enrollments table on every module load.
don't have to hit the enrollments table on every module load.
"""
"""
re
turn
(
re
sponse
=
(
not
descriptor
.
visible_to_staff_only
_visible_to_nonstaff_users
(
descriptor
)
and
_has_group_access
(
descriptor
,
user
,
course_key
)
and
_has_group_access
(
descriptor
,
user
,
course_key
)
and
(
and
'detached'
in
descriptor
.
_class_tags
# pylint: disable=protected-access
(
_has_detached_class_tag
(
descriptor
)
or
_can_access_descriptor_with_start_date
(
user
,
descriptor
,
course_key
)
or
_can_access_descriptor_with_start_date
(
user
,
descriptor
,
course_key
)
)
)
)
or
_has_staff_access_to_descriptor
(
user
,
descriptor
,
course_key
)
)
return
(
ACCESS_GRANTED
if
(
response
or
_has_staff_access_to_descriptor
(
user
,
descriptor
,
course_key
))
else
response
)
checkers
=
{
checkers
=
{
'load'
:
can_load
,
'load'
:
can_load
,
...
@@ -592,10 +633,13 @@ def _has_access_string(user, action, perm):
...
@@ -592,10 +633,13 @@ def _has_access_string(user, action, perm):
"""
"""
def
check_staff
():
def
check_staff
():
"""
Checks for staff access
"""
if
perm
!=
'global'
:
if
perm
!=
'global'
:
debug
(
"Deny: invalid permission '
%
s'"
,
perm
)
debug
(
"Deny: invalid permission '
%
s'"
,
perm
)
return
False
return
ACCESS_DENIED
return
GlobalStaff
()
.
has_user
(
user
)
return
ACCESS_GRANTED
if
GlobalStaff
()
.
has_user
(
user
)
else
ACCESS_DENIED
checkers
=
{
checkers
=
{
'staff'
:
check_staff
'staff'
:
check_staff
...
@@ -674,38 +718,37 @@ def _has_staff_access_to_location(user, location, course_key=None):
...
@@ -674,38 +718,37 @@ def _has_staff_access_to_location(user, location, course_key=None):
def
_has_access_to_course
(
user
,
access_level
,
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 the course with the given course_key.
instructor) access to the course with the given course_key.
This ensures the user is authenticated and checks if global staff or has
This ensures the user is authenticated and checks if global staff or has
staff / instructor access.
staff / instructor access.
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
()):
debug
(
"Deny: no user or anon user"
)
debug
(
"Deny: no user or anon user"
)
return
False
return
ACCESS_DENIED
if
is_masquerading_as_student
(
user
,
course_key
):
if
is_masquerading_as_student
(
user
,
course_key
):
return
False
return
ACCESS_DENIED
if
GlobalStaff
()
.
has_user
(
user
):
if
GlobalStaff
()
.
has_user
(
user
):
debug
(
"Allow: user.is_staff"
)
debug
(
"Allow: user.is_staff"
)
return
True
return
ACCESS_GRANTED
if
access_level
not
in
(
'staff'
,
'instructor'
):
if
access_level
not
in
(
'staff'
,
'instructor'
):
log
.
debug
(
"Error in access._has_access_to_course 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
ACCESS_DENIED
staff_access
=
(
staff_access
=
(
CourseStaffRole
(
course_key
)
.
has_user
(
user
)
or
CourseStaffRole
(
course_key
)
.
has_user
(
user
)
or
OrgStaffRole
(
course_key
.
org
)
.
has_user
(
user
)
OrgStaffRole
(
course_key
.
org
)
.
has_user
(
user
)
)
)
if
staff_access
and
access_level
==
'staff'
:
if
staff_access
and
access_level
==
'staff'
:
debug
(
"Allow: user has course staff access"
)
debug
(
"Allow: user has course staff access"
)
return
True
return
ACCESS_GRANTED
instructor_access
=
(
instructor_access
=
(
CourseInstructorRole
(
course_key
)
.
has_user
(
user
)
or
CourseInstructorRole
(
course_key
)
.
has_user
(
user
)
or
...
@@ -714,10 +757,10 @@ def _has_access_to_course(user, access_level, course_key):
...
@@ -714,10 +757,10 @@ def _has_access_to_course(user, access_level, course_key):
if
instructor_access
and
access_level
in
(
'staff'
,
'instructor'
):
if
instructor_access
and
access_level
in
(
'staff'
,
'instructor'
):
debug
(
"Allow: user has course instructor access"
)
debug
(
"Allow: user has course instructor access"
)
return
True
return
ACCESS_GRANTED
debug
(
"Deny: user did not have correct access"
)
debug
(
"Deny: user did not have correct access"
)
return
False
return
ACCESS_DENIED
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
...
@@ -738,6 +781,64 @@ def _has_staff_access_to_descriptor(user, descriptor, course_key):
...
@@ -738,6 +781,64 @@ def _has_staff_access_to_descriptor(user, descriptor, course_key):
return
_has_staff_access_to_location
(
user
,
descriptor
.
location
,
course_key
)
return
_has_staff_access_to_location
(
user
,
descriptor
.
location
,
course_key
)
def
_visible_to_nonstaff_users
(
descriptor
):
"""
Returns if the object is visible to nonstaff users.
Arguments:
descriptor: object to check
"""
return
VisibilityError
()
if
descriptor
.
visible_to_staff_only
else
ACCESS_GRANTED
def
_has_detached_class_tag
(
descriptor
):
"""
Returns if the given descriptor's type is marked as detached.
Arguments:
descriptor: object to check
"""
return
ACCESS_GRANTED
if
'detached'
in
descriptor
.
_class_tags
else
ACCESS_DENIED
# pylint: disable=protected-access
def
_has_fulfilled_all_milestones
(
user
,
course_id
):
"""
Returns whether the given user has fulfilled all milestones for the
given course.
Arguments:
course_id: ID of the course to check
user_id: ID of the user to check
"""
return
MilestoneError
()
if
any_unfulfilled_milestones
(
course_id
,
user
.
id
)
else
ACCESS_GRANTED
def
_has_fulfilled_prerequisites
(
user
,
course_id
):
"""
Returns whether the given user has fulfilled all prerequisites for the
given course.
Arguments:
user: user to check
course_id: ID of the course to check
"""
return
MilestoneError
()
if
get_pre_requisite_courses_not_completed
(
user
,
course_id
)
else
ACCESS_GRANTED
def
_has_catalog_visibility
(
course
,
visibility_type
):
"""
Returns whether the given course has the given visibility type
"""
return
ACCESS_GRANTED
if
course
.
catalog_visibility
==
visibility_type
else
ACCESS_DENIED
def
_is_descriptor_mobile_available
(
descriptor
):
"""
Returns if descriptor is available on mobile.
"""
return
ACCESS_GRANTED
if
descriptor
.
mobile_available
else
MobileAvailabilityError
()
def
is_mobile_available_for_user
(
user
,
descriptor
):
def
is_mobile_available_for_user
(
user
,
descriptor
):
"""
"""
Returns whether the given course is mobile_available for the given user.
Returns whether the given course is mobile_available for the given user.
...
@@ -748,9 +849,9 @@ def is_mobile_available_for_user(user, descriptor):
...
@@ -748,9 +849,9 @@ def is_mobile_available_for_user(user, descriptor):
descriptor (CourseDescriptor|CourseOverview): course or overview of course in question
descriptor (CourseDescriptor|CourseOverview): course or overview of course in question
"""
"""
return
(
return
(
descriptor
.
mobile_available
or
auth
.
user_has_role
(
user
,
CourseBetaTesterRole
(
descriptor
.
id
))
auth
.
has_access
(
user
,
CourseBetaTesterRole
(
descriptor
.
id
))
or
or
_has_staff_access_to_descriptor
(
user
,
descriptor
,
descriptor
.
id
)
_has_staff_access_to_descriptor
(
user
,
descriptor
,
descriptor
.
id
)
or
_is_descriptor_mobile_available
(
descriptor
)
)
)
...
...
lms/djangoapps/courseware/access_response.py
0 → 100644
View file @
4fc3ee47
"""
This file contains all the classes used by has_access for error handling
"""
from
django.utils.translation
import
ugettext
as
_
class
AccessResponse
(
object
):
"""Class that represents a response from a has_access permission check."""
def
__init__
(
self
,
has_access
,
error_code
=
None
,
developer_message
=
None
,
user_message
=
None
):
"""
Creates an AccessResponse object.
Arguments:
has_access (bool): if the user is granted access or not
error_code (String): optional - default is None. Unique identifier
for the specific type of error
developer_message (String): optional - default is None. Message
to show the developer
user_message (String): optional - default is None. Message to
show the user
"""
self
.
has_access
=
has_access
self
.
error_code
=
error_code
self
.
developer_message
=
developer_message
self
.
user_message
=
user_message
if
has_access
:
assert
error_code
is
None
def
__nonzero__
(
self
):
"""
Overrides bool().
Allows for truth value testing of AccessResponse objects, so callers
who do not need the specific error information can check if access
is granted.
Returns:
bool: whether or not access is granted
"""
return
self
.
has_access
def
to_json
(
self
):
"""
Creates a serializable JSON representation of an AccessResponse object.
Returns:
dict: JSON representation
"""
return
{
"has_access"
:
self
.
has_access
,
"error_code"
:
self
.
error_code
,
"developer_message"
:
self
.
developer_message
,
"user_message"
:
self
.
user_message
}
class
AccessError
(
AccessResponse
):
"""
Class that holds information about the error in the case of an access
denial in has_access. Contains the error code, user and developer
messages. Subclasses represent specific errors.
"""
def
__init__
(
self
,
error_code
,
developer_message
,
user_message
):
"""
Creates an AccessError object.
An AccessError object represents an AccessResponse where access is
denied (has_access is False).
Arguments:
error_code (String): unique identifier for the specific type of
error developer_message (String): message to show the developer
user_message (String): message to show the user
"""
super
(
AccessError
,
self
)
.
__init__
(
False
,
error_code
,
developer_message
,
user_message
)
class
StartDateError
(
AccessError
):
"""
Access denied because the course has not started yet and the user
is not staff
"""
def
__init__
(
self
,
start_date
):
error_code
=
"course_not_started"
developer_message
=
"Course does not start until {}"
.
format
(
start_date
)
user_message
=
_
(
"Course does not start until {}"
# pylint: disable=translation-of-non-string
.
format
(
"{:
%
B
%
d,
%
Y}"
.
format
(
start_date
)))
super
(
StartDateError
,
self
)
.
__init__
(
error_code
,
developer_message
,
user_message
)
class
MilestoneError
(
AccessError
):
"""
Access denied because the user has unfulfilled milestones
"""
def
__init__
(
self
):
error_code
=
"unfulfilled_milestones"
developer_message
=
"User has unfulfilled milestones"
user_message
=
_
(
"You have unfulfilled milestones"
)
super
(
MilestoneError
,
self
)
.
__init__
(
error_code
,
developer_message
,
user_message
)
class
VisibilityError
(
AccessError
):
"""
Access denied because the user does have the correct role to view this
course.
"""
def
__init__
(
self
):
error_code
=
"not_visible_to_user"
developer_message
=
"Course is not visible to this user"
user_message
=
_
(
"You do not have access to this course"
)
super
(
VisibilityError
,
self
)
.
__init__
(
error_code
,
developer_message
,
user_message
)
class
MobileAvailabilityError
(
AccessError
):
"""
Access denied because the course is not available on mobile for the user
"""
def
__init__
(
self
):
error_code
=
"mobile_unavailable"
developer_message
=
"Course is not available on mobile for this user"
user_message
=
_
(
"You do not have access to this course on a mobile device"
)
super
(
MobileAvailabilityError
,
self
)
.
__init__
(
error_code
,
developer_message
,
user_message
)
lms/djangoapps/courseware/module_render.py
View file @
4fc3ee47
...
@@ -605,11 +605,11 @@ def get_module_system_for_user(user, student_data, # TODO # pylint: disable=to
...
@@ -605,11 +605,11 @@ def get_module_system_for_user(user, student_data, # TODO # pylint: disable=to
# the result would always be "False".
# the result would always be "False".
masquerade_settings
=
user
.
real_user
.
masquerade_settings
masquerade_settings
=
user
.
real_user
.
masquerade_settings
del
user
.
real_user
.
masquerade_settings
del
user
.
real_user
.
masquerade_settings
instructor_access
=
has_access
(
user
.
real_user
,
'instructor'
,
descriptor
,
course_id
)
instructor_access
=
bool
(
has_access
(
user
.
real_user
,
'instructor'
,
descriptor
,
course_id
)
)
user
.
real_user
.
masquerade_settings
=
masquerade_settings
user
.
real_user
.
masquerade_settings
=
masquerade_settings
else
:
else
:
staff_access
=
has_access
(
user
,
'staff'
,
descriptor
,
course_id
)
staff_access
=
has_access
(
user
,
'staff'
,
descriptor
,
course_id
)
instructor_access
=
has_access
(
user
,
'instructor'
,
descriptor
,
course_id
)
instructor_access
=
bool
(
has_access
(
user
,
'instructor'
,
descriptor
,
course_id
)
)
if
staff_access
:
if
staff_access
:
block_wrappers
.
append
(
partial
(
add_staff_markup
,
user
,
instructor_access
,
disable_staff_debug_info
))
block_wrappers
.
append
(
partial
(
add_staff_markup
,
user
,
instructor_access
,
disable_staff_debug_info
))
...
@@ -629,7 +629,7 @@ def get_module_system_for_user(user, student_data, # TODO # pylint: disable=to
...
@@ -629,7 +629,7 @@ def get_module_system_for_user(user, student_data, # TODO # pylint: disable=to
field_data
=
LmsFieldData
(
descriptor
.
_field_data
,
student_data
)
# pylint: disable=protected-access
field_data
=
LmsFieldData
(
descriptor
.
_field_data
,
student_data
)
# pylint: disable=protected-access
user_is_staff
=
has_access
(
user
,
u'staff'
,
descriptor
.
location
,
course_id
)
user_is_staff
=
bool
(
has_access
(
user
,
u'staff'
,
descriptor
.
location
,
course_id
)
)
system
=
LmsModuleSystem
(
system
=
LmsModuleSystem
(
track_function
=
track_function
,
track_function
=
track_function
,
...
@@ -703,7 +703,7 @@ def get_module_system_for_user(user, student_data, # TODO # pylint: disable=to
...
@@ -703,7 +703,7 @@ def get_module_system_for_user(user, student_data, # TODO # pylint: disable=to
)
)
system
.
set
(
u'user_is_staff'
,
user_is_staff
)
system
.
set
(
u'user_is_staff'
,
user_is_staff
)
system
.
set
(
u'user_is_admin'
,
has_access
(
user
,
u'staff'
,
'global'
))
system
.
set
(
u'user_is_admin'
,
bool
(
has_access
(
user
,
u'staff'
,
'global'
)
))
system
.
set
(
u'user_is_beta_tester'
,
CourseBetaTesterRole
(
course_id
)
.
has_user
(
user
))
system
.
set
(
u'user_is_beta_tester'
,
CourseBetaTesterRole
(
course_id
)
.
has_user
(
user
))
system
.
set
(
u'days_early_for_beta'
,
getattr
(
descriptor
,
'days_early_for_beta'
))
system
.
set
(
u'days_early_for_beta'
,
getattr
(
descriptor
,
'days_early_for_beta'
))
...
...
lms/djangoapps/courseware/tabs.py
View file @
4fc3ee47
...
@@ -20,7 +20,7 @@ class EnrolledTab(CourseTab):
...
@@ -20,7 +20,7 @@ class EnrolledTab(CourseTab):
def
is_enabled
(
cls
,
course
,
user
=
None
):
def
is_enabled
(
cls
,
course
,
user
=
None
):
if
user
is
None
:
if
user
is
None
:
return
True
return
True
return
CourseEnrollment
.
is_enrolled
(
user
,
course
.
id
)
or
has_access
(
user
,
'staff'
,
course
,
course
.
id
)
return
bool
(
CourseEnrollment
.
is_enrolled
(
user
,
course
.
id
)
or
has_access
(
user
,
'staff'
,
course
,
course
.
id
)
)
class
CoursewareTab
(
EnrolledTab
):
class
CoursewareTab
(
EnrolledTab
):
...
...
lms/djangoapps/courseware/tests/test_access.py
View file @
4fc3ee47
# -*- coding: utf-8 -*-
"""
Test the access control framework
"""
import
datetime
import
datetime
import
ddt
import
ddt
import
itertools
import
itertools
...
@@ -10,18 +14,29 @@ from nose.plugins.attrib import attr
...
@@ -10,18 +14,29 @@ from nose.plugins.attrib import attr
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
import
courseware.access
as
access
import
courseware.access
as
access
import
courseware.access_response
as
access_response
from
courseware.masquerade
import
CourseMasquerade
from
courseware.masquerade
import
CourseMasquerade
from
courseware.tests.factories
import
UserFactory
,
StaffFactory
,
InstructorFactory
,
BetaTesterFactory
from
courseware.tests.factories
import
(
BetaTesterFactory
,
GlobalStaffFactory
,
InstructorFactory
,
StaffFactory
,
UserFactory
,
)
from
courseware.tests.helpers
import
LoginEnrollmentTestCase
from
courseware.tests.helpers
import
LoginEnrollmentTestCase
from
openedx.core.djangoapps.content.course_overviews.models
import
CourseOverview
from
openedx.core.djangoapps.content.course_overviews.models
import
CourseOverview
from
student.tests.factories
import
AnonymousUserFactory
,
CourseEnrollmentAllowedFactory
,
CourseEnrollmentFactory
from
student.tests.factories
import
(
AnonymousUserFactory
,
CourseEnrollmentAllowedFactory
,
CourseEnrollmentFactory
,
)
from
xmodule.course_module
import
(
from
xmodule.course_module
import
(
CATALOG_VISIBILITY_CATALOG_AND_ABOUT
,
CATALOG_VISIBILITY_ABOUT
,
CATALOG_VISIBILITY_CATALOG_AND_ABOUT
,
CATALOG_VISIBILITY_NONE
CATALOG_VISIBILITY_ABOUT
,
CATALOG_VISIBILITY_NONE
,
)
)
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
from
util.milestones_helpers
import
fulfill_course_milestone
from
util.milestones_helpers
import
(
from
util.milestones_helpers
import
(
set_prerequisite_courses
,
set_prerequisite_courses
,
...
@@ -34,26 +49,36 @@ from util.milestones_helpers import (
...
@@ -34,26 +49,36 @@ from util.milestones_helpers import (
@attr
(
'shard_1'
)
@attr
(
'shard_1'
)
@ddt.ddt
class
AccessTestCase
(
LoginEnrollmentTestCase
,
ModuleStoreTestCase
):
class
AccessTestCase
(
LoginEnrollmentTestCase
,
ModuleStoreTestCase
):
"""
"""
Tests for the various access controls on the student dashboard
Tests for the various access controls on the student dashboard
"""
"""
TOMORROW
=
datetime
.
datetime
.
now
(
pytz
.
utc
)
+
datetime
.
timedelta
(
days
=
1
)
YESTERDAY
=
datetime
.
datetime
.
now
(
pytz
.
utc
)
-
datetime
.
timedelta
(
days
=
1
)
def
setUp
(
self
):
def
setUp
(
self
):
super
(
AccessTestCase
,
self
)
.
setUp
()
super
(
AccessTestCase
,
self
)
.
setUp
()
course_key
=
SlashSeparatedCourseKey
(
'edX'
,
'toy'
,
'2012_Fall'
)
course_key
=
SlashSeparatedCourseKey
(
'edX'
,
'toy'
,
'2012_Fall'
)
self
.
course
=
course_key
.
make_usage_key
(
'course'
,
course_key
.
run
)
self
.
course
=
course_key
.
make_usage_key
(
'course'
,
course_key
.
run
)
self
.
anonymous_user
=
AnonymousUserFactory
()
self
.
anonymous_user
=
AnonymousUserFactory
()
self
.
beta_user
=
BetaTesterFactory
(
course_key
=
self
.
course
.
course_key
)
self
.
student
=
UserFactory
()
self
.
student
=
UserFactory
()
self
.
global_staff
=
UserFactory
(
is_staff
=
True
)
self
.
global_staff
=
UserFactory
(
is_staff
=
True
)
self
.
course_staff
=
StaffFactory
(
course_key
=
self
.
course
.
course_key
)
self
.
course_staff
=
StaffFactory
(
course_key
=
self
.
course
.
course_key
)
self
.
course_instructor
=
InstructorFactory
(
course_key
=
self
.
course
.
course_key
)
self
.
course_instructor
=
InstructorFactory
(
course_key
=
self
.
course
.
course_key
)
self
.
staff
=
GlobalStaffFactory
()
def
verify_access
(
self
,
mock_unit
,
student_should_have_access
):
def
verify_access
(
self
,
mock_unit
,
student_should_have_access
,
expected_error_type
=
None
):
""" Verify the expected result from _has_access_descriptor """
""" Verify the expected result from _has_access_descriptor """
self
.
assertEqual
(
response
=
access
.
_has_access_descriptor
(
self
.
anonymous_user
,
'load'
,
student_should_have_access
,
mock_unit
,
course_key
=
self
.
course
.
course_key
)
access
.
_has_access_descriptor
(
self
.
anonymous_user
,
'load'
,
mock_unit
,
course_key
=
self
.
course
.
course_key
)
self
.
assertEqual
(
student_should_have_access
,
bool
(
response
))
)
if
expected_error_type
is
not
None
:
self
.
assertIsInstance
(
response
,
expected_error_type
)
self
.
assertIsNotNone
(
response
.
to_json
()[
'error_code'
])
self
.
assertTrue
(
self
.
assertTrue
(
access
.
_has_access_descriptor
(
self
.
course_staff
,
'load'
,
mock_unit
,
course_key
=
self
.
course
.
course_key
)
access
.
_has_access_descriptor
(
self
.
course_staff
,
'load'
,
mock_unit
,
course_key
=
self
.
course
.
course_key
)
)
)
...
@@ -102,6 +127,10 @@ class AccessTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
...
@@ -102,6 +127,10 @@ class AccessTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
self
.
student
,
'instructor'
,
self
.
course
.
course_key
self
.
student
,
'instructor'
,
self
.
course
.
course_key
))
))
self
.
assertFalse
(
access
.
_has_access_to_course
(
self
.
student
,
'not_staff_or_instructor'
,
self
.
course
.
course_key
))
def
test__has_access_string
(
self
):
def
test__has_access_string
(
self
):
user
=
Mock
(
is_staff
=
True
)
user
=
Mock
(
is_staff
=
True
)
self
.
assertFalse
(
access
.
_has_access_string
(
user
,
'staff'
,
'not_global'
))
self
.
assertFalse
(
access
.
_has_access_string
(
user
,
'staff'
,
'not_global'
))
...
@@ -111,20 +140,24 @@ class AccessTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
...
@@ -111,20 +140,24 @@ class AccessTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
self
.
assertRaises
(
ValueError
,
access
.
_has_access_string
,
user
,
'not_staff'
,
'global'
)
self
.
assertRaises
(
ValueError
,
access
.
_has_access_string
,
user
,
'not_staff'
,
'global'
)
def
test__has_access_error_desc
(
self
):
@ddt.data
(
(
'load'
,
False
,
True
,
True
),
(
'staff'
,
False
,
True
,
True
),
(
'instructor'
,
False
,
False
,
True
)
)
@ddt.unpack
def
test__has_access_error_desc
(
self
,
action
,
expected_student
,
expected_staff
,
expected_instructor
):
descriptor
=
Mock
()
descriptor
=
Mock
()
self
.
assertFalse
(
access
.
_has_access_error_desc
(
self
.
student
,
'load'
,
descriptor
,
self
.
course
.
course_key
))
for
(
user
,
expected_response
)
in
(
self
.
assertTrue
(
access
.
_has_access_error_desc
(
self
.
course_staff
,
'load'
,
descriptor
,
self
.
course
.
course_key
))
(
self
.
student
,
expected_student
),
self
.
assertTrue
(
access
.
_has_access_error_desc
(
self
.
course_instructor
,
'load'
,
descriptor
,
self
.
course
.
course_key
))
(
self
.
course_staff
,
expected_staff
),
(
self
.
course_instructor
,
expected_instructor
)
self
.
assertFalse
(
access
.
_has_access_error_desc
(
self
.
student
,
'staff'
,
descriptor
,
self
.
course
.
course_key
))
):
self
.
assertTrue
(
access
.
_has_access_error_desc
(
self
.
course_staff
,
'staff'
,
descriptor
,
self
.
course
.
course_key
))
self
.
assertEquals
(
self
.
assertTrue
(
access
.
_has_access_error_desc
(
self
.
course_instructor
,
'staff'
,
descriptor
,
self
.
course
.
course_key
))
bool
(
access
.
_has_access_error_desc
(
user
,
action
,
descriptor
,
self
.
course
.
course_key
)),
expected_response
self
.
assertFalse
(
access
.
_has_access_error_desc
(
self
.
student
,
'instructor'
,
descriptor
,
self
.
course
.
course_key
))
)
self
.
assertFalse
(
access
.
_has_access_error_desc
(
self
.
course_staff
,
'instructor'
,
descriptor
,
self
.
course
.
course_key
))
self
.
assertTrue
(
access
.
_has_access_error_desc
(
self
.
course_instructor
,
'instructor'
,
descriptor
,
self
.
course
.
course_key
))
with
self
.
assertRaises
(
ValueError
):
with
self
.
assertRaises
(
ValueError
):
access
.
_has_access_error_desc
(
self
.
course_instructor
,
'not_load_or_staff'
,
descriptor
,
self
.
course
.
course_key
)
access
.
_has_access_error_desc
(
self
.
course_instructor
,
'not_load_or_staff'
,
descriptor
,
self
.
course
.
course_key
)
...
@@ -133,6 +166,7 @@ class AccessTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
...
@@ -133,6 +166,7 @@ class AccessTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
# TODO: override DISABLE_START_DATES and test the start date branch of the method
# TODO: override DISABLE_START_DATES and test the start date branch of the method
user
=
Mock
()
user
=
Mock
()
descriptor
=
Mock
(
user_partitions
=
[])
descriptor
=
Mock
(
user_partitions
=
[])
descriptor
.
_class_tags
=
{}
# Always returns true because DISABLE_START_DATES is set in test.py
# Always returns true because DISABLE_START_DATES is set in test.py
self
.
assertTrue
(
access
.
_has_access_descriptor
(
user
,
'load'
,
descriptor
))
self
.
assertTrue
(
access
.
_has_access_descriptor
(
user
,
'load'
,
descriptor
))
...
@@ -140,81 +174,68 @@ class AccessTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
...
@@ -140,81 +174,68 @@ class AccessTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
with
self
.
assertRaises
(
ValueError
):
with
self
.
assertRaises
(
ValueError
):
access
.
_has_access_descriptor
(
user
,
'not_load_or_staff'
,
descriptor
)
access
.
_has_access_descriptor
(
user
,
'not_load_or_staff'
,
descriptor
)
@ddt.data
(
(
True
,
None
,
access_response
.
VisibilityError
),
(
False
,
None
),
(
True
,
YESTERDAY
,
access_response
.
VisibilityError
),
(
False
,
YESTERDAY
),
(
True
,
TOMORROW
,
access_response
.
VisibilityError
),
(
False
,
TOMORROW
,
access_response
.
StartDateError
)
)
@ddt.unpack
@patch.dict
(
'django.conf.settings.FEATURES'
,
{
'DISABLE_START_DATES'
:
False
})
@patch.dict
(
'django.conf.settings.FEATURES'
,
{
'DISABLE_START_DATES'
:
False
})
def
test__has_access_descriptor_staff_lock
(
self
):
def
test__has_access_descriptor_staff_lock
(
self
,
visible_to_staff_only
,
start
,
expected_error_type
=
None
):
"""
"""
Tests that "visible_to_staff_only" overrides start date.
Tests that "visible_to_staff_only" overrides start date.
"""
"""
expected_access
=
expected_error_type
is
None
mock_unit
=
Mock
(
user_partitions
=
[])
mock_unit
=
Mock
(
user_partitions
=
[])
mock_unit
.
_class_tags
=
{}
# Needed for detached check in _has_access_descriptor
mock_unit
.
_class_tags
=
{}
# Needed for detached check in _has_access_descriptor
mock_unit
.
visible_to_staff_only
=
visible_to_staff_only
mock_unit
.
start
=
start
self
.
verify_access
(
mock_unit
,
expected_access
,
expected_error_type
)
# No start date, staff lock on
def
test__has_access_descriptor_beta_user
(
self
):
mock_unit
.
visible_to_staff_only
=
True
mock_unit
=
Mock
(
user_partitions
=
[])
self
.
verify_access
(
mock_unit
,
False
)
mock_unit
.
_class_tags
=
{}
mock_unit
.
days_early_for_beta
=
2
# No start date, staff lock off.
mock_unit
.
start
=
self
.
TOMORROW
mock_unit
.
visible_to_staff_only
=
False
self
.
verify_access
(
mock_unit
,
True
)
# Start date in the past, staff lock on.
mock_unit
.
start
=
datetime
.
datetime
.
now
(
pytz
.
utc
)
-
datetime
.
timedelta
(
days
=
1
)
mock_unit
.
visible_to_staff_only
=
True
self
.
verify_access
(
mock_unit
,
False
)
# Start date in the past, staff lock off.
mock_unit
.
visible_to_staff_only
=
False
mock_unit
.
visible_to_staff_only
=
False
self
.
verify_access
(
mock_unit
,
True
)
# Start date in the future, staff lock on.
self
.
assertTrue
(
bool
(
access
.
_has_access_descriptor
(
mock_unit
.
start
=
datetime
.
datetime
.
now
(
pytz
.
utc
)
+
datetime
.
timedelta
(
days
=
1
)
# release date in the future
self
.
beta_user
,
'load'
,
mock_unit
,
course_key
=
self
.
course
.
course_key
)))
mock_unit
.
visible_to_staff_only
=
True
self
.
verify_access
(
mock_unit
,
False
)
# Start date in the future, staff lock off.
mock_unit
.
visible_to_staff_only
=
False
self
.
verify_access
(
mock_unit
,
False
)
@ddt.data
(
None
,
YESTERDAY
,
TOMORROW
)
@patch.dict
(
'django.conf.settings.FEATURES'
,
{
'DISABLE_START_DATES'
:
False
})
@patch.dict
(
'django.conf.settings.FEATURES'
,
{
'DISABLE_START_DATES'
:
False
})
@patch
(
'courseware.access.get_current_request_hostname'
,
Mock
(
return_value
=
'preview.localhost'
))
@patch
(
'courseware.access.get_current_request_hostname'
,
Mock
(
return_value
=
'preview.localhost'
))
def
test__has_access_descriptor_in_preview_mode
(
self
):
def
test__has_access_descriptor_in_preview_mode
(
self
,
start
):
"""
"""
Tests that descriptor has access in preview mode.
Tests that descriptor has access in preview mode.
"""
"""
mock_unit
=
Mock
(
user_partitions
=
[])
mock_unit
=
Mock
(
user_partitions
=
[])
mock_unit
.
_class_tags
=
{}
# Needed for detached check in _has_access_descriptor
mock_unit
.
_class_tags
=
{}
# Needed for detached check in _has_access_descriptor
# No start date.
mock_unit
.
visible_to_staff_only
=
False
mock_unit
.
visible_to_staff_only
=
False
mock_unit
.
start
=
start
self
.
verify_access
(
mock_unit
,
True
)
self
.
verify_access
(
mock_unit
,
True
)
# Start date in the past.
@ddt.data
(
mock_unit
.
start
=
datetime
.
datetime
.
now
(
pytz
.
utc
)
-
datetime
.
timedelta
(
days
=
1
)
(
TOMORROW
,
access_response
.
StartDateError
),
self
.
verify_access
(
mock_unit
,
True
)
(
None
,
None
),
(
YESTERDAY
,
None
)
# Start date in the future.
)
# ddt throws an error if I don't put the None argument there
mock_unit
.
start
=
datetime
.
datetime
.
now
(
pytz
.
utc
)
+
datetime
.
timedelta
(
days
=
1
)
# release date in the future
@ddt.unpack
self
.
verify_access
(
mock_unit
,
True
)
@patch.dict
(
'django.conf.settings.FEATURES'
,
{
'DISABLE_START_DATES'
:
False
})
@patch.dict
(
'django.conf.settings.FEATURES'
,
{
'DISABLE_START_DATES'
:
False
})
@patch
(
'courseware.access.get_current_request_hostname'
,
Mock
(
return_value
=
'localhost'
))
@patch
(
'courseware.access.get_current_request_hostname'
,
Mock
(
return_value
=
'localhost'
))
def
test__has_access_descriptor_when_not_in_preview_mode
(
self
):
def
test__has_access_descriptor_when_not_in_preview_mode
(
self
,
start
,
expected_error_type
):
"""
"""
Tests that descriptor has no access when start date in future & without preview.
Tests that descriptor has no access when start date in future & without preview.
"""
"""
expected_access
=
expected_error_type
is
None
mock_unit
=
Mock
(
user_partitions
=
[])
mock_unit
=
Mock
(
user_partitions
=
[])
mock_unit
.
_class_tags
=
{}
# Needed for detached check in _has_access_descriptor
mock_unit
.
_class_tags
=
{}
# Needed for detached check in _has_access_descriptor
# No start date.
mock_unit
.
visible_to_staff_only
=
False
mock_unit
.
visible_to_staff_only
=
False
self
.
verify_access
(
mock_unit
,
True
)
mock_unit
.
start
=
start
self
.
verify_access
(
mock_unit
,
expected_access
,
expected_error_type
)
# Start date in the past.
mock_unit
.
start
=
datetime
.
datetime
.
now
(
pytz
.
utc
)
-
datetime
.
timedelta
(
days
=
1
)
self
.
verify_access
(
mock_unit
,
True
)
# Start date in the future.
mock_unit
.
start
=
datetime
.
datetime
.
now
(
pytz
.
utc
)
+
datetime
.
timedelta
(
days
=
1
)
# release date in the future
self
.
verify_access
(
mock_unit
,
False
)
def
test__has_access_course_desc_can_enroll
(
self
):
def
test__has_access_course_desc_can_enroll
(
self
):
yesterday
=
datetime
.
datetime
.
now
(
pytz
.
utc
)
-
datetime
.
timedelta
(
days
=
1
)
yesterday
=
datetime
.
datetime
.
now
(
pytz
.
utc
)
-
datetime
.
timedelta
(
days
=
1
)
...
@@ -301,6 +322,16 @@ class AccessTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
...
@@ -301,6 +322,16 @@ class AccessTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
self
.
assertTrue
(
access
.
_has_access_course_desc
(
staff
,
'see_in_catalog'
,
course
))
self
.
assertTrue
(
access
.
_has_access_course_desc
(
staff
,
'see_in_catalog'
,
course
))
self
.
assertTrue
(
access
.
_has_access_course_desc
(
staff
,
'see_about_page'
,
course
))
self
.
assertTrue
(
access
.
_has_access_course_desc
(
staff
,
'see_about_page'
,
course
))
@ddt.data
(
True
,
False
)
@patch.dict
(
"django.conf.settings.FEATURES"
,
{
'ACCESS_REQUIRE_STAFF_FOR_COURSE'
:
True
})
def
test_see_exists
(
self
,
ispublic
):
"""
Test if user can see course
"""
user
=
UserFactory
.
create
(
is_staff
=
False
)
course
=
Mock
(
ispublic
=
ispublic
)
self
.
assertEquals
(
bool
(
access
.
_has_access_course_desc
(
user
,
'see_exists'
,
course
)),
ispublic
)
@patch.dict
(
"django.conf.settings.FEATURES"
,
{
'ENABLE_PREREQUISITE_COURSES'
:
True
,
'MILESTONES_APP'
:
True
})
@patch.dict
(
"django.conf.settings.FEATURES"
,
{
'ENABLE_PREREQUISITE_COURSES'
:
True
,
'MILESTONES_APP'
:
True
})
def
test_access_on_course_with_pre_requisites
(
self
):
def
test_access_on_course_with_pre_requisites
(
self
):
"""
"""
...
@@ -319,10 +350,11 @@ class AccessTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
...
@@ -319,10 +350,11 @@ class AccessTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
)
)
set_prerequisite_courses
(
course
.
id
,
pre_requisite_courses
)
set_prerequisite_courses
(
course
.
id
,
pre_requisite_courses
)
#user should not be able to load course even if enrolled
#
user should not be able to load course even if enrolled
CourseEnrollmentFactory
(
user
=
user
,
course_id
=
course
.
id
)
CourseEnrollmentFactory
(
user
=
user
,
course_id
=
course
.
id
)
self
.
assertFalse
(
access
.
_has_access_course_desc
(
user
,
'view_courseware_with_prerequisites'
,
course
))
response
=
access
.
_has_access_course_desc
(
user
,
'view_courseware_with_prerequisites'
,
course
)
self
.
assertFalse
(
response
)
self
.
assertIsInstance
(
response
,
access_response
.
MilestoneError
)
# Staff can always access course
# Staff can always access course
staff
=
StaffFactory
.
create
(
course_key
=
course
.
id
)
staff
=
StaffFactory
.
create
(
course_key
=
course
.
id
)
self
.
assertTrue
(
access
.
_has_access_course_desc
(
staff
,
'view_courseware_with_prerequisites'
,
course
))
self
.
assertTrue
(
access
.
_has_access_course_desc
(
staff
,
'view_courseware_with_prerequisites'
,
course
))
...
@@ -331,6 +363,26 @@ class AccessTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
...
@@ -331,6 +363,26 @@ class AccessTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
fulfill_course_milestone
(
pre_requisite_course
.
id
,
user
)
fulfill_course_milestone
(
pre_requisite_course
.
id
,
user
)
self
.
assertTrue
(
access
.
_has_access_course_desc
(
user
,
'view_courseware_with_prerequisites'
,
course
))
self
.
assertTrue
(
access
.
_has_access_course_desc
(
user
,
'view_courseware_with_prerequisites'
,
course
))
@ddt.data
(
(
True
,
True
,
True
),
(
False
,
False
,
True
)
)
@ddt.unpack
def
test__access_on_mobile
(
self
,
mobile_available
,
student_expected
,
staff_expected
):
"""
Test course access on mobile for staff and students.
"""
descriptor
=
Mock
(
user_partitions
=
[])
descriptor
.
_class_tags
=
{}
descriptor
.
visible_to_staff_only
=
False
descriptor
.
mobile_available
=
mobile_available
self
.
assertEqual
(
bool
(
access
.
_has_access_course_desc
(
self
.
student
,
'load_mobile'
,
descriptor
)),
student_expected
)
self
.
assertEqual
(
bool
(
access
.
_has_access_course_desc
(
self
.
staff
,
'load_mobile'
,
descriptor
)),
staff_expected
)
@patch.dict
(
"django.conf.settings.FEATURES"
,
{
'ENABLE_PREREQUISITE_COURSES'
:
True
,
'MILESTONES_APP'
:
True
})
@patch.dict
(
"django.conf.settings.FEATURES"
,
{
'ENABLE_PREREQUISITE_COURSES'
:
True
,
'MILESTONES_APP'
:
True
})
def
test_courseware_page_unfulfilled_prereqs
(
self
):
def
test_courseware_page_unfulfilled_prereqs
(
self
):
"""
"""
...
@@ -504,11 +556,11 @@ class CourseOverviewAccessTestCase(ModuleStoreTestCase):
...
@@ -504,11 +556,11 @@ class CourseOverviewAccessTestCase(ModuleStoreTestCase):
course_overview
=
CourseOverview
.
get_from_id
(
course
.
id
)
course_overview
=
CourseOverview
.
get_from_id
(
course
.
id
)
self
.
assertEqual
(
self
.
assertEqual
(
access
.
has_access
(
user
,
action
,
course
,
course_key
=
course
.
id
),
bool
(
access
.
has_access
(
user
,
action
,
course
,
course_key
=
course
.
id
)
),
access
.
has_access
(
user
,
action
,
course_overview
,
course_key
=
course
.
id
)
bool
(
access
.
has_access
(
user
,
action
,
course_overview
,
course_key
=
course
.
id
)
)
)
)
def
test_course_over
iv
ew_unsupported_action
(
self
):
def
test_course_over
vi
ew_unsupported_action
(
self
):
"""
"""
Check that calling has_access with an unsupported action raises a
Check that calling has_access with an unsupported action raises a
ValueError.
ValueError.
...
...
lms/djangoapps/courseware/tests/test_group_access.py
View file @
4fc3ee47
...
@@ -185,7 +185,7 @@ class GroupAccessTestCase(ModuleStoreTestCase):
...
@@ -185,7 +185,7 @@ class GroupAccessTestCase(ModuleStoreTestCase):
DRY helper.
DRY helper.
"""
"""
self
.
assertIs
(
self
.
assertIs
(
access
.
has_access
(
user
,
'load'
,
modulestore
()
.
get_item
(
block_location
),
self
.
course
.
id
),
bool
(
access
.
has_access
(
user
,
'load'
,
modulestore
()
.
get_item
(
block_location
),
self
.
course
.
id
)
),
is_accessible
is_accessible
)
)
...
...
lms/djangoapps/courseware/views.py
View file @
4fc3ee47
...
@@ -766,7 +766,7 @@ def syllabus(request, course_id):
...
@@ -766,7 +766,7 @@ def syllabus(request, course_id):
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
course
=
get_course_with_access
(
request
.
user
,
'load'
,
course_key
)
course
=
get_course_with_access
(
request
.
user
,
'load'
,
course_key
)
staff_access
=
has_access
(
request
.
user
,
'staff'
,
course
)
staff_access
=
bool
(
has_access
(
request
.
user
,
'staff'
,
course
)
)
return
render_to_response
(
'courseware/syllabus.html'
,
{
return
render_to_response
(
'courseware/syllabus.html'
,
{
'course'
:
course
,
'course'
:
course
,
...
@@ -828,7 +828,7 @@ def course_about(request, course_id):
...
@@ -828,7 +828,7 @@ def course_about(request, course_id):
registered
=
registered_for_course
(
course
,
request
.
user
)
registered
=
registered_for_course
(
course
,
request
.
user
)
staff_access
=
has_access
(
request
.
user
,
'staff'
,
course
)
staff_access
=
bool
(
has_access
(
request
.
user
,
'staff'
,
course
)
)
studio_url
=
get_studio_url
(
course
,
'settings/details'
)
studio_url
=
get_studio_url
(
course
,
'settings/details'
)
if
has_access
(
request
.
user
,
'load'
,
course
):
if
has_access
(
request
.
user
,
'load'
,
course
):
...
@@ -836,7 +836,7 @@ def course_about(request, course_id):
...
@@ -836,7 +836,7 @@ def course_about(request, course_id):
else
:
else
:
course_target
=
reverse
(
'about_course'
,
args
=
[
course
.
id
.
to_deprecated_string
()])
course_target
=
reverse
(
'about_course'
,
args
=
[
course
.
id
.
to_deprecated_string
()])
show_courseware_link
=
(
show_courseware_link
=
bool
(
(
(
has_access
(
request
.
user
,
'load'
,
course
)
has_access
(
request
.
user
,
'load'
,
course
)
and
has_access
(
request
.
user
,
'view_courseware_with_prerequisites'
,
course
)
and
has_access
(
request
.
user
,
'view_courseware_with_prerequisites'
,
course
)
...
@@ -865,7 +865,7 @@ def course_about(request, course_id):
...
@@ -865,7 +865,7 @@ def course_about(request, course_id):
can_add_course_to_cart
=
_is_shopping_cart_enabled
and
registration_price
can_add_course_to_cart
=
_is_shopping_cart_enabled
and
registration_price
# Used to provide context to message to student if enrollment not allowed
# Used to provide context to message to student if enrollment not allowed
can_enroll
=
has_access
(
request
.
user
,
'enroll'
,
course
)
can_enroll
=
bool
(
has_access
(
request
.
user
,
'enroll'
,
course
)
)
invitation_only
=
course
.
invitation_only
invitation_only
=
course
.
invitation_only
is_course_full
=
CourseEnrollment
.
objects
.
is_course_full
(
course
)
is_course_full
=
CourseEnrollment
.
objects
.
is_course_full
(
course
)
...
@@ -931,9 +931,9 @@ def mktg_course_about(request, course_id):
...
@@ -931,9 +931,9 @@ def mktg_course_about(request, course_id):
else
:
else
:
course_target
=
reverse
(
'about_course'
,
args
=
[
course
.
id
.
to_deprecated_string
()])
course_target
=
reverse
(
'about_course'
,
args
=
[
course
.
id
.
to_deprecated_string
()])
allow_registration
=
has_access
(
request
.
user
,
'enroll'
,
course
)
allow_registration
=
bool
(
has_access
(
request
.
user
,
'enroll'
,
course
)
)
show_courseware_link
=
(
has_access
(
request
.
user
,
'load'
,
course
)
or
show_courseware_link
=
bool
(
has_access
(
request
.
user
,
'load'
,
course
)
or
settings
.
FEATURES
.
get
(
'ENABLE_LMS_MIGRATION'
))
settings
.
FEATURES
.
get
(
'ENABLE_LMS_MIGRATION'
))
course_modes
=
CourseMode
.
modes_for_course_dict
(
course
.
id
)
course_modes
=
CourseMode
.
modes_for_course_dict
(
course
.
id
)
...
@@ -1028,7 +1028,7 @@ def _progress(request, course_key, student_id):
...
@@ -1028,7 +1028,7 @@ def _progress(request, course_key, student_id):
if
survey
.
utils
.
must_answer_survey
(
course
,
request
.
user
):
if
survey
.
utils
.
must_answer_survey
(
course
,
request
.
user
):
return
redirect
(
reverse
(
'course_survey'
,
args
=
[
unicode
(
course
.
id
)]))
return
redirect
(
reverse
(
'course_survey'
,
args
=
[
unicode
(
course
.
id
)]))
staff_access
=
has_access
(
request
.
user
,
'staff'
,
course
)
staff_access
=
bool
(
has_access
(
request
.
user
,
'staff'
,
course
)
)
if
student_id
is
None
or
student_id
==
request
.
user
.
id
:
if
student_id
is
None
or
student_id
==
request
.
user
.
id
:
# always allowed to see your own profile
# always allowed to see your own profile
...
@@ -1175,7 +1175,7 @@ def submission_history(request, course_id, student_username, location):
...
@@ -1175,7 +1175,7 @@ def submission_history(request, course_id, student_username, location):
return
HttpResponse
(
escape
(
_
(
u'Invalid location.'
)))
return
HttpResponse
(
escape
(
_
(
u'Invalid location.'
)))
course
=
get_course_with_access
(
request
.
user
,
'load'
,
course_key
)
course
=
get_course_with_access
(
request
.
user
,
'load'
,
course_key
)
staff_access
=
has_access
(
request
.
user
,
'staff'
,
course
)
staff_access
=
bool
(
has_access
(
request
.
user
,
'staff'
,
course
)
)
# Permission Denied if they don't have staff access and are trying to see
# Permission Denied if they don't have staff access and are trying to see
# somebody else's submission history.
# somebody else's submission history.
...
@@ -1478,7 +1478,7 @@ def render_xblock(request, usage_key_string, check_if_enrolled=True):
...
@@ -1478,7 +1478,7 @@ def render_xblock(request, usage_key_string, check_if_enrolled=True):
'disable_header'
:
True
,
'disable_header'
:
True
,
'disable_window_wrap'
:
True
,
'disable_window_wrap'
:
True
,
'disable_preview_menu'
:
True
,
'disable_preview_menu'
:
True
,
'staff_access'
:
has_access
(
request
.
user
,
'staff'
,
course
),
'staff_access'
:
bool
(
has_access
(
request
.
user
,
'staff'
,
course
)
),
'xqa_server'
:
settings
.
FEATURES
.
get
(
'XQA_SERVER'
,
'http://your_xqa_server.com'
),
'xqa_server'
:
settings
.
FEATURES
.
get
(
'XQA_SERVER'
,
'http://your_xqa_server.com'
),
}
}
return
render_to_response
(
'courseware/courseware-chromeless.html'
,
context
)
return
render_to_response
(
'courseware/courseware-chromeless.html'
,
context
)
lms/djangoapps/django_comment_client/base/views.py
View file @
4fc3ee47
...
@@ -484,7 +484,7 @@ def un_flag_abuse_for_thread(request, course_id, thread_id):
...
@@ -484,7 +484,7 @@ def un_flag_abuse_for_thread(request, course_id, thread_id):
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
course
=
get_course_by_id
(
course_key
)
course
=
get_course_by_id
(
course_key
)
thread
=
cc
.
Thread
.
find
(
thread_id
)
thread
=
cc
.
Thread
.
find
(
thread_id
)
remove_all
=
(
remove_all
=
bool
(
has_permission
(
request
.
user
,
'openclose_thread'
,
course_key
)
or
has_permission
(
request
.
user
,
'openclose_thread'
,
course_key
)
or
has_access
(
request
.
user
,
'staff'
,
course
)
has_access
(
request
.
user
,
'staff'
,
course
)
)
)
...
@@ -519,7 +519,7 @@ def un_flag_abuse_for_comment(request, course_id, comment_id):
...
@@ -519,7 +519,7 @@ def un_flag_abuse_for_comment(request, course_id, comment_id):
user
=
cc
.
User
.
from_django_user
(
request
.
user
)
user
=
cc
.
User
.
from_django_user
(
request
.
user
)
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
course
=
get_course_by_id
(
course_key
)
course
=
get_course_by_id
(
course_key
)
remove_all
=
(
remove_all
=
bool
(
has_permission
(
request
.
user
,
'openclose_thread'
,
course_key
)
or
has_permission
(
request
.
user
,
'openclose_thread'
,
course_key
)
or
has_access
(
request
.
user
,
'staff'
,
course
)
has_access
(
request
.
user
,
'staff'
,
course
)
)
)
...
...
lms/djangoapps/django_comment_client/forum/views.py
View file @
4fc3ee47
...
@@ -272,11 +272,11 @@ def forum_form_discussion(request, course_key):
...
@@ -272,11 +272,11 @@ def forum_form_discussion(request, course_key):
'csrf'
:
csrf
(
request
)[
'csrf_token'
],
'csrf'
:
csrf
(
request
)[
'csrf_token'
],
'course'
:
course
,
'course'
:
course
,
#'recent_active_threads': recent_active_threads,
#'recent_active_threads': recent_active_threads,
'staff_access'
:
has_access
(
request
.
user
,
'staff'
,
course
),
'staff_access'
:
bool
(
has_access
(
request
.
user
,
'staff'
,
course
)
),
'threads'
:
_attr_safe_json
(
threads
),
'threads'
:
_attr_safe_json
(
threads
),
'thread_pages'
:
query_params
[
'num_pages'
],
'thread_pages'
:
query_params
[
'num_pages'
],
'user_info'
:
_attr_safe_json
(
user_info
),
'user_info'
:
_attr_safe_json
(
user_info
),
'flag_moderator'
:
(
'flag_moderator'
:
bool
(
has_permission
(
request
.
user
,
'openclose_thread'
,
course
.
id
)
or
has_permission
(
request
.
user
,
'openclose_thread'
,
course
.
id
)
or
has_access
(
request
.
user
,
'staff'
,
course
)
has_access
(
request
.
user
,
'staff'
,
course
)
),
),
...
@@ -385,7 +385,7 @@ def single_thread(request, course_key, discussion_id, thread_id):
...
@@ -385,7 +385,7 @@ def single_thread(request, course_key, discussion_id, thread_id):
'is_moderator'
:
is_moderator
,
'is_moderator'
:
is_moderator
,
'thread_pages'
:
query_params
[
'num_pages'
],
'thread_pages'
:
query_params
[
'num_pages'
],
'is_course_cohorted'
:
is_course_cohorted
(
course_key
),
'is_course_cohorted'
:
is_course_cohorted
(
course_key
),
'flag_moderator'
:
(
'flag_moderator'
:
bool
(
has_permission
(
request
.
user
,
'openclose_thread'
,
course
.
id
)
or
has_permission
(
request
.
user
,
'openclose_thread'
,
course
.
id
)
or
has_access
(
request
.
user
,
'staff'
,
course
)
has_access
(
request
.
user
,
'staff'
,
course
)
),
),
...
...
lms/djangoapps/instructor/paidcourse_enrollment_report.py
View file @
4fc3ee47
...
@@ -24,7 +24,7 @@ class PaidCourseEnrollmentReportProvider(BaseAbstractEnrollmentReportProvider):
...
@@ -24,7 +24,7 @@ class PaidCourseEnrollmentReportProvider(BaseAbstractEnrollmentReportProvider):
Returns the User Enrollment information.
Returns the User Enrollment information.
"""
"""
course
=
get_course_by_id
(
course_id
,
depth
=
0
)
course
=
get_course_by_id
(
course_id
,
depth
=
0
)
is_course_staff
=
has_access
(
user
,
'staff'
,
course
)
is_course_staff
=
bool
(
has_access
(
user
,
'staff'
,
course
)
)
# check the user enrollment role
# check the user enrollment role
if
user
.
is_staff
:
if
user
.
is_staff
:
...
...
lms/djangoapps/instructor/views/api.py
View file @
4fc3ee47
...
@@ -274,7 +274,7 @@ def require_sales_admin(func):
...
@@ -274,7 +274,7 @@ def require_sales_admin(func):
log
.
error
(
u"Unable to find course with course key
%
s"
,
course_id
)
log
.
error
(
u"Unable to find course with course key
%
s"
,
course_id
)
return
HttpResponseNotFound
()
return
HttpResponseNotFound
()
access
=
auth
.
has_access
(
request
.
user
,
CourseSalesAdminRole
(
course_key
))
access
=
auth
.
user_has_role
(
request
.
user
,
CourseSalesAdminRole
(
course_key
))
if
access
:
if
access
:
return
func
(
request
,
course_id
)
return
func
(
request
,
course_id
)
...
@@ -299,7 +299,7 @@ def require_finance_admin(func):
...
@@ -299,7 +299,7 @@ def require_finance_admin(func):
log
.
error
(
u"Unable to find course with course key
%
s"
,
course_id
)
log
.
error
(
u"Unable to find course with course key
%
s"
,
course_id
)
return
HttpResponseNotFound
()
return
HttpResponseNotFound
()
access
=
auth
.
has_access
(
request
.
user
,
CourseFinanceAdminRole
(
course_key
))
access
=
auth
.
user_has_role
(
request
.
user
,
CourseFinanceAdminRole
(
course_key
))
if
access
:
if
access
:
return
func
(
request
,
course_id
)
return
func
(
request
,
course_id
)
...
...
lms/djangoapps/instructor/views/instructor_dashboard.py
View file @
4fc3ee47
...
@@ -62,7 +62,7 @@ class InstructorDashboardTab(CourseTab):
...
@@ -62,7 +62,7 @@ class InstructorDashboardTab(CourseTab):
"""
"""
Returns true if the specified user has staff access.
Returns true if the specified user has staff access.
"""
"""
return
user
and
has_access
(
user
,
'staff'
,
course
,
course
.
id
)
return
bool
(
user
and
has_access
(
user
,
'staff'
,
course
,
course
.
id
)
)
@ensure_csrf_cookie
@ensure_csrf_cookie
...
@@ -79,10 +79,10 @@ def instructor_dashboard_2(request, course_id):
...
@@ -79,10 +79,10 @@ def instructor_dashboard_2(request, course_id):
access
=
{
access
=
{
'admin'
:
request
.
user
.
is_staff
,
'admin'
:
request
.
user
.
is_staff
,
'instructor'
:
has_access
(
request
.
user
,
'instructor'
,
course
),
'instructor'
:
bool
(
has_access
(
request
.
user
,
'instructor'
,
course
)
),
'finance_admin'
:
CourseFinanceAdminRole
(
course_key
)
.
has_user
(
request
.
user
),
'finance_admin'
:
CourseFinanceAdminRole
(
course_key
)
.
has_user
(
request
.
user
),
'sales_admin'
:
CourseSalesAdminRole
(
course_key
)
.
has_user
(
request
.
user
),
'sales_admin'
:
CourseSalesAdminRole
(
course_key
)
.
has_user
(
request
.
user
),
'staff'
:
has_access
(
request
.
user
,
'staff'
,
course
),
'staff'
:
bool
(
has_access
(
request
.
user
,
'staff'
,
course
)
),
'forum_admin'
:
has_forum_access
(
request
.
user
,
course_key
,
FORUM_ROLE_ADMINISTRATOR
),
'forum_admin'
:
has_forum_access
(
request
.
user
,
course_key
,
FORUM_ROLE_ADMINISTRATOR
),
}
}
...
...
lms/djangoapps/instructor/views/legacy.py
View file @
4fc3ee47
...
@@ -84,7 +84,7 @@ def instructor_dashboard(request, course_id):
...
@@ -84,7 +84,7 @@ def instructor_dashboard(request, course_id):
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
course
=
get_course_with_access
(
request
.
user
,
'staff'
,
course_key
,
depth
=
None
)
course
=
get_course_with_access
(
request
.
user
,
'staff'
,
course_key
,
depth
=
None
)
instructor_access
=
has_access
(
request
.
user
,
'instructor'
,
course
)
# an instructor can manage staff lists
instructor_access
=
bool
(
has_access
(
request
.
user
,
'instructor'
,
course
)
)
# an instructor can manage staff lists
forum_admin_access
=
has_forum_access
(
request
.
user
,
course_key
,
FORUM_ROLE_ADMINISTRATOR
)
forum_admin_access
=
has_forum_access
(
request
.
user
,
course_key
,
FORUM_ROLE_ADMINISTRATOR
)
...
...
lms/djangoapps/open_ended_grading/open_ended_notifications.py
View file @
4fc3ee47
...
@@ -118,7 +118,7 @@ def combined_notifications(course, user):
...
@@ -118,7 +118,7 @@ def combined_notifications(course, user):
#Initialize controller query service using our mock system
#Initialize controller query service using our mock system
controller_qs
=
ControllerQueryService
(
settings
.
OPEN_ENDED_GRADING_INTERFACE
,
render_to_string
)
controller_qs
=
ControllerQueryService
(
settings
.
OPEN_ENDED_GRADING_INTERFACE
,
render_to_string
)
student_id
=
unique_id_for_user
(
user
)
student_id
=
unique_id_for_user
(
user
)
user_is_staff
=
has_access
(
user
,
'staff'
,
course
)
user_is_staff
=
bool
(
has_access
(
user
,
'staff'
,
course
)
)
course_id
=
course
.
id
course_id
=
course
.
id
notification_type
=
"combined"
notification_type
=
"combined"
...
...
lms/djangoapps/staticbook/views.py
View file @
4fc3ee47
...
@@ -22,7 +22,7 @@ def index(request, course_id, book_index, page=None):
...
@@ -22,7 +22,7 @@ def index(request, course_id, book_index, page=None):
"""
"""
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
course
=
get_course_with_access
(
request
.
user
,
'load'
,
course_key
)
course
=
get_course_with_access
(
request
.
user
,
'load'
,
course_key
)
staff_access
=
has_access
(
request
.
user
,
'staff'
,
course
)
staff_access
=
bool
(
has_access
(
request
.
user
,
'staff'
,
course
)
)
book_index
=
int
(
book_index
)
book_index
=
int
(
book_index
)
if
book_index
<
0
or
book_index
>=
len
(
course
.
textbooks
):
if
book_index
<
0
or
book_index
>=
len
(
course
.
textbooks
):
...
@@ -79,7 +79,7 @@ def pdf_index(request, course_id, book_index, chapter=None, page=None):
...
@@ -79,7 +79,7 @@ def pdf_index(request, course_id, book_index, chapter=None, page=None):
"""
"""
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
course
=
get_course_with_access
(
request
.
user
,
'load'
,
course_key
)
course
=
get_course_with_access
(
request
.
user
,
'load'
,
course_key
)
staff_access
=
has_access
(
request
.
user
,
'staff'
,
course
)
staff_access
=
bool
(
has_access
(
request
.
user
,
'staff'
,
course
)
)
book_index
=
int
(
book_index
)
book_index
=
int
(
book_index
)
if
book_index
<
0
or
book_index
>=
len
(
course
.
pdf_textbooks
):
if
book_index
<
0
or
book_index
>=
len
(
course
.
pdf_textbooks
):
...
@@ -147,7 +147,7 @@ def html_index(request, course_id, book_index, chapter=None):
...
@@ -147,7 +147,7 @@ def html_index(request, course_id, book_index, chapter=None):
"""
"""
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
course
=
get_course_with_access
(
request
.
user
,
'load'
,
course_key
)
course
=
get_course_with_access
(
request
.
user
,
'load'
,
course_key
)
staff_access
=
has_access
(
request
.
user
,
'staff'
,
course
)
staff_access
=
bool
(
has_access
(
request
.
user
,
'staff'
,
course
)
)
notes_enabled
=
notes_enabled_for_course
(
course
)
notes_enabled
=
notes_enabled_for_course
(
course
)
book_index
=
int
(
book_index
)
book_index
=
int
(
book_index
)
...
...
lms/lib/courseware_search/lms_search_initializer.py
View file @
4fc3ee47
...
@@ -21,5 +21,5 @@ class LmsSearchInitializer(SearchInitializer):
...
@@ -21,5 +21,5 @@ class LmsSearchInitializer(SearchInitializer):
course_key
=
CourseKey
.
from_string
(
kwargs
[
'course_id'
])
course_key
=
CourseKey
.
from_string
(
kwargs
[
'course_id'
])
except
InvalidKeyError
:
except
InvalidKeyError
:
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
kwargs
[
'course_id'
])
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
kwargs
[
'course_id'
])
staff_access
=
has_access
(
request
.
user
,
'staff'
,
course_key
)
staff_access
=
bool
(
has_access
(
request
.
user
,
'staff'
,
course_key
)
)
setup_masquerade
(
request
,
course_key
,
staff_access
)
setup_masquerade
(
request
,
course_key
,
staff_access
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment