diff --git a/cms/djangoapps/auth/authz.py b/cms/djangoapps/auth/authz.py index e3d2e352a1..22bbc4bc1c 100644 --- a/cms/djangoapps/auth/authz.py +++ b/cms/djangoapps/auth/authz.py @@ -71,6 +71,23 @@ def _delete_course_group(location): user.groups.remove(staff) user.save() +''' +This is to be called only by either a command line code path or through an app which has already +asserted permissions to do this action +''' +def _copy_course_group(source, dest): + instructors = Group.objects.get(name=get_course_groupname_for_role(source, INSTRUCTOR_ROLE_NAME)) + new_instructors_group = Group.objects.get(name=get_course_groupname_for_role(dest, INSTRUCTOR_ROLE_NAME)) + for user in instructors.user_set.all(): + user.groups.add(new_instructors_group) + user.save() + + staff = Group.objects.get(name=get_course_groupname_for_role(source, STAFF_ROLE_NAME)) + new_staff_group = Group.objects.get(name=get_course_groupname_for_role(dest, STAFF_ROLE_NAME)) + for user in staff.user_set.all(): + user.groups.add(new_staff_group) + user.save() + def add_user_to_course_group(caller, user, location, role): # only admins can add/remove other users diff --git a/cms/djangoapps/contentstore/management/commands/clone.py b/cms/djangoapps/contentstore/management/commands/clone.py index 64cf4d4263..0f0f020599 100644 --- a/cms/djangoapps/contentstore/management/commands/clone.py +++ b/cms/djangoapps/contentstore/management/commands/clone.py @@ -8,6 +8,8 @@ from xmodule.contentstore.django import contentstore from xmodule.modulestore import Location from xmodule.course_module import CourseDescriptor +from auth.authz import _copy_course_group + # # To run from command line: rake cms:clone SOURCE_LOC=MITx/111/Foo1 DEST_LOC=MITx/135/Foo3 # @@ -18,14 +20,19 @@ class Command(BaseCommand): def handle(self, *args, **options): if len(args) != 2: - raise CommandError("clone requires two arguments: ") + raise CommandError("clone requires either two or six arguments: ") source_location_str = args[0] dest_location_str = args[1] + ms = modulestore('direct') + cs = contentstore() + print "Cloning course {0} to {1}".format(source_location_str, dest_location_str) source_location = CourseDescriptor.id_to_location(source_location_str) dest_location = CourseDescriptor.id_to_location(dest_location_str) - clone_course(modulestore('direct'), contentstore(), source_location, dest_location) + if clone_course(ms, cs, source_location, dest_location): + print "copying User permissions..." + _copy_course_group(source_location, dest_location) diff --git a/cms/djangoapps/contentstore/management/commands/delete_course.py b/cms/djangoapps/contentstore/management/commands/delete_course.py index 55c04bf5ea..0313f7faed 100644 --- a/cms/djangoapps/contentstore/management/commands/delete_course.py +++ b/cms/djangoapps/contentstore/management/commands/delete_course.py @@ -21,14 +21,18 @@ class Command(BaseCommand): def handle(self, *args, **options): if len(args) != 1: - raise CommandError("delete_course requires one arguments: ") + raise CommandError("delete_course requires one argument: ") loc_str = args[0] + ms = modulestore('direct') + cs = contentstore() + if query_yes_no("Deleting course {0}. Confirm?".format(loc_str), default="no"): if query_yes_no("Are you sure. This action cannot be undone!", default="no"): loc = CourseDescriptor.id_to_location(loc_str) - if delete_course(modulestore('direct'), contentstore(), loc) == True: + if delete_course(ms, cs, loc) == True: + print 'removing User permissions from course....' # in the django layer, we need to remove all the user permissions groups associated with this course _delete_course_group(loc) diff --git a/common/lib/xmodule/xmodule/contentstore/content.py b/common/lib/xmodule/xmodule/contentstore/content.py index 9badd4b892..b70ab5058f 100644 --- a/common/lib/xmodule/xmodule/contentstore/content.py +++ b/common/lib/xmodule/xmodule/contentstore/content.py @@ -18,7 +18,7 @@ class StaticContent(object): self.content_type = content_type self.data = data self.last_modified_at = last_modified_at - self.thumbnail_location = thumbnail_location + self.thumbnail_location = Location(thumbnail_location) @property def is_thumbnail(self): diff --git a/common/lib/xmodule/xmodule/contentstore/mongo.py b/common/lib/xmodule/xmodule/contentstore/mongo.py index 213beb140a..aebb6dfd32 100644 --- a/common/lib/xmodule/xmodule/contentstore/mongo.py +++ b/common/lib/xmodule/xmodule/contentstore/mongo.py @@ -47,7 +47,7 @@ class MongoContentStore(ContentStore): try: with self.fs.get(id) as fp: return StaticContent(location, fp.displayname, fp.content_type, fp.read(), - fp.uploadDate, thumbnail_location = fp.thumbnail_location if 'thumbnail_location' in fp else None) + fp.uploadDate, thumbnail_location = fp.thumbnail_location if hasattr(fp, 'thumbnail_location') else None) except NoFile: raise NotFoundError() diff --git a/common/lib/xmodule/xmodule/modulestore/store_utilities.py b/common/lib/xmodule/xmodule/modulestore/store_utilities.py index df89cbf41c..af346dbb7e 100644 --- a/common/lib/xmodule/xmodule/modulestore/store_utilities.py +++ b/common/lib/xmodule/xmodule/modulestore/store_utilities.py @@ -81,14 +81,15 @@ def clone_course(modulestore, contentstore, source_location, dest_location, dele # be sure to update the pointer to the thumbnail if content.thumbnail_location is not None: - content.thumbnail_location._replace(tag = dest_location.tag, org = dest_location.org, + content.thumbnail_location = content.thumbnail_location._replace(org = dest_location.org, course = dest_location.course) - print "Cloning asset {0} to {1}".format(asset_loc, content.location) contentstore.save(content) + return True + def delete_course(modulestore, contentstore, source_location): # first check to see if the modulestore is Mongo backed if not isinstance(modulestore, MongoModuleStore): diff --git a/rakefile b/rakefile index 9d3540ee8a..0d5ff5cf82 100644 --- a/rakefile +++ b/rakefile @@ -399,6 +399,7 @@ end namespace :cms do desc "Clone existing MongoDB based course" task :clone do + if ENV['SOURCE_LOC'] and ENV['DEST_LOC'] sh(django_admin(:cms, :dev, :clone, ENV['SOURCE_LOC'], ENV['DEST_LOC'])) else