Example #1
0
    def enabled_for_course(cls, course_key, target_datetime=None):
        """
        Return whether Course Duration Limits are enabled for this course as of a particular date.

        Course Duration Limits are enabled for a course on a date if they are enabled either specifically,
        or via a containing context, such as the org, site, or globally, and if the configuration
        is specified to be ``enabled_as_of`` before ``target_datetime``.

        Only one of enrollment and (user, course_key) may be specified at a time.

        Arguments:
            course_key: The CourseKey of the course being queried.
            target_datetime: The datetime to checked enablement as of. Defaults to the current date and time.
        """

        if FEATURE_BASED_ENROLLMENT_GLOBAL_KILL_FLAG.is_enabled():
            return False

        if CONTENT_TYPE_GATING_FLAG.is_enabled():
            return True

        if target_datetime is None:
            target_datetime = timezone.now()

        current_config = cls.current(course_key=course_key)
        return current_config.enabled_as_of_datetime(target_datetime=target_datetime)
Example #2
0
    def enabled_as_of_datetime(self, target_datetime):
        """
        Return whether this Course Duration Limit configuration context is enabled as of a date and time.

        Arguments:
            target_datetime (:class:`datetime.datetime`): The datetime that ``enabled_as_of`` must be equal to or before
        """

        if FEATURE_BASED_ENROLLMENT_GLOBAL_KILL_FLAG.is_enabled():
            return True

        if CONTENT_TYPE_GATING_FLAG.is_enabled():
            return True

        # Explicitly cast this to bool, so that when self.enabled is None the method doesn't return None
        return bool(self.enabled and self.enabled_as_of <= target_datetime)
Example #3
0
    def enabled_for_enrollment(cls, enrollment=None, user=None, course_key=None):
        """
        Return whether Course Duration Limits are enabled for this enrollment.

        Course Duration Limits are enabled for an enrollment if they are enabled for
        the course being enrolled in (either specifically, or via a containing context,
        such as the org, site, or globally), and if the configuration is specified to be
        ``enabled_as_of`` before the enrollment was created.

        Only one of enrollment and (user, course_key) may be specified at a time.

        Arguments:
            enrollment: The enrollment being queried.
            user: The user being queried.
            course_key: The CourseKey of the course being queried.
        """

        if FEATURE_BASED_ENROLLMENT_GLOBAL_KILL_FLAG.is_enabled():
            return False

        if CONTENT_TYPE_GATING_FLAG.is_enabled():
            return True

        if enrollment is not None and (user is not None or course_key is not None):
            raise ValueError('Specify enrollment or user/course_key, but not both')

        if enrollment is None and (user is None or course_key is None):
            raise ValueError('Both user and course_key must be specified if no enrollment is provided')

        if enrollment is None and user is None and course_key is None:
            raise ValueError('At least one of enrollment or user and course_key must be specified')

        if course_key is None:
            course_key = enrollment.course_id

        if enrollment is None:
            enrollment = CourseEnrollment.get_enrollment(user, course_key)

        if user is None and enrollment is not None:
            user = enrollment.user

        if user and user.id:
            course_masquerade = get_course_masquerade(user, course_key)
            if course_masquerade:
                if cls.has_full_access_role_in_masquerade(user, course_key, course_masquerade):
                    return False
            elif has_staff_roles(user, course_key):
                return False

        is_masquerading = get_course_masquerade(user, course_key)
        no_masquerade = is_masquerading is None
        student_masquerade = is_masquerading_as_specific_student(user, course_key)

        # check if user is in holdback
        if (no_masquerade or student_masquerade) and is_in_holdback(user):
            return False

        not_student_masquerade = is_masquerading and not student_masquerade

        # enrollment might be None if the user isn't enrolled. In that case,
        # return enablement as if the user enrolled today
        # When masquerading as a user group rather than a specific learner,
        # course duration limits will be on if they are on for the course.
        # When masquerading as a specific learner, course duration limits
        # will be on if they are currently on for the learner.
        if enrollment is None or not_student_masquerade:
            return cls.enabled_for_course(course_key=course_key, target_datetime=timezone.now())
        else:
            current_config = cls.current(course_key=enrollment.course_id)
            return current_config.enabled_as_of_datetime(target_datetime=enrollment.created)
Example #4
0
def get_visibility_partition_info(xblock, course=None):
    """
    Retrieve user partition information for the component visibility editor.

    This pre-processes partition information to simplify the template.

    Arguments:
        xblock (XBlock): The component being edited.

        course (XBlock): The course descriptor.  If provided, uses this to look up the user partitions
            instead of loading the course.  This is useful if we're calling this function multiple
            times for the same course want to minimize queries to the modulestore.

    Returns: dict

    """
    selectable_partitions = []
    # We wish to display enrollment partitions before cohort partitions.
    enrollment_user_partitions = get_user_partition_info(
        xblock, schemes=["enrollment_track"], course=course)

    # For enrollment partitions, we only show them if there is a selected group or
    # or if the number of groups > 1.
    for partition in enrollment_user_partitions:
        if len(partition["groups"]) > 1 or any(
                group["selected"] for group in partition["groups"]):
            selectable_partitions.append(partition)

    flag_enabled = CONTENT_TYPE_GATING_FLAG.is_enabled(
    ) and not FEATURE_BASED_ENROLLMENT_GLOBAL_KILL_FLAG.is_enabled()
    course_key = xblock.scope_ids.usage_id.course_key
    is_library = isinstance(course_key, LibraryLocator)
    if not is_library and (flag_enabled or ContentTypeGatingConfig.current(
            course_key=course_key).studio_override_enabled):
        selectable_partitions += get_user_partition_info(
            xblock, schemes=[CONTENT_TYPE_GATING_SCHEME], course=course)

    # Now add the cohort user partitions.
    selectable_partitions = selectable_partitions + get_user_partition_info(
        xblock, schemes=["cohort"], course=course)

    # Find the first partition with a selected group. That will be the one initially enabled in the dialog
    # (if the course has only been added in Studio, only one partition should have a selected group).
    selected_partition_index = -1

    # At the same time, build up all the selected groups as they are displayed in the dialog title.
    selected_groups_label = ''

    for index, partition in enumerate(selectable_partitions):
        for group in partition["groups"]:
            if group["selected"]:
                if len(selected_groups_label) == 0:
                    selected_groups_label = group['name']
                else:
                    # Translators: This is building up a list of groups. It is marked for translation because of the
                    # comma, which is used as a separator between each group.
                    selected_groups_label = _(
                        '{previous_groups}, {current_group}').format(
                            previous_groups=selected_groups_label,
                            current_group=group['name'])
                if selected_partition_index == -1:
                    selected_partition_index = index

    return {
        "selectable_partitions": selectable_partitions,
        "selected_partition_index": selected_partition_index,
        "selected_groups_label": selected_groups_label,
    }
Example #5
0
    def enabled_for_enrollment(cls, enrollment=None, user=None, course_key=None, user_partition=None):
        """
        Return whether Content Type Gating is enabled for this enrollment.

        Content Type Gating is enabled for an enrollment if it is enabled for
        the course being enrolled in (either specifically, or via a containing context,
        such as the org, site, or globally), and if the configuration is specified to be
        ``enabled_as_of`` before the enrollment was created.

        Only one of enrollment and (user, course_key) may be specified at a time.

        Arguments:
            enrollment: The enrollment being queried.
            user: The user being queried.
            course_key: The CourseKey of the course being queried.
        """
        if FEATURE_BASED_ENROLLMENT_GLOBAL_KILL_FLAG.is_enabled():
            return False

        if CONTENT_TYPE_GATING_FLAG.is_enabled():
            return True

        if enrollment is not None and (user is not None or course_key is not None):
            raise ValueError('Specify enrollment or user/course_key, but not both')

        if enrollment is None and (user is None or course_key is None):
            raise ValueError('Both user and course_key must be specified if no enrollment is provided')

        if enrollment is None and user is None and course_key is None:
            raise ValueError('At least one of enrollment or user and course_key must be specified')

        if course_key is None:
            course_key = enrollment.course_id

        if enrollment is None:
            enrollment = CourseEnrollment.get_enrollment(user, course_key)

        if user is None and enrollment is not None:
            user = enrollment.user

        course_masquerade = get_course_masquerade(user, course_key)
        no_masquerade = course_masquerade is None
        student_masquerade = is_masquerading_as_specific_student(user, course_key)
        user_variable_represents_correct_user = (no_masquerade or student_masquerade)

        if course_masquerade:
            if cls.has_full_access_role_in_masquerade(user, course_key, course_masquerade, student_masquerade,
                                                      user_partition):
                return False
        # When a request is not in a masquerade state the user variable represents the correct user.
        elif user and user.id and has_staff_roles(user, course_key):
            return False

        # check if user is in holdback
        if user_variable_represents_correct_user and is_in_holdback(user):
            return False

        # enrollment might be None if the user isn't enrolled. In that case,
        # return enablement as if the user enrolled today
        # Also, ignore enrollment creation date if the user is masquerading.
        if enrollment is None or course_masquerade:
            return cls.enabled_for_course(course_key=course_key, target_datetime=timezone.now())
        else:
            current_config = cls.current(course_key=enrollment.course_id)
            return current_config.enabled_as_of_datetime(target_datetime=enrollment.created)
Example #6
0
    def enabled_for_enrollment(cls,
                               enrollment=None,
                               user=None,
                               course_key=None):
        """
        Return whether Course Duration Limits are enabled for this enrollment.

        Course Duration Limits are enabled for an enrollment if they are enabled for
        the course being enrolled in (either specifically, or via a containing context,
        such as the org, site, or globally), and if the configuration is specified to be
        ``enabled_as_of`` before the enrollment was created.

        Only one of enrollment and (user, course_key) may be specified at a time.

        Arguments:
            enrollment: The enrollment being queried.
            user: The user being queried.
            course_key: The CourseKey of the course being queried.
        """

        if FEATURE_BASED_ENROLLMENT_GLOBAL_KILL_FLAG.is_enabled():
            return False

        if CONTENT_TYPE_GATING_FLAG.is_enabled():
            return True

        if enrollment is not None and (user is not None
                                       or course_key is not None):
            raise ValueError(
                'Specify enrollment or user/course_key, but not both')

        if enrollment is None and (user is None or course_key is None):
            raise ValueError(
                'Both user and course_key must be specified if no enrollment is provided'
            )

        if enrollment is None and user is None and course_key is None:
            raise ValueError(
                'At least one of enrollment or user and course_key must be specified'
            )

        if course_key is None:
            course_key = enrollment.course_id

        if enrollment is None:
            enrollment = CourseEnrollment.get_enrollment(user, course_key)

        if user is None and enrollment is not None:
            user = enrollment.user

        if user and user.id:
            course_masquerade = get_course_masquerade(user, course_key)
            if course_masquerade:
                if cls.has_full_access_role_in_masquerade(
                        user, course_key, course_masquerade):
                    return False
            elif has_staff_roles(user, course_key):
                return False

        # enrollment might be None if the user isn't enrolled. In that case,
        # return enablement as if the user enrolled today
        if enrollment is None:
            return cls.enabled_for_course(course_key=course_key,
                                          target_datetime=timezone.now())
        else:
            # TODO: clean up as part of REV-100
            is_in_holdback = False
            no_masquerade = get_course_masquerade(user, course_key) is None
            student_masquerade = is_masquerading_as_specific_student(
                user, course_key)
            if user and (no_masquerade or student_masquerade):
                try:
                    holdback_value = ExperimentData.objects.get(
                        user=user,
                        experiment_id=EXPERIMENT_ID,
                        key=EXPERIMENT_DATA_HOLDBACK_KEY,
                    ).value
                    is_in_holdback = holdback_value == 'True'
                except ExperimentData.DoesNotExist:
                    pass
            if is_in_holdback:
                return False
            current_config = cls.current(course_key=enrollment.course_id)
            return current_config.enabled_as_of_datetime(
                target_datetime=enrollment.created)
Example #7
0
    def enabled_for_enrollment(cls,
                               enrollment=None,
                               user=None,
                               course_key=None):
        """
        Return whether Content Type Gating is enabled for this enrollment.

        Content Type Gating is enabled for an enrollment if it is enabled for
        the course being enrolled in (either specifically, or via a containing context,
        such as the org, site, or globally), and if the configuration is specified to be
        ``enabled_as_of`` before the enrollment was created.

        Only one of enrollment and (user, course_key) may be specified at a time.

        Arguments:
            enrollment: The enrollment being queried.
            user: The user being queried.
            course_key: The CourseKey of the course being queried.
        """
        if FEATURE_BASED_ENROLLMENT_GLOBAL_KILL_FLAG.is_enabled():
            return False

        if CONTENT_TYPE_GATING_FLAG.is_enabled():
            return True

        if enrollment is not None and (user is not None
                                       or course_key is not None):
            raise ValueError(
                'Specify enrollment or user/course_key, but not both')

        if enrollment is None and (user is None or course_key is None):
            raise ValueError(
                'Both user and course_key must be specified if no enrollment is provided'
            )

        if enrollment is None and user is None and course_key is None:
            raise ValueError(
                'At least one of enrollment or user and course_key must be specified'
            )

        if course_key is None:
            course_key = enrollment.course_id

        if enrollment is None:
            enrollment = CourseEnrollment.get_enrollment(user, course_key)

        if user is None and enrollment is not None:
            user = enrollment.user

        no_masquerade = get_course_masquerade(user, course_key) is None
        student_masquerade = is_masquerading_as_specific_student(
            user, course_key)
        # We can only use the user variable for the code below when the request is not in a masquerade state
        # or is masquerading as a specific user.
        # When a request is not in a masquerade state the user variable represents the correct user.
        # When a request is in a masquerade state and not masquerading as a specific user,
        # then then user variable will be the incorrect (original) user, not the masquerade user.
        # If a request is masquerading as a specific user, the user variable will represent the correct user.
        user_variable_represents_correct_user = (no_masquerade
                                                 or student_masquerade)
        if user and user.id:
            # TODO: Move masquerade checks to enabled_for_enrollment from content_type_gating/partitions.py
            # TODO: Consolidate masquerade checks into shared function like has_staff_roles below
            if user_variable_represents_correct_user and has_staff_roles(
                    user, course_key):
                return False

        # check if user is in holdback
        is_in_holdback = False
        if user and user.is_authenticated and (
                user_variable_represents_correct_user):
            try:
                holdback_value = ExperimentData.objects.get(
                    user=user,
                    experiment_id=EXPERIMENT_ID,
                    key=EXPERIMENT_DATA_HOLDBACK_KEY,
                ).value
                is_in_holdback = holdback_value == 'True'
            except ExperimentData.DoesNotExist:
                pass
        if is_in_holdback:
            return False

        # enrollment might be None if the user isn't enrolled. In that case,
        # return enablement as if the user enrolled today
        if enrollment is None:
            return cls.enabled_for_course(course_key=course_key,
                                          target_datetime=timezone.now())
        else:
            current_config = cls.current(course_key=enrollment.course_id)
            return current_config.enabled_as_of_datetime(
                target_datetime=enrollment.created)