def handle(self, *args, **options): if len(args) != 1 and len(args) != 2: raise CommandError( "delete_course requires one or more arguments: <course_id> |commit|" ) try: course_key = CourseKey.from_string(args[0]) except InvalidKeyError: course_key = SlashSeparatedCourseKey.from_deprecated_string( args[0]) commit = False if len(args) == 2: commit = args[1] == 'commit' if commit: print('Actually going to delete the course from DB....') if query_yes_no("Deleting course {0}. Confirm?".format(course_key), default="no"): if query_yes_no("Are you sure. This action cannot be undone!", default="no"): delete_course_and_groups( course_key, ModuleStoreEnum.UserID.mgmt_command)
def test_get_course_list_with_invalid_course_location(self): """ Test getting courses with invalid course location (course deleted from modulestore). """ course_key = self.store.make_course_key('Org', 'Course', 'Run') self._create_course_with_access_groups(course_key, self.user) # get courses through iterating all courses courses_list, __ = _accessible_courses_list(self.request) self.assertEqual(len(courses_list), 1) # get courses by reversing group name formats courses_list_by_groups, __ = _accessible_courses_list_from_groups( self.request) self.assertEqual(len(courses_list_by_groups), 1) # check both course lists have same courses self.assertEqual(courses_list, courses_list_by_groups) # now delete this course and re-add user to instructor group of this course delete_course_and_groups(course_key, self.user.id) CourseInstructorRole(course_key).add_users(self.user) # test that get courses through iterating all courses now returns no course courses_list, __ = _accessible_courses_list(self.request) self.assertEqual(len(courses_list), 0)
def test_get_course_list_with_invalid_course_location(self): """ Test getting courses with invalid course location (course deleted from modulestore). """ request = self.factory.get('/course') request.user = self.user course_key = SlashSeparatedCourseKey('Org', 'Course', 'Run') self._create_course_with_access_groups(course_key, self.user) # get courses through iterating all courses courses_list = _accessible_courses_list(request) self.assertEqual(len(courses_list), 1) # get courses by reversing group name formats courses_list_by_groups = _accessible_courses_list_from_groups(request) self.assertEqual(len(courses_list_by_groups), 1) # check both course lists have same courses self.assertEqual(courses_list, courses_list_by_groups) # now delete this course and re-add user to instructor group of this course delete_course_and_groups(course_key, commit=True) CourseInstructorRole(course_key).add_users(self.user) # test that get courses through iterating all courses now returns no course courses_list = _accessible_courses_list(request) self.assertEqual(len(courses_list), 0) # now test that get courses by reversing group name formats gives 'ItemNotFoundError' with self.assertRaises(ItemNotFoundError): _accessible_courses_list_from_groups(request)
def handle(self, *args, **options): if len(args) == 0: raise CommandError("Arguments missing: 'org/number/run commit'") if len(args) == 1: if args[0] == 'commit': raise CommandError("Delete_course requires a course_key <org/number/run> argument.") else: raise CommandError("Delete_course requires a commit argument at the end") elif len(args) == 2: try: course_key = CourseKey.from_string(args[0]) except InvalidKeyError: try: course_key = SlashSeparatedCourseKey.from_deprecated_string(args[0]) except InvalidKeyError: raise CommandError("Invalid course_key: '%s'. Proper syntax: 'org/number/run commit' " % args[0]) if args[1] != 'commit': raise CommandError("Delete_course requires a commit argument at the end") elif len(args) > 2: raise CommandError("Too many arguments! Expected <course_key> <commit>") if not modulestore().get_course(course_key): raise CommandError("Course with '%s' key not found." % args[0]) print 'Actually going to delete the %s course from DB....' % args[0] if query_yes_no("Deleting course {0}. Confirm?".format(course_key), default="no"): if query_yes_no("Are you sure. This action cannot be undone!", default="no"): delete_course_and_groups(course_key, ModuleStoreEnum.UserID.mgmt_command) print "Deleted course {}".format(course_key)
def delete_library_task(user_id, library_key_string): profile = UserProfile.objects.get(pk=user_id) user = User.objects.get(pk=profile.user_id) library_key = CourseKey.from_string(library_key_string) delete_course_and_groups(library_key, user.id)
def test_get_course_list_with_invalid_course_location(self): """ Test getting courses with invalid course location (course deleted from modulestore). """ course_key = SlashSeparatedCourseKey('Org', 'Course', 'Run') self._create_course_with_access_groups(course_key, self.user) # get courses through iterating all courses courses_list = _accessible_courses_list(self.request) self.assertEqual(len(courses_list), 1) # get courses by reversing group name formats courses_list_by_groups = _accessible_courses_list_from_groups(self.request) self.assertEqual(len(courses_list_by_groups), 1) # check both course lists have same courses self.assertEqual(courses_list, courses_list_by_groups) # now delete this course and re-add user to instructor group of this course delete_course_and_groups(course_key, commit=True) CourseInstructorRole(course_key).add_users(self.user) # test that get courses through iterating all courses now returns no course courses_list = _accessible_courses_list(self.request) self.assertEqual(len(courses_list), 0)
def test_get_course_list_with_same_course_id(self): """ Test getting courses with same id but with different name case. Then try to delete one of them and check that it is properly deleted and other one is accessible """ request = self.factory.get('/course') request.user = self.user course_location_caps = Location(['i4x', 'Org', 'COURSE', 'course', 'Run']) self._create_course_with_access_groups(course_location_caps, 'group_name_with_dots', self.user) # get courses through iterating all courses courses_list = _accessible_courses_list(request) self.assertEqual(len(courses_list), 1) # get courses by reversing group name formats courses_list_by_groups = _accessible_courses_list_from_groups(request) self.assertEqual(len(courses_list_by_groups), 1) # check both course lists have same courses self.assertEqual(courses_list, courses_list_by_groups) # now create another course with same course_id but different name case course_location_camel = Location(['i4x', 'Org', 'Course', 'course', 'Run']) self._create_course_with_access_groups(course_location_camel, 'group_name_with_dots', self.user) # test that get courses through iterating all courses returns both courses courses_list = _accessible_courses_list(request) self.assertEqual(len(courses_list), 2) # test that get courses by reversing group name formats returns only one course courses_list_by_groups = _accessible_courses_list_from_groups(request) self.assertEqual(len(courses_list_by_groups), 1) course_locator = loc_mapper().translate_location(course_location_caps.course_id, course_location_caps) outline_url = course_locator.url_reverse('course/') # now delete first course (course_location_caps) and check that it is no longer accessible delete_course_and_groups(course_location_caps.course_id, commit=True) # add user to this course instructor group since he was removed from that group on course delete instructor_group_name = CourseInstructorRole(course_locator)._group_names[0] # pylint: disable=protected-access group, __ = Group.objects.get_or_create(name=instructor_group_name) self.user.groups.add(group) # test that get courses through iterating all courses now returns one course courses_list = _accessible_courses_list(request) self.assertEqual(len(courses_list), 1) # test that get courses by reversing group name formats also returns one course courses_list_by_groups = _accessible_courses_list_from_groups(request) self.assertEqual(len(courses_list_by_groups), 1) # now check that deleted course in not accessible response = self.client.get(outline_url, HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, 403) # now check that other course in accessible course_locator = loc_mapper().translate_location(course_location_camel.course_id, course_location_camel) outline_url = course_locator.url_reverse('course/') response = self.client.get(outline_url, HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, 200)
def cm_course_delete(request, course_id = None): response_format = request.REQUEST.get('format','html') if response_format == 'json' or 'application/json' in request.META.get('HTTP/ACCEPT', 'application/json'): if request.method == 'POST': if validate_token(request.body, request) is False: log.warn("Unauthorized access made by course: %s, user: %s", request.json.get('email')) return HttpResponse('Unauthorized', status=401) email = request.json.get('email') try: instructor = User.objects.get(email = email) request.user = instructor except User.DoesNotExist: log.error("course deletion attempted by unregistered user: %s", email) return JsonResponse(json.dumps({ 'error': 'course deletion attempted by unregistered user' }), status = 400) if course_id is None: return JsonResponse(json.dumps({'error': 'Course ID does not exist'}), status = 404) try: course_key = CourseKey.from_string(course_id) except InvalidKeyError: try: course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id) except InvalidKeyError: course_key = None if course_key is None: return JsonResponse(json.dumps({'error': 'Course Key not found for course id: ' + str(course_id)}), status = 404) if not auth.has_access(instructor, CourseInstructorRole(course_key)): log.error("course deletion attempted by unauthorized user: %s", email) return JsonResponse(json.dumps({'error': 'course deletion attempted by unauthorized user'}), status = 401) try: delete_course_and_groups(course_key, instructor.id) try: StudentModule.objects.filter(course_id=course_key).delete() except: # We need this for testing. The above mentioned model lives in # LMS but our tests are executed via CMS. This piece of code # makes sure that the test safely skips over this and runs # successfully. pass CourseEnrollment.objects.filter(course_id=course_key).delete() try: CourseAccessRole.objects.get(course_id=course_key).delete() except CourseAccessRole.DoesNotExist: pass except Exception as e: return JsonResponse(json.dumps({'error' : str(e)}), status = 500) return JsonResponse(json.dumps({'message': "successfully deleted course"}), status = 200) else: return JsonResponse(json.dumps({}), status=404) else: return JsonResponse(content=json.dumps({}), status=404)
def test_get_course_list_with_same_course_id(self): """ Test getting courses with same id but with different name case. Then try to delete one of them and check that it is properly deleted and other one is accessible """ # create and log in a non-staff user self.user = UserFactory() request = self.factory.get('/course') request.user = self.user self.client.login(username=self.user.username, password='******') course_location_caps = SlashSeparatedCourseKey('Org', 'COURSE', 'Run') self._create_course_with_access_groups(course_location_caps, self.user) # get courses through iterating all courses courses_list = _accessible_courses_list(request) self.assertEqual(len(courses_list), 1) # get courses by reversing group name formats courses_list_by_groups = _accessible_courses_list_from_groups(request) self.assertEqual(len(courses_list_by_groups), 1) # check both course lists have same courses self.assertEqual(courses_list, courses_list_by_groups) # now create another course with same course_id but different name case course_location_camel = SlashSeparatedCourseKey('Org', 'Course', 'Run') self._create_course_with_access_groups(course_location_camel, self.user) # test that get courses through iterating all courses returns both courses courses_list = _accessible_courses_list(request) self.assertEqual(len(courses_list), 2) # test that get courses by reversing group name formats returns both courses courses_list_by_groups = _accessible_courses_list_from_groups(request) self.assertEqual(len(courses_list_by_groups), 2) # now delete first course (course_location_caps) and check that it is no longer accessible delete_course_and_groups(course_location_caps, commit=True) # test that get courses through iterating all courses now returns one course courses_list = _accessible_courses_list(request) self.assertEqual(len(courses_list), 1) # test that get courses by reversing group name formats also returns one course courses_list_by_groups = _accessible_courses_list_from_groups(request) self.assertEqual(len(courses_list_by_groups), 1) # now check that deleted course is not accessible outline_url = reverse_course_url('course_handler', course_location_caps) response = self.client.get(outline_url, HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, 403) # now check that other course is accessible outline_url = reverse_course_url('course_handler', course_location_camel) response = self.client.get(outline_url, HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, 200)
def test_get_course_list_with_invalid_course_location(self, store): """ Test getting courses with invalid course location (course deleted from modulestore). """ with self.store.default_store(store): course_key = self.store.make_course_key('Org', 'Course', 'Run') self._create_course_with_access_groups(course_key, self.user, store) # get courses through iterating all courses courses_list, __ = _accessible_courses_list(self.request) self.assertEqual(len(courses_list), 1) courses_summary_list, __ = _accessible_courses_summary_list( self.request) # Verify fetched accessible courses list is a list of CourseSummery instances and only one course # is returned self.assertTrue( all( isinstance(course, CourseSummary) for course in courses_summary_list)) self.assertEqual(len(courses_summary_list), 1) # get courses by reversing group name formats courses_list_by_groups, __ = _accessible_courses_list_from_groups( self.request) self.assertEqual(len(courses_list_by_groups), 1) # check course lists have same courses self.assertEqual(courses_list, courses_list_by_groups) # now delete this course and re-add user to instructor group of this course delete_course_and_groups(course_key, self.user.id) CourseInstructorRole(course_key).add_users(self.user) # Get courses through iterating all courses courses_list, __ = _accessible_courses_list(self.request) # Get course summaries by iterating all courses courses_summary_list, __ = _accessible_courses_summary_list( self.request) # Get courses by reversing group name formats courses_list_by_groups, __ = _accessible_courses_list_from_groups( self.request) # Test that course list returns no course self.assertEqual([ len(courses_list), len(courses_list_by_groups), len(courses_summary_list) ], [0, 0, 0])
def delete_course_task(user_id, course_key_string): profile = UserProfile.objects.get(pk=user_id) user = User.objects.get(pk=profile.user_id) course_key = CourseKey.from_string(course_key_string) delete_course_and_groups(course_key, user.id) searcher = SearchEngine.get_search_engine(CoursewareSearchIndexer.INDEX_NAME) if searcher != None: CoursewareSearchIndexer.remove_deleted_items(searcher, CourseKey.from_string(course_key_string), []) searcher.remove(CourseAboutSearchIndexer.DISCOVERY_DOCUMENT_TYPE, [course_key_string])
def handle(self, *args, **options): try: course_key = CourseKey.from_string(options['course_key']) except InvalidKeyError: raise CommandError("Invalid course_key: '%s'." % options['course_key']) if not modulestore().get_course(course_key): raise CommandError("Course with '%s' key not found." % options['course_key']) print 'Going to delete the %s course from DB....' % options['course_key'] if query_yes_no("Deleting course {0}. Confirm?".format(course_key), default="no"): if query_yes_no("Are you sure. This action cannot be undone!", default="no"): delete_course_and_groups(course_key, ModuleStoreEnum.UserID.mgmt_command) print "Deleted course {}".format(course_key)
def handle(self, *args, **options): try: course_key = CourseKey.from_string(options["course_key"]) except InvalidKeyError: raise CommandError("Invalid course_key: '%s'." % options["course_key"]) if not modulestore().get_course(course_key): raise CommandError("Course with '%s' key not found." % options["course_key"]) print "Going to delete the %s course from DB...." % options["course_key"] if query_yes_no("Deleting course {0}. Confirm?".format(course_key), default="no"): if query_yes_no("Are you sure. This action cannot be undone!", default="no"): delete_course_and_groups(course_key, ModuleStoreEnum.UserID.mgmt_command) print "Deleted course {}".format(course_key)
def test_get_course_list_with_same_course_id(self): """ Test getting courses with same id but with different name case. Then try to delete one of them and check that it is properly deleted and other one is accessible """ course_location_caps = SlashSeparatedCourseKey("Org", "COURSE", "Run") self._create_course_with_access_groups(course_location_caps, self.user) # get courses through iterating all courses courses_list = _accessible_courses_list(self.request) self.assertEqual(len(courses_list), 1) # get courses by reversing group name formats courses_list_by_groups = _accessible_courses_list_from_groups(self.request) self.assertEqual(len(courses_list_by_groups), 1) # check both course lists have same courses self.assertEqual(courses_list, courses_list_by_groups) # now create another course with same course_id but different name case course_location_camel = SlashSeparatedCourseKey("Org", "Course", "Run") self._create_course_with_access_groups(course_location_camel, self.user) # test that get courses through iterating all courses returns both courses courses_list = _accessible_courses_list(self.request) self.assertEqual(len(courses_list), 2) # test that get courses by reversing group name formats returns both courses courses_list_by_groups = _accessible_courses_list_from_groups(self.request) self.assertEqual(len(courses_list_by_groups), 2) # now delete first course (course_location_caps) and check that it is no longer accessible delete_course_and_groups(course_location_caps, self.user.id) # test that get courses through iterating all courses now returns one course courses_list = _accessible_courses_list(self.request) self.assertEqual(len(courses_list), 1) # test that get courses by reversing group name formats also returns one course courses_list_by_groups = _accessible_courses_list_from_groups(self.request) self.assertEqual(len(courses_list_by_groups), 1) # now check that deleted course is not accessible outline_url = reverse_course_url("course_handler", course_location_caps) response = self.client.get(outline_url, HTTP_ACCEPT="application/json") self.assertEqual(response.status_code, 403) # now check that other course is accessible outline_url = reverse_course_url("course_handler", course_location_camel) response = self.client.get(outline_url, HTTP_ACCEPT="application/json") self.assertEqual(response.status_code, 200)
def handle(self, *args, **options): if len(args) != 1 and len(args) != 2: raise CommandError("delete_course requires one or more arguments: <location> |commit|") course_id = args[0] commit = False if len(args) == 2: commit = args[1] == 'commit' if commit: print 'Actually going to delete the course from DB....' 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"): delete_course_and_groups(course_id, commit)
def test_user_role_on_course_recreate_with_change_name_case(self): """ Test that creating same course again with different name case after deleting it gives user his default forum role "Student" for that course """ # check that user has enrollment and his default "Student" forum role for this course self.assertTrue(CourseEnrollment.is_enrolled(self.user, self.course_key)) # delete this course and recreate this course with same user delete_course_and_groups(self.course_key, self.user.id) # now create same course with different name case ('uppercase') new_course_key = self.course_key.replace(course=self.course_key.course.upper()) resp = self._create_course_with_given_location(new_course_key) self.assertEqual(resp.status_code, 200) # check that user has his default "Student" forum role again for this course (with changed name case) self.assertTrue(self.user.roles.filter(name="Student", course_id=new_course_key)) # pylint: disable=no-member
def test_get_course_list_with_invalid_course_location(self, store): """ Test getting courses with invalid course location (course deleted from modulestore). """ with self.store.default_store(store): course_key = self.store.make_course_key('Org', 'Course', 'Run') self._create_course_with_access_groups(course_key, self.user, store) # get courses through iterating all courses courses_list, __ = _accessible_courses_list(self.request) self.assertEqual(len(courses_list), 1) courses_summary_list, __ = _accessible_courses_summary_list(self.request) # Verify fetched accessible courses list is a list of CourseSummery instances and only one course # is returned self.assertTrue(all(isinstance(course, CourseSummary) for course in courses_summary_list)) self.assertEqual(len(courses_summary_list), 1) # get courses by reversing group name formats courses_list_by_groups, __ = _accessible_courses_list_from_groups(self.request) self.assertEqual(len(courses_list_by_groups), 1) # check course lists have same courses self.assertEqual(courses_list, courses_list_by_groups) # now delete this course and re-add user to instructor group of this course delete_course_and_groups(course_key, self.user.id) CourseInstructorRole(course_key).add_users(self.user) # Get courses through iterating all courses courses_list, __ = _accessible_courses_list(self.request) # Get course summaries by iterating all courses courses_summary_list, __ = _accessible_courses_summary_list(self.request) # Get courses by reversing group name formats courses_list_by_groups, __ = _accessible_courses_list_from_groups(self.request) # Test that course list returns no course self.assertEqual( [len(courses_list), len(courses_list_by_groups), len(courses_summary_list)], [0, 0, 0] )
def test_user_forum_default_role_on_course_deletion(self): """ Test that a user enrolls and gets "Student" forum role for that course which he creates and remains enrolled even the course is deleted and keeps its "Student" forum role for that course """ # check that user has enrollment for this course self.assertTrue(CourseEnrollment.is_enrolled(self.user, self.course_key)) # check that user has his default "Student" forum role for this course self.assertTrue(self.user.roles.filter(name="Student", course_id=self.course_key)) # pylint: disable=no-member delete_course_and_groups(self.course_key, self.user.id) # check that user's enrollment for this course is not deleted self.assertTrue(CourseEnrollment.is_enrolled(self.user, self.course_key)) # check that user has forum role for this course even after deleting it self.assertTrue(self.user.roles.filter(name="Student", course_id=self.course_key)) # pylint: disable=no-member
def test_user_forum_default_role_on_course_deletion(self): """ Test that a user enrolls and gets "Student" forum role for that course which he creates and remains enrolled even the course is deleted and keeps its "Student" forum role for that course """ course_id = self.course_location.course_id # check that user has enrollment for this course self.assertTrue(CourseEnrollment.is_enrolled(self.user, course_id)) # check that user has his default "Student" forum role for this course self.assertTrue(self.user.roles.filter(name="Student", course_id=course_id)) # pylint: disable=no-member delete_course_and_groups(course_id, commit=True) # check that user's enrollment for this course is not deleted self.assertTrue(CourseEnrollment.is_enrolled(self.user, course_id)) # check that user has forum role for this course even after deleting it self.assertTrue(self.user.roles.filter(name="Student", course_id=course_id)) # pylint: disable=no-member
def delete_temp_user_task(request, user_id): profile = UserProfile.objects.get(pk=user_id) user = User.objects.get(pk=profile.user_id) courses = [format_course_for_view(c) for c in get_courses_accessible_to_user(request, user)[0]] libraries = [format_library_for_view(lib, user) for lib in accessible_libraries_list(user)] for course in courses: course_key = CourseKey.from_string(course["course_key"]) delete_course_and_groups(course_key, user.id) searcher = SearchEngine.get_search_engine(CoursewareSearchIndexer.INDEX_NAME) if searcher != None: CoursewareSearchIndexer.remove_deleted_items(searcher, CourseKey.from_string(course_key_string), []) searcher.remove(CourseAboutSearchIndexer.DISCOVERY_DOCUMENT_TYPE, [course_key_string]) for library in libraries: library_key = CourseKey.from_string(library['library_key']) delete_course_and_groups(library_key, user.id)
def handle(self, *args, **options): if len(args) != 1 and len(args) != 2: raise CommandError("delete_course requires one or more arguments: <course_id> |commit|") try: course_key = CourseKey.from_string(args[0]) except InvalidKeyError: course_key = SlashSeparatedCourseKey.from_deprecated_string(args[0]) commit = False if len(args) == 2: commit = args[1] == 'commit' if commit: print('Actually going to delete the course from DB....') if query_yes_no("Deleting course {0}. Confirm?".format(course_key), default="no"): if query_yes_no("Are you sure. This action cannot be undone!", default="no"): delete_course_and_groups(course_key, commit)
def test_user_role_on_course_recreate(self): """ Test that creating same course again after deleting it gives user his default forum role "Student" for that course """ # check that user has enrollment and his default "Student" forum role for this course self.assertTrue(CourseEnrollment.is_enrolled(self.user, self.course_key)) self.assertTrue(self.user.roles.filter(name="Student", course_id=self.course_key)) # pylint: disable=no-member # delete this course and recreate this course with same user delete_course_and_groups(self.course_key, self.user.id) resp = self._create_course_with_given_location(self.course_key) self.assertEqual(resp.status_code, 200) # check that user has his enrollment for this course self.assertTrue(CourseEnrollment.is_enrolled(self.user, self.course_key)) # check that user has his default "Student" forum role for this course self.assertTrue(self.user.roles.filter(name="Student", course_id=self.course_key)) # pylint: disable=no-member
def handle(self, *args, **options): if len(args) == 0: raise CommandError("Arguments missing: 'org/number/run commit'") if len(args) == 1: if args[0] == 'commit': raise CommandError( "Delete_course requires a course_key <org/number/run> argument." ) else: raise CommandError( "Delete_course requires a commit argument at the end") elif len(args) == 2: try: course_key = CourseKey.from_string(args[0]) except InvalidKeyError: try: course_key = SlashSeparatedCourseKey.from_deprecated_string( args[0]) except InvalidKeyError: raise CommandError( "Invalid course_key: '%s'. Proper syntax: 'org/number/run commit' " % args[0]) if args[1] != 'commit': raise CommandError( "Delete_course requires a commit argument at the end") elif len(args) > 2: raise CommandError( "Too many arguments! Expected <course_key> <commit>") print_out_all_courses() if not modulestore().get_course(course_key): raise CommandError("Course with '%s' key not found." % args[0]) print 'Actually going to delete the %s course from DB....' % args[0] if query_yes_no("Deleting course {0}. Confirm?".format(course_key), default="no"): if query_yes_no("Are you sure. This action cannot be undone!", default="no"): delete_course_and_groups(course_key, ModuleStoreEnum.UserID.mgmt_command) print_out_all_courses()
def test_user_role_on_course_recreate(self): """ Test that creating same course again after deleting it gives user his default forum role "Student" for that course """ course_id = self.course_location.course_id # check that user has enrollment and his default "Student" forum role for this course self.assertTrue(CourseEnrollment.is_enrolled(self.user, course_id)) self.assertTrue(self.user.roles.filter(name="Student", course_id=course_id)) # pylint: disable=no-member # delete this course and recreate this course with same user delete_course_and_groups(course_id, commit=True) resp = self._create_course_with_given_location(self.course_location) self.assertEqual(resp.status_code, 200) # check that user has his enrollment for this course self.assertTrue(CourseEnrollment.is_enrolled(self.user, course_id)) # check that user has his default "Student" forum role for this course self.assertTrue(self.user.roles.filter(name="Student", course_id=course_id)) # pylint: disable=no-member
def test_user_role_on_course_recreate_with_change_name_case(self): """ Test that creating same course again with different name case after deleting it gives user his default forum role "Student" for that course """ # check that user has enrollment and his default "Student" forum role for this course self.assertTrue( CourseEnrollment.is_enrolled(self.user, self.course_key)) # delete this course and recreate this course with same user delete_course_and_groups(self.course_key, self.user.id) # now create same course with different name case ('uppercase') new_course_key = self.course_key.replace( course=self.course_key.course.upper()) resp = self._create_course_with_given_location(new_course_key) self.assertEqual(resp.status_code, 200) # check that user has his default "Student" forum role again for this course (with changed name case) self.assertTrue( self.user.roles.filter(name="Student", course_id=new_course_key))
def handle(self, *args, **options): if len(args) != 1 and len(args) != 2: raise CommandError( "delete_course requires one or more arguments: <location> |commit|" ) course_id = args[0] commit = False if len(args) == 2: commit = args[1] == 'commit' if commit: print('Actually going to delete the course from DB....') 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"): delete_course_and_groups(course_id, commit)
def test_get_course_list_with_invalid_course_location(self): """ Test getting courses with invalid course location (course deleted from modulestore but location exists in loc_mapper). """ request = self.factory.get('/course') request.user = self.user course_location = Location('i4x', 'Org', 'Course', 'course', 'Run') self._create_course_with_access_groups(course_location, 'group_name_with_dots', self.user) # get courses through iterating all courses courses_list = _accessible_courses_list(request) self.assertEqual(len(courses_list), 1) # get courses by reversing group name formats courses_list_by_groups = _accessible_courses_list_from_groups(request) self.assertEqual(len(courses_list_by_groups), 1) # check both course lists have same courses self.assertEqual(courses_list, courses_list_by_groups) # now delete this course and re-add user to instructor group of this course delete_course_and_groups(course_location.course_id, commit=True) course_locator = loc_mapper().translate_location( course_location.course_id, course_location) instructor_group_name = CourseInstructorRole( course_locator)._group_names[0] # pylint: disable=protected-access group, __ = Group.objects.get_or_create(name=instructor_group_name) self.user.groups.add(group) # test that get courses through iterating all courses now returns no course courses_list = _accessible_courses_list(request) self.assertEqual(len(courses_list), 0) # now test that get courses by reversing group name formats gives 'ItemNotFoundError' with self.assertRaises(ItemNotFoundError): _accessible_courses_list_from_groups(request)
def test_user_role_on_course_recreate_with_change_name_case(self): """ Test that creating same course again with different name case after deleting it gives user his default forum role "Student" for that course """ course_location = self.course_location # check that user has enrollment and his default "Student" forum role for this course self.assertTrue(CourseEnrollment.is_enrolled(self.user, course_location.course_id)) # delete this course and recreate this course with same user delete_course_and_groups(course_location.course_id, commit=True) # now create same course with different name case ('uppercase') new_course_location = Location( ['i4x', course_location.org, course_location.course.upper(), 'course', course_location.name] ) resp = self._create_course_with_given_location(new_course_location) self.assertEqual(resp.status_code, 200) # check that user has his default "Student" forum role again for this course (with changed name case) self.assertTrue( self.user.roles.filter(name="Student", course_id=new_course_location.course_id) # pylint: disable=no-member )
def test_user_forum_default_role_on_course_deletion(self): """ Test that a user enrolls and gets "Student" forum role for that course which he creates and remains enrolled even the course is deleted and keeps its "Student" forum role for that course """ # check that user has enrollment for this course self.assertTrue( CourseEnrollment.is_enrolled(self.user, self.course_key)) # check that user has his default "Student" forum role for this course self.assertTrue( self.user.roles.filter(name="Student", course_id=self.course_key)) delete_course_and_groups(self.course_key, self.user.id) # check that user's enrollment for this course is not deleted self.assertTrue( CourseEnrollment.is_enrolled(self.user, self.course_key)) # check that user has forum role for this course even after deleting it self.assertTrue( self.user.roles.filter(name="Student", course_id=self.course_key))
def test_get_course_list_with_invalid_course_location(self): """ Test getting courses with invalid course location (course deleted from modulestore but location exists in loc_mapper). """ request = self.factory.get('/course') request.user = self.user course_location = Location('i4x', 'Org', 'Course', 'course', 'Run') self._create_course_with_access_groups(course_location, 'group_name_with_dots', self.user) # get courses through iterating all courses courses_list = _accessible_courses_list(request) self.assertEqual(len(courses_list), 1) # get courses by reversing group name formats courses_list_by_groups = _accessible_courses_list_from_groups(request) self.assertEqual(len(courses_list_by_groups), 1) # check both course lists have same courses self.assertEqual(courses_list, courses_list_by_groups) # now delete this course and re-add user to instructor group of this course delete_course_and_groups(course_location.course_id, commit=True) course_locator = loc_mapper().translate_location(course_location.course_id, course_location) instructor_group_name = CourseInstructorRole(course_locator)._group_names[0] # pylint: disable=protected-access group, __ = Group.objects.get_or_create(name=instructor_group_name) self.user.groups.add(group) # test that get courses through iterating all courses now returns no course courses_list = _accessible_courses_list(request) self.assertEqual(len(courses_list), 0) # now test that get courses by reversing group name formats gives 'ItemNotFoundError' with self.assertRaises(ItemNotFoundError): _accessible_courses_list_from_groups(request)
def test_get_course_list_with_same_course_id(self): """ Test getting courses with same id but with different name case. Then try to delete one of them and check that it is properly deleted and other one is accessible """ # create and log in a non-staff user self.user = UserFactory() request = self.factory.get('/course') request.user = self.user self.client.login(username=self.user.username, password='******') course_location_caps = Location( ['i4x', 'Org', 'COURSE', 'course', 'Run']) self._create_course_with_access_groups(course_location_caps, 'group_name_with_dots', self.user) # get courses through iterating all courses courses_list = _accessible_courses_list(request) self.assertEqual(len(courses_list), 1) # get courses by reversing group name formats courses_list_by_groups = _accessible_courses_list_from_groups(request) self.assertEqual(len(courses_list_by_groups), 1) # check both course lists have same courses self.assertEqual(courses_list, courses_list_by_groups) # now create another course with same course_id but different name case course_location_camel = Location( ['i4x', 'Org', 'Course', 'course', 'Run']) self._create_course_with_access_groups(course_location_camel, 'group_name_with_dots', self.user) # test that get courses through iterating all courses returns both courses courses_list = _accessible_courses_list(request) self.assertEqual(len(courses_list), 2) # test that get courses by reversing group name formats returns only one course courses_list_by_groups = _accessible_courses_list_from_groups(request) self.assertEqual(len(courses_list_by_groups), 1) course_locator = loc_mapper().translate_location( course_location_caps.course_id, course_location_caps) outline_url = course_locator.url_reverse('course/') # now delete first course (course_location_caps) and check that it is no longer accessible delete_course_and_groups(course_location_caps.course_id, commit=True) # add user to this course instructor group since he was removed from that group on course delete instructor_group_name = CourseInstructorRole( course_locator)._group_names[0] # pylint: disable=protected-access group, __ = Group.objects.get_or_create(name=instructor_group_name) self.user.groups.add(group) # test viewing the index page which creates missing courses loc_map entries resp = self.client.get_html('/course') self.assertContains(resp, '<h1 class="page-header">My Courses</h1>', status_code=200, html=True) # test that get courses through iterating all courses now returns one course courses_list = _accessible_courses_list(request) self.assertEqual(len(courses_list), 1) # test that get courses by reversing group name formats also returns one course courses_list_by_groups = _accessible_courses_list_from_groups(request) self.assertEqual(len(courses_list_by_groups), 1) # now check that deleted course in not accessible response = self.client.get(outline_url, HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, 403) # now check that other course in accessible course_locator = loc_mapper().translate_location( course_location_camel.course_id, course_location_camel) outline_url = course_locator.url_reverse('course/') response = self.client.get(outline_url, HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, 200)