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
8d15acc9
Commit
8d15acc9
authored
Mar 10, 2014
by
Usman Khalid
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2559 from edx/usman/lms2136-wiki-access
Refactor of permissions checking for wiki pages.
parents
21db0bff
d335713d
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
239 additions
and
71 deletions
+239
-71
cms/djangoapps/contentstore/tests/test_contentstore.py
+29
-2
cms/djangoapps/contentstore/views/course.py
+7
-0
common/lib/xmodule/xmodule/course_module.py
+5
-0
common/lib/xmodule/xmodule/modulestore/mixed.py
+11
-0
common/lib/xmodule/xmodule/modulestore/mongo/base.py
+9
-0
common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
+12
-0
common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py
+18
-0
common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py
+40
-3
common/lib/xmodule/xmodule/modulestore/tests/test_xml.py
+27
-4
common/lib/xmodule/xmodule/modulestore/xml.py
+9
-0
common/lib/xmodule/xmodule/modulestore/xml_importer.py
+14
-5
common/test/data/two_toys/course/TT_2012_Fall.xml
+1
-0
lms/djangoapps/course_wiki/tests/test_access.py
+47
-26
lms/djangoapps/course_wiki/utils.py
+10
-31
No files found.
cms/djangoapps/contentstore/tests/test_contentstore.py
View file @
8d15acc9
...
...
@@ -1761,8 +1761,27 @@ class ContentStoreTest(ModuleStoreTestCase):
self
.
assertEquals
(
course_module
.
pdf_textbooks
[
0
][
"chapters"
][
0
][
"url"
],
'/c4x/MITx/999/asset/Chapter1.pdf'
)
self
.
assertEquals
(
course_module
.
pdf_textbooks
[
0
][
"chapters"
][
1
][
"url"
],
'/c4x/MITx/999/asset/Chapter2.pdf'
)
# check that URL slug got updated to new course slug
self
.
assertEquals
(
course_module
.
wiki_slug
,
'999'
)
def
test_import_into_new_course_id_wiki_slug_renamespacing
(
self
):
module_store
=
modulestore
(
'direct'
)
target_location
=
Location
(
'i4x'
,
'MITx'
,
'999'
,
'course'
,
'2013_Spring'
)
course_data
=
{
'org'
:
target_location
.
org
,
'number'
:
target_location
.
course
,
'display_name'
:
'Robot Super Course'
,
'run'
:
target_location
.
name
}
target_course_id
=
'{0}/{1}/{2}'
.
format
(
target_location
.
org
,
target_location
.
course
,
target_location
.
name
)
_create_course
(
self
,
course_data
)
# Import a course with wiki_slug == location.course
import_from_xml
(
module_store
,
'common/test/data/'
,
[
'toy'
],
target_location_namespace
=
target_location
)
course_module
=
module_store
.
get_instance
(
target_location
.
course_id
,
target_location
)
self
.
assertEquals
(
course_module
.
wiki_slug
,
'MITx.999.2013_Spring'
)
# Now try importing a course with wiki_slug == '{0}{1}{2}'.format(location.org, location.course, location.name)
import_from_xml
(
module_store
,
'common/test/data/'
,
[
'two_toys'
],
target_location_namespace
=
target_location
)
course_module
=
module_store
.
get_instance
(
target_course_id
,
target_location
)
self
.
assertEquals
(
course_module
.
wiki_slug
,
'MITx.999.2013_Spring'
)
def
test_import_metadata_with_attempts_empty_string
(
self
):
module_store
=
modulestore
(
'direct'
)
...
...
@@ -1915,6 +1934,14 @@ class ContentStoreTest(ModuleStoreTestCase):
_test_no_locations
(
self
,
resp
)
return
resp
def
test_wiki_slug
(
self
):
"""When creating a course a unique wiki_slug should be set."""
course_location
=
Location
([
'i4x'
,
'MITx'
,
'999'
,
'course'
,
'2013_Spring'
])
_create_course
(
self
,
self
.
course_data
)
course_module
=
modulestore
(
'direct'
)
.
get_item
(
course_location
)
self
.
assertEquals
(
course_module
.
wiki_slug
,
'MITx.999.2013_Spring'
)
@override_settings
(
MODULESTORE
=
TEST_MODULESTORE
)
class
MetadataSaveTestCase
(
ModuleStoreTestCase
):
...
...
cms/djangoapps/contentstore/views/course.py
View file @
8d15acc9
...
...
@@ -376,8 +376,15 @@ def create_new_course(request):
metadata
=
{}
else
:
metadata
=
{
'display_name'
:
display_name
}
# Set a unique wiki_slug for newly created courses. To maintain active wiki_slugs for existing xml courses this
# cannot be changed in CourseDescriptor.
wiki_slug
=
"{0}.{1}.{2}"
.
format
(
dest_location
.
org
,
dest_location
.
course
,
dest_location
.
name
)
definition_data
=
{
'wiki_slug'
:
wiki_slug
}
modulestore
(
'direct'
)
.
create_and_save_xmodule
(
dest_location
,
definition_data
=
definition_data
,
metadata
=
metadata
)
new_course
=
modulestore
(
'direct'
)
.
get_item
(
dest_location
)
...
...
common/lib/xmodule/xmodule/course_module.py
View file @
8d15acc9
...
...
@@ -603,6 +603,11 @@ class CourseDescriptor(CourseFields, SequenceDescriptor):
xml_object
.
append
(
textbook_xml_object
)
if
self
.
wiki_slug
is
not
None
:
wiki_xml_object
=
etree
.
Element
(
'wiki'
)
wiki_xml_object
.
set
(
'slug'
,
self
.
wiki_slug
)
xml_object
.
append
(
wiki_xml_object
)
return
xml_object
def
has_ended
(
self
):
...
...
common/lib/xmodule/xmodule/modulestore/mixed.py
View file @
8d15acc9
...
...
@@ -417,6 +417,17 @@ class MixedModuleStore(ModuleStoreWriteBase):
for
course
in
store
.
get_courses
():
loc_mapper
()
.
translate_location
(
course
.
location
.
course_id
,
course
.
location
)
def
get_courses_for_wiki
(
self
,
wiki_slug
):
"""
Return the list of courses which use this wiki_slug
:param wiki_slug: the course wiki root slug
:return: list of course locations
"""
courses
=
[]
for
modulestore
in
self
.
modulestores
.
values
():
courses
.
extend
(
modulestore
.
get_courses_for_wiki
(
wiki_slug
))
return
courses
def
_compare_stores
(
left
,
right
):
"""
...
...
common/lib/xmodule/xmodule/modulestore/mongo/base.py
View file @
8d15acc9
...
...
@@ -878,6 +878,15 @@ class MongoModuleStore(ModuleStoreWriteBase):
item_locs
-=
all_reachable
return
list
(
item_locs
)
def
get_courses_for_wiki
(
self
,
wiki_slug
):
"""
Return the list of courses which use this wiki_slug
:param wiki_slug: the course wiki root slug
:return: list of course locations
"""
courses
=
self
.
collection
.
find
({
'definition.data.wiki_slug'
:
wiki_slug
})
return
[
Location
(
course
[
'_id'
])
for
course
in
courses
]
def
_create_new_field_data
(
self
,
_category
,
_location
,
definition_data
,
metadata
):
"""
To instantiate a new xmodule which will be saved latter, set up the dbModel and kvs
...
...
common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
View file @
8d15acc9
...
...
@@ -1645,3 +1645,14 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
be a json dict key.
"""
structure
[
'blocks'
][
LocMapperStore
.
encode_key_for_mongo
(
block_id
)]
=
content
def
get_courses_for_wiki
(
self
,
wiki_slug
):
"""
Return the list of courses which use this wiki_slug
:param wiki_slug: the course wiki root slug
:return: list of course locations
Todo: Needs to be implemented.
"""
courses
=
[]
return
courses
\ No newline at end of file
common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py
View file @
8d15acc9
...
...
@@ -368,6 +368,24 @@ class TestMixedModuleStore(LocMapperSetupSansDjango):
orphans
=
self
.
store
.
get_orphans
(
self
.
course_locations
[
self
.
MONGO_COURSEID
],
None
)
self
.
assertEqual
(
len
(
orphans
),
0
,
"unexpected orphans: {}"
.
format
(
orphans
))
@ddt.data
(
'direct'
)
def
test_get_courses_for_wiki
(
self
,
default_ms
):
"""
Test the get_courses_for_wiki method
"""
self
.
initdb
(
default_ms
)
course_locations
=
self
.
store
.
get_courses_for_wiki
(
'toy'
)
self
.
assertEqual
(
len
(
course_locations
),
1
)
self
.
assertIn
(
Location
(
'i4x'
,
'edX'
,
'toy'
,
'course'
,
'2012_Fall'
),
course_locations
)
course_locations
=
self
.
store
.
get_courses_for_wiki
(
'simple'
)
self
.
assertEqual
(
len
(
course_locations
),
1
)
self
.
assertIn
(
Location
(
'i4x'
,
'edX'
,
'simple'
,
'course'
,
'2012_Fall'
),
course_locations
)
self
.
assertEqual
(
len
(
self
.
store
.
get_courses_for_wiki
(
'edX.simple.2012_Fall'
)),
0
)
self
.
assertEqual
(
len
(
self
.
store
.
get_courses_for_wiki
(
'no_such_wiki'
)),
0
)
#=============================================================================================================
# General utils for not using django settings
#=============================================================================================================
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py
View file @
8d15acc9
...
...
@@ -37,6 +37,9 @@ RENDER_TEMPLATE = lambda t_n, d, ctx = None, nsp = 'main': ''
class
TestMongoModuleStore
(
object
):
'''Tests!'''
# Explicitly list the courses to load (don't want the big one)
courses
=
[
'toy'
,
'simple'
,
'simple_with_draft'
,
'test_unicode'
]
@classmethod
def
setupClass
(
cls
):
cls
.
connection
=
pymongo
.
MongoClient
(
...
...
@@ -74,9 +77,7 @@ class TestMongoModuleStore(object):
# Also test draft store imports
#
draft_store
=
DraftModuleStore
(
doc_store_config
,
FS_ROOT
,
RENDER_TEMPLATE
,
default_class
=
DEFAULT_CLASS
)
# Explicitly list the courses to load (don't want the big one)
courses
=
[
'toy'
,
'simple'
,
'simple_with_draft'
,
'test_unicode'
]
import_from_xml
(
store
,
DATA_DIR
,
courses
,
draft_store
=
draft_store
,
static_content_store
=
content_store
)
import_from_xml
(
store
,
DATA_DIR
,
TestMongoModuleStore
.
courses
,
draft_store
=
draft_store
,
static_content_store
=
content_store
)
# also test a course with no importing of static content
import_from_xml
(
...
...
@@ -273,6 +274,42 @@ class TestMongoModuleStore(object):
{
'displayname'
:
'hello'
}
)
def
test_get_courses_for_wiki
(
self
):
"""
Test the get_courses_for_wiki method
"""
for
course_number
in
self
.
courses
:
course_locations
=
self
.
store
.
get_courses_for_wiki
(
course_number
)
assert_equals
(
len
(
course_locations
),
1
)
assert_equals
(
Location
(
'i4x'
,
'edX'
,
course_number
,
'course'
,
'2012_Fall'
),
course_locations
[
0
])
course_locations
=
self
.
store
.
get_courses_for_wiki
(
'no_such_wiki'
)
assert_equals
(
len
(
course_locations
),
0
)
# set toy course to share the wiki with simple course
toy_course
=
self
.
store
.
get_course
(
'edX/toy/2012_Fall'
)
toy_course
.
wiki_slug
=
'simple'
self
.
store
.
update_item
(
toy_course
)
# now toy_course should not be retrievable with old wiki_slug
course_locations
=
self
.
store
.
get_courses_for_wiki
(
'toy'
)
assert_equals
(
len
(
course_locations
),
0
)
# but there should be two courses with wiki_slug 'simple'
course_locations
=
self
.
store
.
get_courses_for_wiki
(
'simple'
)
assert_equals
(
len
(
course_locations
),
2
)
for
course_number
in
[
'toy'
,
'simple'
]:
assert_in
(
Location
(
'i4x'
,
'edX'
,
course_number
,
'course'
,
'2012_Fall'
),
course_locations
)
# configure simple course to use unique wiki_slug.
simple_course
=
self
.
store
.
get_course
(
'edX/simple/2012_Fall'
)
simple_course
.
wiki_slug
=
'edX.simple.2012_Fall'
self
.
store
.
update_item
(
simple_course
)
# it should be retrievable with its new wiki_slug
course_locations
=
self
.
store
.
get_courses_for_wiki
(
'edX.simple.2012_Fall'
)
assert_equals
(
len
(
course_locations
),
1
)
assert_in
(
Location
(
'i4x'
,
'edX'
,
'simple'
,
'course'
,
'2012_Fall'
),
course_locations
)
class
TestMongoKeyValueStore
(
object
):
"""
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_xml.py
View file @
8d15acc9
...
...
@@ -7,8 +7,6 @@ import unittest
from
glob
import
glob
from
mock
import
patch
from
nose.tools
import
assert_raises
,
assert_equals
# pylint: disable=E0611
from
xmodule.course_module
import
CourseDescriptor
from
xmodule.modulestore.xml
import
XMLModuleStore
from
xmodule.modulestore
import
Location
,
XML_MODULESTORE_TYPE
...
...
@@ -43,7 +41,7 @@ class TestXMLModuleStore(unittest.TestCase):
def
test_xml_modulestore_type
(
self
):
store
=
XMLModuleStore
(
DATA_DIR
,
course_dirs
=
[
'toy'
,
'simple'
])
assert_equals
(
store
.
get_modulestore_type
(
'foo/bar/baz'
),
XML_MODULESTORE_TYPE
)
self
.
assertEqual
(
store
.
get_modulestore_type
(
'foo/bar/baz'
),
XML_MODULESTORE_TYPE
)
def
test_unicode_chars_in_xml_content
(
self
):
# edX/full/6.002_Spring_2012 has non-ASCII chars, and during
...
...
@@ -52,7 +50,7 @@ class TestXMLModuleStore(unittest.TestCase):
# Ensure that there really is a non-ASCII character in the course.
with
open
(
os
.
path
.
join
(
DATA_DIR
,
"toy/sequential/vertical_sequential.xml"
))
as
xmlf
:
xml
=
xmlf
.
read
()
with
assert_r
aises
(
UnicodeDecodeError
):
with
self
.
assertR
aises
(
UnicodeDecodeError
):
xml
.
decode
(
'ascii'
)
# Load the course, but don't make error modules. This will succeed,
...
...
@@ -78,3 +76,28 @@ class TestXMLModuleStore(unittest.TestCase):
about_module
=
course_module
[
about_location
]
self
.
assertIn
(
"GREEN"
,
about_module
.
data
)
self
.
assertNotIn
(
"RED"
,
about_module
.
data
)
def
test_get_courses_for_wiki
(
self
):
"""
Test the get_courses_for_wiki method
"""
store
=
XMLModuleStore
(
DATA_DIR
,
course_dirs
=
[
'toy'
,
'simple'
])
for
course
in
store
.
get_courses
():
course_locations
=
store
.
get_courses_for_wiki
(
course
.
wiki_slug
)
self
.
assertEqual
(
len
(
course_locations
),
1
)
self
.
assertIn
(
Location
(
'i4x'
,
'edX'
,
course
.
location
.
course
,
'course'
,
'2012_Fall'
),
course_locations
)
course_locations
=
store
.
get_courses_for_wiki
(
'no_such_wiki'
)
self
.
assertEqual
(
len
(
course_locations
),
0
)
# now set toy course to share the wiki with simple course
toy_course
=
store
.
get_course
(
'edX/toy/2012_Fall'
)
toy_course
.
wiki_slug
=
'simple'
course_locations
=
store
.
get_courses_for_wiki
(
'toy'
)
self
.
assertEqual
(
len
(
course_locations
),
0
)
course_locations
=
store
.
get_courses_for_wiki
(
'simple'
)
self
.
assertEqual
(
len
(
course_locations
),
2
)
for
course_number
in
[
'toy'
,
'simple'
]:
self
.
assertIn
(
Location
(
'i4x'
,
'edX'
,
course_number
,
'course'
,
'2012_Fall'
),
course_locations
)
common/lib/xmodule/xmodule/modulestore/xml.py
View file @
8d15acc9
...
...
@@ -790,3 +790,12 @@ class XMLModuleStore(ModuleStoreReadBase):
"split" for new-style split MongoDB backed courses.
"""
return
XML_MODULESTORE_TYPE
def
get_courses_for_wiki
(
self
,
wiki_slug
):
"""
Return the list of courses which use this wiki_slug
:param wiki_slug: the course wiki root slug
:return: list of course locations
"""
courses
=
self
.
get_courses
()
return
[
course
.
location
for
course
in
courses
if
(
course
.
wiki_slug
==
wiki_slug
)]
common/lib/xmodule/xmodule/modulestore/xml_importer.py
View file @
8d15acc9
...
...
@@ -514,11 +514,20 @@ def remap_namespace(module, target_location_namespace):
chapter
[
'url'
],
target_location_namespace
)
# if there is a wiki_slug which is the same as the original location
# (aka default value), then remap that so the wiki doesn't point to
# the old Wiki.
if
module
.
wiki_slug
==
original_location
.
course
:
module
.
wiki_slug
=
target_location_namespace
.
course
# Original wiki_slugs had value location.course. To make them unique this was changed to 'org.course.name'.
# If the wiki_slug is equal to either of these default values then remap that so that the wiki does not point
# to the old wiki.
original_unique_wiki_slug
=
'{0}.{1}.{2}'
.
format
(
original_location
.
org
,
original_location
.
course
,
original_location
.
name
)
if
module
.
wiki_slug
==
original_unique_wiki_slug
or
module
.
wiki_slug
==
original_location
.
course
:
module
.
wiki_slug
=
'{0}.{1}.{2}'
.
format
(
target_location_namespace
.
org
,
target_location_namespace
.
course
,
target_location_namespace
.
name
,
)
module
.
save
()
...
...
common/test/data/two_toys/course/TT_2012_Fall.xml
View file @
8d15acc9
<course
display_name=
"Toy Course"
graceperiod=
"2 days 5 hours 59 minutes 59 seconds"
start=
"2015-07-17T12:00"
>
<chapter
url_name=
"Overview"
/>
<wiki
slug=
"edX.toy.TT_2012_Fall"
/>
</course>
lms/djangoapps/course_wiki/tests/test_access.py
View file @
8d15acc9
...
...
@@ -4,6 +4,7 @@ Tests for wiki permissions
from
django.contrib.auth.models
import
Group
from
student.tests.factories
import
UserFactory
from
xmodule.modulestore.django
import
loc_mapper
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
...
...
@@ -24,21 +25,37 @@ class TestWikiAccessBase(ModuleStoreTestCase):
self
.
wiki
=
get_or_create_root
()
self
.
course_math101
=
CourseFactory
.
create
(
org
=
'org'
,
number
=
'math101'
,
display_name
=
'Course'
)
self
.
course_math101_staff
=
[
InstructorFactory
(
course
=
self
.
course_math101
.
location
),
StaffFactory
(
course
=
self
.
course_math101
.
location
)
]
self
.
course_math101
=
CourseFactory
.
create
(
org
=
'org'
,
number
=
'math101'
,
display_name
=
'Course'
,
metadata
=
{
'use_unique_wiki_id'
:
'false'
})
self
.
course_math101_staff
=
self
.
create_staff_for_course
(
self
.
course_math101
)
wiki_math101
=
self
.
create_urlpath
(
self
.
wiki
,
course_wiki_slug
(
self
.
course_math101
))
wiki_math101_page
=
self
.
create_urlpath
(
wiki_math101
,
'Child'
)
wiki_math101_page_page
=
self
.
create_urlpath
(
wiki_math101_page
,
'Grandchild'
)
self
.
wiki_math101_pages
=
[
wiki_math101
,
wiki_math101_page
,
wiki_math101_page_page
]
self
.
course_math101b
=
CourseFactory
.
create
(
org
=
'org'
,
number
=
'math101b'
,
display_name
=
'Course'
,
metadata
=
{
'use_unique_wiki_id'
:
'true'
})
self
.
course_math101b_staff
=
self
.
create_staff_for_course
(
self
.
course_math101b
)
wiki_math101b
=
self
.
create_urlpath
(
self
.
wiki
,
course_wiki_slug
(
self
.
course_math101b
))
wiki_math101b_page
=
self
.
create_urlpath
(
wiki_math101b
,
'Child'
)
wiki_math101b_page_page
=
self
.
create_urlpath
(
wiki_math101b_page
,
'Grandchild'
)
self
.
wiki_math101b_pages
=
[
wiki_math101b
,
wiki_math101b_page
,
wiki_math101b_page_page
]
def
create_urlpath
(
self
,
parent
,
slug
):
"""Creates an article at /parent/slug and returns its URLPath"""
return
URLPath
.
create_article
(
parent
,
slug
,
title
=
slug
)
def
create_staff_for_course
(
self
,
course
):
"""Creates and returns users with instructor and staff access to course."""
course_locator
=
loc_mapper
()
.
translate_location
(
course
.
id
,
course
.
location
)
return
[
InstructorFactory
(
course
=
course
.
location
),
# Creates instructor_org/number/run role name
StaffFactory
(
course
=
course
.
location
),
# Creates staff_org/number/run role name
InstructorFactory
(
course
=
course_locator
),
# Creates instructor_org.number.run role name
StaffFactory
(
course
=
course_locator
),
# Creates staff_org.number.run role name
]
@override_settings
(
MODULESTORE
=
TEST_DATA_MIXED_MODULESTORE
)
class
TestWikiAccess
(
TestWikiAccessBase
):
...
...
@@ -47,21 +64,15 @@ class TestWikiAccess(TestWikiAccessBase):
super
(
TestWikiAccess
,
self
)
.
setUp
()
self
.
course_310b
=
CourseFactory
.
create
(
org
=
'org'
,
number
=
'310b'
,
display_name
=
'Course'
)
self
.
course_310b_staff
=
[
InstructorFactory
(
course
=
self
.
course_310b
.
location
),
StaffFactory
(
course
=
self
.
course_310b
.
location
)
]
self
.
course_310b_
=
CourseFactory
.
create
(
org
=
'org'
,
number
=
'310b_'
,
display_name
=
'Course'
)
self
.
course_310b__staff
=
[
InstructorFactory
(
course
=
self
.
course_310b_
.
location
),
StaffFactory
(
course
=
self
.
course_310b_
.
location
)
]
self
.
course_310b_staff
=
self
.
create_staff_for_course
(
self
.
course_310b
)
self
.
course_310b2
=
CourseFactory
.
create
(
org
=
'org'
,
number
=
'310b_'
,
display_name
=
'Course'
)
self
.
course_310b2_staff
=
self
.
create_staff_for_course
(
self
.
course_310b2
)
self
.
wiki_310b
=
self
.
create_urlpath
(
self
.
wiki
,
course_wiki_slug
(
self
.
course_310b
))
self
.
wiki_310b
_
=
self
.
create_urlpath
(
self
.
wiki
,
course_wiki_slug
(
self
.
course_310b_
))
self
.
wiki_310b
2
=
self
.
create_urlpath
(
self
.
wiki
,
course_wiki_slug
(
self
.
course_310b2
))
def
test_no_one_is_root_wiki_staff
(
self
):
all_course_staff
=
self
.
course_math101_staff
+
self
.
course_310b_staff
+
self
.
course_310b
_
_staff
all_course_staff
=
self
.
course_math101_staff
+
self
.
course_310b_staff
+
self
.
course_310b
2
_staff
for
course_staff
in
all_course_staff
:
self
.
assertFalse
(
user_is_article_course_staff
(
course_staff
,
self
.
wiki
.
article
))
...
...
@@ -70,6 +81,10 @@ class TestWikiAccess(TestWikiAccessBase):
for
course_staff
in
self
.
course_math101_staff
:
self
.
assertTrue
(
user_is_article_course_staff
(
course_staff
,
page
.
article
))
for
page
in
self
.
wiki_math101b_pages
:
for
course_staff
in
self
.
course_math101b_staff
:
self
.
assertTrue
(
user_is_article_course_staff
(
course_staff
,
page
.
article
))
def
test_settings
(
self
):
for
page
in
self
.
wiki_math101_pages
:
for
course_staff
in
self
.
course_math101_staff
:
...
...
@@ -79,15 +94,27 @@ class TestWikiAccess(TestWikiAccessBase):
self
.
assertTrue
(
settings
.
CAN_ASSIGN
(
page
.
article
,
course_staff
))
self
.
assertTrue
(
settings
.
CAN_ASSIGN_OWNER
(
page
.
article
,
course_staff
))
for
page
in
self
.
wiki_math101b_pages
:
for
course_staff
in
self
.
course_math101b_staff
:
self
.
assertTrue
(
settings
.
CAN_DELETE
(
page
.
article
,
course_staff
))
self
.
assertTrue
(
settings
.
CAN_MODERATE
(
page
.
article
,
course_staff
))
self
.
assertTrue
(
settings
.
CAN_CHANGE_PERMISSIONS
(
page
.
article
,
course_staff
))
self
.
assertTrue
(
settings
.
CAN_ASSIGN
(
page
.
article
,
course_staff
))
self
.
assertTrue
(
settings
.
CAN_ASSIGN_OWNER
(
page
.
article
,
course_staff
))
def
test_other_course_staff_is_not_course_wiki_staff
(
self
):
for
page
in
self
.
wiki_math101_pages
:
for
course_staff
in
self
.
course_math101b_staff
:
self
.
assertFalse
(
user_is_article_course_staff
(
course_staff
,
page
.
article
))
for
page
in
self
.
wiki_math101_pages
:
for
course_staff
in
self
.
course_310b_staff
:
self
.
assertFalse
(
user_is_article_course_staff
(
course_staff
,
page
.
article
))
for
course_staff
in
self
.
course_310b_staff
:
self
.
assertFalse
(
user_is_article_course_staff
(
course_staff
,
self
.
wiki_310b
_
.
article
))
self
.
assertFalse
(
user_is_article_course_staff
(
course_staff
,
self
.
wiki_310b
2
.
article
))
for
course_staff
in
self
.
course_310b
_
_staff
:
for
course_staff
in
self
.
course_310b
2
_staff
:
self
.
assertFalse
(
user_is_article_course_staff
(
course_staff
,
self
.
wiki_310b
.
article
))
...
...
@@ -114,10 +141,7 @@ class TestWikiAccessForNumericalCourseNumber(TestWikiAccessBase):
super
(
TestWikiAccessForNumericalCourseNumber
,
self
)
.
setUp
()
self
.
course_200
=
CourseFactory
.
create
(
org
=
'org'
,
number
=
'200'
,
display_name
=
'Course'
)
self
.
course_200_staff
=
[
InstructorFactory
(
course
=
self
.
course_200
.
location
),
StaffFactory
(
course
=
self
.
course_200
.
location
)
]
self
.
course_200_staff
=
self
.
create_staff_for_course
(
self
.
course_200
)
wiki_200
=
self
.
create_urlpath
(
self
.
wiki
,
course_wiki_slug
(
self
.
course_200
))
wiki_200_page
=
self
.
create_urlpath
(
wiki_200
,
'Child'
)
...
...
@@ -138,10 +162,7 @@ class TestWikiAccessForOldFormatCourseStaffGroups(TestWikiAccessBase):
self
.
course_math101c
=
CourseFactory
.
create
(
org
=
'org'
,
number
=
'math101c'
,
display_name
=
'Course'
)
Group
.
objects
.
get_or_create
(
name
=
'instructor_math101c'
)
self
.
course_math101c_staff
=
[
InstructorFactory
(
course
=
self
.
course_math101c
.
location
),
StaffFactory
(
course
=
self
.
course_math101c
.
location
)
]
self
.
course_math101c_staff
=
self
.
create_staff_for_course
(
self
.
course_math101c
)
wiki_math101c
=
self
.
create_urlpath
(
self
.
wiki
,
course_wiki_slug
(
self
.
course_math101c
))
wiki_math101c_page
=
self
.
create_urlpath
(
wiki_math101c
,
'Child'
)
...
...
lms/djangoapps/course_wiki/utils.py
View file @
8d15acc9
...
...
@@ -3,7 +3,8 @@ Utility functions for course_wiki.
"""
from
django.core.exceptions
import
ObjectDoesNotExist
from
xmodule
import
modulestore
import
courseware
def
user_is_article_course_staff
(
user
,
article
):
"""
...
...
@@ -20,24 +21,24 @@ def user_is_article_course_staff(user, article):
so this will return True.
"""
course
_slug
=
article_course_wiki_root_slug
(
article
)
wiki
_slug
=
article_course_wiki_root_slug
(
article
)
if
course
_slug
is
None
:
if
wiki
_slug
is
None
:
return
False
user_groups
=
user
.
groups
.
all
()
# The wiki expects article slugs to contain at least one non-digit so if
# the course number is just a number the course wiki root slug is set to
# be '<course_number>_'. This means slug '202_' can belong to either
# course numbered '202_' or '202' and so we need to consider both.
if
user_is_staff_on_course_number
(
user_groups
,
course_slug
):
courses
=
modulestore
.
django
.
modulestore
()
.
get_courses_for_wiki
(
wiki_slug
)
if
any
(
courseware
.
access
.
has_access
(
user
,
course
,
'staff'
,
course
.
course_id
)
for
course
in
courses
):
return
True
if
(
course_slug
.
endswith
(
'_'
)
and
slug_is_numerical
(
course_slug
[:
-
1
])
and
user_is_staff_on_course_number
(
user_groups
,
course_slug
[:
-
1
])):
return
True
if
(
wiki_slug
.
endswith
(
'_'
)
and
slug_is_numerical
(
wiki_slug
[:
-
1
])):
courses
=
modulestore
.
django
.
modulestore
()
.
get_courses_for_wiki
(
wiki_slug
[:
-
1
])
if
any
(
courseware
.
access
.
has_access
(
user
,
course
,
'staff'
,
course
.
course_id
)
for
course
in
courses
):
return
True
return
False
...
...
@@ -64,28 +65,6 @@ def course_wiki_slug(course):
return
slug
def
user_is_staff_on_course_number
(
user_groups
,
course_number
):
"""Returns whether the groups contain a staff group for the course number"""
# Course groups have format 'instructor_<course_id>' and 'staff_<course_id>' where
# course_id = org/course_number/run. So check if user's groups contain a group
# whose name starts with 'instructor_' or 'staff_' and contains '/course_number/'.
course_number_fragment
=
'/{0}/'
.
format
(
course_number
)
if
[
group
for
group
in
user_groups
if
(
group
.
name
.
startswith
((
'instructor_'
,
'staff_'
))
and
course_number_fragment
in
group
.
name
)]:
return
True
# Old course groups had format 'instructor_<course_number>' and 'staff_<course_number>'
# Check if user's groups contain either of these.
old_instructor_group_name
=
'instructor_{0}'
.
format
(
course_number
)
old_staff_group_name
=
'staff_{0}'
.
format
(
course_number
)
if
[
group
for
group
in
user_groups
if
(
group
.
name
==
old_instructor_group_name
or
group
.
name
==
old_staff_group_name
)]:
return
True
return
False
def
article_course_wiki_root_slug
(
article
):
"""
We assume the second level ancestor is the course wiki root. Examples:
...
...
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