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
a8084628
Commit
a8084628
authored
May 23, 2013
by
chrisndodge
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1956 from edx/feature/cdodge/autoprovision-forums-master
Feature/cdodge/autoprovision forums master
parents
257dae63
e6a1a9fa
Hide whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
306 additions
and
150 deletions
+306
-150
cms/djangoapps/contentstore/tests/test_contentstore.py
+28
-18
cms/djangoapps/contentstore/views/course.py
+12
-9
cms/envs/common.py
+3
-0
cms/envs/dev.py
+1
-2
common/djangoapps/django_comment_common/__init__.py
+0
-0
common/djangoapps/django_comment_common/migrations/0001_initial.py
+92
-0
common/djangoapps/django_comment_common/migrations/__init__.py
+0
-0
common/djangoapps/django_comment_common/models.py
+74
-0
common/djangoapps/django_comment_common/utils.py
+56
-0
common/lib/xmodule/xmodule/modulestore/__init__.py
+11
-17
common/lib/xmodule/xmodule/modulestore/draft.py
+2
-1
common/lib/xmodule/xmodule/modulestore/tests/factories.py
+0
-1
lms/djangoapps/django_comment_client/base/views.py
+1
-1
lms/djangoapps/django_comment_client/management/commands/assign_role.py
+1
-1
lms/djangoapps/django_comment_client/management/commands/assign_roles_for_course.py
+1
-1
lms/djangoapps/django_comment_client/management/commands/create_roles_for_existing.py
+1
-1
lms/djangoapps/django_comment_client/management/commands/seed_permissions_roles.py
+2
-24
lms/djangoapps/django_comment_client/management/commands/show_permissions.py
+1
-0
lms/djangoapps/django_comment_client/models.py
+1
-64
lms/djangoapps/django_comment_client/permissions.py
+1
-1
lms/djangoapps/django_comment_client/tests.py
+1
-1
lms/djangoapps/django_comment_client/tests/factories.py
+1
-1
lms/djangoapps/django_comment_client/tests/test_models.py
+1
-1
lms/djangoapps/django_comment_client/tests/test_utils.py
+1
-1
lms/djangoapps/django_comment_client/utils.py
+1
-1
lms/djangoapps/instructor/tests/test_forum_admin.py
+1
-1
lms/djangoapps/instructor/views.py
+1
-1
lms/envs/common.py
+1
-2
rakefiles/tests.rake
+10
-0
No files found.
cms/djangoapps/contentstore/tests/test_contentstore.py
View file @
a8084628
...
@@ -34,6 +34,8 @@ from xmodule.course_module import CourseDescriptor
...
@@ -34,6 +34,8 @@ from xmodule.course_module import CourseDescriptor
from
xmodule.seq_module
import
SequenceDescriptor
from
xmodule.seq_module
import
SequenceDescriptor
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
from
django_comment_common.utils
import
are_permissions_roles_seeded
TEST_DATA_MODULESTORE
=
copy
.
deepcopy
(
settings
.
MODULESTORE
)
TEST_DATA_MODULESTORE
=
copy
.
deepcopy
(
settings
.
MODULESTORE
)
TEST_DATA_MODULESTORE
[
'default'
][
'OPTIONS'
][
'fs_root'
]
=
path
(
'common/test/data'
)
TEST_DATA_MODULESTORE
[
'default'
][
'OPTIONS'
][
'fs_root'
]
=
path
(
'common/test/data'
)
TEST_DATA_MODULESTORE
[
'direct'
][
'OPTIONS'
][
'fs_root'
]
=
path
(
'common/test/data'
)
TEST_DATA_MODULESTORE
[
'direct'
][
'OPTIONS'
][
'fs_root'
]
=
path
(
'common/test/data'
)
...
@@ -45,7 +47,7 @@ class MongoCollectionFindWrapper(object):
...
@@ -45,7 +47,7 @@ class MongoCollectionFindWrapper(object):
self
.
counter
=
0
self
.
counter
=
0
def
find
(
self
,
query
,
*
args
,
**
kwargs
):
def
find
(
self
,
query
,
*
args
,
**
kwargs
):
self
.
counter
=
self
.
counter
+
1
self
.
counter
=
self
.
counter
+
1
return
self
.
original
(
query
,
*
args
,
**
kwargs
)
return
self
.
original
(
query
,
*
args
,
**
kwargs
)
...
@@ -352,7 +354,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
...
@@ -352,7 +354,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
clone_items
=
module_store
.
get_items
(
Location
([
'i4x'
,
'MITx'
,
'999'
,
'vertical'
,
None
]))
clone_items
=
module_store
.
get_items
(
Location
([
'i4x'
,
'MITx'
,
'999'
,
'vertical'
,
None
]))
self
.
assertGreater
(
len
(
clone_items
),
0
)
self
.
assertGreater
(
len
(
clone_items
),
0
)
for
descriptor
in
items
:
for
descriptor
in
items
:
new_loc
=
descriptor
.
location
.
_
replace
(
org
=
'MITx'
,
course
=
'999'
)
new_loc
=
descriptor
.
location
.
replace
(
org
=
'MITx'
,
course
=
'999'
)
print
"Checking {0} should now also be at {1}"
.
format
(
descriptor
.
location
.
url
(),
new_loc
.
url
())
print
"Checking {0} should now also be at {1}"
.
format
(
descriptor
.
location
.
url
(),
new_loc
.
url
())
resp
=
self
.
client
.
get
(
reverse
(
'edit_unit'
,
kwargs
=
{
'location'
:
new_loc
.
url
()}))
resp
=
self
.
client
.
get
(
reverse
(
'edit_unit'
,
kwargs
=
{
'location'
:
new_loc
.
url
()}))
self
.
assertEqual
(
resp
.
status_code
,
200
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
...
@@ -375,15 +377,15 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
...
@@ -375,15 +377,15 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
self
.
assertEqual
(
len
(
items
),
0
)
self
.
assertEqual
(
len
(
items
),
0
)
def
verify_content_existence
(
self
,
modulestore
,
root_dir
,
location
,
dirname
,
category_name
,
filename_suffix
=
''
):
def
verify_content_existence
(
self
,
modulestore
,
root_dir
,
location
,
dirname
,
category_name
,
filename_suffix
=
''
):
f
s
=
OSFS
(
root_dir
/
'test_export'
)
f
ilesystem
=
OSFS
(
root_dir
/
'test_export'
)
self
.
assertTrue
(
f
s
.
exists
(
dirname
))
self
.
assertTrue
(
f
ilesystem
.
exists
(
dirname
))
query_loc
=
Location
(
'i4x'
,
location
.
org
,
location
.
course
,
category_name
,
None
)
query_loc
=
Location
(
'i4x'
,
location
.
org
,
location
.
course
,
category_name
,
None
)
items
=
modulestore
.
get_items
(
query_loc
)
items
=
modulestore
.
get_items
(
query_loc
)
for
item
in
items
:
for
item
in
items
:
f
s
=
OSFS
(
root_dir
/
(
'test_export/'
+
dirname
))
f
ilesystem
=
OSFS
(
root_dir
/
(
'test_export/'
+
dirname
))
self
.
assertTrue
(
f
s
.
exists
(
item
.
location
.
name
+
filename_suffix
))
self
.
assertTrue
(
f
ilesystem
.
exists
(
item
.
location
.
name
+
filename_suffix
))
def
test_export_course
(
self
):
def
test_export_course
(
self
):
module_store
=
modulestore
(
'direct'
)
module_store
=
modulestore
(
'direct'
)
...
@@ -415,7 +417,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
...
@@ -415,7 +417,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
# add private to list of children
# add private to list of children
sequential
=
module_store
.
get_item
(
Location
([
'i4x'
,
'edX'
,
'full'
,
sequential
=
module_store
.
get_item
(
Location
([
'i4x'
,
'edX'
,
'full'
,
'sequential'
,
'Administrivia_and_Circuit_Elements'
,
None
]))
'sequential'
,
'Administrivia_and_Circuit_Elements'
,
None
]))
private_location_no_draft
=
private_vertical
.
location
.
_
replace
(
revision
=
None
)
private_location_no_draft
=
private_vertical
.
location
.
replace
(
revision
=
None
)
module_store
.
update_children
(
sequential
.
location
,
sequential
.
children
+
module_store
.
update_children
(
sequential
.
location
,
sequential
.
children
+
[
private_location_no_draft
.
url
()])
[
private_location_no_draft
.
url
()])
...
@@ -440,20 +442,20 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
...
@@ -440,20 +442,20 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
self
.
verify_content_existence
(
module_store
,
root_dir
,
location
,
'custom_tags'
,
'custom_tag_template'
)
self
.
verify_content_existence
(
module_store
,
root_dir
,
location
,
'custom_tags'
,
'custom_tag_template'
)
# check for graiding_policy.json
# check for graiding_policy.json
f
s
=
OSFS
(
root_dir
/
'test_export/policies/6.002_Spring_2012'
)
f
ilesystem
=
OSFS
(
root_dir
/
'test_export/policies/6.002_Spring_2012'
)
self
.
assertTrue
(
f
s
.
exists
(
'grading_policy.json'
))
self
.
assertTrue
(
f
ilesystem
.
exists
(
'grading_policy.json'
))
course
=
module_store
.
get_item
(
location
)
course
=
module_store
.
get_item
(
location
)
# compare what's on disk compared to what we have in our course
# compare what's on disk compared to what we have in our course
with
f
s
.
open
(
'grading_policy.json'
,
'r'
)
as
grading_policy
:
with
f
ilesystem
.
open
(
'grading_policy.json'
,
'r'
)
as
grading_policy
:
on_disk
=
loads
(
grading_policy
.
read
())
on_disk
=
loads
(
grading_policy
.
read
())
self
.
assertEqual
(
on_disk
,
course
.
grading_policy
)
self
.
assertEqual
(
on_disk
,
course
.
grading_policy
)
#check for policy.json
#check for policy.json
self
.
assertTrue
(
f
s
.
exists
(
'policy.json'
))
self
.
assertTrue
(
f
ilesystem
.
exists
(
'policy.json'
))
# compare what's on disk to what we have in the course module
# compare what's on disk to what we have in the course module
with
f
s
.
open
(
'policy.json'
,
'r'
)
as
course_policy
:
with
f
ilesystem
.
open
(
'policy.json'
,
'r'
)
as
course_policy
:
on_disk
=
loads
(
course_policy
.
read
())
on_disk
=
loads
(
course_policy
.
read
())
self
.
assertIn
(
'course/6.002_Spring_2012'
,
on_disk
)
self
.
assertIn
(
'course/6.002_Spring_2012'
,
on_disk
)
self
.
assertEqual
(
on_disk
[
'course/6.002_Spring_2012'
],
own_metadata
(
course
))
self
.
assertEqual
(
on_disk
[
'course/6.002_Spring_2012'
],
own_metadata
(
course
))
...
@@ -608,6 +610,14 @@ class ContentStoreTest(ModuleStoreTestCase):
...
@@ -608,6 +610,14 @@ class ContentStoreTest(ModuleStoreTestCase):
data
=
parse_json
(
resp
)
data
=
parse_json
(
resp
)
self
.
assertEqual
(
data
[
'id'
],
'i4x://MITx/999/course/Robot_Super_Course'
)
self
.
assertEqual
(
data
[
'id'
],
'i4x://MITx/999/course/Robot_Super_Course'
)
def
test_create_course_check_forum_seeding
(
self
):
"""Test new course creation and verify forum seeding """
resp
=
self
.
client
.
post
(
reverse
(
'create_new_course'
),
self
.
course_data
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
data
=
parse_json
(
resp
)
self
.
assertEqual
(
data
[
'id'
],
'i4x://MITx/999/course/Robot_Super_Course'
)
self
.
assertTrue
(
are_permissions_roles_seeded
(
'MITx/999/Robot_Super_Course'
))
def
test_create_course_duplicate_course
(
self
):
def
test_create_course_duplicate_course
(
self
):
"""Test new course creation - error path"""
"""Test new course creation - error path"""
resp
=
self
.
client
.
post
(
reverse
(
'create_new_course'
),
self
.
course_data
)
resp
=
self
.
client
.
post
(
reverse
(
'create_new_course'
),
self
.
course_data
)
...
@@ -801,37 +811,37 @@ class ContentStoreTest(ModuleStoreTestCase):
...
@@ -801,37 +811,37 @@ class ContentStoreTest(ModuleStoreTestCase):
self
.
assertEqual
(
200
,
resp
.
status_code
)
self
.
assertEqual
(
200
,
resp
.
status_code
)
# go look at a subsection page
# go look at a subsection page
subsection_location
=
loc
.
_
replace
(
category
=
'sequential'
,
name
=
'test_sequence'
)
subsection_location
=
loc
.
replace
(
category
=
'sequential'
,
name
=
'test_sequence'
)
resp
=
self
.
client
.
get
(
reverse
(
'edit_subsection'
,
resp
=
self
.
client
.
get
(
reverse
(
'edit_subsection'
,
kwargs
=
{
'location'
:
subsection_location
.
url
()}))
kwargs
=
{
'location'
:
subsection_location
.
url
()}))
self
.
assertEqual
(
200
,
resp
.
status_code
)
self
.
assertEqual
(
200
,
resp
.
status_code
)
# go look at the Edit page
# go look at the Edit page
unit_location
=
loc
.
_
replace
(
category
=
'vertical'
,
name
=
'test_vertical'
)
unit_location
=
loc
.
replace
(
category
=
'vertical'
,
name
=
'test_vertical'
)
resp
=
self
.
client
.
get
(
reverse
(
'edit_unit'
,
resp
=
self
.
client
.
get
(
reverse
(
'edit_unit'
,
kwargs
=
{
'location'
:
unit_location
.
url
()}))
kwargs
=
{
'location'
:
unit_location
.
url
()}))
self
.
assertEqual
(
200
,
resp
.
status_code
)
self
.
assertEqual
(
200
,
resp
.
status_code
)
# delete a component
# delete a component
del_loc
=
loc
.
_
replace
(
category
=
'html'
,
name
=
'test_html'
)
del_loc
=
loc
.
replace
(
category
=
'html'
,
name
=
'test_html'
)
resp
=
self
.
client
.
post
(
reverse
(
'delete_item'
),
resp
=
self
.
client
.
post
(
reverse
(
'delete_item'
),
json
.
dumps
({
'id'
:
del_loc
.
url
()}),
"application/json"
)
json
.
dumps
({
'id'
:
del_loc
.
url
()}),
"application/json"
)
self
.
assertEqual
(
200
,
resp
.
status_code
)
self
.
assertEqual
(
200
,
resp
.
status_code
)
# delete a unit
# delete a unit
del_loc
=
loc
.
_
replace
(
category
=
'vertical'
,
name
=
'test_vertical'
)
del_loc
=
loc
.
replace
(
category
=
'vertical'
,
name
=
'test_vertical'
)
resp
=
self
.
client
.
post
(
reverse
(
'delete_item'
),
resp
=
self
.
client
.
post
(
reverse
(
'delete_item'
),
json
.
dumps
({
'id'
:
del_loc
.
url
()}),
"application/json"
)
json
.
dumps
({
'id'
:
del_loc
.
url
()}),
"application/json"
)
self
.
assertEqual
(
200
,
resp
.
status_code
)
self
.
assertEqual
(
200
,
resp
.
status_code
)
# delete a unit
# delete a unit
del_loc
=
loc
.
_
replace
(
category
=
'sequential'
,
name
=
'test_sequence'
)
del_loc
=
loc
.
replace
(
category
=
'sequential'
,
name
=
'test_sequence'
)
resp
=
self
.
client
.
post
(
reverse
(
'delete_item'
),
resp
=
self
.
client
.
post
(
reverse
(
'delete_item'
),
json
.
dumps
({
'id'
:
del_loc
.
url
()}),
"application/json"
)
json
.
dumps
({
'id'
:
del_loc
.
url
()}),
"application/json"
)
self
.
assertEqual
(
200
,
resp
.
status_code
)
self
.
assertEqual
(
200
,
resp
.
status_code
)
# delete a chapter
# delete a chapter
del_loc
=
loc
.
_
replace
(
category
=
'chapter'
,
name
=
'chapter_2'
)
del_loc
=
loc
.
replace
(
category
=
'chapter'
,
name
=
'chapter_2'
)
resp
=
self
.
client
.
post
(
reverse
(
'delete_item'
),
resp
=
self
.
client
.
post
(
reverse
(
'delete_item'
),
json
.
dumps
({
'id'
:
del_loc
.
url
()}),
"application/json"
)
json
.
dumps
({
'id'
:
del_loc
.
url
()}),
"application/json"
)
self
.
assertEqual
(
200
,
resp
.
status_code
)
self
.
assertEqual
(
200
,
resp
.
status_code
)
...
...
cms/djangoapps/contentstore/views/course.py
View file @
a8084628
...
@@ -13,17 +13,13 @@ from django.core.urlresolvers import reverse
...
@@ -13,17 +13,13 @@ from django.core.urlresolvers import reverse
from
mitxmako.shortcuts
import
render_to_response
from
mitxmako.shortcuts
import
render_to_response
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.exceptions
\
import
ItemNotFoundError
,
InvalidLocationError
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
,
InvalidLocationError
from
xmodule.modulestore
import
Location
from
xmodule.modulestore
import
Location
from
contentstore.course_info_model
\
from
contentstore.course_info_model
import
get_course_updates
,
update_course_updates
,
delete_course_update
import
get_course_updates
,
update_course_updates
,
delete_course_update
from
contentstore.utils
import
get_lms_link_for_item
,
add_extra_panel_tab
,
remove_extra_panel_tab
from
contentstore.utils
\
from
models.settings.course_details
import
CourseDetails
,
CourseSettingsEncoder
import
get_lms_link_for_item
,
add_extra_panel_tab
,
\
remove_extra_panel_tab
from
models.settings.course_details
\
import
CourseDetails
,
CourseSettingsEncoder
from
models.settings.course_grading
import
CourseGradingModel
from
models.settings.course_grading
import
CourseGradingModel
from
models.settings.course_metadata
import
CourseMetadata
from
models.settings.course_metadata
import
CourseMetadata
from
auth.authz
import
create_all_course_groups
from
auth.authz
import
create_all_course_groups
...
@@ -35,6 +31,10 @@ from .tabs import initialize_course_tabs
...
@@ -35,6 +31,10 @@ from .tabs import initialize_course_tabs
from
.component
import
OPEN_ENDED_COMPONENT_TYPES
,
\
from
.component
import
OPEN_ENDED_COMPONENT_TYPES
,
\
NOTE_COMPONENT_TYPES
,
ADVANCED_COMPONENT_POLICY_KEY
NOTE_COMPONENT_TYPES
,
ADVANCED_COMPONENT_POLICY_KEY
from
django_comment_common.utils
import
seed_permissions_roles
# TODO: should explicitly enumerate exports with __all__
__all__
=
[
'course_index'
,
'create_new_course'
,
'course_info'
,
__all__
=
[
'course_index'
,
'create_new_course'
,
'course_info'
,
'course_info_updates'
,
'get_course_settings'
,
'course_info_updates'
,
'get_course_settings'
,
'course_config_graders_page'
,
'course_config_graders_page'
,
...
@@ -136,6 +136,9 @@ def create_new_course(request):
...
@@ -136,6 +136,9 @@ def create_new_course(request):
create_all_course_groups
(
request
.
user
,
new_course
.
location
)
create_all_course_groups
(
request
.
user
,
new_course
.
location
)
# seed the forums
seed_permissions_roles
(
new_course
.
location
.
course_id
)
return
HttpResponse
(
json
.
dumps
({
'id'
:
new_course
.
location
.
url
()}))
return
HttpResponse
(
json
.
dumps
({
'id'
:
new_course
.
location
.
url
()}))
...
...
cms/envs/common.py
View file @
a8084628
...
@@ -322,6 +322,9 @@ INSTALLED_APPS = (
...
@@ -322,6 +322,9 @@ INSTALLED_APPS = (
'pipeline'
,
'pipeline'
,
'staticfiles'
,
'staticfiles'
,
'static_replace'
,
'static_replace'
,
# comment common
'django_comment_common'
,
)
)
################# EDX MARKETING SITE ##################################
################# EDX MARKETING SITE ##################################
...
...
cms/envs/dev.py
View file @
a8084628
...
@@ -127,8 +127,7 @@ CELERY_ALWAYS_EAGER = True
...
@@ -127,8 +127,7 @@ CELERY_ALWAYS_EAGER = True
################################ DEBUG TOOLBAR #################################
################################ DEBUG TOOLBAR #################################
INSTALLED_APPS
+=
(
'debug_toolbar'
,
'debug_toolbar_mongo'
)
INSTALLED_APPS
+=
(
'debug_toolbar'
,
'debug_toolbar_mongo'
)
MIDDLEWARE_CLASSES
+=
(
'django_comment_client.utils.QueryCountDebugMiddleware'
,
MIDDLEWARE_CLASSES
+=
(
'debug_toolbar.middleware.DebugToolbarMiddleware'
,)
'debug_toolbar.middleware.DebugToolbarMiddleware'
,)
INTERNAL_IPS
=
(
'127.0.0.1'
,)
INTERNAL_IPS
=
(
'127.0.0.1'
,)
DEBUG_TOOLBAR_PANELS
=
(
DEBUG_TOOLBAR_PANELS
=
(
...
...
common/djangoapps/django_comment_common/__init__.py
0 → 100644
View file @
a8084628
common/djangoapps/django_comment_common/migrations/0001_initial.py
0 → 100644
View file @
a8084628
# -*- coding: utf-8 -*-
from
south.v2
import
SchemaMigration
class
Migration
(
SchemaMigration
):
#
# cdodge: This is basically an empty migration since everything has - up to now - managed in the django_comment_client app
# But going forward we should be using this migration
#
def
forwards
(
self
,
orm
):
pass
def
backwards
(
self
,
orm
):
pass
models
=
{
'auth.group'
:
{
'Meta'
:
{
'object_name'
:
'Group'
},
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'unique'
:
'True'
,
'max_length'
:
'80'
}),
'permissions'
:
(
'django.db.models.fields.related.ManyToManyField'
,
[],
{
'to'
:
"orm['auth.Permission']"
,
'symmetrical'
:
'False'
,
'blank'
:
'True'
})
},
'auth.permission'
:
{
'Meta'
:
{
'ordering'
:
"('content_type__app_label', 'content_type__model', 'codename')"
,
'unique_together'
:
"(('content_type', 'codename'),)"
,
'object_name'
:
'Permission'
},
'codename'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'100'
}),
'content_type'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'to'
:
"orm['contenttypes.ContentType']"
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'50'
})
},
'auth.user'
:
{
'Meta'
:
{
'object_name'
:
'User'
},
'about'
:
(
'django.db.models.fields.TextField'
,
[],
{
'blank'
:
'True'
}),
'avatar_type'
:
(
'django.db.models.fields.CharField'
,
[],
{
'default'
:
"'n'"
,
'max_length'
:
'1'
}),
'bronze'
:
(
'django.db.models.fields.SmallIntegerField'
,
[],
{
'default'
:
'0'
}),
'consecutive_days_visit_count'
:
(
'django.db.models.fields.IntegerField'
,
[],
{
'default'
:
'0'
}),
'country'
:
(
'django_countries.fields.CountryField'
,
[],
{
'max_length'
:
'2'
,
'blank'
:
'True'
}),
'date_joined'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'date_of_birth'
:
(
'django.db.models.fields.DateField'
,
[],
{
'null'
:
'True'
,
'blank'
:
'True'
}),
'display_tag_filter_strategy'
:
(
'django.db.models.fields.SmallIntegerField'
,
[],
{
'default'
:
'0'
}),
'email'
:
(
'django.db.models.fields.EmailField'
,
[],
{
'max_length'
:
'75'
,
'blank'
:
'True'
}),
'email_isvalid'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'email_key'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'32'
,
'null'
:
'True'
}),
'email_tag_filter_strategy'
:
(
'django.db.models.fields.SmallIntegerField'
,
[],
{
'default'
:
'1'
}),
'first_name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'30'
,
'blank'
:
'True'
}),
'gold'
:
(
'django.db.models.fields.SmallIntegerField'
,
[],
{
'default'
:
'0'
}),
'gravatar'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'32'
}),
'groups'
:
(
'django.db.models.fields.related.ManyToManyField'
,
[],
{
'to'
:
"orm['auth.Group']"
,
'symmetrical'
:
'False'
,
'blank'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'ignored_tags'
:
(
'django.db.models.fields.TextField'
,
[],
{
'blank'
:
'True'
}),
'interesting_tags'
:
(
'django.db.models.fields.TextField'
,
[],
{
'blank'
:
'True'
}),
'is_active'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'True'
}),
'is_staff'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'is_superuser'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'last_login'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'last_name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'30'
,
'blank'
:
'True'
}),
'last_seen'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'location'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'100'
,
'blank'
:
'True'
}),
'new_response_count'
:
(
'django.db.models.fields.IntegerField'
,
[],
{
'default'
:
'0'
}),
'password'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'128'
}),
'questions_per_page'
:
(
'django.db.models.fields.SmallIntegerField'
,
[],
{
'default'
:
'10'
}),
'real_name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'100'
,
'blank'
:
'True'
}),
'reputation'
:
(
'django.db.models.fields.PositiveIntegerField'
,
[],
{
'default'
:
'1'
}),
'seen_response_count'
:
(
'django.db.models.fields.IntegerField'
,
[],
{
'default'
:
'0'
}),
'show_country'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'silver'
:
(
'django.db.models.fields.SmallIntegerField'
,
[],
{
'default'
:
'0'
}),
'status'
:
(
'django.db.models.fields.CharField'
,
[],
{
'default'
:
"'w'"
,
'max_length'
:
'2'
}),
'user_permissions'
:
(
'django.db.models.fields.related.ManyToManyField'
,
[],
{
'to'
:
"orm['auth.Permission']"
,
'symmetrical'
:
'False'
,
'blank'
:
'True'
}),
'username'
:
(
'django.db.models.fields.CharField'
,
[],
{
'unique'
:
'True'
,
'max_length'
:
'30'
}),
'website'
:
(
'django.db.models.fields.URLField'
,
[],
{
'max_length'
:
'200'
,
'blank'
:
'True'
})
},
'contenttypes.contenttype'
:
{
'Meta'
:
{
'ordering'
:
"('name',)"
,
'unique_together'
:
"(('app_label', 'model'),)"
,
'object_name'
:
'ContentType'
,
'db_table'
:
"'django_content_type'"
},
'app_label'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'100'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'model'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'100'
}),
'name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'100'
})
},
'django_comment_common.permission'
:
{
'Meta'
:
{
'object_name'
:
'Permission'
},
'name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'30'
,
'primary_key'
:
'True'
}),
'roles'
:
(
'django.db.models.fields.related.ManyToManyField'
,
[],
{
'related_name'
:
"'permissions'"
,
'symmetrical'
:
'False'
,
'to'
:
"orm['django_comment_common.Role']"
})
},
'django_comment_common.role'
:
{
'Meta'
:
{
'object_name'
:
'Role'
},
'course_id'
:
(
'django.db.models.fields.CharField'
,
[],
{
'db_index'
:
'True'
,
'max_length'
:
'255'
,
'blank'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'30'
}),
'users'
:
(
'django.db.models.fields.related.ManyToManyField'
,
[],
{
'related_name'
:
"'roles'"
,
'symmetrical'
:
'False'
,
'to'
:
"orm['auth.User']"
})
}
}
complete_apps
=
[
'django_comment_common'
]
common/djangoapps/django_comment_common/migrations/__init__.py
0 → 100644
View file @
a8084628
common/djangoapps/django_comment_common/models.py
0 → 100644
View file @
a8084628
import
logging
from
django.db
import
models
from
django.contrib.auth.models
import
User
from
django.dispatch
import
receiver
from
django.db.models.signals
import
post_save
from
student.models
import
CourseEnrollment
from
xmodule.modulestore.django
import
modulestore
from
xmodule.course_module
import
CourseDescriptor
FORUM_ROLE_ADMINISTRATOR
=
'Administrator'
FORUM_ROLE_MODERATOR
=
'Moderator'
FORUM_ROLE_COMMUNITY_TA
=
'Community TA'
FORUM_ROLE_STUDENT
=
'Student'
@receiver
(
post_save
,
sender
=
CourseEnrollment
)
def
assign_default_role
(
sender
,
instance
,
**
kwargs
):
if
instance
.
user
.
is_staff
:
role
=
Role
.
objects
.
get_or_create
(
course_id
=
instance
.
course_id
,
name
=
"Moderator"
)[
0
]
else
:
role
=
Role
.
objects
.
get_or_create
(
course_id
=
instance
.
course_id
,
name
=
"Student"
)[
0
]
logging
.
info
(
"assign_default_role: adding
%
s as
%
s"
%
(
instance
.
user
,
role
))
instance
.
user
.
roles
.
add
(
role
)
class
Role
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
30
,
null
=
False
,
blank
=
False
)
users
=
models
.
ManyToManyField
(
User
,
related_name
=
"roles"
)
course_id
=
models
.
CharField
(
max_length
=
255
,
blank
=
True
,
db_index
=
True
)
class
Meta
:
# use existing table that was originally created from django_comment_client app
db_table
=
'django_comment_client_role'
def
__unicode__
(
self
):
return
self
.
name
+
" for "
+
(
self
.
course_id
if
self
.
course_id
else
"all courses"
)
def
inherit_permissions
(
self
,
role
):
# TODO the name of this method is a little bit confusing,
# since it's one-off and doesn't handle inheritance later
if
role
.
course_id
and
role
.
course_id
!=
self
.
course_id
:
logging
.
warning
(
"
%
s cannot inherit permissions from
%
s due to course_id inconsistency"
,
\
self
,
role
)
for
per
in
role
.
permissions
.
all
():
self
.
add_permission
(
per
)
def
add_permission
(
self
,
permission
):
self
.
permissions
.
add
(
Permission
.
objects
.
get_or_create
(
name
=
permission
)[
0
])
def
has_permission
(
self
,
permission
):
course_loc
=
CourseDescriptor
.
id_to_location
(
self
.
course_id
)
course
=
modulestore
()
.
get_instance
(
self
.
course_id
,
course_loc
)
if
self
.
name
==
FORUM_ROLE_STUDENT
and
\
(
permission
.
startswith
(
'edit'
)
or
permission
.
startswith
(
'update'
)
or
permission
.
startswith
(
'create'
))
and
\
(
not
course
.
forum_posts_allowed
):
return
False
return
self
.
permissions
.
filter
(
name
=
permission
)
.
exists
()
class
Permission
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
30
,
null
=
False
,
blank
=
False
,
primary_key
=
True
)
roles
=
models
.
ManyToManyField
(
Role
,
related_name
=
"permissions"
)
class
Meta
:
# use existing table that was originally created from django_comment_client app
db_table
=
'django_comment_client_permission'
def
__unicode__
(
self
):
return
self
.
name
common/djangoapps/django_comment_common/utils.py
0 → 100644
View file @
a8084628
from
django_comment_common.models
import
Role
_STUDENT_ROLE_PERMISSIONS
=
[
"vote"
,
"update_thread"
,
"follow_thread"
,
"unfollow_thread"
,
"update_comment"
,
"create_sub_comment"
,
"unvote"
,
"create_thread"
,
"follow_commentable"
,
"unfollow_commentable"
,
"create_comment"
,
]
_MODERATOR_ROLE_PERMISSIONS
=
[
"edit_content"
,
"delete_thread"
,
"openclose_thread"
,
"endorse_comment"
,
"delete_comment"
,
"see_all_cohorts"
]
_ADMINISTRATOR_ROLE_PERMISSIONS
=
[
"manage_moderator"
]
def
seed_permissions_roles
(
course_id
):
administrator_role
=
Role
.
objects
.
get_or_create
(
name
=
"Administrator"
,
course_id
=
course_id
)[
0
]
moderator_role
=
Role
.
objects
.
get_or_create
(
name
=
"Moderator"
,
course_id
=
course_id
)[
0
]
community_ta_role
=
Role
.
objects
.
get_or_create
(
name
=
"Community TA"
,
course_id
=
course_id
)[
0
]
student_role
=
Role
.
objects
.
get_or_create
(
name
=
"Student"
,
course_id
=
course_id
)[
0
]
for
per
in
_STUDENT_ROLE_PERMISSIONS
:
student_role
.
add_permission
(
per
)
for
per
in
_MODERATOR_ROLE_PERMISSIONS
:
moderator_role
.
add_permission
(
per
)
for
per
in
_ADMINISTRATOR_ROLE_PERMISSIONS
:
administrator_role
.
add_permission
(
per
)
moderator_role
.
inherit_permissions
(
student_role
)
# For now, Community TA == Moderator, except for the styling.
community_ta_role
.
inherit_permissions
(
moderator_role
)
administrator_role
.
inherit_permissions
(
moderator_role
)
def
are_permissions_roles_seeded
(
course_id
):
try
:
administrator_role
=
Role
.
objects
.
get
(
name
=
"Administrator"
,
course_id
=
course_id
)
moderator_role
=
Role
.
objects
.
get
(
name
=
"Moderator"
,
course_id
=
course_id
)
student_role
=
Role
.
objects
.
get
(
name
=
"Student"
,
course_id
=
course_id
)
except
:
return
False
for
per
in
_STUDENT_ROLE_PERMISSIONS
:
if
not
student_role
.
has_permission
(
per
):
return
False
for
per
in
_MODERATOR_ROLE_PERMISSIONS
+
_STUDENT_ROLE_PERMISSIONS
:
if
not
moderator_role
.
has_permission
(
per
):
return
False
for
per
in
_ADMINISTRATOR_ROLE_PERMISSIONS
+
_MODERATOR_ROLE_PERMISSIONS
+
_STUDENT_ROLE_PERMISSIONS
:
if
not
administrator_role
.
has_permission
(
per
):
return
False
return
True
common/lib/xmodule/xmodule/modulestore/__init__.py
View file @
a8084628
...
@@ -9,7 +9,7 @@ import re
...
@@ -9,7 +9,7 @@ import re
from
collections
import
namedtuple
from
collections
import
namedtuple
from
.exceptions
import
InvalidLocationError
,
InsufficientSpecificationError
from
.exceptions
import
InvalidLocationError
,
InsufficientSpecificationError
from
xmodule.errortracker
import
ErrorLog
,
make_error_tracker
from
xmodule.errortracker
import
make_error_tracker
from
bson.son
import
SON
from
bson.son
import
SON
log
=
logging
.
getLogger
(
'mitx.'
+
'modulestore'
)
log
=
logging
.
getLogger
(
'mitx.'
+
'modulestore'
)
...
@@ -64,7 +64,6 @@ class Location(_LocationBase):
...
@@ -64,7 +64,6 @@ class Location(_LocationBase):
"""
"""
return
re
.
sub
(
'_+'
,
'_'
,
invalid
.
sub
(
'_'
,
value
))
return
re
.
sub
(
'_+'
,
'_'
,
invalid
.
sub
(
'_'
,
value
))
@staticmethod
@staticmethod
def
clean
(
value
):
def
clean
(
value
):
"""
"""
...
@@ -72,7 +71,6 @@ class Location(_LocationBase):
...
@@ -72,7 +71,6 @@ class Location(_LocationBase):
"""
"""
return
Location
.
_clean
(
value
,
INVALID_CHARS
)
return
Location
.
_clean
(
value
,
INVALID_CHARS
)
@staticmethod
@staticmethod
def
clean_keeping_underscores
(
value
):
def
clean_keeping_underscores
(
value
):
"""
"""
...
@@ -82,7 +80,6 @@ class Location(_LocationBase):
...
@@ -82,7 +80,6 @@ class Location(_LocationBase):
"""
"""
return
INVALID_CHARS
.
sub
(
'_'
,
value
)
return
INVALID_CHARS
.
sub
(
'_'
,
value
)
@staticmethod
@staticmethod
def
clean_for_url_name
(
value
):
def
clean_for_url_name
(
value
):
"""
"""
...
@@ -154,9 +151,7 @@ class Location(_LocationBase):
...
@@ -154,9 +151,7 @@ class Location(_LocationBase):
to mean wildcard selection.
to mean wildcard selection.
"""
"""
if
(
org
is
None
and
course
is
None
and
category
is
None
and
name
is
None
and
revision
is
None
):
if
(
org
is
None
and
course
is
None
and
category
is
None
and
name
is
None
and
revision
is
None
):
location
=
loc_or_tag
location
=
loc_or_tag
else
:
else
:
location
=
(
loc_or_tag
,
org
,
course
,
category
,
name
,
revision
)
location
=
(
loc_or_tag
,
org
,
course
,
category
,
name
,
revision
)
...
@@ -191,7 +186,7 @@ class Location(_LocationBase):
...
@@ -191,7 +186,7 @@ class Location(_LocationBase):
match
=
MISSING_SLASH_URL_RE
.
match
(
location
)
match
=
MISSING_SLASH_URL_RE
.
match
(
location
)
if
match
is
None
:
if
match
is
None
:
log
.
debug
(
'location is instance of
%
s but no URL match'
%
basestring
)
log
.
debug
(
'location is instance of
%
s but no URL match'
%
basestring
)
raise
InvalidLocationError
(
location
)
raise
InvalidLocationError
(
location
)
groups
=
match
.
groupdict
()
groups
=
match
.
groupdict
()
check_dict
(
groups
)
check_dict
(
groups
)
return
_LocationBase
.
__new__
(
_cls
,
**
groups
)
return
_LocationBase
.
__new__
(
_cls
,
**
groups
)
...
@@ -233,7 +228,7 @@ class Location(_LocationBase):
...
@@ -233,7 +228,7 @@ class Location(_LocationBase):
html id attributes
html id attributes
"""
"""
s
=
"-"
.
join
(
str
(
v
)
for
v
in
self
.
list
()
s
=
"-"
.
join
(
str
(
v
)
for
v
in
self
.
list
()
if
v
is
not
None
)
if
v
is
not
None
)
return
Location
.
clean_for_html
(
s
)
return
Location
.
clean_for_html
(
s
)
def
dict
(
self
):
def
dict
(
self
):
...
@@ -258,6 +253,12 @@ class Location(_LocationBase):
...
@@ -258,6 +253,12 @@ class Location(_LocationBase):
at the location URL hierachy"""
at the location URL hierachy"""
return
"/"
.
join
([
self
.
org
,
self
.
course
,
self
.
name
])
return
"/"
.
join
([
self
.
org
,
self
.
course
,
self
.
name
])
def
replace
(
self
,
**
kwargs
):
'''
Expose a public method for replacing location elements
'''
return
self
.
_replace
(
**
kwargs
)
class
ModuleStore
(
object
):
class
ModuleStore
(
object
):
"""
"""
...
@@ -382,12 +383,6 @@ class ModuleStore(object):
...
@@ -382,12 +383,6 @@ class ModuleStore(object):
'''
'''
raise
NotImplementedError
raise
NotImplementedError
def
get_course
(
self
,
course_id
):
'''
Look for a specific course id. Returns the course descriptor, or None if not found.
'''
raise
NotImplementedError
def
get_parent_locations
(
self
,
location
,
course_id
):
def
get_parent_locations
(
self
,
location
,
course_id
):
'''Find all locations that are the parents of this location in this
'''Find all locations that are the parents of this location in this
course. Needed for path_to_location().
course. Needed for path_to_location().
...
@@ -406,8 +401,7 @@ class ModuleStore(object):
...
@@ -406,8 +401,7 @@ class ModuleStore(object):
courses
=
[
courses
=
[
course
course
for
course
in
self
.
get_courses
()
for
course
in
self
.
get_courses
()
if
course
.
location
.
org
==
location
.
org
if
course
.
location
.
org
==
location
.
org
and
course
.
location
.
course
==
location
.
course
and
course
.
location
.
course
==
location
.
course
]
]
return
courses
return
courses
...
...
common/lib/xmodule/xmodule/modulestore/draft.py
View file @
a8084628
...
@@ -13,11 +13,12 @@ def as_draft(location):
...
@@ -13,11 +13,12 @@ def as_draft(location):
"""
"""
return
Location
(
location
)
.
_replace
(
revision
=
DRAFT
)
return
Location
(
location
)
.
_replace
(
revision
=
DRAFT
)
def
as_published
(
location
):
def
as_published
(
location
):
"""
"""
Returns the Location that is the published version for `location`
Returns the Location that is the published version for `location`
"""
"""
return
Location
(
location
)
.
_replace
(
revision
=
None
)
return
Location
(
location
)
.
_replace
(
revision
=
None
)
def
wrap_draft
(
item
):
def
wrap_draft
(
item
):
...
...
common/lib/xmodule/xmodule/modulestore/tests/factories.py
View file @
a8084628
...
@@ -3,7 +3,6 @@ from time import gmtime
...
@@ -3,7 +3,6 @@ from time import gmtime
from
uuid
import
uuid4
from
uuid
import
uuid4
from
xmodule.modulestore
import
Location
from
xmodule.modulestore
import
Location
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.django
import
modulestore
from
xmodule.timeparse
import
stringify_time
from
xmodule.modulestore.inheritance
import
own_metadata
from
xmodule.modulestore.inheritance
import
own_metadata
...
...
lms/djangoapps/django_comment_client/base/views.py
View file @
a8084628
...
@@ -26,7 +26,7 @@ from course_groups.cohorts import get_cohort_id, is_commentable_cohorted
...
@@ -26,7 +26,7 @@ from course_groups.cohorts import get_cohort_id, is_commentable_cohorted
from
django_comment_client.utils
import
JsonResponse
,
JsonError
,
extract
,
get_courseware_context
from
django_comment_client.utils
import
JsonResponse
,
JsonError
,
extract
,
get_courseware_context
from
django_comment_client.permissions
import
check_permissions_by_view
,
cached_has_permission
from
django_comment_client.permissions
import
check_permissions_by_view
,
cached_has_permission
from
django_comment_c
lient
.models
import
Role
from
django_comment_c
ommon
.models
import
Role
from
courseware.access
import
has_access
from
courseware.access
import
has_access
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
...
...
lms/djangoapps/django_comment_client/management/commands/assign_role.py
View file @
a8084628
from
optparse
import
make_option
from
optparse
import
make_option
from
django.core.management.base
import
BaseCommand
,
CommandError
from
django.core.management.base
import
BaseCommand
,
CommandError
from
django_comment_c
lient
.models
import
Role
from
django_comment_c
ommon
.models
import
Role
from
django.contrib.auth.models
import
User
from
django.contrib.auth.models
import
User
...
...
lms/djangoapps/django_comment_client/management/commands/assign_roles_for_course.py
View file @
a8084628
...
@@ -7,7 +7,7 @@ Enrollments.
...
@@ -7,7 +7,7 @@ Enrollments.
from
django.core.management.base
import
BaseCommand
,
CommandError
from
django.core.management.base
import
BaseCommand
,
CommandError
from
student.models
import
CourseEnrollment
from
student.models
import
CourseEnrollment
from
django_comment_c
lient
.models
import
assign_default_role
from
django_comment_c
ommon
.models
import
assign_default_role
class
Command
(
BaseCommand
):
class
Command
(
BaseCommand
):
...
...
lms/djangoapps/django_comment_client/management/commands/create_roles_for_existing.py
View file @
a8084628
...
@@ -7,7 +7,7 @@ Enrollments.
...
@@ -7,7 +7,7 @@ Enrollments.
from
django.core.management.base
import
BaseCommand
,
CommandError
from
django.core.management.base
import
BaseCommand
,
CommandError
from
student.models
import
CourseEnrollment
from
student.models
import
CourseEnrollment
from
django_comment_c
lient
.models
import
assign_default_role
from
django_comment_c
ommon
.models
import
assign_default_role
class
Command
(
BaseCommand
):
class
Command
(
BaseCommand
):
...
...
lms/djangoapps/django_comment_client/management/commands/seed_permissions_roles.py
View file @
a8084628
from
django.core.management.base
import
BaseCommand
,
CommandError
from
django.core.management.base
import
BaseCommand
,
CommandError
from
django_comment_c
lient.models
import
Role
from
django_comment_c
ommon.utils
import
seed_permissions_roles
class
Command
(
BaseCommand
):
class
Command
(
BaseCommand
):
...
@@ -13,26 +13,4 @@ class Command(BaseCommand):
...
@@ -13,26 +13,4 @@ class Command(BaseCommand):
raise
CommandError
(
"Too many arguments"
)
raise
CommandError
(
"Too many arguments"
)
course_id
=
args
[
0
]
course_id
=
args
[
0
]
administrator_role
=
Role
.
objects
.
get_or_create
(
name
=
"Administrator"
,
course_id
=
course_id
)[
0
]
seed_permissions_roles
(
course_id
)
moderator_role
=
Role
.
objects
.
get_or_create
(
name
=
"Moderator"
,
course_id
=
course_id
)[
0
]
community_ta_role
=
Role
.
objects
.
get_or_create
(
name
=
"Community TA"
,
course_id
=
course_id
)[
0
]
student_role
=
Role
.
objects
.
get_or_create
(
name
=
"Student"
,
course_id
=
course_id
)[
0
]
for
per
in
[
"vote"
,
"update_thread"
,
"follow_thread"
,
"unfollow_thread"
,
"update_comment"
,
"create_sub_comment"
,
"unvote"
,
"create_thread"
,
"follow_commentable"
,
"unfollow_commentable"
,
"create_comment"
,
]:
student_role
.
add_permission
(
per
)
for
per
in
[
"edit_content"
,
"delete_thread"
,
"openclose_thread"
,
"endorse_comment"
,
"delete_comment"
,
"see_all_cohorts"
]:
moderator_role
.
add_permission
(
per
)
for
per
in
[
"manage_moderator"
]:
administrator_role
.
add_permission
(
per
)
moderator_role
.
inherit_permissions
(
student_role
)
# For now, Community TA == Moderator, except for the styling.
community_ta_role
.
inherit_permissions
(
moderator_role
)
administrator_role
.
inherit_permissions
(
moderator_role
)
lms/djangoapps/django_comment_client/management/commands/show_permissions.py
View file @
a8084628
from
django.core.management.base
import
BaseCommand
,
CommandError
from
django.core.management.base
import
BaseCommand
,
CommandError
from
django_comment_common.models
import
Permission
,
Role
from
django.contrib.auth.models
import
User
from
django.contrib.auth.models
import
User
...
...
lms/djangoapps/django_comment_client/models.py
View file @
a8084628
import
logging
# This file is intentionally blank. It has been moved to common/djangoapps/django_comment_common
from
django.db
import
models
from
django.contrib.auth.models
import
User
from
django.dispatch
import
receiver
from
django.db.models.signals
import
post_save
from
student.models
import
CourseEnrollment
from
courseware.courses
import
get_course_by_id
FORUM_ROLE_ADMINISTRATOR
=
'Administrator'
FORUM_ROLE_MODERATOR
=
'Moderator'
FORUM_ROLE_COMMUNITY_TA
=
'Community TA'
FORUM_ROLE_STUDENT
=
'Student'
@receiver
(
post_save
,
sender
=
CourseEnrollment
)
def
assign_default_role
(
sender
,
instance
,
**
kwargs
):
if
instance
.
user
.
is_staff
:
role
=
Role
.
objects
.
get_or_create
(
course_id
=
instance
.
course_id
,
name
=
"Moderator"
)[
0
]
else
:
role
=
Role
.
objects
.
get_or_create
(
course_id
=
instance
.
course_id
,
name
=
"Student"
)[
0
]
logging
.
info
(
"assign_default_role: adding
%
s as
%
s"
%
(
instance
.
user
,
role
))
instance
.
user
.
roles
.
add
(
role
)
class
Role
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
30
,
null
=
False
,
blank
=
False
)
users
=
models
.
ManyToManyField
(
User
,
related_name
=
"roles"
)
course_id
=
models
.
CharField
(
max_length
=
255
,
blank
=
True
,
db_index
=
True
)
def
__unicode__
(
self
):
return
self
.
name
+
" for "
+
(
self
.
course_id
if
self
.
course_id
else
"all courses"
)
def
inherit_permissions
(
self
,
role
):
# TODO the name of this method is a little bit confusing,
# since it's one-off and doesn't handle inheritance later
if
role
.
course_id
and
role
.
course_id
!=
self
.
course_id
:
logging
.
warning
(
"
%
s cannot inherit permissions from
%
s due to course_id inconsistency"
,
self
,
role
)
for
per
in
role
.
permissions
.
all
():
self
.
add_permission
(
per
)
def
add_permission
(
self
,
permission
):
self
.
permissions
.
add
(
Permission
.
objects
.
get_or_create
(
name
=
permission
)[
0
])
def
has_permission
(
self
,
permission
):
course
=
get_course_by_id
(
self
.
course_id
)
if
self
.
name
==
FORUM_ROLE_STUDENT
and
\
(
permission
.
startswith
(
'edit'
)
or
permission
.
startswith
(
'update'
)
or
permission
.
startswith
(
'create'
))
and
\
(
not
course
.
forum_posts_allowed
):
return
False
return
self
.
permissions
.
filter
(
name
=
permission
)
.
exists
()
class
Permission
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
30
,
null
=
False
,
blank
=
False
,
primary_key
=
True
)
roles
=
models
.
ManyToManyField
(
Role
,
related_name
=
"permissions"
)
def
__unicode__
(
self
):
return
self
.
name
lms/djangoapps/django_comment_client/permissions.py
View file @
a8084628
from
.models
import
Role
,
Permission
from
django_comment_common
.models
import
Role
,
Permission
from
django.db.models.signals
import
post_save
from
django.db.models.signals
import
post_save
from
django.dispatch
import
receiver
from
django.dispatch
import
receiver
from
student.models
import
CourseEnrollment
from
student.models
import
CourseEnrollment
...
...
lms/djangoapps/django_comment_client/tests.py
View file @
a8084628
...
@@ -6,7 +6,7 @@ from django.test import TestCase
...
@@ -6,7 +6,7 @@ from django.test import TestCase
from
student.models
import
CourseEnrollment
from
student.models
import
CourseEnrollment
from
django_comment_client.permissions
import
has_permission
from
django_comment_client.permissions
import
has_permission
from
django_comment_c
lient
.models
import
Role
from
django_comment_c
ommon
.models
import
Role
class
PermissionsTestCase
(
TestCase
):
class
PermissionsTestCase
(
TestCase
):
...
...
lms/djangoapps/django_comment_client/tests/factories.py
View file @
a8084628
from
factory
import
DjangoModelFactory
from
factory
import
DjangoModelFactory
from
django_comment_c
lient
.models
import
Role
,
Permission
from
django_comment_c
ommon
.models
import
Role
,
Permission
class
RoleFactory
(
DjangoModelFactory
):
class
RoleFactory
(
DjangoModelFactory
):
...
...
lms/djangoapps/django_comment_client/tests/test_models.py
View file @
a8084628
import
django_comment_c
lient
.models
as
models
import
django_comment_c
ommon
.models
as
models
import
django_comment_client.permissions
as
permissions
import
django_comment_client.permissions
as
permissions
from
django.test
import
TestCase
from
django.test
import
TestCase
...
...
lms/djangoapps/django_comment_client/tests/test_utils.py
View file @
a8084628
from
django.test
import
TestCase
from
django.test
import
TestCase
from
student.tests.factories
import
UserFactory
,
CourseEnrollmentFactory
from
student.tests.factories
import
UserFactory
,
CourseEnrollmentFactory
from
django_comment_common.models
import
Role
,
Permission
from
factories
import
RoleFactory
from
factories
import
RoleFactory
import
django_comment_client.utils
as
utils
import
django_comment_client.utils
as
utils
...
...
lms/djangoapps/django_comment_client/utils.py
View file @
a8084628
...
@@ -14,7 +14,7 @@ from django.core.urlresolvers import reverse
...
@@ -14,7 +14,7 @@ from django.core.urlresolvers import reverse
from
django.db
import
connection
from
django.db
import
connection
from
django.http
import
HttpResponse
from
django.http
import
HttpResponse
from
django.utils
import
simplejson
from
django.utils
import
simplejson
from
django_comment_c
lient
.models
import
Role
from
django_comment_c
ommon
.models
import
Role
from
django_comment_client.permissions
import
check_permissions_by_view
from
django_comment_client.permissions
import
check_permissions_by_view
from
xmodule.modulestore.exceptions
import
NoPathToItem
from
xmodule.modulestore.exceptions
import
NoPathToItem
...
...
lms/djangoapps/instructor/tests/test_forum_admin.py
View file @
a8084628
...
@@ -9,7 +9,7 @@ from django.test.utils import override_settings
...
@@ -9,7 +9,7 @@ from django.test.utils import override_settings
from
django.contrib.auth.models
import
Group
from
django.contrib.auth.models
import
Group
from
django.core.urlresolvers
import
reverse
from
django.core.urlresolvers
import
reverse
from
django_comment_c
lient
.models
import
Role
,
FORUM_ROLE_ADMINISTRATOR
,
\
from
django_comment_c
ommon
.models
import
Role
,
FORUM_ROLE_ADMINISTRATOR
,
\
FORUM_ROLE_MODERATOR
,
FORUM_ROLE_COMMUNITY_TA
,
FORUM_ROLE_STUDENT
FORUM_ROLE_MODERATOR
,
FORUM_ROLE_COMMUNITY_TA
,
FORUM_ROLE_STUDENT
from
django_comment_client.utils
import
has_forum_access
from
django_comment_client.utils
import
has_forum_access
...
...
lms/djangoapps/instructor/views.py
View file @
a8084628
...
@@ -27,7 +27,7 @@ from courseware.access import (has_access, get_access_group_name,
...
@@ -27,7 +27,7 @@ from courseware.access import (has_access, get_access_group_name,
course_beta_test_group_name
)
course_beta_test_group_name
)
from
courseware.courses
import
get_course_with_access
from
courseware.courses
import
get_course_with_access
from
courseware.models
import
StudentModule
from
courseware.models
import
StudentModule
from
django_comment_c
lient
.models
import
(
Role
,
from
django_comment_c
ommon
.models
import
(
Role
,
FORUM_ROLE_ADMINISTRATOR
,
FORUM_ROLE_ADMINISTRATOR
,
FORUM_ROLE_MODERATOR
,
FORUM_ROLE_MODERATOR
,
FORUM_ROLE_COMMUNITY_TA
)
FORUM_ROLE_COMMUNITY_TA
)
...
...
lms/envs/common.py
View file @
a8084628
...
@@ -700,8 +700,7 @@ INSTALLED_APPS = (
...
@@ -700,8 +700,7 @@ INSTALLED_APPS = (
# Discussion forums
# Discussion forums
'django_comment_client'
,
'django_comment_client'
,
'django_comment_common'
,
# Student notes
'notes'
,
'notes'
,
)
)
...
...
rakefiles/tests.rake
View file @
a8084628
...
@@ -26,6 +26,16 @@ def run_tests(system, report_dir, test_id=nil, stop_on_failure=true)
...
@@ -26,6 +26,16 @@ def run_tests(system, report_dir, test_id=nil, stop_on_failure=true)
end
end
def
run_acceptance_tests
(
system
,
report_dir
,
harvest_args
)
def
run_acceptance_tests
(
system
,
report_dir
,
harvest_args
)
# HACK: Since now the CMS depends on the existence of some database tables
# that used to be in LMS (Role/Permissions for Forums) we need to make
# sure the acceptance tests create/migrate the database tables
# that are represented in the LMS. We might be able to address this by moving
# out the migrations from lms/django_comment_client, but then we'd have to
# repair all the existing migrations from the upgrade tables in the DB.
if
system
==
:cms
sh
(
django_admin
(
'lms'
,
'acceptance'
,
'syncdb'
,
'--noinput'
))
sh
(
django_admin
(
'lms'
,
'acceptance'
,
'migrate'
,
'--noinput'
))
end
sh
(
django_admin
(
system
,
'acceptance'
,
'syncdb'
,
'--noinput'
))
sh
(
django_admin
(
system
,
'acceptance'
,
'syncdb'
,
'--noinput'
))
sh
(
django_admin
(
system
,
'acceptance'
,
'migrate'
,
'--noinput'
))
sh
(
django_admin
(
system
,
'acceptance'
,
'migrate'
,
'--noinput'
))
sh
(
django_admin
(
system
,
'acceptance'
,
'harvest'
,
'--debug-mode'
,
'--tag -skip'
,
harvest_args
))
sh
(
django_admin
(
system
,
'acceptance'
,
'harvest'
,
'--debug-mode'
,
'--tag -skip'
,
harvest_args
))
...
...
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