Example #1
0
    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)
Example #2
0
    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)
Example #5
0
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)
Example #6
0
    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)
Example #8
0
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])
Example #11
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])
Example #12
0
    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)
Example #13
0
    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)
Example #15
0
    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
Example #19
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
        """
        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
Example #20
0
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)
Example #21
0
    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
Example #23
0
    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()
Example #24
0
    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))
Example #26
0
    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)
Example #28
0
    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)