Example #1
0
def get_aggregate_exclusion_user_ids(course_key, roles=None):  # pylint: disable=invalid-name
    """
    This helper method will return the list of user ids that are marked in roles
    that can be excluded from certain aggregate queries. The list of roles to exclude
    can either be passed in roles argument or defined in a AGGREGATION_EXCLUDE_ROLES settings variable.
    """

    cache_key = get_cache_key('exclude_users',
                              unicode(course_key) + '_'.join(roles or 'None'))
    cached_data = cache.get(cache_key)
    if cached_data is not None:
        return cached_data
    exclude_user_ids = set()
    exclude_role_list = roles or getattr(settings, 'AGGREGATION_EXCLUDE_ROLES',
                                         [CourseStaffRole.ROLE])

    for role in exclude_role_list:
        users = CourseRole(role, course_key).users_with_role()
        user_ids = set()
        for user in users:
            user_ids.add(user.id)

        exclude_user_ids = exclude_user_ids.union(user_ids)

    cache.set(cache_key, exclude_user_ids, 60 * 60)
    return exclude_user_ids
Example #2
0
    def test_group_name_case_insensitive(self):
        uppercase_loc = "i4x://ORG/COURSE/course/NAME"
        lowercase_loc = uppercase_loc.lower()

        lowercase_group = "role_org/course/name"
        uppercase_group = lowercase_group.upper()

        lowercase_user = UserFactory(groups=lowercase_group)
        uppercase_user = UserFactory(groups=uppercase_group)

        self.assertTrue(
            CourseRole("role", lowercase_loc).has_user(lowercase_user))
        self.assertTrue(
            CourseRole("role", uppercase_loc).has_user(lowercase_user))
        self.assertTrue(
            CourseRole("role", lowercase_loc).has_user(uppercase_user))
        self.assertTrue(
            CourseRole("role", uppercase_loc).has_user(uppercase_user))
Example #3
0
    def check(self, user, instance=None):
        if not user.is_authenticated:
            return False
        if isinstance(instance, CourseKey):
            course_key = instance
        elif isinstance(instance, (CourseDescriptor, CourseOverview)):
            course_key = instance.id
        elif isinstance(instance, (ErrorDescriptor, XModule, XBlock)):
            course_key = instance.scope_ids.usage_id.course_key
        else:
            course_key = CourseKey.from_string(str(instance))

        for role in self.roles:
            if CourseRole(role, course_key).has_user(user):
                return True
            if OrgRole(role, course_key.org).has_user(user):
                return True
        return False
Example #4
0
def get_master_course(user=None, command=None):
    from contentstore.utils import add_instructor, initialize_permissions
    from courseware.courses import get_course_by_id
    from opaque_keys.edx.locations import SlashSeparatedCourseKey
    from student.roles import CourseRole
    from xmodule.modulestore.exceptions import InvalidLocationError

    if not user:
        user = User.objects.get(id=ADMIN_USER_ID)

    display_name = "LabsterX Master"
    org, number, run = COURSE_ID.split('/')

    try:
        course_key = SlashSeparatedCourseKey(org, number, run)
        fields = {'display_name': display_name}

        wiki_slug = u"{0}.{1}.{2}".format(course_key.org, course_key.course, course_key.run)
        definition_data = {'wiki_slug': wiki_slug}
        fields.update(definition_data)

        if CourseRole.course_group_already_exists(course_key):
            raise InvalidLocationError()

        course = get_modulestore().create_course(
            course_key.org,
            course_key.course,
            course_key.run,
            user.id,
            fields=fields,
        )

        # Make sure user has instructor and staff access to the new course
        add_instructor(course.id, user, user)

        # Initialize permissions for user in the new course
        initialize_permissions(course.id, user)
        command and command.stdout.write("name: {}\n".format(course.display_name))

    except InvalidLocationError:
        course = get_course_by_id(course_key)

    return course
Example #5
0
    def test_group_name_case_sensitive(self):
        uppercase_course_id = "ORG/COURSE/NAME"
        lowercase_course_id = uppercase_course_id.lower()
        uppercase_course_key = SlashSeparatedCourseKey.from_deprecated_string(uppercase_course_id)
        lowercase_course_key = SlashSeparatedCourseKey.from_deprecated_string(lowercase_course_id)

        role = "role"

        lowercase_user = UserFactory()
        CourseRole(role, lowercase_course_key).add_users(lowercase_user)
        uppercase_user = UserFactory()
        CourseRole(role, uppercase_course_key).add_users(uppercase_user)

        self.assertTrue(CourseRole(role, lowercase_course_key).has_user(lowercase_user))
        self.assertFalse(CourseRole(role, uppercase_course_key).has_user(lowercase_user))
        self.assertFalse(CourseRole(role, lowercase_course_key).has_user(uppercase_user))
        self.assertTrue(CourseRole(role, uppercase_course_key).has_user(uppercase_user))
Example #6
0
def get_or_create_course(source, target, user):
    source_course = get_course_by_id(SlashSeparatedCourseKey.from_deprecated_string(source))

    display_name = source_course.display_name
    org, number, run = target.split('/')

    course_key = SlashSeparatedCourseKey(org, number, run)
    fields = {'display_name': display_name}

    wiki_slug = u"{0}.{1}.{2}".format(course_key.org, course_key.course, course_key.run)
    definition_data = {'wiki_slug': wiki_slug}
    fields.update(definition_data)

    try:
        if CourseRole.course_group_already_exists(course_key):
            raise InvalidLocationError()

        course = modulestore().create_course(
            course_key.org,
            course_key.course,
            course_key.run,
            user.id,
            fields=fields,
        )

    except InvalidLocationError:
        course = get_course(course_key)

    else:
        # Make sure user has instructor and staff access to the new course
        add_instructor(course.id, user, user)

        # Initialize permissions for user in the new course
        initialize_permissions(course.id, user)

    return course
Example #7
0
def create_new_course(request):
    """
    Create a new course.

    Returns the URL for the course overview page.
    """
    if not auth.has_access(request.user, CourseCreatorRole()):
        raise PermissionDenied()

    org = request.json.get('org')
    number = request.json.get('number')
    display_name = request.json.get('display_name')
    run = request.json.get('run')

    # allow/disable unicode characters in course_id according to settings
    if not settings.FEATURES.get('ALLOW_UNICODE_COURSE_ID'):
        if _has_non_ascii_characters(org) or _has_non_ascii_characters(number) or _has_non_ascii_characters(run):
            return JsonResponse(
                {'error': _('Special characters not allowed in organization, course number, and course run.')},
                status=400
            )

    try:
        course_key = SlashSeparatedCourseKey(org, number, run)

        # instantiate the CourseDescriptor and then persist it
        # note: no system to pass
        if display_name is None:
            metadata = {}
        else:
            metadata = {'display_name': display_name}

        # Set a unique wiki_slug for newly created courses. To maintain active wiki_slugs for
        # existing xml courses this cannot be changed in CourseDescriptor.
        # # TODO get rid of defining wiki slug in this org/course/run specific way and reconcile
        # w/ xmodule.course_module.CourseDescriptor.__init__
        wiki_slug = u"{0}.{1}.{2}".format(course_key.org, course_key.course, course_key.run)
        definition_data = {'wiki_slug': wiki_slug}

        # Create the course then fetch it from the modulestore
        # Check if role permissions group for a course named like this already exists
        # Important because role groups are case insensitive
        if CourseRole.course_group_already_exists(course_key):
            raise InvalidLocationError()

        fields = {}
        fields.update(definition_data)
        fields.update(metadata)

        # Creating the course raises InvalidLocationError if an existing course with this org/name is found
        new_course = modulestore('direct').create_course(
            course_key.org,
            course_key.offering,
            fields=fields,
        )

        # can't use auth.add_users here b/c it requires request.user to already have Instructor perms in this course
        # however, we can assume that b/c this user had authority to create the course, the user can add themselves
        CourseInstructorRole(new_course.id).add_users(request.user)
        auth.add_users(request.user, CourseStaffRole(new_course.id), request.user)

        # seed the forums
        seed_permissions_roles(new_course.id)

        # auto-enroll the course creator in the course so that "View Live" will
        # work.
        CourseEnrollment.enroll(request.user, new_course.id)
        _users_assign_default_role(new_course.id)

        return JsonResponse({
            'url': reverse_course_url('course_handler', new_course.id)
        })

    except InvalidLocationError:
        return JsonResponse({
            'ErrMsg': _(
                'There is already a course defined with the same '
                'organization, course number, and course run. Please '
                'change either organization or course number to be unique.'
            ),
            'OrgErrMsg': _(
                'Please change either the organization or '
                'course number so that it is unique.'),
            'CourseErrMsg': _(
                'Please change either the organization or '
                'course number so that it is unique.'),
        })
    except InvalidKeyError as error:
        return JsonResponse({
            "ErrMsg": _("Unable to create course '{name}'.\n\n{err}").format(name=display_name, err=error.message)}
        )
Example #8
0
def create_new_course(request):
    """
    Create a new course.

    Returns the URL for the course overview page.
    """
    if not auth.has_access(request.user, CourseCreatorRole()):
        raise PermissionDenied()

    org = request.json.get('org')
    number = request.json.get('number')
    display_name = request.json.get('display_name')
    run = request.json.get('run')

    # allow/disable unicode characters in course_id according to settings
    if not settings.FEATURES.get('ALLOW_UNICODE_COURSE_ID'):
        if _has_non_ascii_characters(org) or _has_non_ascii_characters(
                number) or _has_non_ascii_characters(run):
            return JsonResponse(
                {
                    'error':
                    _('Special characters not allowed in organization, course number, and course run.'
                      )
                },
                status=400)

    try:
        course_key = SlashSeparatedCourseKey(org, number, run)

        # instantiate the CourseDescriptor and then persist it
        # note: no system to pass
        if display_name is None:
            metadata = {}
        else:
            metadata = {'display_name': display_name}

        # Set a unique wiki_slug for newly created courses. To maintain active wiki_slugs for
        # existing xml courses this cannot be changed in CourseDescriptor.
        # # TODO get rid of defining wiki slug in this org/course/run specific way and reconcile
        # w/ xmodule.course_module.CourseDescriptor.__init__
        wiki_slug = u"{0}.{1}.{2}".format(course_key.org, course_key.course,
                                          course_key.run)
        definition_data = {'wiki_slug': wiki_slug}

        # Create the course then fetch it from the modulestore
        # Check if role permissions group for a course named like this already exists
        # Important because role groups are case insensitive
        if CourseRole.course_group_already_exists(course_key):
            raise InvalidLocationError()

        fields = {}
        fields.update(definition_data)
        fields.update(metadata)

        # Creating the course raises InvalidLocationError if an existing course with this org/name is found
        new_course = modulestore('direct').create_course(
            course_key.org,
            course_key.offering,
            fields=fields,
        )

        # can't use auth.add_users here b/c it requires request.user to already have Instructor perms in this course
        # however, we can assume that b/c this user had authority to create the course, the user can add themselves
        CourseInstructorRole(new_course.id).add_users(request.user)
        auth.add_users(request.user, CourseStaffRole(new_course.id),
                       request.user)

        # seed the forums
        seed_permissions_roles(new_course.id)

        # auto-enroll the course creator in the course so that "View Live" will
        # work.
        CourseEnrollment.enroll(request.user, new_course.id)
        _users_assign_default_role(new_course.id)

        return JsonResponse(
            {'url': reverse_course_url('course_handler', new_course.id)})

    except InvalidLocationError:
        return JsonResponse({
            'ErrMsg':
            _('There is already a course defined with the same '
              'organization, course number, and course run. Please '
              'change either organization or course number to be unique.'),
            'OrgErrMsg':
            _('Please change either the organization or '
              'course number so that it is unique.'),
            'CourseErrMsg':
            _('Please change either the organization or '
              'course number so that it is unique.'),
        })
    except InvalidKeyError as error:
        return JsonResponse({
            "ErrMsg":
            _("Unable to create course '{name}'.\n\n{err}").format(
                name=display_name, err=error.message)
        })
Example #9
0
def force_create_course(source, target, user, extra_fields=None):
    source_course_key = SlashSeparatedCourseKey.from_deprecated_string(source)
    source_course = get_course_by_id(source_course_key)
    display_name = source_course.display_name

    fields = {'display_name': display_name}
    # duplicated_fields = [
    #     'key_dates', 'video',
    #     'course_staff_short', 'course_staff_extended',
    #     'requirements', 'textbook', 'faq', 'more_info',
    #     'number', 'instructors', 'end_date',
    #     'prerequisites', 'ocw_links',
    # ]

    # for field in duplicated_fields:
    #     fields[field] = getattr(source_course, field)

    course = None
    start_index = 0
    org, original_number, run = target.split('/')

    number = original_number
    while course is None:
        course_key = SlashSeparatedCourseKey(org, number, run)

        wiki_slug = u"{0}.{1}.{2}".format(course_key.org, course_key.course, course_key.run)
        definition_data = {'wiki_slug': wiki_slug}
        fields.update(definition_data)
        if extra_fields:
            fields.update(extra_fields)

        try:
            if CourseRole.course_group_already_exists(course_key):
                raise InvalidLocationError()

            course = modulestore().create_course(
                course_key.org,
                course_key.course,
                course_key.run,
                user.id,
                fields=fields,
            )

        except InvalidLocationError:
            start_index += 1
            number = "{}{}".format(original_number, start_index)
            continue

        else:
            # Make sure user has instructor and staff access to the new course
            add_instructor(course.id, user, user)

            # Initialize permissions for user in the new course
            initialize_permissions(course.id, user)

    copy_about_fields(user, source_course_key, course_key, course)

    UserProfile.objects\
        .filter(user_id=user.id)\
        .exclude(user_type=UserProfile.USER_TYPE_TEACHER)\
        .update(user_type=UserProfile.USER_TYPE_TEACHER)

    return course