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
f45abe3d
Commit
f45abe3d
authored
Oct 23, 2013
by
Don Mitchell
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use new restful pattern instead
parent
8bbaf006
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
46 additions
and
52 deletions
+46
-52
cms/djangoapps/contentstore/tests/test_orphan.py
+13
-17
cms/djangoapps/contentstore/views/item.py
+11
-9
cms/urls.py
+1
-1
common/lib/xmodule/xmodule/modulestore/mongo/base.py
+4
-18
common/lib/xmodule/xmodule/modulestore/tests/test_orphan.py
+17
-7
No files found.
cms/djangoapps/contentstore/tests/test_orphan.py
View file @
f45abe3d
...
...
@@ -3,7 +3,7 @@ Test finding orphans via the view and django config
"""
import
json
from
contentstore.tests.utils
import
CourseTestCase
from
xmodule.modulestore.django
import
editable_modulestore
from
xmodule.modulestore.django
import
editable_modulestore
,
loc_mapper
from
django.core.urlresolvers
import
reverse
from
student.models
import
CourseEnrollment
...
...
@@ -41,12 +41,12 @@ class TestOrphan(CourseTestCase):
"""
Test that old mongo finds the orphans
"""
locator
=
loc_mapper
()
.
translate_location
(
self
.
course
.
location
.
course_id
,
self
.
course
.
location
,
False
,
True
)
orphan_url
=
locator
.
url_reverse
(
'orphan/'
,
''
)
orphans
=
json
.
loads
(
self
.
client
.
get
(
reverse
(
'orphan'
,
kwargs
=
{
'course_id'
:
'{}.{}'
.
format
(
self
.
course
.
location
.
org
,
self
.
course
.
location
.
course
)}
),
orphan_url
,
HTTP_ACCEPT
=
'application/json'
)
.
content
)
...
...
@@ -62,13 +62,11 @@ class TestOrphan(CourseTestCase):
"""
Test that old mongo deletes the orphans
"""
url
=
reverse
(
'orphan'
,
kwargs
=
{
'course_id'
:
'{}.{}'
.
format
(
self
.
course
.
location
.
org
,
self
.
course
.
location
.
course
)}
)
self
.
client
.
delete
(
url
)
locator
=
loc_mapper
()
.
translate_location
(
self
.
course
.
location
.
course_id
,
self
.
course
.
location
,
False
,
True
)
orphan_url
=
locator
.
url_reverse
(
'orphan/'
,
''
)
self
.
client
.
delete
(
orphan_url
)
orphans
=
json
.
loads
(
self
.
client
.
get
(
url
,
HTTP_ACCEPT
=
'application/json'
)
.
content
self
.
client
.
get
(
orphan_
url
,
HTTP_ACCEPT
=
'application/json'
)
.
content
)
self
.
assertEqual
(
len
(
orphans
),
0
,
"Orphans not deleted {}"
.
format
(
orphans
))
...
...
@@ -78,11 +76,9 @@ class TestOrphan(CourseTestCase):
"""
test_user_client
,
test_user
=
self
.
createNonStaffAuthedUserClient
()
CourseEnrollment
.
enroll
(
test_user
,
self
.
course
.
location
.
course_id
)
url
=
reverse
(
'orphan'
,
kwargs
=
{
'course_id'
:
'{}.{}'
.
format
(
self
.
course
.
location
.
org
,
self
.
course
.
location
.
course
)}
)
response
=
test_user_client
.
get
(
url
)
locator
=
loc_mapper
()
.
translate_location
(
self
.
course
.
location
.
course_id
,
self
.
course
.
location
,
False
,
True
)
orphan_url
=
locator
.
url_reverse
(
'orphan/'
,
''
)
response
=
test_user_client
.
get
(
orphan_url
)
self
.
assertEqual
(
response
.
status_code
,
403
)
response
=
test_user_client
.
delete
(
url
)
response
=
test_user_client
.
delete
(
orphan_
url
)
self
.
assertEqual
(
response
.
status_code
,
403
)
cms/djangoapps/contentstore/views/item.py
View file @
f45abe3d
...
...
@@ -21,7 +21,7 @@ from .access import has_access
from
.helpers
import
_xmodule_recurse
from
xmodule.x_module
import
XModuleDescriptor
from
django.views.decorators.http
import
require_http_methods
from
xmodule.modulestore.locator
import
CourseLocator
from
xmodule.modulestore.locator
import
CourseLocator
,
BlockUsageLocator
from
student.models
import
CourseEnrollment
__all__
=
[
'save_item'
,
'create_item'
,
'delete_item'
,
'orphan'
]
...
...
@@ -204,13 +204,13 @@ def delete_item(request):
return
JsonResponse
()
# pylint: disable=W0613
@login_required
@require_http_methods
((
"GET"
,
"DELETE"
))
def
orphan
(
request
,
course_id
):
def
orphan
(
request
,
tag
=
None
,
course_id
=
None
,
branch
=
None
,
version_guid
=
None
,
block
=
None
):
"""
View for handling orphan related requests.
A get
gets all of the current orphans.
DELETE
, PUT and POST are meaningless for now.
View for handling orphan related requests.
GET
gets all of the current orphans.
DELETE
removes all orphans (requires is_staff access)
An orphan is a block whose category is not in the DETACHED_CATEGORY list, is not the root, and is not reachable
from the root via children
...
...
@@ -218,15 +218,17 @@ def orphan(request, course_id):
:param request:
:param course_id: Locator syntax course_id
"""
course_loc
=
CourseLocator
(
course_id
=
course_id
)
location
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
usage_id
=
block
)
# DHM: when split becomes back-end, move or conditionalize this conversion
old_location
=
loc_mapper
()
.
translate_locator_to_location
(
location
)
if
request
.
method
==
'GET'
:
if
has_access
(
request
.
user
,
course_loc
):
return
JsonResponse
(
modulestore
()
.
get_orphans
(
course_id
,
DETACHED_CATEGORIES
,
'draft'
))
if
has_access
(
request
.
user
,
old_location
):
return
JsonResponse
(
modulestore
()
.
get_orphans
(
old_location
,
DETACHED_CATEGORIES
,
'draft'
))
else
:
raise
PermissionDenied
()
if
request
.
method
==
'DELETE'
:
if
request
.
user
.
is_staff
:
items
=
modulestore
()
.
get_orphans
(
course_id
,
DETACHED_CATEGORIES
,
'draft'
)
items
=
modulestore
()
.
get_orphans
(
old_location
,
DETACHED_CATEGORIES
,
'draft'
)
for
item
in
items
:
modulestore
(
'draft'
)
.
delete_item
(
item
,
True
)
return
JsonResponse
({
'deleted'
:
items
})
...
...
cms/urls.py
View file @
f45abe3d
...
...
@@ -131,7 +131,6 @@ urlpatterns += patterns(
url
(
r'^logout$'
,
'student.views.logout_user'
,
name
=
'logout'
),
url
(
r'^(?P<course_id>[^/]+)/orphan'
,
'contentstore.views.orphan'
,
name
=
'orphan'
)
)
# restful api
...
...
@@ -142,6 +141,7 @@ urlpatterns += patterns(
# (?ix) == ignore case and verbose (multiline regex)
url
(
r'(?ix)^course/{}$'
.
format
(
parsers
.
URL_RE_SOURCE
),
'course_handler'
),
url
(
r'(?ix)^checklists/{}(/)?(?P<checklist_index>\d+)?$'
.
format
(
parsers
.
URL_RE_SOURCE
),
'checklists_handler'
),
url
(
r'(?ix)^orphan/{}$'
.
format
(
parsers
.
URL_RE_SOURCE
),
'orphan'
)
)
js_info_dict
=
{
...
...
common/lib/xmodule/xmodule/modulestore/mongo/base.py
View file @
f45abe3d
...
...
@@ -855,27 +855,13 @@ class MongoModuleStore(ModuleStoreBase):
"""
return
MONGO_MODULESTORE_TYPE
COURSE_ID_RE
=
re
.
compile
(
r'(?P<org>[^.]+)\.(?P<course_id>.+)'
)
def
parse_course_id
(
self
,
course_id
):
def
get_orphans
(
self
,
course_location
,
detached_categories
,
_branch
):
"""
Parse a Locator style course_id into a dict w/ the org and course_id
:param course_id: a string looking like 'org.course.id.part'
Return an array all of the locations for orphans in the course.
"""
match
=
self
.
COURSE_ID_RE
.
match
(
course_id
)
if
match
is
None
:
raise
ValueError
(
course_id
)
return
match
.
groupdict
()
def
get_orphans
(
self
,
course_id
,
detached_categories
,
_branch
):
"""
Return a dict of all of the orphans in the course.
:param course_id:
"""
locator_dict
=
self
.
parse_course_id
(
course_id
)
all_items
=
self
.
collection
.
find
({
'_id.org'
:
locator_dict
[
'org'
]
,
'_id.course'
:
locator_dict
[
'course_id'
]
,
'_id.org'
:
course_location
.
org
,
'_id.course'
:
course_location
.
course
,
'_id.category'
:
{
'$nin'
:
detached_categories
}
})
all_reachable
=
set
()
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_orphan.py
View file @
f45abe3d
...
...
@@ -23,12 +23,12 @@ class TestOrphan(unittest.TestCase):
'db'
:
'test_xmodule'
,
}
modulestore_options
=
dict
(
{
modulestore_options
=
{
'default_class'
:
'xmodule.raw_module.RawDescriptor'
,
'fs_root'
:
''
,
'render_template'
:
mock
.
Mock
(
return_value
=
""
),
'xblock_mixins'
:
(
InheritanceMixin
,)
}
)
}
split_course_id
=
'test_org.test_course.runid'
...
...
@@ -41,25 +41,35 @@ class TestOrphan(unittest.TestCase):
self
.
db_config
,
**
self
.
modulestore_options
)
self
.
addCleanup
(
self
.
tear
DownS
plit
)
self
.
addCleanup
(
self
.
tear
_down_s
plit
)
self
.
old_mongo
=
MongoModuleStore
(
self
.
db_config
,
**
self
.
modulestore_options
)
self
.
addCleanup
(
self
.
tear
DownM
ongo
)
self
.
addCleanup
(
self
.
tear
_down_m
ongo
)
self
.
course_location
=
None
self
.
_create_course
()
def
tearDownSplit
(
self
):
def
tear_down_split
(
self
):
"""
Remove the test collections, close the db connection
"""
split_db
=
self
.
split_mongo
.
db
split_db
.
drop_collection
(
split_db
.
course_index
)
split_db
.
drop_collection
(
split_db
.
structures
)
split_db
.
drop_collection
(
split_db
.
definitions
)
split_db
.
connection
.
close
()
def
tearDownMongo
(
self
):
def
tear_down_mongo
(
self
):
"""
Remove the test collections, close the db connection
"""
split_db
=
self
.
split_mongo
.
db
# old_mongo doesn't give a db attr, but all of the dbs are the same
split_db
.
drop_collection
(
self
.
old_mongo
.
collection
)
def
_create_item
(
self
,
category
,
name
,
data
,
metadata
,
parent_category
,
parent_name
,
runtime
):
"""
Create the item of the given category and block id in split and old mongo, add it to the optional
parent. The parent category is only needed because old mongo requires it for the id.
"""
location
=
Location
(
'i4x'
,
'test_org'
,
'test_course'
,
category
,
name
)
self
.
old_mongo
.
create_and_save_xmodule
(
location
,
data
,
metadata
,
runtime
)
if
isinstance
(
data
,
basestring
):
...
...
@@ -125,7 +135,7 @@ class TestOrphan(unittest.TestCase):
"""
Test that old mongo finds the orphans
"""
orphans
=
self
.
old_mongo
.
get_orphans
(
'test_org.test_course'
,
[
'static_tab'
,
'about'
,
'course_info'
],
None
)
orphans
=
self
.
old_mongo
.
get_orphans
(
self
.
course_location
,
[
'static_tab'
,
'about'
,
'course_info'
],
None
)
self
.
assertEqual
(
len
(
orphans
),
3
,
"Wrong # {}"
.
format
(
orphans
))
location
=
self
.
course_location
.
replace
(
category
=
'chapter'
,
name
=
'OrphanChapter'
)
self
.
assertIn
(
location
.
url
(),
orphans
)
...
...
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