Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 2 additions & 21 deletions cms/djangoapps/contentstore/management/commands/delete_course.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,8 @@
### Script for cloning a course
###
from django.core.management.base import BaseCommand, CommandError
from xmodule.modulestore.store_utilities import delete_course
from xmodule.modulestore.django import modulestore
from xmodule.contentstore.django import contentstore
from xmodule.course_module import CourseDescriptor
from .prompt import query_yes_no

from auth.authz import _delete_course_group
from contentstore.utils import delete_course_and_groups


#
Expand All @@ -30,20 +25,6 @@ def handle(self, *args, **options):
if commit:
print 'Actually going to delete the course from DB....'

ms = modulestore('direct')
cs = contentstore()

org, course_num, run = course_id.split("/")
ms.ignore_write_events_on_courses.append('{0}/{1}'.format(org, course_num))

if query_yes_no("Deleting course {0}. Confirm?".format(course_id), default="no"):
if query_yes_no("Are you sure. This action cannot be undone!", default="no"):
loc = CourseDescriptor.id_to_location(course_id)
if delete_course(ms, cs, loc, commit):
print 'removing User permissions from course....'
# in the django layer, we need to remove all the user permissions groups associated with this course
if commit:
try:
_delete_course_group(loc)
except Exception as err:
print("Error in deleting course groups for {0}: {1}".format(loc, err))
delete_course_and_groups(course_id, commit)
24 changes: 24 additions & 0 deletions cms/djangoapps/contentstore/tests/test_contentstore.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
from pymongo import MongoClient
from student.models import CourseEnrollment

from contentstore.utils import delete_course_and_groups

TEST_DATA_CONTENTSTORE = copy.deepcopy(settings.CONTENTSTORE)
TEST_DATA_CONTENTSTORE['OPTIONS']['db'] = 'test_xcontent_%s' % uuid4().hex

Expand Down Expand Up @@ -1292,6 +1294,28 @@ def test_create_course_check_forum_seeding(self):
test_course_data = self.assert_created_course(number_suffix=uuid4().hex)
self.assertTrue(are_permissions_roles_seeded(self._get_course_id(test_course_data)))

def test_forum_unseeding_on_delete(self):
"""Test new course creation and verify forum unseeding """

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment should be updated.

test_course_data = self.assert_created_course(number_suffix=uuid4().hex)
self.assertTrue(are_permissions_roles_seeded(self._get_course_id(test_course_data)))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this down and use course_id

course_id = self._get_course_id(test_course_data)
delete_course_and_groups(course_id, commit=True)
self.assertFalse(are_permissions_roles_seeded(course_id))

def test_forum_unseeding_with_multiple_courses(self):
"""Test new course creation and verify forum unseeding when there are multiple courses"""
test_course_data = self.assert_created_course(number_suffix=uuid4().hex)
second_course_data = self.assert_created_course(number_suffix=uuid4().hex)

# unseed the forums for the first course
course_id = self._get_course_id(test_course_data)
delete_course_and_groups(course_id, commit=True)
self.assertFalse(are_permissions_roles_seeded(course_id))

second_course_id = self._get_course_id(second_course_data)
# permissions should still be there for the other course
self.assertTrue(are_permissions_roles_seeded(second_course_id))

def _get_course_id(self, test_course_data):
"""Returns the course ID (org/number/run)."""
return "{org}/{number}/{run}".format(**test_course_data)
Expand Down
31 changes: 30 additions & 1 deletion cms/djangoapps/contentstore/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.contentstore.content import StaticContent
from django.core.urlresolvers import reverse
from xmodule.contentstore.django import contentstore
import copy
import logging
import re
from xmodule.modulestore.draft import DIRECT_ONLY_CATEGORIES
from django.utils.translation import ugettext as _
from django_comment_common.utils import unseed_permissions_roles
from auth.authz import _delete_course_group
from xmodule.modulestore.store_utilities import delete_course
from xmodule.course_module import CourseDescriptor

log = logging.getLogger(__name__)

Expand All @@ -20,6 +24,31 @@
EXTRA_TAB_PANELS = dict([(p['type'], p) for p in [OPEN_ENDED_PANEL, NOTES_PANEL]])


def delete_course_and_groups(course_id, commit=False):
"""
This deletes the courseware associated with a course_id as well as cleaning update_item
the various user table stuff (groups, permissions, etc.)
"""
module_store = modulestore('direct')
content_store = contentstore()

org, course_num, run = course_id.split("/")
module_store.ignore_write_events_on_courses.append('{0}/{1}'.format(org, course_num))

loc = CourseDescriptor.id_to_location(course_id)
if delete_course(module_store, content_store, loc, commit):
print 'removing forums permissions and roles...'
unseed_permissions_roles(course_id)

print 'removing User permissions from course....'
# in the django layer, we need to remove all the user permissions groups associated with this course
if commit:
try:
_delete_course_group(loc)
except Exception as err:
log.error("Error in deleting course groups for {0}: {1}".format(loc, err))


def get_modulestore(category_or_location):
"""
Returns the correct modulestore to use for modifying the specified location
Expand Down
24 changes: 23 additions & 1 deletion common/djangoapps/django_comment_common/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,30 @@ def seed_permissions_roles(course_id):
administrator_role.inherit_permissions(moderator_role)


def are_permissions_roles_seeded(course_id):
def _remove_permission_role(course_id, name):
try:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would create a helper function (defined within this one) that does

try:
if role.course_id == course_id:
role.delete()
except Role.DoesNotExist
pass

Then you can just call that function with each role type.

role = Role.objects.get(name=name, course_id=course_id)
if role.course_id == course_id:
role.delete()
except Role.DoesNotExist:
pass


def unseed_permissions_roles(course_id):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, this looks better! But (ducking...) can you also add a test for unseed_permissions_roles in isolation? It would be in the test file for django_comment_common/utils.py.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, I agree. But when I try to do this, I see that in django_comment_common/module.py, there's a dependency on a course to be in the modulestore (line 70) so that it can dereference course.forum_posts_allowed. I'm sure there's a way to get a course factory or something else in there, but I'd like to timebox this...

"""
A utility method to clean up all forum related permissions and roles
"""
_remove_permission_role(name="Administrator", course_id=course_id)
_remove_permission_role(name="Moderator", course_id=course_id)
_remove_permission_role(name="Community TA", course_id=course_id)
_remove_permission_role(name="Student", course_id=course_id)


def are_permissions_roles_seeded(course_id):
"""
Returns whether the forums permissions for a course have been provisioned in
the database
"""
try:
administrator_role = Role.objects.get(name="Administrator", course_id=course_id)
moderator_role = Role.objects.get(name="Moderator", course_id=course_id)
Expand Down