Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
E
edx-platform-release
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Code
Merge requests
1
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Package Registry
Model registry
Operate
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Hsin-Yu Chien
edx-platform-release
Commits
bb952e14
Commit
bb952e14
authored
9 years ago
by
muzaffaryousaf
Committed by
Usman Khalid
9 years ago
Browse files
Options
Downloads
Patches
Plain Diff
Restrice non-staff users to access preview content.
TNL-4194
parent
3ca2523a
Loading
Loading
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
lms/djangoapps/courseware/access.py
+54
-1
54 additions, 1 deletion
lms/djangoapps/courseware/access.py
lms/djangoapps/courseware/tests/test_access.py
+115
-23
115 additions, 23 deletions
lms/djangoapps/courseware/tests/test_access.py
with
169 additions
and
24 deletions
lms/djangoapps/courseware/access.py
+
54
−
1
View file @
bb952e14
...
...
@@ -61,7 +61,10 @@ from courseware.access_response import (
MobileAvailabilityError
,
VisibilityError
,
)
from
courseware.access_utils
import
adjust_start_date
,
check_start_date
,
debug
,
ACCESS_GRANTED
,
ACCESS_DENIED
from
courseware.access_utils
import
(
adjust_start_date
,
check_start_date
,
debug
,
ACCESS_GRANTED
,
ACCESS_DENIED
,
in_preview_mode
)
from
lms.djangoapps.ccx.custom_exception
import
CCXLocatorValidationException
from
lms.djangoapps.ccx.models
import
CustomCourseForEdX
...
...
@@ -135,6 +138,10 @@ def has_access(user, action, obj, course_key=None):
if
isinstance
(
course_key
,
CCXLocator
):
course_key
=
course_key
.
to_course_locator
()
if
in_preview_mode
():
if
not
bool
(
has_staff_access_to_preview_mode
(
user
=
user
,
obj
=
obj
,
course_key
=
course_key
)):
return
ACCESS_DENIED
# delegate the work to type-specific functions.
# (start with more specific types, then get more general)
if
isinstance
(
obj
,
CourseDescriptor
):
...
...
@@ -172,6 +179,52 @@ def has_access(user, action, obj, course_key=None):
# ================ Implementation helpers ================================
def
has_staff_access_to_preview_mode
(
user
,
obj
,
course_key
=
None
):
"""
Returns whether user has staff access to specified modules or not.
Arguments:
user: a Django user object.
obj: The object to check access for.
course_key: A course_key specifying which course this access is for.
Returns an AccessResponse object.
"""
if
course_key
is
None
:
if
isinstance
(
obj
,
CourseDescriptor
)
or
isinstance
(
obj
,
CourseOverview
):
course_key
=
obj
.
id
elif
isinstance
(
obj
,
ErrorDescriptor
):
course_key
=
obj
.
location
.
course_key
elif
isinstance
(
obj
,
XModule
):
course_key
=
obj
.
descriptor
.
course_key
elif
isinstance
(
obj
,
XBlock
):
course_key
=
obj
.
location
.
course_key
elif
isinstance
(
obj
,
CCXLocator
):
course_key
=
obj
.
to_course_locator
()
elif
isinstance
(
obj
,
CourseKey
):
course_key
=
obj
elif
isinstance
(
obj
,
UsageKey
):
course_key
=
obj
.
course_key
if
course_key
is
None
:
if
GlobalStaff
().
has_user
(
user
):
return
ACCESS_GRANTED
else
:
return
ACCESS_DENIED
return
_has_access_to_course
(
user
,
'
staff
'
,
course_key
=
course_key
)
def
_can_access_descriptor_with_start_date
(
user
,
descriptor
,
course_key
):
# pylint: disable=invalid-name
"""
Checks if a user has access to a descriptor based on its start date.
...
...
This diff is collapsed.
Click to expand it.
lms/djangoapps/courseware/tests/test_access.py
+
115
−
23
View file @
bb952e14
...
...
@@ -17,6 +17,7 @@ from mock import Mock, patch
from
nose.plugins.attrib
import
attr
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
from
ccx.tests.factories
import
CcxFactory
import
courseware.access
as
access
import
courseware.access_response
as
access_response
from
courseware.masquerade
import
CourseMasquerade
...
...
@@ -39,17 +40,21 @@ from student.tests.factories import (
CourseEnrollmentAllowedFactory
,
CourseEnrollmentFactory
,
)
from
xmodule.course_module
import
(
CATALOG_VISIBILITY_CATALOG_AND_ABOUT
,
CATALOG_VISIBILITY_ABOUT
,
CATALOG_VISIBILITY_NONE
,
)
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
xmodule.error_module
import
ErrorDescriptor
from
xmodule.modulestore.tests.factories
import
CourseFactory
,
ItemFactory
from
xmodule.modulestore.tests.django_utils
import
(
ModuleStoreTestCase
,
SharedModuleStoreTestCase
,
TEST_DATA_SPLIT_MODULESTORE
)
from
xmodule.modulestore.xml
import
CourseLocationManager
from
xmodule.tests
import
get_test_system
from
util.milestones_helpers
import
(
set_prerequisite_courses
,
...
...
@@ -157,23 +162,23 @@ class AccessTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase, MilestonesTes
"""
TOMORROW
=
datetime
.
datetime
.
now
(
pytz
.
utc
)
+
datetime
.
timedelta
(
days
=
1
)
YESTERDAY
=
datetime
.
datetime
.
now
(
pytz
.
utc
)
-
datetime
.
timedelta
(
days
=
1
)
MODULESTORE
=
TEST_DATA_SPLIT_MODULESTORE
def
setUp
(
self
):
super
(
AccessTestCase
,
self
).
setUp
()
course_key
=
SlashSeparatedCourseKey
(
'
edX
'
,
'
toy
'
,
'
2012_Fall
'
)
self
.
course
=
course_key
.
make_usage_key
(
'
course
'
,
course_key
.
run
)
self
.
course
=
CourseFactory
.
create
(
org
=
'
edX
'
,
course
=
'
toy
'
,
run
=
'
test_run
'
)
self
.
anonymous_user
=
AnonymousUserFactory
()
self
.
beta_user
=
BetaTesterFactory
(
course_key
=
self
.
course
.
course_key
)
self
.
beta_user
=
BetaTesterFactory
(
course_key
=
self
.
course
.
id
)
self
.
student
=
UserFactory
()
self
.
global_staff
=
UserFactory
(
is_staff
=
True
)
self
.
course_staff
=
StaffFactory
(
course_key
=
self
.
course
.
course_key
)
self
.
course_instructor
=
InstructorFactory
(
course_key
=
self
.
course
.
course_key
)
self
.
course_staff
=
StaffFactory
(
course_key
=
self
.
course
.
id
)
self
.
course_instructor
=
InstructorFactory
(
course_key
=
self
.
course
.
id
)
self
.
staff
=
GlobalStaffFactory
()
def
verify_access
(
self
,
mock_unit
,
student_should_have_access
,
expected_error_type
=
None
):
"""
Verify the expected result from _has_access_descriptor
"""
response
=
access
.
_has_access_descriptor
(
self
.
anonymous_user
,
'
load
'
,
mock_unit
,
course_key
=
self
.
course
.
course_key
)
mock_unit
,
course_key
=
self
.
course
.
id
)
self
.
assertEqual
(
student_should_have_access
,
bool
(
response
))
if
expected_error_type
is
not
None
:
...
...
@@ -181,55 +186,142 @@ class AccessTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase, MilestonesTes
self
.
assertIsNotNone
(
response
.
to_json
()[
'
error_code
'
])
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
.
id
)
)
def
test_has_staff_access_to_preview_mode
(
self
):
"""
Tests users have right access to content in preview mode.
"""
course_key
=
self
.
course
.
id
usage_key
=
self
.
course
.
scope_ids
.
usage_id
chapter
=
ItemFactory
.
create
(
category
=
"
chapter
"
,
parent_location
=
self
.
course
.
location
)
overview
=
CourseOverview
.
get_from_id
(
course_key
)
test_system
=
get_test_system
()
ccx
=
CcxFactory
(
course_id
=
course_key
)
ccx_locator
=
CCXLocator
.
from_course_locator
(
course_key
,
ccx
.
id
)
error_descriptor
=
ErrorDescriptor
.
from_xml
(
u
"
<problem>ABC
\N{SNOWMAN}
</problem>
"
,
test_system
,
CourseLocationManager
(
course_key
),
"
error msg
"
)
# Enroll student to the course
CourseEnrollmentFactory
(
user
=
self
.
student
,
course_id
=
self
.
course
.
id
)
modules
=
[
self
.
course
,
overview
,
chapter
,
ccx_locator
,
error_descriptor
,
course_key
,
usage_key
,
]
# Course key is not None
self
.
assertTrue
(
bool
(
access
.
has_staff_access_to_preview_mode
(
self
.
global_staff
,
obj
=
self
.
course
,
course_key
=
course_key
))
)
for
user
in
[
self
.
global_staff
,
self
.
course_staff
,
self
.
course_instructor
]:
for
obj
in
modules
:
self
.
assertTrue
(
bool
(
access
.
has_staff_access_to_preview_mode
(
user
,
obj
=
obj
)))
self
.
assertFalse
(
bool
(
access
.
has_staff_access_to_preview_mode
(
self
.
student
,
obj
=
obj
)))
def
test_student_has_access
(
self
):
"""
Tests course student have right access to content w/o preview.
"""
course_key
=
self
.
course
.
id
chapter
=
ItemFactory
.
create
(
category
=
"
chapter
"
,
parent_location
=
self
.
course
.
location
)
overview
=
CourseOverview
.
get_from_id
(
course_key
)
# Enroll student to the course
CourseEnrollmentFactory
(
user
=
self
.
student
,
course_id
=
self
.
course
.
id
)
modules
=
[
self
.
course
,
overview
,
chapter
,
]
with
patch
(
'
courseware.access.in_preview_mode
'
)
as
mock_preview
:
mock_preview
.
return_value
=
False
for
obj
in
modules
:
self
.
assertTrue
(
bool
(
access
.
has_access
(
self
.
student
,
'
load
'
,
obj
,
course_key
=
self
.
course
.
id
)))
with
patch
(
'
courseware.access.in_preview_mode
'
)
as
mock_preview
:
mock_preview
.
return_value
=
True
for
obj
in
modules
:
self
.
assertFalse
(
bool
(
access
.
has_access
(
self
.
student
,
'
load
'
,
obj
,
course_key
=
self
.
course
.
id
)))
def
test_string_has_staff_access_to_preview_mode
(
self
):
"""
Tests different users has right access to string content in preview mode.
"""
self
.
assertTrue
(
bool
(
access
.
has_staff_access_to_preview_mode
(
self
.
global_staff
,
obj
=
'
global
'
)))
self
.
assertFalse
(
bool
(
access
.
has_staff_access_to_preview_mode
(
self
.
course_staff
,
obj
=
'
global
'
)))
self
.
assertFalse
(
bool
(
access
.
has_staff_access_to_preview_mode
(
self
.
course_instructor
,
obj
=
'
global
'
)))
self
.
assertFalse
(
bool
(
access
.
has_staff_access_to_preview_mode
(
self
.
student
,
obj
=
'
global
'
)))
@patch
(
'
courseware.access.in_preview_mode
'
,
Mock
(
return_value
=
True
))
def
test_has_access_with_preview_mode
(
self
):
"""
Tests particular user
'
s can access content via has_access in preview mode.
"""
self
.
assertTrue
(
bool
(
access
.
has_access
(
self
.
global_staff
,
'
staff
'
,
self
.
course
,
course_key
=
self
.
course
.
id
)))
self
.
assertTrue
(
bool
(
access
.
has_access
(
self
.
course_staff
,
'
staff
'
,
self
.
course
,
course_key
=
self
.
course
.
id
)))
self
.
assertTrue
(
bool
(
access
.
has_access
(
self
.
course_instructor
,
'
staff
'
,
self
.
course
,
course_key
=
self
.
course
.
id
)))
self
.
assertFalse
(
bool
(
access
.
has_access
(
self
.
student
,
'
staff
'
,
self
.
course
,
course_key
=
self
.
course
.
id
)))
self
.
assertFalse
(
bool
(
access
.
has_access
(
self
.
student
,
'
load
'
,
self
.
course
,
course_key
=
self
.
course
.
id
)))
def
test_has_access_to_course
(
self
):
self
.
assertFalse
(
access
.
_has_access_to_course
(
None
,
'
staff
'
,
self
.
course
.
course_key
None
,
'
staff
'
,
self
.
course
.
id
))
self
.
assertFalse
(
access
.
_has_access_to_course
(
self
.
anonymous_user
,
'
staff
'
,
self
.
course
.
course_key
self
.
anonymous_user
,
'
staff
'
,
self
.
course
.
id
))
self
.
assertFalse
(
access
.
_has_access_to_course
(
self
.
anonymous_user
,
'
instructor
'
,
self
.
course
.
course_key
self
.
anonymous_user
,
'
instructor
'
,
self
.
course
.
id
))
self
.
assertTrue
(
access
.
_has_access_to_course
(
self
.
global_staff
,
'
staff
'
,
self
.
course
.
course_key
self
.
global_staff
,
'
staff
'
,
self
.
course
.
id
))
self
.
assertTrue
(
access
.
_has_access_to_course
(
self
.
global_staff
,
'
instructor
'
,
self
.
course
.
course_key
self
.
global_staff
,
'
instructor
'
,
self
.
course
.
id
))
# A user has staff access if they are in the staff group
self
.
assertTrue
(
access
.
_has_access_to_course
(
self
.
course_staff
,
'
staff
'
,
self
.
course
.
course_key
self
.
course_staff
,
'
staff
'
,
self
.
course
.
id
))
self
.
assertFalse
(
access
.
_has_access_to_course
(
self
.
course_staff
,
'
instructor
'
,
self
.
course
.
course_key
self
.
course_staff
,
'
instructor
'
,
self
.
course
.
id
))
# A user has staff and instructor access if they are in the instructor group
self
.
assertTrue
(
access
.
_has_access_to_course
(
self
.
course_instructor
,
'
staff
'
,
self
.
course
.
course_key
self
.
course_instructor
,
'
staff
'
,
self
.
course
.
id
))
self
.
assertTrue
(
access
.
_has_access_to_course
(
self
.
course_instructor
,
'
instructor
'
,
self
.
course
.
course_key
self
.
course_instructor
,
'
instructor
'
,
self
.
course
.
id
))
# A user does not have staff or instructor access if they are
# not in either the staff or the the instructor group
self
.
assertFalse
(
access
.
_has_access_to_course
(
self
.
student
,
'
staff
'
,
self
.
course
.
course_key
self
.
student
,
'
staff
'
,
self
.
course
.
id
))
self
.
assertFalse
(
access
.
_has_access_to_course
(
self
.
student
,
'
instructor
'
,
self
.
course
.
course_key
self
.
student
,
'
instructor
'
,
self
.
course
.
id
))
self
.
assertFalse
(
access
.
_has_access_to_course
(
self
.
student
,
'
not_staff_or_instructor
'
,
self
.
course
.
course_key
self
.
student
,
'
not_staff_or_instructor
'
,
self
.
course
.
id
))
def
test__has_access_string
(
self
):
...
...
@@ -256,12 +348,12 @@ class AccessTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase, MilestonesTes
(
self
.
course_instructor
,
expected_instructor
)
):
self
.
assertEquals
(
bool
(
access
.
_has_access_error_desc
(
user
,
action
,
descriptor
,
self
.
course
.
course_key
)),
bool
(
access
.
_has_access_error_desc
(
user
,
action
,
descriptor
,
self
.
course
.
id
)),
expected_response
)
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
.
id
)
def
test__has_access_descriptor
(
self
):
# TODO: override DISABLE_START_DATES and test the start date branch of the method
...
...
@@ -304,7 +396,7 @@ class AccessTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase, MilestonesTes
mock_unit
.
visible_to_staff_only
=
False
self
.
assertTrue
(
bool
(
access
.
_has_access_descriptor
(
self
.
beta_user
,
'
load
'
,
mock_unit
,
course_key
=
self
.
course
.
course_key
)))
self
.
beta_user
,
'
load
'
,
mock_unit
,
course_key
=
self
.
course
.
id
)))
@ddt.data
(
None
,
YESTERDAY
,
TOMORROW
)
@patch.dict
(
'
django.conf.settings.FEATURES
'
,
{
'
DISABLE_START_DATES
'
:
False
})
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment