def _verify_masquerade_for_group(self, group):
        """
        Verify that the masquerade works for the specified group id.
        """
        # Send the request to set the masquerade
        request_json = {
            "role": "student",
            "user_partition_id": self.user_partition.id,
            "group_id": group.id if group is not None else None
        }
        request = self._create_mock_json_request(
            self.test_user,
            data=request_json,
            session=self.session
        )
        response = handle_ajax(request, unicode(self.course.id))
        # pylint has issues analyzing this class (maybe due to circular imports?)
        self.assertEquals(response.status_code, 200)  # pylint: disable=no-member

        # Now setup the masquerade for the test user
        setup_masquerade(request, self.course.id, True)
        scheme = self.user_partition.scheme
        self.assertEqual(
            scheme.get_group_for_user(self.course.id, self.test_user, self.user_partition),
            group
        )
예제 #2
0
def get_module_by_usage_id(request, course_id, usage_id, disable_staff_debug_info=False, course=None):
    """
    Gets a module instance based on its `usage_id` in a course, for a given request/user

    Returns (instance, tracking_context)
    """
    user = request.user

    try:
        course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id)
        usage_key = course_id.make_usage_key_from_deprecated_string(unquote_slashes(usage_id))
    except InvalidKeyError:
        raise Http404("Invalid location")

    try:
        descriptor = modulestore().get_item(usage_key)
        descriptor_orig_usage_key, descriptor_orig_version = modulestore().get_block_original_usage(usage_key)
    except ItemNotFoundError:
        log.warn(
            "Invalid location for course id {course_id}: {usage_key}".format(
                course_id=usage_key.course_key,
                usage_key=usage_key
            )
        )
        raise Http404

    tracking_context = {
        'module': {
            'display_name': descriptor.display_name_with_default,
            'usage_key': unicode(descriptor.location),
        }
    }

    # For blocks that are inherited from a content library, we add some additional metadata:
    if descriptor_orig_usage_key is not None:
        tracking_context['module']['original_usage_key'] = unicode(descriptor_orig_usage_key)
        tracking_context['module']['original_usage_version'] = unicode(descriptor_orig_version)

    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course_id,
        user,
        descriptor
    )
    setup_masquerade(request, course_id, has_access(user, 'staff', descriptor, course_id))
    instance = get_module_for_descriptor(
        user,
        request,
        descriptor,
        field_data_cache,
        usage_key.course_key,
        disable_staff_debug_info=disable_staff_debug_info,
        course=course
    )
    if instance is None:
        # Either permissions just changed, or someone is trying to be clever
        # and load something they shouldn't have access to.
        log.debug("No module %s for user %s -- access denied?", usage_key, user)
        raise Http404

    return (instance, tracking_context)
예제 #3
0
def masquerade_as_group_member(user, course, partition_id, group_id):
    """
    Installs a masquerade for the specified user and course, to enable
    the user to masquerade as belonging to the specific partition/group
    combination.

    Arguments:
        user (User): a user.
        course (CourseDescriptor): a course.
        partition_id (int): the integer partition id, referring to partitions already
           configured in the course.
        group_id (int); the integer group id, within the specified partition.

    Returns: the status code for the AJAX response to update the user's masquerade for
        the specified course.
    """
    request = _create_mock_json_request(user,
                                        data={
                                            "role": "student",
                                            "user_partition_id": partition_id,
                                            "group_id": group_id
                                        })
    response = handle_ajax(request, unicode(course.id))
    setup_masquerade(request, course.id, True)
    return response.status_code
    def _verify_masquerade_for_group(self, group):
        """
        Verify that the masquerade works for the specified group id.
        """
        # Send the request to set the masquerade
        request_json = {
            "role": "student",
        }
        if group and self.user_partition:
            request_json['user_partition_id'] = self.user_partition.id
            request_json['group_id'] = group.id
        request = self._create_mock_json_request(
            self.test_user,
            body=json.dumps(request_json),
            session=self.session
        )
        handle_ajax(request, unicode(self.course.id))

        # Now setup the masquerade for the test user
        setup_masquerade(request, self.test_user, True)
        scheme = self.user_partition.scheme    # pylint: disable=no-member
        self.assertEqual(
            scheme.get_group_for_user(self.course.id, self.test_user, self.user_partition),
            group
        )
예제 #5
0
def get_module_for_descriptor(user,
                              request,
                              descriptor,
                              field_data_cache,
                              course_id,
                              position=None,
                              wrap_xmodule_display=True,
                              grade_bucket_type=None,
                              static_asset_path=''):
    """
    Implements get_module, extracting out the request-specific functionality.

    See get_module() docstring for further details.
    """
    # allow course staff to masquerade as student
    if has_access(user, descriptor, 'staff', course_id):
        setup_masquerade(request, True)

    track_function = make_track_function(request)
    xqueue_callback_url_prefix = get_xqueue_callback_url_prefix(request)

    return get_module_for_descriptor_internal(
        user, descriptor, field_data_cache, course_id, track_function,
        xqueue_callback_url_prefix, position, wrap_xmodule_display,
        grade_bucket_type, static_asset_path)
def get_module_for_descriptor(
    user,
    request,
    descriptor,
    field_data_cache,
    course_id,
    position=None,
    wrap_xmodule_display=True,
    grade_bucket_type=None,
    static_asset_path="",
):
    """
    Implements get_module, extracting out the request-specific functionality.

    See get_module() docstring for further details.
    """
    # allow course staff to masquerade as student
    if has_access(user, descriptor, "staff", course_id):
        setup_masquerade(request, True)

    track_function = make_track_function(request)
    xqueue_callback_url_prefix = get_xqueue_callback_url_prefix(request)

    return get_module_for_descriptor_internal(
        user,
        descriptor,
        field_data_cache,
        course_id,
        track_function,
        xqueue_callback_url_prefix,
        position,
        wrap_xmodule_display,
        grade_bucket_type,
        static_asset_path,
    )
예제 #7
0
def get_module_for_descriptor(user, request, descriptor, field_data_cache, course_id,
                              position=None, wrap_xmodule_display=True, grade_bucket_type=None,
                              static_asset_path=''):
    """
    Implements get_module, extracting out the request-specific functionality.

    See get_module() docstring for further details.
    """
    # allow course staff to masquerade as student
    if has_access(user, 'staff', descriptor, course_id):
        setup_masquerade(request, True)

    track_function = make_track_function(request)
    xqueue_callback_url_prefix = get_xqueue_callback_url_prefix(request)

    user_location = getattr(request, 'session', {}).get('country_code')

    return get_module_for_descriptor_internal(
        user=user,
        descriptor=descriptor,
        field_data_cache=field_data_cache,
        course_id=course_id,
        track_function=track_function,
        xqueue_callback_url_prefix=xqueue_callback_url_prefix,
        position=position,
        wrap_xmodule_display=wrap_xmodule_display,
        grade_bucket_type=grade_bucket_type,
        static_asset_path=static_asset_path,
        user_location=user_location,
        request_token=request_token(request),
    )
예제 #8
0
 def initialize(self, **kwargs):
     if 'request' in kwargs and kwargs['request'] and kwargs['course_id']:
         request = kwargs['request']
         try:
             course_key = CourseKey.from_string(kwargs['course_id'])
         except InvalidKeyError:
             course_key = SlashSeparatedCourseKey.from_deprecated_string(kwargs['course_id'])
         staff_access = bool(has_access(request.user, 'staff', course_key))
         setup_masquerade(request, course_key, staff_access)
 def initialize(self, **kwargs):
     if 'request' in kwargs and kwargs['request'] and kwargs['course_id']:
         request = kwargs['request']
         try:
             course_key = CourseKey.from_string(kwargs['course_id'])
         except InvalidKeyError:
             course_key = SlashSeparatedCourseKey.from_deprecated_string(kwargs['course_id'])
         staff_access = has_access(request.user, 'staff', course_key)
         setup_masquerade(request, course_key, staff_access)
예제 #10
0
def get_module_by_usage_id(request, course_id, usage_id):
    """
    Gets a module instance based on its `usage_id` in a course, for a given request/user

    Returns (instance, tracking_context)
    """
    user = request.user

    try:
        course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id)
        usage_key = course_id.make_usage_key_from_deprecated_string(
            unquote_slashes(usage_id))
    except InvalidKeyError:
        raise Http404("Invalid location")

    try:
        descriptor = modulestore().get_item(usage_key)
        descriptor_orig_usage_key, descriptor_orig_version = modulestore(
        ).get_block_original_usage(usage_key)
    except ItemNotFoundError:
        log.warn(
            "Invalid location for course id {course_id}: {usage_key}".format(
                course_id=usage_key.course_key, usage_key=usage_key))
        raise Http404

    tracking_context = {
        'module': {
            'display_name': descriptor.display_name_with_default,
            'usage_key': unicode(descriptor.location),
        }
    }

    # For blocks that are inherited from a content library, we add some additional metadata:
    if descriptor_orig_usage_key is not None:
        tracking_context['module']['original_usage_key'] = unicode(
            descriptor_orig_usage_key)
        tracking_context['module']['original_usage_version'] = unicode(
            descriptor_orig_version)

    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course_id, user, descriptor)
    setup_masquerade(request, course_id,
                     has_access(user, 'staff', descriptor, course_id))
    instance = get_module(user,
                          request,
                          usage_key,
                          field_data_cache,
                          grade_bucket_type='ajax')
    if instance is None:
        # Either permissions just changed, or someone is trying to be clever
        # and load something they shouldn't have access to.
        log.debug("No module %s for user %s -- access denied?", usage_key,
                  user)
        raise Http404

    return (instance, tracking_context)
예제 #11
0
def course_info(request, course_id):
    """
    Display the course's info.html, or 404 if there is no such course.

    Assumes the course_id is in a valid format.
    """
    course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    course = get_course_with_access(request.user, "load", course_key)
    staff_access = has_access(request.user, "staff", course)
    masq = setup_masquerade(request, staff_access)  # allow staff to toggle masquerade on info page
    reverifications = fetch_reverify_banner_info(request, course_key)
    studio_url = get_studio_url(course_key, "course_info")

    context = {
        "request": request,
        "course_id": course_key.to_deprecated_string(),
        "cache": None,
        "course": course,
        "staff_access": staff_access,
        "masquerade": masq,
        "studio_url": studio_url,
        "reverifications": reverifications,
    }

    return render_to_response("courseware/info.html", context)
예제 #12
0
    def render_to_fragment(self, request, course_id, **kwargs):
        if(not _has_page_access(request.user, course_id)):
            raise Http404()

        course_key = CourseKey.from_string(course_id)
        course = get_course_with_access(request.user, "load", course_key)

        # masquerade and student required for preview_menu (admin)
        staff_access = bool(has_access(request.user, 'staff', course))
        can_masquerade = request.user.has_perm(MASQUERADE_AS_STUDENT, course)
        masquerade, student = setup_masquerade(request, course_key, staff_access, reset_masquerade_data=True)
        prefetch_related_objects([student], 'groups')
        if request.user.id != student.id:
            course = get_course_with_access(student, 'load', course_key, check_if_enrolled=True)

        context = {
            "course": course,
            "student_id": student.id,
            "supports_preview_menu": True,
            "staff_access": staff_access,
            "can_masquerade": can_masquerade,
            "masquerade": masquerade,
            'studio_url': get_studio_url(course, 'settings/grading'),
            "DEV_URL": configuration_helpers.get_value('EOL_PROGRESS_TAB_DEV_URL', settings.EOL_PROGRESS_TAB_DEV_URL)
        }
        html = render_to_string('eol_progress_tab/eol_progress_tab_fragment.html', context)
        fragment = Fragment(html)
        return fragment
예제 #13
0
def course_info(request, course_id):
    """
    Display the course's info.html, or 404 if there is no such course.

    Assumes the course_id is in a valid format.
    """
    course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    course = get_course_with_access(request.user, 'load', course_key)
    staff_access = has_access(request.user, 'staff', course)
    masq = setup_masquerade(request, staff_access)    # allow staff to toggle masquerade on info page
    reverifications = fetch_reverify_banner_info(request, course_key)
    studio_url = get_studio_url(course_key, 'course_info')

    context = {
        'request': request,
        'course_id': course_key.to_deprecated_string(),
        'cache': None,
        'course': course,
        'staff_access': staff_access,
        'masquerade': masq,
        'studio_url': studio_url,
        'reverifications': reverifications,
    }

    return render_to_response('courseware/info.html', context)
예제 #14
0
def course_info(request, course_id):
    """
    Display the course's info.html, or 404 if there is no such course.

    Assumes the course_id is in a valid format.
    """
    course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    course = get_course_with_access(request.user, 'load', course_key)
    staff_access = has_access(request.user, 'staff', course)
    masq = setup_masquerade(
        request, staff_access)  # allow staff to toggle masquerade on info page
    reverifications = fetch_reverify_banner_info(request, course_key)
    studio_url = get_studio_url(course_key, 'course_info')

    context = {
        'request': request,
        'course_id': course_key.to_deprecated_string(),
        'cache': None,
        'course': course,
        'staff_access': staff_access,
        'masquerade': masq,
        'studio_url': studio_url,
        'reverifications': reverifications,
    }

    return render_to_response('courseware/info.html', context)
예제 #15
0
def get_module_by_usage_id(request, course_id, usage_id, disable_staff_debug_info=False, course=None):
    """
    Gets a module instance based on its `usage_id` in a course, for a given request/user

    Returns (instance, tracking_context)
    """
    user = request.user

    try:
        course_id = CourseKey.from_string(course_id)
        usage_key = UsageKey.from_string(unquote_slashes(usage_id)).map_into_course(course_id)
    except InvalidKeyError:
        raise Http404("Invalid location")

    try:
        descriptor = modulestore().get_item(usage_key)
        descriptor_orig_usage_key, descriptor_orig_version = modulestore().get_block_original_usage(usage_key)
    except ItemNotFoundError:
        log.warn(
            "Invalid location for course id %s: %s",
            usage_key.course_key,
            usage_key
        )
        raise Http404

    tracking_context = {
        'module': {
            'display_name': descriptor.display_name_with_default_escaped,
            'usage_key': unicode(descriptor.location),
        }
    }

    # For blocks that are inherited from a content library, we add some additional metadata:
    if descriptor_orig_usage_key is not None:
        tracking_context['module']['original_usage_key'] = unicode(descriptor_orig_usage_key)
        tracking_context['module']['original_usage_version'] = unicode(descriptor_orig_version)

    unused_masquerade, user = setup_masquerade(request, course_id, has_access(user, 'staff', descriptor, course_id))
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course_id,
        user,
        descriptor,
        read_only=CrawlersConfig.is_crawler(request),
    )
    instance = get_module_for_descriptor(
        user,
        request,
        descriptor,
        field_data_cache,
        usage_key.course_key,
        disable_staff_debug_info=disable_staff_debug_info,
        course=course
    )
    if instance is None:
        # Either permissions just changed, or someone is trying to be clever
        # and load something they shouldn't have access to.
        log.debug("No module %s for user %s -- access denied?", usage_key, user)
        raise Http404

    return (instance, tracking_context)
예제 #16
0
    def _verify_masquerade_for_group(self, group):
        """
        Verify that the masquerade works for the specified group id.
        """
        # Send the request to set the masquerade
        request_json = {
            "role": "student",
            "user_partition_id": self.user_partition.id,
            "group_id": group.id if group is not None else None,
        }
        request = self._create_mock_json_request(self.test_user, body=json.dumps(request_json), session=self.session)
        handle_ajax(request, unicode(self.course.id))

        # Now setup the masquerade for the test user
        setup_masquerade(request, self.test_user, True)
        scheme = self.user_partition.scheme
        self.assertEqual(scheme.get_group_for_user(self.course.id, self.test_user, self.user_partition), group)
예제 #17
0
def mobi_directory(request, course_id):
    user = User.objects.prefetch_related("groups").get(id=request.user.id)
    request.user = user  # keep just one instance of User
    course = get_course_with_access(user, course_id, 'load', depth=2)
    staff_access = has_access(user, course, 'staff')
    registered = registered_for_course(course, user)
    if not registered:
        # TODO (vshnayder): do course instructors need to be registered to see course?
        log.debug(u'User %s tried to view course %s but is not enrolled', user, course.location.url())
        return redirect(reverse('about_course', args=[course.id]))

    masq = setup_masquerade(request, staff_access)

    try:
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course.id, user, course, depth=2)

        course_module = get_module_for_descriptor(user, request, course, field_data_cache, course.id)
        if course_module is None:
            log.warning(u'If you see this, something went wrong: if we got this'
                        u' far, should have gotten a course module for this user')
            return redirect(reverse('about_course', args=[course.id]))
        context = {
            'csrf': csrf(request)['csrf_token'],
            'accordion': mobi_render_accordion(request, course),
            'COURSE_TITLE': course.display_name_with_default,
            'course': course,
            'init': '',
            'fragment': Fragment(),
            'staff_access': staff_access,
            'masquerade': masq,
            'xqa_server': settings.FEATURES.get('USE_XQA_SERVER', 'http://*****:*****@content-qa.mitx.mit.edu/xqa'),
            'reverifications': fetch_reverify_banner_info(request, course_id),
            }
        result = render_to_response('wechat/mobi_directory.html', context)
    except Exception as e:
        if isinstance(e, Http404):
            # let it propagate
            raise

        # In production, don't want to let a 500 out for any reason
        if settings.DEBUG:
            raise
        else:
            log.exception("Error in index view: user={user}, course={course},".format(
                              user=user,
                              course=course,))
            try:
                result = render_to_response('courseware/courseware-error.html',
                                            {'staff_access': staff_access,
                                            'course': course})
            except:
                # Let the exception propagate, relying on global config to at
                # at least return a nice error message
                log.exception("Error while rendering courseware-error page")
                raise
    return result
예제 #18
0
def course_info(request, course_id):
    """
    Display the course's info.html, or 404 if there is no such course.

    Assumes the course_id is in a valid format.
    """

    course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)

    with modulestore().bulk_operations(course_key):
        course = get_course_with_access(request.user, 'load', course_key)

        # check to see if there is a required survey that must be taken before
        # the user can access the course.
        if request.user.is_authenticated() and survey.utils.must_answer_survey(
                course, request.user):
            return redirect(reverse('course_survey',
                                    args=[unicode(course.id)]))

        staff_access = has_access(request.user, 'staff', course)
        masq = setup_masquerade(
            request,
            staff_access)  # allow staff to toggle masquerade on info page
        reverifications = fetch_reverify_banner_info(request, course_key)
        studio_url = get_studio_url(course, 'course_info')

        # link to where the student should go to enroll in the course:
        # about page if there is not marketing site, SITE_NAME if there is
        url_to_enroll = reverse(course_about, args=[course_id])
        if settings.FEATURES.get('ENABLE_MKTG_SITE'):
            url_to_enroll = marketing_link('COURSES')

        show_enroll_banner = request.user.is_authenticated(
        ) and not CourseEnrollment.is_enrolled(request.user, course.id)

        context = {
            'request': request,
            'course_id': course_key.to_deprecated_string(),
            'cache': None,
            'course': course,
            'staff_access': staff_access,
            'masquerade': masq,
            'studio_url': studio_url,
            'reverifications': reverifications,
            'show_enroll_banner': show_enroll_banner,
            'url_to_enroll': url_to_enroll,
        }

        now = datetime.now(UTC())
        effective_start = _adjust_start_date_for_beta_testers(
            request.user, course, course_key)
        if staff_access and now < effective_start:
            # Disable student view button if user is staff and
            # course is not yet visible to students.
            context['disable_student_access'] = True

        return render_to_response('courseware/info.html', context)
예제 #19
0
def piazza_discussion(request, course_id):
    '''
    Shows the page under the Discussion tab with an iframe containing Piazza
    '''
    # Create a new tool configuration
    config = ToolConfig(title = 'Piazza',
            launch_url = LTI_LAUNCH_URL)

    # Create tool consumer using LTI!
    consumer = ToolConsumer(LTI_CONSUMER_KEY,
            LTI_CONSUMER_SECRET)
    consumer.set_config(config)

    
    #retrieve user and course models
    user = User.objects.prefetch_related("groups").get(id=request.user.id)
    userProfile = UserProfile.objects.get(user_id=user.id)
    course = course_from_id(course_id)

    #check for permissions to determine what role to pass to Piazza.com through 
    piazza_role = ''
    if user.groups.filter(name=('instructor_'+course_id)).count() != 0 or request.user.is_staff:
        piazza_role = 'Instructor'
    elif user.groups.filter(name=('staff_'+course_id)).count() != 0:
        piazza_role = 'Staff'
    else:
        piazza_role = 'Learner'

    # Set some launch data from: http://www.imsglobal.org/LTI/v1p1pd/ltiIMGv1p1pd.html#_Toc309649684
    consumer.resource_link_id = course_id
    consumer.lis_person_contact_email_primary = user.email
    consumer.lis_person_name_full = str(userProfile.name)
    hash = hashlib.md5()
    hash.update(str(userProfile.user_id))
    consumer.user_id = hash.hexdigest()

    #TODO: check if user is is_staff, student, professor, or staff and set the role appropriately
    consumer.roles = piazza_role
    consumer.context_id = course_id
    consumer.context_title = course.display_name_with_default
    consumer.context_label = course.number.replace('_', ' ')
    consumer.tool_consumer_instance_guid = 'lms.cvn.columbia.edu'
    consumer.tool_consumer_instance_description = 'Columbia University'
 

    launch_data = consumer.generate_launch_data()
    launch_url = consumer.launch_url


    course = get_course_with_access(request.user, course_id, 'load')
    staff_access = has_access(request.user, course, 'staff')
    masq = setup_masquerade(request, staff_access)    # allow staff to toggle masquerade on info page

    return render_to_response('courseware/piazza_discussion.html', {'request': request, 'course_id': course_id, 'cache': None,
            'course': course, 'staff_access': staff_access, 'masquerade': masq, 'launch_url':launch_url, 'launch_data':launch_data})
예제 #20
0
    def test_group_masquerade(self):
        """
        Tests that a staff member can masquerade as being in a particular group.
        """
        # Verify that there is no masquerading group initially
        group_id, user_partition_id = get_masquerading_group_info(self.test_user, self.course.id)
        self.assertIsNone(group_id)
        self.assertIsNone(user_partition_id)

        # Install a masquerading group
        request = self._create_mock_json_request(
            self.test_user, body='{"role": "student", "user_partition_id": 0, "group_id": 1}'
        )
        handle_ajax(request, unicode(self.course.id))
        setup_masquerade(request, self.test_user, True)

        # Verify that the masquerading group is returned
        group_id, user_partition_id = get_masquerading_group_info(self.test_user, self.course.id)
        self.assertEqual(group_id, 1)
        self.assertEqual(user_partition_id, 0)
예제 #21
0
def course_info(request, course_id):
    """
    Display the course's info.html, or 404 if there is no such course.

    Assumes the course_id is in a valid format.
    """
    course = get_course_with_access(request.user, course_id, 'load')
    staff_access = has_access(request.user, course, 'staff')
    masq = setup_masquerade(request, staff_access)    # allow staff to toggle masquerade on info page

    return render_to_response('courseware/info.html', {'request': request, 'course_id': course_id, 'cache': None,
            'course': course, 'staff_access': staff_access, 'masquerade': masq})
예제 #22
0
    def _verify_masquerade_for_group(self, group):
        """
        Verify that the masquerade works for the specified group id.
        """
        # Send the request to set the masquerade
        request_json = {
            "role": "student",
            "user_partition_id": self.user_partition.id,
            "group_id": group.id if group is not None else None
        }
        request = self._create_mock_json_request(self.test_user,
                                                 body=json.dumps(request_json),
                                                 session=self.session)
        handle_ajax(request, unicode(self.course.id))

        # Now setup the masquerade for the test user
        setup_masquerade(request, self.test_user, True)
        scheme = self.user_partition.scheme  # pylint: disable=no-member
        self.assertEqual(
            scheme.get_group_for_user(self.course.id, self.test_user,
                                      self.user_partition), group)
예제 #23
0
def course_info(request, course_id):
    """
    Display the course's info.html, or 404 if there is no such course.

    Assumes the course_id is in a valid format.
    """
    course = get_course_with_access(request.user, course_id, 'load')
    staff_access = has_access(request.user, course, 'staff')
    masq = setup_masquerade(request, staff_access)    # allow staff to toggle masquerade on info page

    return render_to_response('courseware/info.html', {'request': request, 'course_id': course_id, 'cache': None,
            'course': course, 'staff_access': staff_access, 'masquerade': masq})
예제 #24
0
    def test_group_masquerade(self):
        """
        Tests that a staff member can masquerade as being in a particular group.
        """
        # Verify that there is no masquerading group initially
        group_id, user_partition_id = get_masquerading_group_info(self.test_user, self.course.id)
        self.assertIsNone(group_id)
        self.assertIsNone(user_partition_id)

        # Install a masquerading group
        request = self._create_mock_json_request(
            self.test_user,
            body='{"role": "student", "user_partition_id": 0, "group_id": 1}'
        )
        handle_ajax(request, unicode(self.course.id))
        setup_masquerade(request, self.test_user, True)

        # Verify that the masquerading group is returned
        group_id, user_partition_id = get_masquerading_group_info(self.test_user, self.course.id)
        self.assertEqual(group_id, 1)
        self.assertEqual(user_partition_id, 0)
예제 #25
0
def course_info(request, course_id):
    """
    Display the course's info.html, or 404 if there is no such course.

    Assumes the course_id is in a valid format.
    """

    course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)

    with modulestore().bulk_operations(course_key):
        course = get_course_with_access(request.user, "load", course_key)

        # check to see if there is a required survey that must be taken before
        # the user can access the course.
        if request.user.is_authenticated() and survey.utils.must_answer_survey(course, request.user):
            return redirect(reverse("course_survey", args=[unicode(course.id)]))

        staff_access = has_access(request.user, "staff", course)
        masquerade = setup_masquerade(request, course_key, staff_access)  # allow staff to masquerade on the info page
        reverifications = fetch_reverify_banner_info(request, course_key)
        studio_url = get_studio_url(course, "course_info")

        # link to where the student should go to enroll in the course:
        # about page if there is not marketing site, SITE_NAME if there is
        url_to_enroll = reverse(course_about, args=[course_id])
        if settings.FEATURES.get("ENABLE_MKTG_SITE"):
            url_to_enroll = marketing_link("COURSES")

        show_enroll_banner = request.user.is_authenticated() and not CourseEnrollment.is_enrolled(
            request.user, course.id
        )

        context = {
            "request": request,
            "course_id": course_key.to_deprecated_string(),
            "cache": None,
            "course": course,
            "staff_access": staff_access,
            "masquerade": masquerade,
            "studio_url": studio_url,
            "reverifications": reverifications,
            "show_enroll_banner": show_enroll_banner,
            "url_to_enroll": url_to_enroll,
        }

        now = datetime.now(UTC())
        effective_start = _adjust_start_date_for_beta_testers(request.user, course, course_key)
        if staff_access and now < effective_start:
            # Disable student view button if user is staff and
            # course is not yet visible to students.
            context["disable_student_access"] = True

        return render_to_response("courseware/info.html", context)
예제 #26
0
 def _setup_masquerade_for_effective_user(self):
     """
     Setup the masquerade information to allow the request to
     be processed for the requested effective user.
     """
     self.real_user = self.request.user
     self.masquerade, self.effective_user = setup_masquerade(
         self.request,
         self.course_key,
         self.is_staff,
         reset_masquerade_data=True)
     # Set the user in the request to the effective user.
     self.request.user = self.effective_user
예제 #27
0
    def _verify_masquerade_for_group(self, group):
        """
        Verify that the masquerade works for the specified group id.
        """
        # Send the request to set the masquerade
        request_json = {
            "role": "student",
            "user_partition_id": self.user_partition.id,
            "group_id": group.id if group is not None else None
        }
        request = self._create_mock_json_request(self.test_user,
                                                 data=request_json,
                                                 session=self.session)
        response = handle_ajax(request, unicode(self.course.id))
        # pylint has issues analyzing this class (maybe due to circular imports?)
        self.assertEquals(response.status_code, 200)  # pylint: disable=no-member

        # Now setup the masquerade for the test user
        setup_masquerade(request, self.course.id, True)
        scheme = self.user_partition.scheme
        self.assertEqual(
            scheme.get_group_for_user(self.course.id, self.test_user,
                                      self.user_partition), group)
예제 #28
0
def masquerade_as_group_member(user, course, partition_id, group_id):
    """
    Installs a masquerade for the specified user and course, to enable
    the user to masquerade as belonging to the specific partition/group
    combination.

    Arguments:
        user (User): a user.
        course (CourseDescriptor): a course.
        partition_id (int): the integer partition id, referring to partitions already
           configured in the course.
        group_id (int); the integer group id, within the specified partition.

    Returns: the status code for the AJAX response to update the user's masquerade for
        the specified course.
    """
    request = _create_mock_json_request(
        user,
        data={"role": "student", "user_partition_id": partition_id, "group_id": group_id}
    )
    response = handle_ajax(request, unicode(course.id))
    setup_masquerade(request, course.id, True)
    return response.status_code
예제 #29
0
def _get_context(request, course_id):
    """
        Return all course/student/user data
    """
    course_key = CourseKey.from_string(course_id)
    course = get_course_with_access(request.user, "load", course_key)

    # Get general info of course
    grade_cutoff, avg_grade, min_grade, max_grade = _get_course_info(
        course, course_key)

    # masquerade and student required for preview_menu (admin)
    staff_access = bool(has_access(request.user, 'staff', course))
    masquerade, student = setup_masquerade(request,
                                           course_key,
                                           staff_access,
                                           reset_masquerade_data=True)
    prefetch_related_objects([student], 'groups')
    if request.user.id != student.id:
        # refetch the course as the assumed student
        course = get_course_with_access(student,
                                        'load',
                                        course_key,
                                        check_if_enrolled=True)
    course_grade = CourseGradeFactory().read(student, course)  # Student grades
    courseware_summary = list(course_grade.chapter_grades.values())
    course_expiration_fragment = generate_course_expired_fragment(
        student, course)

    context = {
        "course": course,
        "avg_grade": avg_grade,
        "min_grade": min_grade,
        "max_grade": max_grade,
        "grade_cutoff": grade_cutoff,
        "supports_preview_menu": True,
        "staff_access": staff_access,
        "masquerade": masquerade,
        "student": student,
        "courseware_summary": courseware_summary,
        "grade_summary": course_grade.summary,
        "course_expiration_fragment": course_expiration_fragment,
        "grade_percent_scaled": grade_percent_scaled,
        "get_section_visibility": get_section_visibility,
        "get_feedback": get_feedback,
        "update_url": reverse('feedback_post_update'),
        "set_visibility_url": reverse('feedback_post_set_visibility'),
    }
    return context
예제 #30
0
def course_info(request, course_id):
    """
    Display the course's info.html, or 404 if there is no such course.

    Assumes the course_id is in a valid format.
    """

    course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)

    with modulestore().bulk_operations(course_key):
        course = get_course_with_access(request.user, 'load', course_key)
        staff_access = has_access(request.user, 'staff', course)
        masq = setup_masquerade(request, staff_access)    # allow staff to toggle masquerade on info page
        reverifications = fetch_reverify_banner_info(request, course_key)
        studio_url = get_studio_url(course, 'course_info')

        # link to where the student should go to enroll in the course:
        # about page if there is not marketing site, SITE_NAME if there is
        url_to_enroll = reverse(course_about, args=[course_id])
        if settings.FEATURES.get('ENABLE_MKTG_SITE'):
            url_to_enroll = marketing_link('COURSES')

        show_enroll_banner = request.user.is_authenticated() and not CourseEnrollment.is_enrolled(request.user, course.id)

        context = {
            'request': request,
            'course_id': course_key.to_deprecated_string(),
            'cache': None,
            'course': course,
            'staff_access': staff_access,
            'masquerade': masq,
            'studio_url': studio_url,
            'reverifications': reverifications,
            'show_enroll_banner': show_enroll_banner,
            'url_to_enroll': url_to_enroll,
        }

        now = datetime.now(UTC())
        effective_start = _adjust_start_date_for_beta_testers(request.user, course, course_key)
        if staff_access and now < effective_start:
            # Disable student view button if user is staff and
            # course is not yet visible to students.
            context['disable_student_access'] = True

        return render_to_response('courseware/info.html', context)
예제 #31
0
def course_info(request, course_id):
    """
    Display the course's info.html, or 404 if there is no such course.

    Assumes the course_id is in a valid format.
    """
    course = get_course_with_access(request.user, course_id, "load")
    staff_access = has_access(request.user, course, "staff")
    masq = setup_masquerade(request, staff_access)  # allow staff to toggle masquerade on info page

    return render_to_response(
        "courseware/info.html",
        {
            "request": request,
            "course_id": course_id,
            "cache": None,
            "course": course,
            "staff_access": staff_access,
            "masquerade": masq,
        },
    )
예제 #32
0
def course_info(request, course_id):
    """
    Display the course's info.html, or 404 if there is no such course.

    Assumes the course_id is in a valid format.
    """

    course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)

    course = get_course_with_access(request.user, 'load', course_key)
    staff_access = has_access(request.user, 'staff', course)
    masq = setup_masquerade(
        request, staff_access)  # allow staff to toggle masquerade on info page
    reverifications = fetch_reverify_banner_info(request, course_key)
    studio_url = get_studio_url(course, 'course_info')

    # link to where the student should go to enroll in the course:
    # about page if there is not marketing site, SITE_NAME if there is
    url_to_enroll = reverse(course_about, args=[course_id])
    if settings.FEATURES.get('ENABLE_MKTG_SITE'):
        url_to_enroll = marketing_link('COURSES')

    show_enroll_banner = request.user.is_authenticated(
    ) and not CourseEnrollment.is_enrolled(request.user, course.id)

    context = {
        'request': request,
        'course_id': course_key.to_deprecated_string(),
        'cache': None,
        'course': course,
        'staff_access': staff_access,
        'masquerade': masq,
        'studio_url': studio_url,
        'reverifications': reverifications,
        'show_enroll_banner': show_enroll_banner,
        'url_to_enroll': url_to_enroll,
    }

    return render_to_response('courseware/info.html', context)
예제 #33
0
def course_info(request, course_id):
    """
    Display the course's info.html, or 404 if there is no such course.

    Assumes the course_id is in a valid format.
    """

    course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)

    course = get_course_with_access(request.user, 'load', course_key)
    staff_access = has_access(request.user, 'staff', course)
    masq = setup_masquerade(request, staff_access)    # allow staff to toggle masquerade on info page
    reverifications = fetch_reverify_banner_info(request, course_key)
    studio_url = get_studio_url(course, 'course_info')

    # link to where the student should go to enroll in the course:
    # about page if there is not marketing site, SITE_NAME if there is
    url_to_enroll = reverse(course_about, args=[course_id])
    if settings.FEATURES.get('ENABLE_MKTG_SITE'):
        url_to_enroll = marketing_link('COURSES')

    show_enroll_banner = request.user.is_authenticated() and not CourseEnrollment.is_enrolled(request.user, course.id)

    context = {
        'request': request,
        'course_id': course_key.to_deprecated_string(),
        'cache': None,
        'course': course,
        'staff_access': staff_access,
        'masquerade': masq,
        'studio_url': studio_url,
        'reverifications': reverifications,
        'show_enroll_banner': show_enroll_banner,
        'url_to_enroll': url_to_enroll,
    }

    return render_to_response('courseware/info.html', context)
예제 #34
0
def _invoke_xblock_handler(request, course_id, usage_id, handler, suffix,
                           user):
    """
    Invoke an XBlock handler, either authenticated or not.

    Arguments:
        request (HttpRequest): the current request
        course_id (str): A string of the form org/course/run
        usage_id (str): A string of the form i4x://org/course/category/name@revision
        handler (str): The name of the handler to invoke
        suffix (str): The suffix to pass to the handler when invoked
        user (User): The currently logged in user

    """
    try:
        course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id)
        usage_key = course_id.make_usage_key_from_deprecated_string(
            unquote_slashes(usage_id))
    except InvalidKeyError:
        raise Http404("Invalid location")

    # Check submitted files
    files = request.FILES or {}
    error_msg = _check_files_limits(files)
    if error_msg:
        return HttpResponse(json.dumps({'success': error_msg}))

    try:
        descriptor = modulestore().get_item(usage_key)
        descriptor_orig_usage_key, descriptor_orig_version = modulestore(
        ).get_block_original_usage(usage_key)
    except ItemNotFoundError:
        log.warn(
            "Invalid location for course id {course_id}: {usage_key}".format(
                course_id=usage_key.course_key, usage_key=usage_key))
        raise Http404

    tracking_context_name = 'module_callback_handler'
    tracking_context = {
        'module': {
            'display_name': descriptor.display_name_with_default,
            'usage_key': unicode(descriptor.location),
        }
    }
    # For blocks that are inherited from a content library, we add some additional metadata:
    if descriptor_orig_usage_key is not None:
        tracking_context['module']['original_usage_key'] = unicode(
            descriptor_orig_usage_key)
        tracking_context['module']['original_usage_version'] = unicode(
            descriptor_orig_version)

    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course_id, user, descriptor)
    setup_masquerade(request, course_id,
                     has_access(user, 'staff', descriptor, course_id))
    instance = get_module(user,
                          request,
                          usage_key,
                          field_data_cache,
                          grade_bucket_type='ajax')
    if instance is None:
        # Either permissions just changed, or someone is trying to be clever
        # and load something they shouldn't have access to.
        log.debug("No module %s for user %s -- access denied?", usage_key,
                  user)
        raise Http404

    req = django_to_webob_request(request)
    try:
        with tracker.get_tracker().context(tracking_context_name,
                                           tracking_context):
            resp = instance.handle(handler, req, suffix)

    except NoSuchHandlerError:
        log.exception("XBlock %s attempted to access missing handler %r",
                      instance, handler)
        raise Http404

    # If we can't find the module, respond with a 404
    except NotFoundError:
        log.exception("Module indicating to user that request doesn't exist")
        raise Http404

    # For XModule-specific errors, we log the error and respond with an error message
    except ProcessingError as err:
        log.warning("Module encountered an error while processing AJAX call",
                    exc_info=True)
        return JsonResponse(object={'success': err.args[0]}, status=200)

    # If any other error occurred, re-raise it to trigger a 500 response
    except Exception:
        log.exception("error executing xblock handler")
        raise

    return webob_to_django_response(resp)
예제 #35
0
def get_module_for_descriptor(user,
                              request,
                              descriptor,
                              model_data_cache,
                              course_id,
                              position=None,
                              wrap_xmodule_display=True,
                              grade_bucket_type=None):
    """
    Actually implement get_module.  See docstring there for details.
    """

    # allow course staff to masquerade as student
    if has_access(user, descriptor, 'staff', course_id):
        setup_masquerade(request, True)

    # Short circuit--if the user shouldn't have access, bail without doing any work
    if not has_access(user, descriptor, 'load', course_id):
        return None

    # Setup system context for module instance
    ajax_url = reverse(
        'modx_dispatch',
        kwargs=dict(course_id=course_id,
                    location=descriptor.location.url(),
                    dispatch=''),
    )
    # Intended use is as {ajax_url}/{dispatch_command}, so get rid of the trailing slash.
    ajax_url = ajax_url.rstrip('/')

    def make_xqueue_callback(dispatch='score_update'):
        # Fully qualified callback URL for external queueing system
        xqueue_callback_url = '{proto}://{host}'.format(
            host=request.get_host(),
            proto=request.META.get('HTTP_X_FORWARDED_PROTO',
                                   'https' if request.is_secure() else 'http'))
        xqueue_callback_url = settings.XQUEUE_INTERFACE.get(
            'callback_url', xqueue_callback_url)  # allow override

        xqueue_callback_url += reverse(
            'xqueue_callback',
            kwargs=dict(course_id=course_id,
                        userid=str(user.id),
                        id=descriptor.location.url(),
                        dispatch=dispatch),
        )
        return xqueue_callback_url

    # Default queuename is course-specific and is derived from the course that
    #   contains the current module.
    # TODO: Queuename should be derived from 'course_settings.json' of each course
    xqueue_default_queuename = descriptor.location.org + '-' + descriptor.location.course

    xqueue = {
        'interface': xqueue_interface,
        'construct_callback': make_xqueue_callback,
        'default_queuename': xqueue_default_queuename.replace(' ', '_'),
        'waittime': settings.XQUEUE_WAITTIME_BETWEEN_REQUESTS
    }

    #This is a hacky way to pass settings to the combined open ended xmodule
    #It needs an S3 interface to upload images to S3
    #It needs the open ended grading interface in order to get peer grading to be done
    #this first checks to see if the descriptor is the correct one, and only sends settings if it is

    #Get descriptor metadata fields indicating needs for various settings
    needs_open_ended_interface = getattr(descriptor,
                                         "needs_open_ended_interface", False)
    needs_s3_interface = getattr(descriptor, "needs_s3_interface", False)

    #Initialize interfaces to None
    open_ended_grading_interface = None
    s3_interface = None

    #Create interfaces if needed
    if needs_open_ended_interface:
        open_ended_grading_interface = settings.OPEN_ENDED_GRADING_INTERFACE
        open_ended_grading_interface[
            'mock_peer_grading'] = settings.MOCK_PEER_GRADING
        open_ended_grading_interface[
            'mock_staff_grading'] = settings.MOCK_STAFF_GRADING
    if needs_s3_interface:
        s3_interface = {
            'access_key':
            getattr(settings, 'AWS_ACCESS_KEY_ID', ''),
            'secret_access_key':
            getattr(settings, 'AWS_SECRET_ACCESS_KEY', ''),
            'storage_bucket_name':
            getattr(settings, 'AWS_STORAGE_BUCKET_NAME', 'openended')
        }

    def inner_get_module(descriptor):
        """
        Delegate to get_module.  It does an access check, so may return None
        """
        return get_module_for_descriptor(user, request, descriptor,
                                         model_data_cache, course_id, position)

    def xblock_model_data(descriptor):
        return DbModel(
            LmsKeyValueStore(descriptor._model_data, model_data_cache),
            descriptor.module_class, user.id,
            LmsUsage(descriptor.location, descriptor.location))

    def publish(event):
        if event.get('event_name') != 'grade':
            return

        student_module, created = StudentModule.objects.get_or_create(
            course_id=course_id,
            student=user,
            module_type=descriptor.location.category,
            module_state_key=descriptor.location.url(),
            defaults={'state': '{}'},
        )
        student_module.grade = event.get('value')
        student_module.max_grade = event.get('max_value')
        student_module.save()

        #Bin score into range and increment stats
        score_bucket = get_score_bucket(student_module.grade,
                                        student_module.max_grade)
        org, course_num, run = course_id.split("/")

        tags = [
            "org:{0}".format(org), "course:{0}".format(course_num),
            "run:{0}".format(run), "score_bucket:{0}".format(score_bucket)
        ]

        if grade_bucket_type is not None:
            tags.append('type:%s' % grade_bucket_type)

        statsd.increment("lms.courseware.question_answered", tags=tags)

    def can_execute_unsafe_code():
        # To decide if we can run unsafe code, we check the course id against
        # a list of regexes configured on the server.
        for regex in settings.COURSES_WITH_UNSAFE_CODE:
            if re.match(regex, course_id):
                return True
        return False

    # TODO (cpennington): When modules are shared between courses, the static
    # prefix is going to have to be specific to the module, not the directory
    # that the xml was loaded from
    system = ModuleSystem(
        track_function=make_track_function(request),
        render_template=render_to_string,
        ajax_url=ajax_url,
        xqueue=xqueue,
        # TODO (cpennington): Figure out how to share info between systems
        filestore=descriptor.system.resources_fs,
        get_module=inner_get_module,
        user=user,
        # TODO (cpennington): This should be removed when all html from
        # a module is coming through get_html and is therefore covered
        # by the replace_static_urls code below
        replace_urls=partial(
            static_replace.replace_static_urls,
            data_directory=getattr(descriptor, 'data_dir', None),
            course_namespace=descriptor.location._replace(category=None,
                                                          name=None),
        ),
        node_path=settings.NODE_PATH,
        xblock_model_data=xblock_model_data,
        publish=publish,
        anonymous_student_id=unique_id_for_user(user),
        course_id=course_id,
        open_ended_grading_interface=open_ended_grading_interface,
        s3_interface=s3_interface,
        cache=cache,
        can_execute_unsafe_code=can_execute_unsafe_code,
    )
    # pass position specified in URL to module through ModuleSystem
    system.set('position', position)
    system.set('DEBUG', settings.DEBUG)
    if settings.MITX_FEATURES.get('ENABLE_PSYCHOMETRICS'):
        system.set(
            'psychometrics_handler',  # set callback for updating PsychometricsData
            make_psychometrics_data_update_handler(course_id, user,
                                                   descriptor.location.url()))

    try:
        module = descriptor.xmodule(system)
    except:
        log.exception(
            "Error creating module from descriptor {0}".format(descriptor))

        # make an ErrorDescriptor -- assuming that the descriptor's system is ok
        if has_access(user, descriptor.location, 'staff', course_id):
            err_descriptor_class = ErrorDescriptor
        else:
            err_descriptor_class = NonStaffErrorDescriptor

        err_descriptor = err_descriptor_class.from_xml(
            str(descriptor),
            descriptor.system,
            org=descriptor.location.org,
            course=descriptor.location.course,
            error_msg=exc_info_to_str(sys.exc_info()))

        # Make an error module
        return err_descriptor.xmodule(system)

    system.set('user_is_staff',
               has_access(user, descriptor.location, 'staff', course_id))
    _get_html = module.get_html

    if wrap_xmodule_display == True:
        _get_html = wrap_xmodule(module.get_html, module,
                                 'xmodule_display.html')

    module.get_html = replace_static_urls(
        _get_html,
        getattr(descriptor, 'data_dir', None),
        course_namespace=module.location._replace(category=None, name=None))

    # Allow URLs of the form '/course/' refer to the root of multicourse directory
    #   hierarchy of this course
    module.get_html = replace_course_urls(module.get_html, course_id)

    if settings.MITX_FEATURES.get('DISPLAY_HISTOGRAMS_TO_STAFF'):
        if has_access(user, module, 'staff', course_id):
            module.get_html = add_histogram(module.get_html, module, user)

    return module
예제 #36
0
파일: views.py 프로젝트: alexmerser/lms
def _index_bulk_op(request, course_key, chapter, section, position):
    """
    Render the index page for the specified course.
    """
    user = request.user
    course = get_course_with_access(user, 'load', course_key, depth=2)

    staff_access = has_access(user, 'staff', course)
    registered = registered_for_course(course, user)
    if not registered:
        # TODO (vshnayder): do course instructors need to be registered to see course?
        log.debug(u'User %s tried to view course %s but is not enrolled', user, course.location.to_deprecated_string())
        return redirect(reverse('about_course', args=[course_key.to_deprecated_string()]))

    # see if all pre-requisites (as per the milestones app feature) have been fulfilled
    # Note that if the pre-requisite feature flag has been turned off (default) then this check will
    # always pass
    if not has_access(user, 'view_courseware_with_prerequisites', course):
        # prerequisites have not been fulfilled therefore redirect to the Dashboard
        log.info(
            u'User %d tried to view course %s '
            u'without fulfilling prerequisites',
            user.id, unicode(course.id))
        return redirect(reverse('dashboard'))

    # check to see if there is a required survey that must be taken before
    # the user can access the course.
    if survey.utils.must_answer_survey(course, user):
        return redirect(reverse('course_survey', args=[unicode(course.id)]))

    masquerade = setup_masquerade(request, course_key, staff_access)

    try:
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course_key, user, course, depth=2)

        course_module = get_module_for_descriptor(user, request, course, field_data_cache, course_key)
        if course_module is None:
            log.warning(u'If you see this, something went wrong: if we got this'
                        u' far, should have gotten a course module for this user')
            return redirect(reverse('about_course', args=[course_key.to_deprecated_string()]))

        studio_url = get_studio_url(course, 'course')

        context = {
            'csrf': csrf(request)['csrf_token'],
            'accordion': render_accordion(request, course, chapter, section, field_data_cache),
            'COURSE_TITLE': course.display_name_with_default,
            'course': course,
            'init': '',
            'fragment': Fragment(),
            'staff_access': staff_access,
            'studio_url': studio_url,
            'masquerade': masquerade,
            'xqa_server': settings.FEATURES.get('USE_XQA_SERVER', 'http://*****:*****@content-qa.mitx.mit.edu/xqa'),
            'reverifications': fetch_reverify_banner_info(request, course_key),
        }

        now = datetime.now(UTC())
        effective_start = _adjust_start_date_for_beta_testers(user, course, course_key)
        if staff_access and now < effective_start:
            # Disable student view button if user is staff and
            # course is not yet visible to students.
            context['disable_student_access'] = True

        has_content = course.has_children_at_depth(CONTENT_DEPTH)
        if not has_content:
            # Show empty courseware for a course with no units
            return render_to_response('courseware/courseware.html', context)
        elif chapter is None:
            # passing CONTENT_DEPTH avoids returning 404 for a course with an
            # empty first section and a second section with content
            return redirect_to_course_position(course_module, CONTENT_DEPTH)

        # Only show the chat if it's enabled by the course and in the
        # settings.
        show_chat = course.show_chat and settings.FEATURES['ENABLE_CHAT']
        if show_chat:
            context['chat'] = chat_settings(course, user)
            # If we couldn't load the chat settings, then don't show
            # the widget in the courseware.
            if context['chat'] is None:
                show_chat = False

        context['show_chat'] = show_chat

        chapter_descriptor = course.get_child_by(lambda m: m.location.name == chapter)
        if chapter_descriptor is not None:
            save_child_position(course_module, chapter)
        else:
            raise Http404('No chapter descriptor found with name {}'.format(chapter))

        chapter_module = course_module.get_child_by(lambda m: m.location.name == chapter)
        if chapter_module is None:
            # User may be trying to access a chapter that isn't live yet
            if masquerade and masquerade.role == 'student':  # if staff is masquerading as student be kinder, don't 404
                log.debug('staff masquerading as student: no chapter %s', chapter)
                return redirect(reverse('courseware', args=[course.id.to_deprecated_string()]))
            raise Http404

        if section is not None:
            section_descriptor = chapter_descriptor.get_child_by(lambda m: m.location.name == section)

            if section_descriptor is None:
                # Specifically asked-for section doesn't exist
                if masquerade and masquerade.role == 'student':  # don't 404 if staff is masquerading as student
                    log.debug('staff masquerading as student: no section %s', section)
                    return redirect(reverse('courseware', args=[course.id.to_deprecated_string()]))
                raise Http404

            ## Allow chromeless operation
            if section_descriptor.chrome:
                chrome = [s.strip() for s in section_descriptor.chrome.lower().split(",")]
                if 'accordion' not in chrome:
                    context['disable_accordion'] = True
                if 'tabs' not in chrome:
                    context['disable_tabs'] = True

            if section_descriptor.default_tab:
                context['default_tab'] = section_descriptor.default_tab

            # cdodge: this looks silly, but let's refetch the section_descriptor with depth=None
            # which will prefetch the children more efficiently than doing a recursive load
            section_descriptor = modulestore().get_item(section_descriptor.location, depth=None)

            # Load all descendants of the section, because we're going to display its
            # html, which in general will need all of its children
            section_field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
                course_key, user, section_descriptor, depth=None, asides=XBlockAsidesConfig.possible_asides()
            )

            # Verify that position a string is in fact an int
            if position is not None:
                try:
                    int(position)
                except ValueError:
                    raise Http404("Position {} is not an integer!".format(position))

            section_module = get_module_for_descriptor(
                request.user,
                request,
                section_descriptor,
                section_field_data_cache,
                course_key,
                position
            )

            if section_module is None:
                # User may be trying to be clever and access something
                # they don't have access to.
                raise Http404

            # Save where we are in the chapter
            save_child_position(chapter_module, section)
            context['fragment'] = section_module.render(STUDENT_VIEW)
            context['section_title'] = section_descriptor.display_name_with_default
        else:
            # section is none, so display a message
            studio_url = get_studio_url(course, 'course')
            prev_section = get_current_child(chapter_module)
            if prev_section is None:
                # Something went wrong -- perhaps this chapter has no sections visible to the user.
                # Clearing out the last-visited state and showing "first-time" view by redirecting
                # to courseware.
                course_module.position = None
                course_module.save()
                return redirect(reverse('courseware', args=[course.id.to_deprecated_string()]))
            prev_section_url = reverse('courseware_section', kwargs={
                'course_id': course_key.to_deprecated_string(),
                'chapter': chapter_descriptor.url_name,
                'section': prev_section.url_name
            })
            context['fragment'] = Fragment(content=render_to_string(
                'courseware/welcome-back.html',
                {
                    'course': course,
                    'studio_url': studio_url,
                    'chapter_module': chapter_module,
                    'prev_section': prev_section,
                    'prev_section_url': prev_section_url
                }
            ))

        result = render_to_response('courseware/courseware.html', context)
    except Exception as e:

        # Doesn't bar Unicode characters from URL, but if Unicode characters do
        # cause an error it is a graceful failure.
        if isinstance(e, UnicodeEncodeError):
            raise Http404("URL contains Unicode characters")

        if isinstance(e, Http404):
            # let it propagate
            raise

        # In production, don't want to let a 500 out for any reason
        if settings.DEBUG:
            raise
        else:
            log.exception(
                u"Error in index view: user={user}, course={course}, chapter={chapter}"
                u" section={section} position={position}".format(
                    user=user,
                    course=course,
                    chapter=chapter,
                    section=section,
                    position=position
                ))
            try:
                result = render_to_response('courseware/courseware-error.html', {
                    'staff_access': staff_access,
                    'course': course
                })
            except:
                # Let the exception propagate, relying on global config to at
                # at least return a nice error message
                log.exception("Error while rendering courseware-error page")
                raise

    return result
예제 #37
0
def index(request, course_id):
    # Palette
    color_not = '#CCCCCC'
    color_fail = '#e41a1c'
    color_ok = '#F2F20D'
    color_prof = '#4daf4a'
    problem_activity='#377eb8'
    video_activity='#ff7f00'
    video_repetition='#fdbf6f'
    course_activity='#984ea3'
    graded_time='#88419d'
    ungraded_time='#8c6bb1'
    chapter_time='#8c96c6'
    play_event='#1b9e77'
    pause_event='#d95f02'
    seek_from_event='#7570b3'
    seek_to_event='#e7298a'
    change_speed_event='#66a61e'
    morning_time='#C9C96C'
    afternoon_time ='#7F7160'
    night_time ='#50587C'
    # Request data
    course_key = get_course_key(course_id)
    course = get_course_module(course_key)
    #course2= get_course_by_id(SlashSeparatedCourseKey.from_deprecated_string(course_id))
    #user = request.user #Codigo Jose A. Gascon
    staff_access = has_access(request.user, 'staff', course).has_access#Codigo Jose A. Gascon
    instructor_access = has_access(request.user, 'instructor', course).has_access#Codigo Jose A. Gascon
    #Codigo Jose A. Gascon
    masq, user = setup_masquerade(request, course_key,staff_access, reset_masquerade_data=True)  # allow staff to toggle masquerade on info page
    user = request.user
    studio_url = get_studio_url(course, 'course_info')
    
    #reverifications = fetch_reverify_banner_info(request, course_key)
    #course = get_course_with_access(request.user, action='load', course_key=course_key, depth=None, check_if_enrolled=False)
    #user = User.objects.get(request.user.email)
    # Proficiency and pass limit
    pass_limit = get_course_grade_cutoff(course)
    proficiency_limit = (1 - pass_limit) / 2 + pass_limit
    usernames_in = []
    for student in CourseEnrollment.objects.users_enrolled_in(course_key):#Codigo Jose A. Gascon, se cambia la forma de llamar al metode users_enrolled_in
        usernames_in.append(student.username.encode('utf-8'))


    # Data for visualization in JSON
    user_for_charts = '#average' if (staff_access or instructor_access) else user
    kwargs = {
        'qualifiers': {'category': 'video', },
    }     
    # This returns video descriptors in the order they appear on the course
    video_descriptors = videos_problems_in(course)[0]
    #WARNINIG 
    #video_durations = get_info_videos_descriptors(video_descriptors)[2]
    #video_names, video_module_keys, video_durations = get_info_videos_descriptors(video_descriptors) # NO SE USAN LAS OTRAS VARIABLES
    video_names, video_module_keys, video_durations =get_DB_infovideos(course_key)
    video_names_sorted = video_names
    video_ids_sort = video_names_sorted

    #course_name = get_course_by_id(course_key, depth=None)
    names_students=[]
    only_students = []
    students_names = get_course_students(course_key)
    print students_names
    for student in students_names:
        staff_access_user = has_access(student, 'staff', course).has_access
        instructor_access_user = has_access(student, 'instructor', course).has_access
        if not (staff_access_user or instructor_access_user):
            names_students.append(student.username.encode('utf-8'))
            only_students.append(student)

    video_ids_str = []
    course_video_names = []
    problem_ids_str=[]
    for descriptor in video_descriptors:
        video_ids_str.append((course_key.make_usage_key('video', descriptor.location.name))._to_string())
        course_video_names.append(unicodedata.normalize('NFKD', descriptor.display_name_with_default).encode('ASCII', 'ignore'))
    if len(video_descriptors) > 0:
        first_video_id = course_key.make_usage_key('video', video_descriptors[0].location.name)
        # Video progress visualization. Video percentage seen total and non-overlapped.
        video_names, avg_video_time, video_percentages = get_video_time_watched(user_for_charts, course_key)  
        if avg_video_time != []:
            all_video_time_percent = map(truediv, avg_video_time, video_durations)
            all_video_time_percent = [int(round(x*100,0)) for x in all_video_time_percent]
        else:
            all_video_time_percent = avg_video_time


        column_headers = ['Video', 'Different video time', 'Total video time']
        # Codigo Javier Orcoyen
        video_prog_json = ready_for_arraytodatatable(column_headers, video_names, video_percentages, all_video_time_percent)
        video_names, all_video_time = get_module_consumption(user_for_charts, course_key, 'video')
        # Time spent on every video resource
        column_headers = ['Video', 'Time watched']
        video_distrib_json = ready_for_arraytodatatable(column_headers, video_names, all_video_time)
  
        # Video events dispersion within video length
        scatter_array = get_video_events_info(user_for_charts, first_video_id)    
  
        # Repetitions per video intervals
        user_for_vid_intervals = '#class_total_times' if user_for_charts == '#average' else user_for_charts
        video_intervals_array = get_user_video_intervals(user_for_vid_intervals, first_video_id)        

    # Case no videos in course
    else:
        video_names = None
        video_prog_json = json.dumps(None)
        video_distrib_json = json.dumps(None)
        scatter_array = json.dumps(None)
        video_intervals_array = json.dumps(None)
          
    # Time spent on every problem resource
    # Codigo Javier Orcoyen
    problem_names, time_x_problem = get_module_consumption(user_for_charts, course_key, 'problem')
    column_headers = ['Problem', 'Time on problem']
    problem_distrib_json = ready_for_arraytodatatable(column_headers, problem_names, time_x_problem)
    print 'USER'
    print user
    problems_in = videos_problems_in(course)[1]
    problem_names_sorted = [x.display_name_with_default.encode('utf-8') for x in problems_in]
    orden=[]
    orden.append(i for i, x in enumerate(problem_names_sorted))
    problem_ids_str=list(problem_names_sorted)
    for n in range(len(problem_names_sorted)):
        problem_names_sorted[n]= unicodedata.normalize('NFKD', unicode(problem_names_sorted[n],'utf-8')).encode('ASCII', 'ignore')
        problem_ids_str[n]= unicodedata.normalize('NFKD', unicode(problem_ids_str[n],'utf-8')).encode('ASCII', 'ignore')
    user_val=1
    # Daily time spent on video and/or problem resources
    video_days, video_daily_time = get_daily_consumption(user_for_charts, course_key, 'video')
    problem_days, problem_daily_time = get_daily_consumption(user_for_charts, course_key, 'problem')    
    vid_and_prob_daily_time = join_video_problem_time(video_days, video_daily_time, problem_days, problem_daily_time) 
    #Analytics visualizations
    if staff_access or instructor_access:
        # Instructor access
        std_sort = get_DB_sort_course_homework(course_key)
        # Chapter time
        cs, st = get_DB_course_spent_time(course_key, student_id=ALL_STUDENTS)
        students_spent_time = chapter_time_to_js(cs, st)
        students_grades = get_DB_student_grades(course_key, student_id=ALL_STUDENTS) 
        cs, sa = course_accesses = get_DB_course_section_accesses(course_key, student_id=ALL_STUDENTS)
        students_course_accesses = course_accesses_to_js(cs, sa)
        #students_prob_vid_progress = get_DB_course_video_problem_progress(course_key, student_id=ALL_STUDENTS)# C. J. A. Gascon ERROR
        students_time_schedule = get_DB_time_schedule(course_key, student_id=ALL_STUDENTS)
    else:
        # Sort homework                    
        # Chapter time
        std_sort = None
        cs, st = get_DB_course_spent_time(course_key, user.id)
        students_spent_time = chapter_time_to_js(cs, st) 
        students_grades = get_DB_student_grades(course_key, user.id) 
        cs, sa = course_accesses = get_DB_course_section_accesses(course_key, user.id)
        students_course_accesses = course_accesses_to_js(cs, sa) 
        students_time_schedule = get_DB_time_schedule(course_key, user.id)  
        #students_prob_vid_progress = get_DB_course_video_problem_progress(course_key, user.id)  #C. J. A. Gascon ERROR

    context = {'course': course,
               'request': request,
               'user': user,
               'user_id': user.id,
               'staff_access': staff_access,
               'instructor_access': instructor_access,
               'masquerade': masq,
               'studio_url': studio_url,
               #'reverifications': reverifications,
               'course_id': course_id,
               'students': students_to_js(only_students),
               'visualizations_id': VISUALIZATIONS_ID,
               'std_grades_dump': dumps(students_grades),
               'sort_std_dump': dumps(std_sort),
               'time_dump': dumps(students_spent_time),
               'accesses_dump': dumps(students_course_accesses),
               'std_time_schedule_dumb': dumps(students_time_schedule), 
               #'vid_prob_prog_dump': dumps(students_prob_vid_progress), #C. J. A. Gascon ERROR
               'pass_limit': pass_limit,
               'prof_limit': proficiency_limit,
               'usernames_in' : usernames_in,
               'video_names' : course_video_names,
               'video_ids' : video_ids_str,
               'video_prog_json' : video_prog_json,
               'video_distrib_json' : video_distrib_json,
               'problem_distrib_json' : problem_distrib_json,
               'video_intervals_array' : video_intervals_array,
               'vid_and_prob_daily_time' : vid_and_prob_daily_time,
               'scatter_array' : scatter_array,
               'problem_names' : problem_names,
               'problem_ids' : problem_ids_str,
               'color_not' : color_not,
               'color_ok' : color_ok,
               'color_prof' : color_prof,
               'color_fail' : color_fail,
               'problem_activity' : problem_activity,
               'video_activity' : video_activity,
               'course_activity' : course_activity,
               'video_repetition' : video_repetition,
               'graded_time' : graded_time,
               'ungraded_time' : ungraded_time,
               'chapter_time' : chapter_time,
               'user_for_charts' : user_for_charts,
               'video_ids_sort' : video_ids_sort,
               'video_names_sorted' : video_names_sorted,
               'problem_names_sorted' : problem_names_sorted,
               'play_event' : play_event,
               'pause_event' : pause_event,
               'seek_from_event' : seek_from_event,
               'seek_to_event' : seek_to_event,
               'change_speed_event' : change_speed_event,
               'morning_time' : morning_time,
               'afternoon_time' : afternoon_time,
               'night_time' : night_time,
               'names_students' : names_students,
               'user_val' : user_val,}
        
    return render_to_response('learning_analytics/learning_analytics.html', context)    
 def initialize(self, **kwargs):
     if 'request' in kwargs and kwargs['request'] and kwargs['course_id']:
         request = kwargs['request']
         course_key = CourseKey.from_string(kwargs['course_id'])
         staff_access = bool(has_access(request.user, 'staff', course_key))
         setup_masquerade(request, course_key, staff_access)
예제 #39
0
def index(request, course_id, chapter=None, section=None, position=None):
    """
    Displays courseware accordion and associated content.  If course, chapter,
    and section are all specified, renders the page, or returns an error if they
    are invalid.

    If section is not specified, displays the accordion opened to the right chapter.

    If neither chapter or section are specified, redirects to user's most recent
    chapter, or the first chapter if this is the user's first visit.

    Arguments:

     - request    : HTTP request
     - course_id  : course id (str: ORG/course/URL_NAME)
     - chapter    : chapter url_name (str)
     - section    : section url_name (str)
     - position   : position in module, eg of <sequential> module (str)

    Returns:

     - HTTPresponse
    """
    user = User.objects.prefetch_related("groups").get(id=request.user.id)
    request.user = user  # keep just one instance of User
    course = get_course_with_access(user, course_id, "load", depth=2)
    staff_access = has_access(user, course, "staff")
    registered = registered_for_course(course, user)
    if not registered:
        # TODO (vshnayder): do course instructors need to be registered to see course?
        log.debug("User %s tried to view course %s but is not enrolled" % (user, course.location.url()))
        return redirect(reverse("about_course", args=[course.id]))

    masq = setup_masquerade(request, staff_access)

    try:
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(course.id, user, course, depth=2)

        course_module = get_module_for_descriptor(user, request, course, field_data_cache, course.id)
        if course_module is None:
            log.warning(
                "If you see this, something went wrong: if we got this"
                " far, should have gotten a course module for this user"
            )
            return redirect(reverse("about_course", args=[course.id]))

        if chapter is None:
            return redirect_to_course_position(course_module)

        context = {
            "csrf": csrf(request)["csrf_token"],
            "accordion": render_accordion(request, course, chapter, section, field_data_cache),
            "COURSE_TITLE": course.display_name_with_default,
            "course": course,
            "init": "",
            "fragment": Fragment(),
            "staff_access": staff_access,
            "masquerade": masq,
            "xqa_server": settings.FEATURES.get("USE_XQA_SERVER", "http://*****:*****@content-qa.mitx.mit.edu/xqa"),
        }

        # Only show the chat if it's enabled by the course and in the
        # settings.
        show_chat = course.show_chat and settings.FEATURES["ENABLE_CHAT"]
        if show_chat:
            context["chat"] = chat_settings(course, user)
            # If we couldn't load the chat settings, then don't show
            # the widget in the courseware.
            if context["chat"] is None:
                show_chat = False

        context["show_chat"] = show_chat

        chapter_descriptor = course.get_child_by(lambda m: m.url_name == chapter)
        if chapter_descriptor is not None:
            save_child_position(course_module, chapter)
        else:
            raise Http404("No chapter descriptor found with name {}".format(chapter))

        chapter_module = course_module.get_child_by(lambda m: m.url_name == chapter)
        if chapter_module is None:
            # User may be trying to access a chapter that isn't live yet
            if masq == "student":  # if staff is masquerading as student be kinder, don't 404
                log.debug("staff masq as student: no chapter %s" % chapter)
                return redirect(reverse("courseware", args=[course.id]))
            raise Http404

        if section is not None:
            section_descriptor = chapter_descriptor.get_child_by(lambda m: m.url_name == section)
            if section_descriptor is None:
                # Specifically asked-for section doesn't exist
                if masq == "student":  # if staff is masquerading as student be kinder, don't 404
                    log.debug("staff masq as student: no section %s" % section)
                    return redirect(reverse("courseware", args=[course.id]))
                raise Http404

            # cdodge: this looks silly, but let's refetch the section_descriptor with depth=None
            # which will prefetch the children more efficiently than doing a recursive load
            section_descriptor = modulestore().get_instance(course.id, section_descriptor.location, depth=None)

            # Load all descendants of the section, because we're going to display its
            # html, which in general will need all of its children
            section_field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
                course_id, user, section_descriptor, depth=None
            )

            section_module = get_module_for_descriptor(
                request.user, request, section_descriptor, section_field_data_cache, course_id, position
            )

            if section_module is None:
                # User may be trying to be clever and access something
                # they don't have access to.
                raise Http404

            # Save where we are in the chapter
            save_child_position(chapter_module, section)
            context["fragment"] = section_module.render("student_view")

        else:
            # section is none, so display a message
            prev_section = get_current_child(chapter_module)
            if prev_section is None:
                # Something went wrong -- perhaps this chapter has no sections visible to the user
                raise Http404
            prev_section_url = reverse(
                "courseware_section",
                kwargs={
                    "course_id": course_id,
                    "chapter": chapter_descriptor.url_name,
                    "section": prev_section.url_name,
                },
            )
            context["fragment"] = Fragment(
                content=render_to_string(
                    "courseware/welcome-back.html",
                    {
                        "course": course,
                        "chapter_module": chapter_module,
                        "prev_section": prev_section,
                        "prev_section_url": prev_section_url,
                    },
                )
            )

        result = render_to_response("courseware/courseware.html", context)
    except Exception as e:
        if isinstance(e, Http404):
            # let it propagate
            raise

        # In production, don't want to let a 500 out for any reason
        if settings.DEBUG:
            raise
        else:
            log.exception(
                "Error in index view: user={user}, course={course},"
                " chapter={chapter} section={section}"
                "position={position}".format(
                    user=user, course=course, chapter=chapter, section=section, position=position
                )
            )
            try:
                result = render_to_response(
                    "courseware/courseware-error.html", {"staff_access": staff_access, "course": course}
                )
            except:
                # Let the exception propagate, relying on global config to at
                # at least return a nice error message
                log.exception("Error while rendering courseware-error page")
                raise

    return result
예제 #40
0
def _invoke_xblock_handler(request, course_id, usage_id, handler, suffix, user):
    """
    Invoke an XBlock handler, either authenticated or not.

    Arguments:
        request (HttpRequest): the current request
        course_id (str): A string of the form org/course/run
        usage_id (str): A string of the form i4x://org/course/category/name@revision
        handler (str): The name of the handler to invoke
        suffix (str): The suffix to pass to the handler when invoked
        user (User): The currently logged in user

    """
    try:
        course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id)
        usage_key = course_id.make_usage_key_from_deprecated_string(unquote_slashes(usage_id))
    except InvalidKeyError:
        raise Http404("Invalid location")

    # Check submitted files
    files = request.FILES or {}
    error_msg = _check_files_limits(files)
    if error_msg:
        return HttpResponse(json.dumps({"success": error_msg}))

    try:
        descriptor = modulestore().get_item(usage_key)
        descriptor_orig_usage_key, descriptor_orig_version = modulestore().get_block_original_usage(usage_key)
    except ItemNotFoundError:
        log.warn(
            "Invalid location for course id {course_id}: {usage_key}".format(
                course_id=usage_key.course_key, usage_key=usage_key
            )
        )
        raise Http404

    tracking_context_name = "module_callback_handler"
    tracking_context = {
        "module": {"display_name": descriptor.display_name_with_default, "usage_key": unicode(descriptor.location)}
    }
    # For blocks that are inherited from a content library, we add some additional metadata:
    if descriptor_orig_usage_key is not None:
        tracking_context["module"]["original_usage_key"] = unicode(descriptor_orig_usage_key)
        tracking_context["module"]["original_usage_version"] = unicode(descriptor_orig_version)

    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(course_id, user, descriptor)
    setup_masquerade(request, course_id, has_access(user, "staff", descriptor, course_id))
    instance = get_module(user, request, usage_key, field_data_cache, grade_bucket_type="ajax")
    if instance is None:
        # Either permissions just changed, or someone is trying to be clever
        # and load something they shouldn't have access to.
        log.debug("No module %s for user %s -- access denied?", usage_key, user)
        raise Http404

    req = django_to_webob_request(request)
    try:
        with tracker.get_tracker().context(tracking_context_name, tracking_context):
            resp = instance.handle(handler, req, suffix)

    except NoSuchHandlerError:
        log.exception("XBlock %s attempted to access missing handler %r", instance, handler)
        raise Http404

    # If we can't find the module, respond with a 404
    except NotFoundError:
        log.exception("Module indicating to user that request doesn't exist")
        raise Http404

    # For XModule-specific errors, we log the error and respond with an error message
    except ProcessingError as err:
        log.warning("Module encountered an error while processing AJAX call", exc_info=True)
        return JsonResponse(object={"success": err.args[0]}, status=200)

    # If any other error occurred, re-raise it to trigger a 500 response
    except Exception:
        log.exception("error executing xblock handler")
        raise

    return webob_to_django_response(resp)
예제 #41
0
def mobi_directory(request, course_id):
    user = User.objects.prefetch_related("groups").get(id=request.user.id)
    request.user = user  # keep just one instance of User
    course = get_course_with_access(user, course_id, 'load', depth=2)
    staff_access = has_access(user, course, 'staff')
    registered = registered_for_course(course, user)

    motoc = mobi_toc_for_course(user, request, course)
    show_list = list()
    for toc in motoc:
        videolist = toc['show_url'][0]
        show_list.append(videolist)
    if not registered:
        # TODO (vshnayder): do course instructors need to be registered to see course?
        log.debug(u'User %s tried to view course %s but is not enrolled', user, course.location.url())
        return redirect(reverse('about_course', args=[course.id]))

    masq = setup_masquerade(request, staff_access)

    try:
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course.id, user, course, depth=2)

        course_module = get_module_for_descriptor(user, request, course, field_data_cache, course.id)
        if course_module is None:
            log.warning(u'If you see this, something went wrong: if we got this'
                        u' far, should have gotten a course module for this user')
            return redirect(reverse('about_course', args=[course.id]))
        context = {
            'csrf': csrf(request)['csrf_token'],
            'accordion': mobi_render_accordion(request, course),
            'COURSE_TITLE': course.display_name_with_default,
            'course': course,
            'init': '',
            'fragment': Fragment(),
            'staff_access': staff_access,
            'masquerade': masq,
            'xqa_server': settings.FEATURES.get('USE_XQA_SERVER', 'http://*****:*****@content-qa.mitx.mit.edu/xqa'),
            'reverifications': fetch_reverify_banner_info(request, course_id),
            'show_url': show_list[0],
            }
        result = render_to_response('wechat/mobi_directory.html', context)
    except Exception as e:
        if isinstance(e, Http404):
            # let it propagate
            raise

        # In production, don't want to let a 500 out for any reason
        if settings.DEBUG:
            raise
        else:
            log.exception("Error in index view: user={user}, course={course},".format(
                              user=user,
                              course=course,))
            try:
                result = render_to_response('courseware/courseware-error.html',
                                            {'staff_access': staff_access,
                                            'course': course})
            except:
                # Let the exception propagate, relying on global config to at
                # at least return a nice error message
                log.exception("Error while rendering courseware-error page")
                raise
    return result
예제 #42
0
파일: views.py 프로젝트: taozeze/ANALYSE
def index(request, course_id):

    # Request data
    course_key = get_course_key(course_id)
    course = get_course_module(course_key)
    user = request.user
    staff_access = has_access(request.user, 'staff', course)
    instructor_access = has_access(request.user, 'instructor', course)
    masq = setup_masquerade(
        request, staff_access)  # allow staff to toggle masquerade on info page
    studio_url = get_studio_url(course, 'course_info')
    reverifications = fetch_reverify_banner_info(request, course_key)

    #course = get_course_with_access(request.user, action='load', course_key=course_key, depth=None, check_if_enrolled=False)

    # Proficiency and pass limit
    pass_limit = get_course_grade_cutoff(course)
    proficiency_limit = (1 - pass_limit) / 2 + pass_limit

    usernames_in = []
    for student in CourseEnrollment.users_enrolled_in(course_key):
        usernames_in.append(student.username.encode('utf-8'))

    # Data for visualization in JSON
    user_for_charts = '#average' if (staff_access
                                     or instructor_access) else user
    kwargs = {
        'qualifiers': {
            'category': 'video',
        },
    }

    # This returns video descriptors in the order they appear on the course
    video_descriptors = videos_problems_in(course)[0]
    video_durations = get_info_videos_descriptors(video_descriptors)[2]

    video_ids_str = []
    course_video_names = []
    for descriptor in video_descriptors:
        video_ids_str.append(
            (course_key.make_usage_key('video',
                                       descriptor.location.name))._to_string())
        course_video_names.append(descriptor.display_name_with_default)

    if len(video_descriptors) > 0:
        first_video_id = course_key.make_usage_key(
            'video', video_descriptors[0].location.name)
        # Video progress visualization. Video percentage seen total and non-overlapped.
        video_names, avg_video_time, video_percentages = get_module_consumption(
            user_for_charts, course_key, 'video', 'video_progress')
        if avg_video_time != []:
            all_video_time_percent = map(truediv, avg_video_time,
                                         video_durations)
            all_video_time_percent = [
                int(round(x * 100, 0)) for x in all_video_time_percent
            ]
        else:
            all_video_time_percent = avg_video_time

        column_headers = ['Video', 'Different video time', 'Total video time']
        video_prog_json = ready_for_arraytodatatable(column_headers,
                                                     video_names,
                                                     video_percentages,
                                                     all_video_time_percent)

        video_names, all_video_time = get_module_consumption(
            user_for_charts, course_key, 'video', 'total_time_vid_prob')[0:2]
        # Time spent on every video resource
        column_headers = ['Video', 'Time watched']
        video_distrib_json = ready_for_arraytodatatable(
            column_headers, video_names, all_video_time)

        # Video events dispersion within video length
        scatter_array = get_video_events_info(user_for_charts, first_video_id)

        # Repetitions per video intervals
        user_for_vid_intervals = '#class_total_times' if user_for_charts == '#average' else user_for_charts
        video_intervals_array = get_user_video_intervals(
            user_for_vid_intervals, first_video_id)

    # Case no videos in course
    else:
        video_names = None
        video_prog_json = simplejson.dumps(None)
        video_distrib_json = simplejson.dumps(None)
        scatter_array = simplejson.dumps(None)
        video_intervals_array = simplejson.dumps(None)

    # Time spent on every problem resource
    problem_names, time_x_problem = get_module_consumption(
        user_for_charts, course_key, 'problem', 'total_time_vid_prob')[0:2]
    column_headers = ['Problem', 'Time on problem']
    problem_distrib_json = ready_for_arraytodatatable(column_headers,
                                                      problem_names,
                                                      time_x_problem)

    # Daily time spent on video and/or problem resources
    video_days, video_daily_time = get_daily_consumption(
        user_for_charts, course_key, 'video')
    problem_days, problem_daily_time = get_daily_consumption(
        user_for_charts, course_key, 'problem')
    vid_and_prob_daily_time = join_video_problem_time(video_days,
                                                      video_daily_time,
                                                      problem_days,
                                                      problem_daily_time)

    #Analytics visualizations
    if staff_access or instructor_access:
        # Instructor access
        std_sort = get_DB_sort_course_homework(course_key)
        # Chapter time
        cs, st = get_DB_course_spent_time(course_key, student_id=ALL_STUDENTS)
        students_spent_time = chapter_time_to_js(cs, st)
        students_grades = get_DB_student_grades(course_key,
                                                student_id=ALL_STUDENTS)
        cs, sa = course_accesses = get_DB_course_section_accesses(
            course_key, student_id=ALL_STUDENTS)
        students_course_accesses = course_accesses_to_js(cs, sa)
        students_prob_vid_progress = get_DB_course_video_problem_progress(
            course_key, student_id=ALL_STUDENTS)
        students_time_schedule = get_DB_time_schedule(course_key,
                                                      student_id=ALL_STUDENTS)
    else:
        # Sort homework
        # Chapter time
        std_sort = None
        cs, st = get_DB_course_spent_time(course_key, user.id)
        students_spent_time = chapter_time_to_js(cs, st)
        students_grades = get_DB_student_grades(course_key, user.id)
        cs, sa = course_accesses = get_DB_course_section_accesses(
            course_key, user.id)
        students_course_accesses = course_accesses_to_js(cs, sa)
        students_time_schedule = get_DB_time_schedule(course_key, user.id)
        students_prob_vid_progress = get_DB_course_video_problem_progress(
            course_key, user.id)

    context = {
        'course': course,
        'request': request,
        'user': user,
        'user_id': user.id,
        'staff_access': staff_access,
        'instructor_access': instructor_access,
        'masquerade': masq,
        'studio_url': studio_url,
        'reverifications': reverifications,
        'course_id': course_id,
        'students': students_to_js(get_course_students(course_key)),
        'visualizations_id': VISUALIZATIONS_ID,
        'std_grades_dump': dumps(students_grades),
        'sort_std_dump': dumps(std_sort),
        'time_dump': dumps(students_spent_time),
        'accesses_dump': dumps(students_course_accesses),
        'std_time_schedule_dumb': dumps(students_time_schedule),
        'vid_prob_prog_dump': dumps(students_prob_vid_progress),
        'pass_limit': pass_limit,
        'prof_limit': proficiency_limit,
        'usernames_in': usernames_in,
        'video_names': course_video_names,
        'video_ids': video_ids_str,
        'video_prog_json': video_prog_json,
        'video_distrib_json': video_distrib_json,
        'problem_distrib_json': problem_distrib_json,
        'video_intervals_array': video_intervals_array,
        'vid_and_prob_daily_time': vid_and_prob_daily_time,
        'scatter_array': scatter_array,
    }

    return render_to_response('learning_analytics/learning_analytics.html',
                              context)
예제 #43
0
def index(request, course_id, chapter=None, section=None,
          position=None):
    """
    Displays courseware accordion and associated content.  If course, chapter,
    and section are all specified, renders the page, or returns an error if they
    are invalid.

    If section is not specified, displays the accordion opened to the right chapter.

    If neither chapter or section are specified, redirects to user's most recent
    chapter, or the first chapter if this is the user's first visit.

    Arguments:

     - request    : HTTP request
     - course_id  : course id (str: ORG/course/URL_NAME)
     - chapter    : chapter url_name (str)
     - section    : section url_name (str)
     - position   : position in module, eg of <sequential> module (str)

    Returns:

     - HTTPresponse
    """
    course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    user = User.objects.prefetch_related("groups").get(id=request.user.id)
    request.user = user  # keep just one instance of User
    course = get_course_with_access(user, 'load', course_key, depth=2)
    staff_access = has_access(user, 'staff', course)
    registered = registered_for_course(course, user)
    if not registered:
        # TODO (vshnayder): do course instructors need to be registered to see course?
        log.debug(u'User %s tried to view course %s but is not enrolled', user, course.location.to_deprecated_string())
        return redirect(reverse('about_course', args=[course_key.to_deprecated_string()]))

    masq = setup_masquerade(request, staff_access)

    try:
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course_key, user, course, depth=2)

        course_module = get_module_for_descriptor(user, request, course, field_data_cache, course_key)
        if course_module is None:
            log.warning(u'If you see this, something went wrong: if we got this'
                        u' far, should have gotten a course module for this user')
            return redirect(reverse('about_course', args=[course_key.to_deprecated_string()]))

        studio_url = get_studio_url(course_key, 'course')

        context = {
            'csrf': csrf(request)['csrf_token'],
            'accordion': render_accordion(request, course, chapter, section, field_data_cache),
            'COURSE_TITLE': course.display_name_with_default,
            'course': course,
            'init': '',
            'fragment': Fragment(),
            'staff_access': staff_access,
            'studio_url': studio_url,
            'masquerade': masq,
            'xqa_server': settings.FEATURES.get('USE_XQA_SERVER', 'http://*****:*****@content-qa.mitx.mit.edu/xqa'),
            'reverifications': fetch_reverify_banner_info(request, course_key),
        }

        has_content = course.has_children_at_depth(CONTENT_DEPTH)
        if not has_content:
            # Show empty courseware for a course with no units
            return render_to_response('courseware/courseware.html', context)
        elif chapter is None:
            # passing CONTENT_DEPTH avoids returning 404 for a course with an
            # empty first section and a second section with content
            return redirect_to_course_position(course_module, CONTENT_DEPTH)

        # Only show the chat if it's enabled by the course and in the
        # settings.
        show_chat = course.show_chat and settings.FEATURES['ENABLE_CHAT']
        if show_chat:
            context['chat'] = chat_settings(course, user)
            # If we couldn't load the chat settings, then don't show
            # the widget in the courseware.
            if context['chat'] is None:
                show_chat = False

        context['show_chat'] = show_chat

        chapter_descriptor = course.get_child_by(lambda m: m.location.name == chapter)
        if chapter_descriptor is not None:
            save_child_position(course_module, chapter)
        else:
            raise Http404('No chapter descriptor found with name {}'.format(chapter))

        chapter_module = course_module.get_child_by(lambda m: m.location.name == chapter)
        if chapter_module is None:
            # User may be trying to access a chapter that isn't live yet
            if masq == 'student':  # if staff is masquerading as student be kinder, don't 404
                log.debug('staff masq as student: no chapter %s' % chapter)
                return redirect(reverse('courseware', args=[course.id.to_deprecated_string()]))
            raise Http404

        if section is not None:
            section_descriptor = chapter_descriptor.get_child_by(lambda m: m.location.name == section)

            if section_descriptor is None:
                # Specifically asked-for section doesn't exist
                if masq == 'student':  # if staff is masquerading as student be kinder, don't 404
                    log.debug('staff masq as student: no section %s' % section)
                    return redirect(reverse('courseware', args=[course.id.to_deprecated_string()]))
                raise Http404

            ## Allow chromeless operation
            if section_descriptor.chrome:
                chrome = [s.strip() for s in section_descriptor.chrome.lower().split(",")]
                if 'accordion' not in chrome:
                    context['disable_accordion'] = True
                if 'tabs' not in chrome:
                    context['disable_tabs'] = True

            if section_descriptor.default_tab:
                context['default_tab'] = section_descriptor.default_tab

            # cdodge: this looks silly, but let's refetch the section_descriptor with depth=None
            # which will prefetch the children more efficiently than doing a recursive load
            section_descriptor = modulestore().get_item(section_descriptor.location, depth=None)

            # Load all descendants of the section, because we're going to display its
            # html, which in general will need all of its children
            section_field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
                course_key, user, section_descriptor, depth=None)

            # Verify that position a string is in fact an int
            if position is not None:
                try:
                    int(position)
                except ValueError:
                    raise Http404("Position {} is not an integer!".format(position))

            section_module = get_module_for_descriptor(
                request.user,
                request,
                section_descriptor,
                section_field_data_cache,
                course_key,
                position
            )

            if section_module is None:
                # User may be trying to be clever and access something
                # they don't have access to.
                raise Http404

            # Save where we are in the chapter
            save_child_position(chapter_module, section)
            context['fragment'] = section_module.render(STUDENT_VIEW)
            context['section_title'] = section_descriptor.display_name_with_default
        else:
            # section is none, so display a message
            studio_url = get_studio_url(course_key, 'course')
            prev_section = get_current_child(chapter_module)
            if prev_section is None:
                # Something went wrong -- perhaps this chapter has no sections visible to the user
                raise Http404
            prev_section_url = reverse('courseware_section', kwargs={
                'course_id': course_key.to_deprecated_string(),
                'chapter': chapter_descriptor.url_name,
                'section': prev_section.url_name
            })
            context['fragment'] = Fragment(content=render_to_string(
                'courseware/welcome-back.html',
                {
                    'course': course,
                    'studio_url': studio_url,
                    'chapter_module': chapter_module,
                    'prev_section': prev_section,
                    'prev_section_url': prev_section_url
                }
            ))

        result = render_to_response('courseware/courseware.html', context)
    except Exception as e:

        # Doesn't bar Unicode characters from URL, but if Unicode characters do
        # cause an error it is a graceful failure.
        if isinstance(e, UnicodeEncodeError):
            raise Http404("URL contains Unicode characters")

        if isinstance(e, Http404):
            # let it propagate
            raise

        # In production, don't want to let a 500 out for any reason
        if settings.DEBUG:
            raise
        else:
            log.exception(
                u"Error in index view: user={user}, course={course}, chapter={chapter}"
                u" section={section} position={position}".format(
                    user=user,
                    course=course,
                    chapter=chapter,
                    section=section,
                    position=position
                ))
            try:
                result = render_to_response('courseware/courseware-error.html', {
                    'staff_access': staff_access,
                    'course': course
                })
            except:
                # Let the exception propagate, relying on global config to at
                # at least return a nice error message
                log.exception("Error while rendering courseware-error page")
                raise

    return result
예제 #44
0
def index(request, course_id):
   
    # Request data
    course_key = get_course_key(course_id)
    course = get_course_module(course_key)
    user = request.user
    staff_access = has_access(request.user, 'staff', course)
    instructor_access = has_access(request.user, 'instructor', course)
    masq = setup_masquerade(request, staff_access)  # allow staff to toggle masquerade on info page
    studio_url = get_studio_url(course, 'course_info')
    reverifications = fetch_reverify_banner_info(request, course_key)
    
    #course = get_course_with_access(request.user, action='load', course_key=course_key, depth=None, check_if_enrolled=False)
    
    # Proficiency and pass limit
    pass_limit = get_course_grade_cutoff(course)
    proficiency_limit = (1 - pass_limit) / 2 + pass_limit
    
    usernames_in = []
    for student in CourseEnrollment.users_enrolled_in(course_key):
        usernames_in.append(student.username.encode('utf-8'))
              
  
    # Data for visualization in JSON
    user_for_charts = '#average' if (staff_access or instructor_access) else user
    kwargs = {
        'qualifiers': {'category': 'video', },
    }
          
    # This returns video descriptors in the order they appear on the course
    video_descriptors = videos_problems_in(course)[0]
    video_durations = get_info_videos_descriptors(video_descriptors)[2]
      
    video_ids_str = []
    course_video_names = []
    for descriptor in video_descriptors:
        video_ids_str.append((course_key.make_usage_key('video', descriptor.location.name))._to_string())
        course_video_names.append(descriptor.display_name_with_default)
  
    if len(video_descriptors) > 0:
        first_video_id = course_key.make_usage_key('video', video_descriptors[0].location.name)
        # Video progress visualization. Video percentage seen total and non-overlapped.
        video_names, avg_video_time, video_percentages = get_module_consumption(user_for_charts, course_key, 'video', 'video_progress')  
        if avg_video_time != []:
            all_video_time_percent = map(truediv, avg_video_time, video_durations)
            all_video_time_percent = [int(round(x*100,0)) for x in all_video_time_percent]
        else:
            all_video_time_percent = avg_video_time
            
        column_headers = ['Video', 'Different video time', 'Total video time']
        video_prog_json = ready_for_arraytodatatable(column_headers, video_names, video_percentages, all_video_time_percent)
        
        video_names, all_video_time = get_module_consumption(user_for_charts, course_key, 'video', 'total_time_vid_prob')[0:2]
        # Time spent on every video resource
        column_headers = ['Video', 'Time watched']
        video_distrib_json = ready_for_arraytodatatable(column_headers, video_names, all_video_time)
  
        # Video events dispersion within video length
        scatter_array = get_video_events_info(user_for_charts, first_video_id)    
  
        # Repetitions per video intervals
        user_for_vid_intervals = '#class_total_times' if user_for_charts == '#average' else user_for_charts
        video_intervals_array = get_user_video_intervals(user_for_vid_intervals, first_video_id)        
          
    # Case no videos in course
    else:
        video_names = None
        video_prog_json = simplejson.dumps(None)
        video_distrib_json = simplejson.dumps(None)
        scatter_array = simplejson.dumps(None)
        video_intervals_array = simplejson.dumps(None)
          
    # Time spent on every problem resource
    problem_names, time_x_problem = get_module_consumption(user_for_charts, course_key, 'problem', 'total_time_vid_prob')[0:2]    
    column_headers = ['Problem', 'Time on problem']
    problem_distrib_json = ready_for_arraytodatatable(column_headers, problem_names, time_x_problem)
      
    # Daily time spent on video and/or problem resources
    video_days, video_daily_time = get_daily_consumption(user_for_charts, course_key, 'video')
    problem_days, problem_daily_time = get_daily_consumption(user_for_charts, course_key, 'problem')    
    vid_and_prob_daily_time = join_video_problem_time(video_days, video_daily_time, problem_days, problem_daily_time) 
    
    #Analytics visualizations
    if staff_access or instructor_access:
        # Instructor access
        std_sort = get_DB_sort_course_homework(course_key)
        # Chapter time
        cs, st = get_DB_course_spent_time(course_key, student_id=ALL_STUDENTS)
        students_spent_time = chapter_time_to_js(cs, st)
        students_grades = get_DB_student_grades(course_key, student_id=ALL_STUDENTS) 
        cs, sa = course_accesses = get_DB_course_section_accesses(course_key, student_id=ALL_STUDENTS)
        students_course_accesses = course_accesses_to_js(cs, sa)
        students_prob_vid_progress = get_DB_course_video_problem_progress(course_key, student_id=ALL_STUDENTS)
        students_time_schedule = get_DB_time_schedule(course_key, student_id=ALL_STUDENTS)
    else:
        # Sort homework                    
        # Chapter time
        std_sort = None
        cs, st = get_DB_course_spent_time(course_key, user.id) 
        students_spent_time = chapter_time_to_js(cs, st) 
        students_grades = get_DB_student_grades(course_key, user.id) 
        cs, sa = course_accesses = get_DB_course_section_accesses(course_key, user.id)
        students_course_accesses = course_accesses_to_js(cs, sa) 
        students_time_schedule = get_DB_time_schedule(course_key, user.id) 
        students_prob_vid_progress = get_DB_course_video_problem_progress(course_key, user.id) 
                    
    context = {'course': course,
               'request': request,
               'user': user,
               'user_id': user.id,
               'staff_access': staff_access,
               'instructor_access': instructor_access,
               'masquerade': masq,
               'studio_url': studio_url,
               'reverifications': reverifications,
               'course_id': course_id,
               'students': students_to_js(get_course_students(course_key)),
               'visualizations_id': VISUALIZATIONS_ID,
               'std_grades_dump': dumps(students_grades),
               'sort_std_dump': dumps(std_sort),
               'time_dump': dumps(students_spent_time),
               'accesses_dump': dumps(students_course_accesses),
               'std_time_schedule_dumb': dumps(students_time_schedule),
               'vid_prob_prog_dump': dumps(students_prob_vid_progress),
               'pass_limit': pass_limit,
               'prof_limit': proficiency_limit,
               'usernames_in' : usernames_in,
               'video_names' : course_video_names,
               'video_ids' : video_ids_str,
               'video_prog_json' : video_prog_json,
               'video_distrib_json' : video_distrib_json,
               'problem_distrib_json' : problem_distrib_json,
               'video_intervals_array' : video_intervals_array,
               'vid_and_prob_daily_time' : vid_and_prob_daily_time,
               'scatter_array' : scatter_array, }                                
        
    return render_to_response('learning_analytics/learning_analytics.html', context)    
예제 #45
0
def piazza_discussion(request, course_id):
    '''
    Shows the page under the Discussion tab with an iframe containing Piazza
    '''
    # Create a new tool configuration
    config = ToolConfig(title='Piazza', launch_url=LTI_LAUNCH_URL)

    # Create tool consumer using LTI!
    consumer = ToolConsumer(LTI_CONSUMER_KEY, LTI_CONSUMER_SECRET)
    consumer.set_config(config)

    #retrieve user and course models
    user = User.objects.prefetch_related("groups").get(id=request.user.id)
    userProfile = UserProfile.objects.get(user_id=user.id)
    course = course_from_id(course_id)

    #check for permissions to determine what role to pass to Piazza.com through
    piazza_role = ''
    if user.groups.filter(name=(
            'instructor_' + course_id)).count() != 0 or request.user.is_staff:
        piazza_role = 'Instructor'
    elif user.groups.filter(name=('staff_' + course_id)).count() != 0:
        piazza_role = 'Staff'
    else:
        piazza_role = 'Learner'

    # Set some launch data from: http://www.imsglobal.org/LTI/v1p1pd/ltiIMGv1p1pd.html#_Toc309649684
    consumer.resource_link_id = course_id
    consumer.lis_person_contact_email_primary = user.email
    consumer.lis_person_name_full = str(userProfile.name)
    hash = hashlib.md5()
    hash.update(str(userProfile.user_id))
    consumer.user_id = hash.hexdigest()

    #TODO: check if user is is_staff, student, professor, or staff and set the role appropriately
    consumer.roles = piazza_role
    consumer.context_id = course_id
    consumer.context_title = course.display_name_with_default
    consumer.context_label = course.number.replace('_', ' ')
    consumer.tool_consumer_instance_guid = 'lms.cvn.columbia.edu'
    consumer.tool_consumer_instance_description = 'Columbia University'

    launch_data = consumer.generate_launch_data()
    launch_url = consumer.launch_url

    course = get_course_with_access(request.user, course_id, 'load')
    staff_access = has_access(request.user, course, 'staff')
    masq = setup_masquerade(
        request, staff_access)  # allow staff to toggle masquerade on info page

    return render_to_response(
        'courseware/piazza_discussion.html', {
            'request': request,
            'course_id': course_id,
            'cache': None,
            'course': course,
            'staff_access': staff_access,
            'masquerade': masq,
            'launch_url': launch_url,
            'launch_data': launch_data
        })
예제 #46
0
def index(request, course_id, chapter=None, section=None, position=None):
    """
    Displays courseware accordion and associated content.  If course, chapter,
    and section are all specified, renders the page, or returns an error if they
    are invalid.

    If section is not specified, displays the accordion opened to the right chapter.

    If neither chapter or section are specified, redirects to user's most recent
    chapter, or the first chapter if this is the user's first visit.

    Arguments:

     - request    : HTTP request
     - course_id  : course id (str: ORG/course/URL_NAME)
     - chapter    : chapter url_name (str)
     - section    : section url_name (str)
     - position   : position in module, eg of <sequential> module (str)

    Returns:

     - HTTPresponse
    """
    course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    user = User.objects.prefetch_related("groups").get(id=request.user.id)
    request.user = user  # keep just one instance of User
    course = get_course_with_access(user, 'load', course_key, depth=2)
    staff_access = has_access(user, 'staff', course)
    registered = registered_for_course(course, user)
    if not registered:
        # TODO (vshnayder): do course instructors need to be registered to see course?
        log.debug(u'User %s tried to view course %s but is not enrolled', user,
                  course.location.to_deprecated_string())
        return redirect(
            reverse('about_course', args=[course_key.to_deprecated_string()]))

    masq = setup_masquerade(request, staff_access)

    try:
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course_key, user, course, depth=2)

        course_module = get_module_for_descriptor(user, request, course,
                                                  field_data_cache, course_key)
        if course_module is None:
            log.warning(
                u'If you see this, something went wrong: if we got this'
                u' far, should have gotten a course module for this user')
            return redirect(
                reverse('about_course',
                        args=[course_key.to_deprecated_string()]))

        studio_url = get_studio_url(course_key, 'course')

        context = {
            'csrf':
            csrf(request)['csrf_token'],
            'accordion':
            render_accordion(request, course, chapter, section,
                             field_data_cache),
            'COURSE_TITLE':
            course.display_name_with_default,
            'course':
            course,
            'init':
            '',
            'fragment':
            Fragment(),
            'staff_access':
            staff_access,
            'studio_url':
            studio_url,
            'masquerade':
            masq,
            'xqa_server':
            settings.FEATURES.get(
                'USE_XQA_SERVER',
                'http://*****:*****@content-qa.mitx.mit.edu/xqa'),
            'reverifications':
            fetch_reverify_banner_info(request, course_key),
        }

        has_content = course.has_children_at_depth(CONTENT_DEPTH)
        if not has_content:
            # Show empty courseware for a course with no units
            return render_to_response('courseware/courseware.html', context)
        elif chapter is None:
            # passing CONTENT_DEPTH avoids returning 404 for a course with an
            # empty first section and a second section with content
            return redirect_to_course_position(course_module, CONTENT_DEPTH)

        # Only show the chat if it's enabled by the course and in the
        # settings.
        show_chat = course.show_chat and settings.FEATURES['ENABLE_CHAT']
        if show_chat:
            context['chat'] = chat_settings(course, user)
            # If we couldn't load the chat settings, then don't show
            # the widget in the courseware.
            if context['chat'] is None:
                show_chat = False

        context['show_chat'] = show_chat

        chapter_descriptor = course.get_child_by(
            lambda m: m.location.name == chapter)
        if chapter_descriptor is not None:
            save_child_position(course_module, chapter)
        else:
            raise Http404(
                'No chapter descriptor found with name {}'.format(chapter))

        chapter_module = course_module.get_child_by(
            lambda m: m.location.name == chapter)
        if chapter_module is None:
            # User may be trying to access a chapter that isn't live yet
            if masq == 'student':  # if staff is masquerading as student be kinder, don't 404
                log.debug('staff masq as student: no chapter %s' % chapter)
                return redirect(
                    reverse('courseware',
                            args=[course.id.to_deprecated_string()]))
            raise Http404

        if section is not None:
            section_descriptor = chapter_descriptor.get_child_by(
                lambda m: m.location.name == section)

            if section_descriptor is None:
                # Specifically asked-for section doesn't exist
                if masq == 'student':  # if staff is masquerading as student be kinder, don't 404
                    log.debug('staff masq as student: no section %s' % section)
                    return redirect(
                        reverse('courseware',
                                args=[course.id.to_deprecated_string()]))
                raise Http404

            ## Allow chromeless operation
            if section_descriptor.chrome:
                chrome = [
                    s.strip()
                    for s in section_descriptor.chrome.lower().split(",")
                ]
                if 'accordion' not in chrome:
                    context['disable_accordion'] = True
                if 'tabs' not in chrome:
                    context['disable_tabs'] = True

            if section_descriptor.default_tab:
                context['default_tab'] = section_descriptor.default_tab

            # cdodge: this looks silly, but let's refetch the section_descriptor with depth=None
            # which will prefetch the children more efficiently than doing a recursive load
            section_descriptor = modulestore().get_item(
                section_descriptor.location, depth=None)

            # Load all descendants of the section, because we're going to display its
            # html, which in general will need all of its children
            section_field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
                course_key, user, section_descriptor, depth=None)

            # Verify that position a string is in fact an int
            if position is not None:
                try:
                    int(position)
                except ValueError:
                    raise Http404(
                        "Position {} is not an integer!".format(position))

            section_module = get_module_for_descriptor(
                request.user, request, section_descriptor,
                section_field_data_cache, course_key, position)

            if section_module is None:
                # User may be trying to be clever and access something
                # they don't have access to.
                raise Http404

            # Save where we are in the chapter
            save_child_position(chapter_module, section)
            context['fragment'] = section_module.render(STUDENT_VIEW)
            context[
                'section_title'] = section_descriptor.display_name_with_default
        else:
            # section is none, so display a message
            studio_url = get_studio_url(course_key, 'course')
            prev_section = get_current_child(chapter_module)
            if prev_section is None:
                # Something went wrong -- perhaps this chapter has no sections visible to the user
                raise Http404
            prev_section_url = reverse('courseware_section',
                                       kwargs={
                                           'course_id':
                                           course_key.to_deprecated_string(),
                                           'chapter':
                                           chapter_descriptor.url_name,
                                           'section':
                                           prev_section.url_name
                                       })
            context['fragment'] = Fragment(content=render_to_string(
                'courseware/welcome-back.html', {
                    'course': course,
                    'studio_url': studio_url,
                    'chapter_module': chapter_module,
                    'prev_section': prev_section,
                    'prev_section_url': prev_section_url
                }))

        result = render_to_response('courseware/courseware.html', context)
    except Exception as e:

        # Doesn't bar Unicode characters from URL, but if Unicode characters do
        # cause an error it is a graceful failure.
        if isinstance(e, UnicodeEncodeError):
            raise Http404("URL contains Unicode characters")

        if isinstance(e, Http404):
            # let it propagate
            raise

        # In production, don't want to let a 500 out for any reason
        if settings.DEBUG:
            raise
        else:
            log.exception(
                u"Error in index view: user={user}, course={course}, chapter={chapter}"
                u" section={section} position={position}".format(
                    user=user,
                    course=course,
                    chapter=chapter,
                    section=section,
                    position=position))
            try:
                result = render_to_response('courseware/courseware-error.html',
                                            {
                                                'staff_access': staff_access,
                                                'course': course
                                            })
            except:
                # Let the exception propagate, relying on global config to at
                # at least return a nice error message
                log.exception("Error while rendering courseware-error page")
                raise

    return result
예제 #47
0
def index(request, course_id, chapter=None, section=None, position=None):
    """
    Displays courseware accordion and associated content.  If course, chapter,
    and section are all specified, renders the page, or returns an error if they
    are invalid.

    If section is not specified, displays the accordion opened to the right chapter.

    If neither chapter or section are specified, redirects to user's most recent
    chapter, or the first chapter if this is the user's first visit.

    Arguments:

     - request    : HTTP request
     - course_id  : course id (str: ORG/course/URL_NAME)
     - chapter    : chapter url_name (str)
     - section    : section url_name (str)
     - position   : position in module, eg of <sequential> module (str)

    Returns:

     - HTTPresponse
    """
    user = User.objects.prefetch_related("groups").get(id=request.user.id)
    request.user = user  # keep just one instance of User
    course = get_course_with_access(user, course_id, 'load', depth=2)
    staff_access = has_access(user, course, 'staff')
    registered = registered_for_course(course, user)
    if not registered:
        # TODO (vshnayder): do course instructors need to be registered to see course?
        log.debug('User %s tried to view course %s but is not enrolled' %
                  (user, course.location.url()))
        return redirect(reverse('about_course', args=[course.id]))

    masq = setup_masquerade(request, staff_access)

    try:
        model_data_cache = ModelDataCache.cache_for_descriptor_descendents(
            course.id, user, course, depth=2)

        course_module = get_module_for_descriptor(user, request, course,
                                                  model_data_cache, course.id)
        if course_module is None:
            log.warning(
                'If you see this, something went wrong: if we got this'
                ' far, should have gotten a course module for this user')
            return redirect(reverse('about_course', args=[course.id]))

        if chapter is None:
            return redirect_to_course_position(course_module)

        context = {
            'csrf':
            csrf(request)['csrf_token'],
            'accordion':
            render_accordion(request, course, chapter, section,
                             model_data_cache),
            'COURSE_TITLE':
            course.display_name_with_default,
            'course':
            course,
            'init':
            '',
            'content':
            '',
            'staff_access':
            staff_access,
            'masquerade':
            masq,
            'xqa_server':
            settings.MITX_FEATURES.get(
                'USE_XQA_SERVER',
                'http://*****:*****@content-qa.mitx.mit.edu/xqa')
        }

        # Only show the chat if it's enabled by the course and in the
        # settings.
        show_chat = course.show_chat and settings.MITX_FEATURES['ENABLE_CHAT']
        if show_chat:
            context['chat'] = chat_settings(course, user)
            # If we couldn't load the chat settings, then don't show
            # the widget in the courseware.
            if context['chat'] is None:
                show_chat = False

        context['show_chat'] = show_chat

        chapter_descriptor = course.get_child_by(
            lambda m: m.url_name == chapter)
        if chapter_descriptor is not None:
            save_child_position(course_module, chapter)
        else:
            raise Http404(
                'No chapter descriptor found with name {}'.format(chapter))

        chapter_module = course_module.get_child_by(
            lambda m: m.url_name == chapter)
        if chapter_module is None:
            # User may be trying to access a chapter that isn't live yet
            if masq == 'student':  # if staff is masquerading as student be kinder, don't 404
                log.debug('staff masq as student: no chapter %s' % chapter)
                return redirect(reverse('courseware', args=[course.id]))
            raise Http404

        if section is not None:
            section_descriptor = chapter_descriptor.get_child_by(
                lambda m: m.url_name == section)
            if section_descriptor is None:
                # Specifically asked-for section doesn't exist
                if masq == 'student':  # if staff is masquerading as student be kinder, don't 404
                    log.debug('staff masq as student: no section %s' % section)
                    return redirect(reverse('courseware', args=[course.id]))
                raise Http404

            # cdodge: this looks silly, but let's refetch the section_descriptor with depth=None
            # which will prefetch the children more efficiently than doing a recursive load
            section_descriptor = modulestore().get_instance(
                course.id, section_descriptor.location, depth=None)

            # Load all descendants of the section, because we're going to display its
            # html, which in general will need all of its children
            section_model_data_cache = ModelDataCache.cache_for_descriptor_descendents(
                course_id, user, section_descriptor, depth=None)
            section_module = get_module(request.user,
                                        request,
                                        section_descriptor.location,
                                        section_model_data_cache,
                                        course_id,
                                        position,
                                        depth=None)

            if section_module is None:
                # User may be trying to be clever and access something
                # they don't have access to.
                raise Http404

            # Save where we are in the chapter
            save_child_position(chapter_module, section)

            # check here if this section *is* a timed module.
            if section_module.category == 'timelimit':
                timer_context = update_timelimit_module(
                    user, course_id, student_module_cache, section_descriptor,
                    section_module)
                if 'timer_expiration_duration' in timer_context:
                    context.update(timer_context)
                else:
                    # if there is no expiration defined, then we know the timer has expired:
                    return HttpResponseRedirect(
                        timer_context['time_expired_redirect_url'])
            else:
                # check here if this page is within a course that has an active timed module running.  If so, then
                # add in the appropriate timer information to the rendering context:
                context.update(
                    check_for_active_timelimit_module(request, course_id,
                                                      course))

            context['content'] = section_module.runtime.render(
                section_module, None, 'student_view').content
        else:
            # section is none, so display a message
            prev_section = get_current_child(chapter_module)
            if prev_section is None:
                # Something went wrong -- perhaps this chapter has no sections visible to the user
                raise Http404
            prev_section_url = reverse('courseware_section',
                                       kwargs={
                                           'course_id': course_id,
                                           'chapter':
                                           chapter_descriptor.url_name,
                                           'section': prev_section.url_name
                                       })
            context['content'] = render_to_string(
                'courseware/welcome-back.html', {
                    'course': course,
                    'chapter_module': chapter_module,
                    'prev_section': prev_section,
                    'prev_section_url': prev_section_url
                })

        result = render_to_response('courseware/courseware.html', context)
    except Exception as e:
        if isinstance(e, Http404):
            # let it propagate
            raise

        # In production, don't want to let a 500 out for any reason
        if settings.DEBUG:
            raise
        else:
            log.exception("Error in index view: user={user}, course={course},"
                          " chapter={chapter} section={section}"
                          "position={position}".format(user=user,
                                                       course=course,
                                                       chapter=chapter,
                                                       section=section,
                                                       position=position))
            try:
                result = render_to_response('courseware/courseware-error.html',
                                            {
                                                'staff_access': staff_access,
                                                'course': course
                                            })
            except:
                # Let the exception propagate, relying on global config to at
                # at least return a nice error message
                log.exception("Error while rendering courseware-error page")
                raise

    return result
예제 #48
0
def mobi_index(request, course_id, chapter=None, section=None,
          position=None):
    user = User.objects.prefetch_related("groups").get(id=request.user.id)
    request.user = user  # keep just one instance of User
    course = get_course_with_access(user, course_id, 'load', depth=2)
    staff_access = has_access(user, course, 'staff')
    registered = registered_for_course(course, user)
    if not registered:
        # TODO (vshnayder): do course instructors need to be registered to see course?
        log.debug(u'User %s tried to view course %s but is not enrolled', user, course.location.url())
        return redirect(reverse('about_course', args=[course.id]))

    masq = setup_masquerade(request, staff_access)

    try:
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course.id, user, course, depth=2)

        course_module = get_module_for_descriptor(user, request, course, field_data_cache, course.id)
        if course_module is None:
            log.warning(u'If you see this, something went wrong: if we got this'
                        u' far, should have gotten a course module for this user')
            return redirect(reverse('about_course', args=[course.id]))

        if chapter is None:
            return redirect_to_course_position(course_module)

        context = {
            'csrf': csrf(request)['csrf_token'],
            'accordion': render_accordion(request, course, chapter, section, field_data_cache),
            'COURSE_TITLE': course.display_name_with_default,
            'course': course,
            'init': '',
            'fragment': Fragment(),
            'staff_access': staff_access,
            'masquerade': masq,
            'xqa_server': settings.FEATURES.get('USE_XQA_SERVER', 'http://*****:*****@content-qa.mitx.mit.edu/xqa'),
            'reverifications': fetch_reverify_banner_info(request, course_id),
            }
        # Only show the chat if it's enabled by the course and in the
        # settings.
        show_chat = course.show_chat and settings.FEATURES['ENABLE_CHAT']
        if show_chat:
            context['chat'] = chat_settings(course, user)
            # If we couldn't load the chat settings, then don't show
            # the widget in the courseware.
            if context['chat'] is None:
                show_chat = False

        context['show_chat'] = show_chat

        chapter_descriptor = course.get_child_by(lambda m: m.url_name == chapter)
        if chapter_descriptor is not None:
            save_child_position(course_module, chapter)
        else:
            raise Http404('No chapter descriptor found with name {}'.format(chapter))

        chapter_module = course_module.get_child_by(lambda m: m.url_name == chapter)
        if chapter_module is None:
            # User may be trying to access a chapter that isn't live yet
            if masq=='student':  # if staff is masquerading as student be kinder, don't 404
                log.debug('staff masq as student: no chapter %s' % chapter)
                return redirect(reverse('courseware', args=[course.id]))
            raise Http404

        if section is not None:
            section_descriptor = chapter_descriptor.get_child_by(lambda m: m.url_name == section)
            if section_descriptor is None:
                # Specifically asked-for section doesn't exist
                if masq=='student':  # if staff is masquerading as student be kinder, don't 404
                    log.debug('staff masq as student: no section %s' % section)
                    return redirect(reverse('courseware', args=[course.id]))
                raise Http404

            # cdodge: this looks silly, but let's refetch the section_descriptor with depth=None
            # which will prefetch the children more efficiently than doing a recursive load
            section_descriptor = modulestore().get_instance(course.id, section_descriptor.location, depth=None)


            # Load all descendants of the section, because we're going to display its
            # html, which in general will need all of its children
            section_field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
                course_id, user, section_descriptor, depth=None)
            section_module = get_module_for_descriptor(request.user,
                request,
                section_descriptor,
                section_field_data_cache,
                course_id,
                position
            )

            if section_module is None:
                # User may be trying to be clever and access something
                # they don't have access to.
                raise Http404

            # Save where we are in the chapter
            save_child_position(chapter_module, section)
            context['fragment'] = section_module.render('mobi_student_view')
            context['section_title'] = section_descriptor.display_name_with_default

        else:
            # section is none, so display a message
            prev_section = get_current_child(chapter_module)
            if prev_section is None:
                # Something went wrong -- perhaps this chapter has no sections visible to the user
                raise Http404
            prev_section_url = reverse('courseware_section', kwargs={'course_id': course_id,
                                                                     'chapter': chapter_descriptor.url_name,
                                                                     'section': prev_section.url_name})
            context['fragment'] = Fragment(content=render_to_string(
                'courseware/welcome-back.html',
                {
                    'course': course,
                    'chapter_module': chapter_module,
                    'prev_section': prev_section,
                    'prev_section_url': prev_section_url
                }
            ))
        result = render_to_response('wechat/mobi_courseware.html', context)
    except Exception as e:
        if isinstance(e, Http404):
            # let it propagate
            raise

        # In production, don't want to let a 500 out for any reason
        if settings.DEBUG:
            raise
        else:
            log.exception("Error in index view: user={user}, course={course},"
                          " chapter={chapter} section={section}"
                          "position={position}".format(
                              user=user,
                              course=course,
                              chapter=chapter,
                              section=section,
                              position=position
                              ))
            try:
                result = render_to_response('courseware/courseware-error.html',
                                            {'staff_access': staff_access,
                                            'course': course})
            except:
                # Let the exception propagate, relying on global config to at
                # at least return a nice error message
                log.exception("Error while rendering courseware-error page")
                raise
    return result
예제 #49
0
def index(request, course_id, chapter=None, section=None,
          position=None):
    """
    Displays courseware accordion and associated content.  If course, chapter,
    and section are all specified, renders the page, or returns an error if they
    are invalid.

    If section is not specified, displays the accordion opened to the right chapter.

    If neither chapter or section are specified, redirects to user's most recent
    chapter, or the first chapter if this is the user's first visit.

    Arguments:

     - request    : HTTP request
     - course_id  : course id (str: ORG/course/URL_NAME)
     - chapter    : chapter url_name (str)
     - section    : section url_name (str)
     - position   : position in module, eg of <sequential> module (str)

    Returns:

     - HTTPresponse
    """
    user = User.objects.prefetch_related("groups").get(id=request.user.id)
    request.user = user	# keep just one instance of User
    course = get_course_with_access(user, course_id, 'load', depth=2)
    staff_access = has_access(user, course, 'staff')
    registered = registered_for_course(course, user)
    if not registered:
        # TODO (vshnayder): do course instructors need to be registered to see course?
        log.debug('User %s tried to view course %s but is not enrolled' % (user, course.location.url()))
        return redirect(reverse('about_course', args=[course.id]))

    masq = setup_masquerade(request, staff_access)

    try:
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course.id, user, course, depth=2)

        course_module = get_module_for_descriptor(user, request, course, field_data_cache, course.id)
        if course_module is None:
            log.warning('If you see this, something went wrong: if we got this'
                        ' far, should have gotten a course module for this user')
            return redirect(reverse('about_course', args=[course.id]))

        if chapter is None:
            return redirect_to_course_position(course_module)

        context = {
            'csrf': csrf(request)['csrf_token'],
            'accordion': render_accordion(request, course, chapter, section, field_data_cache),
            'COURSE_TITLE': course.display_name_with_default,
            'course': course,
            'init': '',
            'content': '',
            'staff_access': staff_access,
            'masquerade': masq,
            'xqa_server': settings.MITX_FEATURES.get('USE_XQA_SERVER', 'http://*****:*****@content-qa.mitx.mit.edu/xqa'),
#@begin:Inform the template that it is in homepage
#@date:2013-11-02        
            'is_index':'True'
#@end                        
            }

        # Only show the chat if it's enabled by the course and in the
        # settings.
        show_chat = course.show_chat and settings.MITX_FEATURES['ENABLE_CHAT']
        if show_chat:
            context['chat'] = chat_settings(course, user)
            # If we couldn't load the chat settings, then don't show
            # the widget in the courseware.
            if context['chat'] is None:
                show_chat = False

        context['show_chat'] = show_chat

        chapter_descriptor = course.get_child_by(lambda m: m.url_name == chapter)
        if chapter_descriptor is not None:
            save_child_position(course_module, chapter)
        else:
            raise Http404('No chapter descriptor found with name {}'.format(chapter))

        chapter_module = course_module.get_child_by(lambda m: m.url_name == chapter)
        if chapter_module is None:
            # User may be trying to access a chapter that isn't live yet
            if masq=='student':  # if staff is masquerading as student be kinder, don't 404
                log.debug('staff masq as student: no chapter %s' % chapter)
                return redirect(reverse('courseware', args=[course.id]))
            raise Http404

        if section is not None:
            section_descriptor = chapter_descriptor.get_child_by(lambda m: m.url_name == section)
            if section_descriptor is None:
                # Specifically asked-for section doesn't exist
                if masq=='student':  # if staff is masquerading as student be kinder, don't 404
                    log.debug('staff masq as student: no section %s' % section)
                    return redirect(reverse('courseware', args=[course.id]))
                raise Http404

            # cdodge: this looks silly, but let's refetch the section_descriptor with depth=None
            # which will prefetch the children more efficiently than doing a recursive load
            section_descriptor = modulestore().get_instance(course.id, section_descriptor.location, depth=None)

            # Load all descendants of the section, because we're going to display its
            # html, which in general will need all of its children
            section_field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
                course_id, user, section_descriptor, depth=None)
            section_module = get_module(request.user, request,
                                section_descriptor.location,
                                section_field_data_cache, course_id, position, depth=None)

            if section_module is None:
                # User may be trying to be clever and access something
                # they don't have access to.
                raise Http404

            # Save where we are in the chapter
            save_child_position(chapter_module, section)

            # check here if this section *is* a timed module.
            if section_module.category == 'timelimit':
                timer_context = update_timelimit_module(user, course_id, student_module_cache,
                                                        section_descriptor, section_module)
                if 'timer_expiration_duration' in timer_context:
                    context.update(timer_context)
                else:
                    # if there is no expiration defined, then we know the timer has expired:
                    return HttpResponseRedirect(timer_context['time_expired_redirect_url'])
            else:
                # check here if this page is within a course that has an active timed module running.  If so, then
                # add in the appropriate timer information to the rendering context:
                context.update(check_for_active_timelimit_module(request, course_id, course))

            context['content'] = section_module.runtime.render(section_module, None, 'student_view').content
        else:
            # section is none, so display a message
            prev_section = get_current_child(chapter_module)
            if prev_section is None:
                # Something went wrong -- perhaps this chapter has no sections visible to the user
                raise Http404
            prev_section_url = reverse('courseware_section', kwargs={'course_id': course_id,
                                                                     'chapter': chapter_descriptor.url_name,
                                                                     'section': prev_section.url_name})
            context['content'] = render_to_string('courseware/welcome-back.html',
                                                  {'course': course,
                                                   'chapter_module': chapter_module,
                                                   'prev_section': prev_section,
                                                   'prev_section_url': prev_section_url})

        result = render_to_response('courseware/courseware.html', context)
    except Exception as e:
        if isinstance(e, Http404):
            # let it propagate
            raise

        # In production, don't want to let a 500 out for any reason
        if settings.DEBUG:
            raise
        else:
            log.exception("Error in index view: user={user}, course={course},"
                          " chapter={chapter} section={section}"
                          "position={position}".format(
                              user=user,
                              course=course,
                              chapter=chapter,
                              section=section,
                              position=position
                              ))
            try:
                result = render_to_response('courseware/courseware-error.html',
                                            {'staff_access': staff_access,
                                            'course': course})
            except:
                # Let the exception propagate, relying on global config to at
                # at least return a nice error message
                log.exception("Error while rendering courseware-error page")
                raise

    return result
예제 #50
0
def mobi_index(request, course_id, chapter=None, section=None,
          position=None):
    user = User.objects.prefetch_related("groups").get(id=request.user.id)
    request.user = user  # keep just one instance of User
    course = get_course_with_access(user, course_id, 'load', depth=2)
    staff_access = has_access(user, course, 'staff')
    registered = registered_for_course(course, user)
    if not registered:
        # TODO (vshnayder): do course instructors need to be registered to see course?
        log.debug(u'User %s tried to view course %s but is not enrolled', user, course.location.url())
        return redirect(reverse('about_course', args=[course.id]))

    masq = setup_masquerade(request, staff_access)

    try:
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course.id, user, course, depth=2)

        course_module = get_module_for_descriptor(user, request, course, field_data_cache, course.id)
        if course_module is None:
            log.warning(u'If you see this, something went wrong: if we got this'
                        u' far, should have gotten a course module for this user')
            return redirect(reverse('about_course', args=[course.id]))

        if chapter is None:
            return redirect_to_course_position(course_module)

        context = {
            'csrf': csrf(request)['csrf_token'],
            'accordion': render_accordion(request, course, chapter, section, field_data_cache),
            'COURSE_TITLE': course.display_name_with_default,
            'course': course,
            'init': '',
            'fragment': Fragment(),
            'staff_access': staff_access,
            'masquerade': masq,
            'xqa_server': settings.FEATURES.get('USE_XQA_SERVER', 'http://*****:*****@content-qa.mitx.mit.edu/xqa'),
            'reverifications': fetch_reverify_banner_info(request, course_id),
            }
        # Only show the chat if it's enabled by the course and in the
        # settings.
        show_chat = course.show_chat and settings.FEATURES['ENABLE_CHAT']
        if show_chat:
            context['chat'] = chat_settings(course, user)
            # If we couldn't load the chat settings, then don't show
            # the widget in the courseware.
            if context['chat'] is None:
                show_chat = False

        context['show_chat'] = show_chat

        chapter_descriptor = course.get_child_by(lambda m: m.url_name == chapter)
        if chapter_descriptor is not None:
            save_child_position(course_module, chapter)
        else:
            raise Http404('No chapter descriptor found with name {}'.format(chapter))

        chapter_module = course_module.get_child_by(lambda m: m.url_name == chapter)
        if chapter_module is None:
            # User may be trying to access a chapter that isn't live yet
            if masq=='student':  # if staff is masquerading as student be kinder, don't 404
                log.debug('staff masq as student: no chapter %s' % chapter)
                return redirect(reverse('courseware', args=[course.id]))
            raise Http404

        if section is not None:
            section_descriptor = chapter_descriptor.get_child_by(lambda m: m.url_name == section)
            if section_descriptor is None:
                # Specifically asked-for section doesn't exist
                if masq=='student':  # if staff is masquerading as student be kinder, don't 404
                    log.debug('staff masq as student: no section %s' % section)
                    return redirect(reverse('courseware', args=[course.id]))
                raise Http404

            # cdodge: this looks silly, but let's refetch the section_descriptor with depth=None
            # which will prefetch the children more efficiently than doing a recursive load
            section_descriptor = modulestore().get_instance(course.id, section_descriptor.location, depth=None)


            # Load all descendants of the section, because we're going to display its
            # html, which in general will need all of its children
            section_field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
                course_id, user, section_descriptor, depth=None)
            section_module = get_module_for_descriptor(request.user,
                request,
                section_descriptor,
                section_field_data_cache,
                course_id,
                position
            )

            if section_module is None:
                # User may be trying to be clever and access something
                # they don't have access to.
                raise Http404

            # Save where we are in the chapter
            save_child_position(chapter_module, section)
            context['fragment'] = section_module.render('mobi_student_view')
            context['section_title'] = section_descriptor.display_name_with_default

        else:
            # section is none, so display a message
            prev_section = get_current_child(chapter_module)
            if prev_section is None:
                # Something went wrong -- perhaps this chapter has no sections visible to the user
                raise Http404
            prev_section_url = reverse('courseware_section', kwargs={'course_id': course_id,
                                                                     'chapter': chapter_descriptor.url_name,
                                                                     'section': prev_section.url_name})
            context['fragment'] = Fragment(content=render_to_string(
                'courseware/welcome-back.html',
                {
                    'course': course,
                    'chapter_module': chapter_module,
                    'prev_section': prev_section,
                    'prev_section_url': prev_section_url
                }
            ))
        result = render_to_response('wechat/mobi_courseware.html', context)
    except Exception as e:
        if isinstance(e, Http404):
            # let it propagate
            raise

        # In production, don't want to let a 500 out for any reason
        if settings.DEBUG:
            raise
        else:
            log.exception("Error in index view: user={user}, course={course},"
                          " chapter={chapter} section={section}"
                          "position={position}".format(
                              user=user,
                              course=course,
                              chapter=chapter,
                              section=section,
                              position=position
                              ))
            try:
                result = render_to_response('courseware/courseware-error.html',
                                            {'staff_access': staff_access,
                                            'course': course})
            except:
                # Let the exception propagate, relying on global config to at
                # at least return a nice error message
                log.exception("Error while rendering courseware-error page")
                raise
    return result
예제 #51
0
def index(request, course_id, chapter=None, section=None,
          position=None):
    """
    Displays courseware accordion and associated content.  If course, chapter,
    and section are all specified, renders the page, or returns an error if they
    are invalid.

    If section is not specified, displays the accordion opened to the right chapter.

    If neither chapter or section are specified, redirects to user's most recent
    chapter, or the first chapter if this is the user's first visit.

    Arguments:

     - request    : HTTP request
     - course_id  : course id (str: ORG/course/URL_NAME)
     - chapter    : chapter url_name (str)
     - section    : section url_name (str)
     - position   : position in module, eg of <sequential> module (str)

    Returns:

     - HTTPresponse
    """
    user = User.objects.prefetch_related("groups").get(id=request.user.id)
    request.user = user	# keep just one instance of User

    # Если пользователь не активен - отправляем на главную страницу

    if not user.is_active and not user.profile.is_demo:
        return redirect('/')

    try:
        course = get_course_with_access(user, course_id, 'load', depth=2)
    except:
        return redirect('/')

    # Если курс помечен, как непубликуемый в LMS - отправляем на главную страницу
    if not course.show_in_lms:
       return redirect('/')


    staff_access = has_access(user, course, 'staff')

    registered = registered_for_course(course, user)
    if not registered:
        # TODO (vshnayder): do course instructors need to be registered to see course?
        log.debug('User %s tried to view course %s but is not enrolled' % (user, course.location.url()))
        return redirect(reverse('about_course', args=[course.id]))

    masq = setup_masquerade(request, staff_access)

    try:
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course.id, user, course, depth=2)

        course_module = get_module_for_descriptor(user, request, course, field_data_cache, course.id)
        if course_module is None:
            log.warning('If you see this, something went wrong: if we got this'
                        ' far, should have gotten a course module for this user')
            return redirect(reverse('about_course', args=[course.id]))

        if chapter is None:
            return redirect_to_course_position(course_module)

        context = {
            'csrf': csrf(request)['csrf_token'],
            'accordion': render_accordion(request, course, chapter, section, field_data_cache),
            'COURSE_TITLE': course.display_name_with_default,
            'course': course,
            'init': '',
            'fragment': Fragment(),
            'staff_access': staff_access,
            'masquerade': masq,
            'xqa_server': settings.FEATURES.get('USE_XQA_SERVER', 'http://*****:*****@content-qa.mitx.mit.edu/xqa')
            }

        # Only show the chat if it's enabled by the course and in the
        # settings.
        show_chat = course.show_chat and settings.FEATURES['ENABLE_CHAT']
        if show_chat:
            context['chat'] = chat_settings(course, user)
            # If we couldn't load the chat settings, then don't show
            # the widget in the courseware.
            if context['chat'] is None:
                show_chat = False

        context['show_chat'] = show_chat

        chapter_descriptor = course.get_child_by(lambda m: m.url_name == chapter)
        if chapter_descriptor is not None:
            save_child_position(course_module, chapter)
        else:
            raise Http404('No chapter descriptor found with name {}'.format(chapter))

        chapter_module = course_module.get_child_by(lambda m: m.url_name == chapter)
        if chapter_module is None:
            # User may be trying to access a chapter that isn't live yet
            if masq=='student':  # if staff is masquerading as student be kinder, don't 404
                log.debug('staff masq as student: no chapter %s' % chapter)
                return redirect(reverse('courseware', args=[course.id]))
            raise Http404

        if section is not None:
            section_descriptor = chapter_descriptor.get_child_by(lambda m: m.url_name == section)
            if section_descriptor is None:
                # Specifically asked-for section doesn't exist
                if masq=='student':  # if staff is masquerading as student be kinder, don't 404
                    log.debug('staff masq as student: no section %s' % section)
                    return redirect(reverse('courseware', args=[course.id]))
                raise Http404

            # cdodge: this looks silly, but let's refetch the section_descriptor with depth=None
            # which will prefetch the children more efficiently than doing a recursive load
            section_descriptor = modulestore().get_instance(course.id, section_descriptor.location, depth=None)

            # Load all descendants of the section, because we're going to display its
            # html, which in general will need all of its children
            section_field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
                course_id, user, section_descriptor, depth=None)

            section_module = get_module_for_descriptor(request.user,
                request,
                section_descriptor,
                section_field_data_cache,
                course_id,
                position
            )

            if section_module is None:
                # User may be trying to be clever and access something
                # they don't have access to.
                raise Http404

            # model_data_cache_for_check = ModelDataCache.cache_for_descriptor_descendents(course_id, user, course, depth=None)

            courseware_summary = grades.progress_summary(user, request, course)


            is_section_unlocked = grades.return_section_by_id(section_module.url_name, courseware_summary)['unlocked']



            #Контент раздела закрыт для демопользователя
            is_demo = UserProfile.objects.get(user=request.user).is_demo
            if is_demo and not section_module.available_for_demo:
                is_section_unlocked = False

            # Save where we are in the chapter
            save_child_position(chapter_module, section)
            context['fragment'] = section_module.render('student_view', context)

        else:
            # section is none, so display a message
            prev_section = get_current_child(chapter_module)
            if prev_section is None:
                # Something went wrong -- perhaps this chapter has no sections visible to the user
                raise Http404
            prev_section_url = reverse('courseware_section', kwargs={'course_id': course_id,
                                                                     'chapter': chapter_descriptor.url_name,
                                                                     'section': prev_section.url_name})
            context['fragment'] = Fragment(content=render_to_string(
                'courseware/welcome-back.html',
                {
                    'course': course,
                    'chapter_module': chapter_module,
                    'prev_section': prev_section,
                    'prev_section_url': prev_section_url
                }
            ))

        result = render_to_response('courseware/courseware.html', context)
    except Exception as e:
        if isinstance(e, Http404):
            # let it propagate
            raise

        # In production, don't want to let a 500 out for any reason
        if settings.DEBUG:
            raise
        else:
            log.exception("Error in index view: user={user}, course={course},"
                          " chapter={chapter} section={section}"
                          "position={position}".format(
                              user=user,
                              course=course,
                              chapter=chapter,
                              section=section,
                              position=position
                              ))
            try:
                result = render_to_response('courseware/courseware-error.html',
                                            {'staff_access': staff_access,
                                            'course': course})
            except:
                # Let the exception propagate, relying on global config to at
                # at least return a nice error message
                log.exception("Error while rendering courseware-error page")
                raise

    return result
예제 #52
0
def get_module_for_descriptor(
    user, request, descriptor, model_data_cache, course_id,
        position=None, wrap_xmodule_display=True, grade_bucket_type=None):
    """
    Actually implement get_module.  See docstring there for details.
    """

    # allow course staff to masquerade as student
    if has_access(user, descriptor, 'staff', course_id):
        setup_masquerade(request, True)

    # Short circuit--if the user shouldn't have access, bail without doing any
    # work
    if not has_access(user, descriptor, 'load', course_id):
        return None

    # Setup system context for module instance
    ajax_url = reverse('modx_dispatch',
                       kwargs=dict(course_id=course_id,
                                   location=descriptor.location.url(),
                                   dispatch=''),
                       )
    # Intended use is as {ajax_url}/{dispatch_command}, so get rid of the
    # trailing slash.
    ajax_url = ajax_url.rstrip('/')

    def make_xqueue_callback(dispatch='score_update'):
        # Fully qualified callback URL for external queueing system
        xqueue_callback_url = '{proto}://{host}'.format(
            host=request.get_host(),
            proto=request.META.get(
                'HTTP_X_FORWARDED_PROTO', 'https' if request.is_secure() else 'http')
        )
        xqueue_callback_url = settings.XQUEUE_INTERFACE.get(
            'callback_url', xqueue_callback_url)  # allow override

        xqueue_callback_url += reverse('xqueue_callback',
                                       kwargs=dict(course_id=course_id,
                                                   userid=str(user.id),
                                                   id=descriptor.location.url(
                                                   ),
                                                   dispatch=dispatch),
                                       )
        return xqueue_callback_url

    # Default queuename is course-specific and is derived from the course that
    #   contains the current module.
    # TODO: Queuename should be derived from 'course_settings.json' of each
    # course
    xqueue_default_queuename = descriptor.location.org + \
        '-' + descriptor.location.course

    xqueue = {'interface': xqueue_interface,
              'construct_callback': make_xqueue_callback,
              'default_queuename': xqueue_default_queuename.replace(' ', '_'),
              'waittime': settings.XQUEUE_WAITTIME_BETWEEN_REQUESTS
              }

    # This is a hacky way to pass settings to the combined open ended xmodule
    # It needs an S3 interface to upload images to S3
    # It needs the open ended grading interface in order to get peer grading to be done
    # this first checks to see if the descriptor is the correct one, and only
    # sends settings if it is

    # Get descriptor metadata fields indicating needs for various settings
    needs_open_ended_interface = getattr(
        descriptor, "needs_open_ended_interface", False)
    needs_s3_interface = getattr(descriptor, "needs_s3_interface", False)

    # Initialize interfaces to None
    open_ended_grading_interface = None
    s3_interface = None

    # Create interfaces if needed
    if needs_open_ended_interface:
        open_ended_grading_interface = settings.OPEN_ENDED_GRADING_INTERFACE
        open_ended_grading_interface[
            'mock_peer_grading'] = settings.MOCK_PEER_GRADING
        open_ended_grading_interface[
            'mock_staff_grading'] = settings.MOCK_STAFF_GRADING
    if needs_s3_interface:
        s3_interface = {
            'access_key': getattr(settings, 'AWS_ACCESS_KEY_ID', ''),
            'secret_access_key': getattr(settings, 'AWS_SECRET_ACCESS_KEY', ''),
            'storage_bucket_name': getattr(settings, 'AWS_STORAGE_BUCKET_NAME', 'openended')
        }

    def inner_get_module(descriptor):
        """
        Delegate to get_module.  It does an access check, so may return None
        """
        return get_module_for_descriptor(user, request, descriptor,
                                         model_data_cache, course_id, position)

    def xblock_model_data(descriptor):
        return DbModel(
            LmsKeyValueStore(descriptor._model_data, model_data_cache),
            descriptor.module_class,
            user.id,
            LmsUsage(descriptor.location, descriptor.location)
        )

    def publish(event):
        if event.get('event_name') != 'grade':
            return

        student_module, created = StudentModule.objects.get_or_create(
            course_id=course_id,
            student=user,
            module_type=descriptor.location.category,
            module_state_key=descriptor.location.url(),
            defaults={'state': '{}'},
        )
        student_module.grade = event.get('value')
        student_module.max_grade = event.get('max_value')
        student_module.save()

        # Bin score into range and increment stats
        score_bucket = get_score_bucket(
            student_module.grade, student_module.max_grade)
        org, course_num, run = course_id.split("/")

        tags = ["org:{0}".format(org),
                "course:{0}".format(course_num),
                "run:{0}".format(run),
                "score_bucket:{0}".format(score_bucket)]

        if grade_bucket_type is not None:
            tags.append('type:%s' % grade_bucket_type)

        statsd.increment("lms.courseware.question_answered", tags=tags)

    def can_execute_unsafe_code():
        # To decide if we can run unsafe code, we check the course id against
        # a list of regexes configured on the server.
        for regex in settings.COURSES_WITH_UNSAFE_CODE:
            if re.match(regex, course_id):
                return True
        return False

    # TODO (cpennington): When modules are shared between courses, the static
    # prefix is going to have to be specific to the module, not the directory
    # that the xml was loaded from
    system = ModuleSystem(track_function=make_track_function(request),
                          render_template=render_to_string,
                          ajax_url=ajax_url,
                          xqueue=xqueue,
                          # TODO (cpennington): Figure out how to share info
                          # between systems
                          filestore=descriptor.system.resources_fs,
                          get_module=inner_get_module,
                          user=user,
                          # TODO (cpennington): This should be removed when all html from
                          # a module is coming through get_html and is therefore covered
                          # by the replace_static_urls code below
                          replace_urls=partial(
                              static_replace.replace_static_urls,
                              data_directory=getattr(
                                  descriptor, 'data_dir', None),
                              course_namespace=descriptor.location._replace(
                                  category=None, name=None),
                          ),
                          node_path=settings.NODE_PATH,
                          xblock_model_data=xblock_model_data,
                          publish=publish,
                          anonymous_student_id=unique_id_for_user(user),
                          course_id=course_id,
                          open_ended_grading_interface=open_ended_grading_interface,
                          s3_interface=s3_interface,
                          cache=cache,
                          can_execute_unsafe_code=can_execute_unsafe_code,
                          )
    # pass position specified in URL to module through ModuleSystem
    system.set('position', position)
    system.set('DEBUG', settings.DEBUG)
    if settings.MITX_FEATURES.get('ENABLE_PSYCHOMETRICS'):
        system.set('psychometrics_handler',		# set callback for updating PsychometricsData
                   make_psychometrics_data_update_handler(course_id, user, descriptor.location.url()))

    try:
        module = descriptor.xmodule(system)
    except:
        log.exception(
            "Error creating module from descriptor {0}".format(descriptor))

        # make an ErrorDescriptor -- assuming that the descriptor's system is
        # ok
        if has_access(user, descriptor.location, 'staff', course_id):
            err_descriptor_class = ErrorDescriptor
        else:
            err_descriptor_class = NonStaffErrorDescriptor

        err_descriptor = err_descriptor_class.from_xml(
            str(descriptor), descriptor.system,
            org=descriptor.location.org, course=descriptor.location.course,
            error_msg=exc_info_to_str(sys.exc_info())
        )

        # Make an error module
        return err_descriptor.xmodule(system)

    system.set('user_is_staff', has_access(
        user, descriptor.location, 'staff', course_id))
    _get_html = module.get_html

    if wrap_xmodule_display:
        _get_html = wrap_xmodule(
            module.get_html, module, 'xmodule_display.html')

    module.get_html = replace_static_urls(
        _get_html,
        getattr(descriptor, 'data_dir', None),
        course_namespace=module.location._replace(category=None, name=None))

    # Allow URLs of the form '/course/' refer to the root of multicourse directory
    #   hierarchy of this course
    module.get_html = replace_course_urls(module.get_html, course_id)

    if settings.MITX_FEATURES.get('DISPLAY_HISTOGRAMS_TO_STAFF'):
        if has_access(user, module, 'staff', course_id):
            module.get_html = add_histogram(module.get_html, module, user)

    return module
예제 #53
0
def _index_bulk_op(request, course_key, chapter, section, position):
    """
    Render the index page for the specified course.
    """
    user = request.user
    course = get_course_with_access(user, 'load', course_key, depth=2)

    staff_access = has_access(user, 'staff', course)
    registered = registered_for_course(course, user)
    if not registered:
        # TODO (vshnayder): do course instructors need to be registered to see course?
        log.debug(u'User %s tried to view course %s but is not enrolled', user, course.location.to_deprecated_string())
        return redirect(reverse('about_course', args=[course_key.to_deprecated_string()]))

    # see if all pre-requisites (as per the milestones app feature) have been fulfilled
    # Note that if the pre-requisite feature flag has been turned off (default) then this check will
    # always pass
    if not has_access(user, 'view_courseware_with_prerequisites', course):
        # prerequisites have not been fulfilled therefore redirect to the Dashboard
        log.info(
            u'User %d tried to view course %s '
            u'without fulfilling prerequisites',
            user.id, unicode(course.id))
        return redirect(reverse('dashboard'))

    # check to see if there is a required survey that must be taken before
    # the user can access the course.
    if survey.utils.must_answer_survey(course, user):
        return redirect(reverse('course_survey', args=[unicode(course.id)]))

    masquerade = setup_masquerade(request, course_key, staff_access)

    try:
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course_key, user, course, depth=2)

        course_module = get_module_for_descriptor(user, request, course, field_data_cache, course_key)
        if course_module is None:
            log.warning(u'If you see this, something went wrong: if we got this'
                        u' far, should have gotten a course module for this user')
            return redirect(reverse('about_course', args=[course_key.to_deprecated_string()]))

        studio_url = get_studio_url(course, 'course')

        context = {
            'csrf': csrf(request)['csrf_token'],
            'accordion': render_accordion(request, course, chapter, section, field_data_cache),
            'COURSE_TITLE': course.display_name_with_default,
            'course': course,
            'init': '',
            'fragment': Fragment(),
            'staff_access': staff_access,
            'studio_url': studio_url,
            'masquerade': masquerade,
            'xqa_server': settings.FEATURES.get('USE_XQA_SERVER', 'http://*****:*****@content-qa.mitx.mit.edu/xqa'),
            'reverifications': fetch_reverify_banner_info(request, course_key),
        }

        now = datetime.now(UTC())
        effective_start = _adjust_start_date_for_beta_testers(user, course, course_key)
        if staff_access and now < effective_start:
            # Disable student view button if user is staff and
            # course is not yet visible to students.
            context['disable_student_access'] = True

        has_content = course.has_children_at_depth(CONTENT_DEPTH)
        if not has_content:
            # Show empty courseware for a course with no units
            return render_to_response('courseware/courseware.html', context)
        elif chapter is None:
            # passing CONTENT_DEPTH avoids returning 404 for a course with an
            # empty first section and a second section with content
            return redirect_to_course_position(course_module, CONTENT_DEPTH)

        # Only show the chat if it's enabled by the course and in the
        # settings.
        show_chat = course.show_chat and settings.FEATURES['ENABLE_CHAT']
        if show_chat:
            context['chat'] = chat_settings(course, user)
            # If we couldn't load the chat settings, then don't show
            # the widget in the courseware.
            if context['chat'] is None:
                show_chat = False

        context['show_chat'] = show_chat

        chapter_descriptor = course.get_child_by(lambda m: m.location.name == chapter)
        if chapter_descriptor is not None:
            save_child_position(course_module, chapter)
        else:
            raise Http404('No chapter descriptor found with name {}'.format(chapter))

        chapter_module = course_module.get_child_by(lambda m: m.location.name == chapter)
        if chapter_module is None:
            # User may be trying to access a chapter that isn't live yet
            if masquerade and masquerade.role == 'student':  # if staff is masquerading as student be kinder, don't 404
                log.debug('staff masquerading as student: no chapter %s', chapter)
                return redirect(reverse('courseware', args=[course.id.to_deprecated_string()]))
            raise Http404

        if section is not None:
            section_descriptor = chapter_descriptor.get_child_by(lambda m: m.location.name == section)

            if section_descriptor is None:
                # Specifically asked-for section doesn't exist
                if masquerade and masquerade.role == 'student':  # don't 404 if staff is masquerading as student
                    log.debug('staff masquerading as student: no section %s', section)
                    return redirect(reverse('courseware', args=[course.id.to_deprecated_string()]))
                raise Http404

            ## Allow chromeless operation
            if section_descriptor.chrome:
                chrome = [s.strip() for s in section_descriptor.chrome.lower().split(",")]
                if 'accordion' not in chrome:
                    context['disable_accordion'] = True
                if 'tabs' not in chrome:
                    context['disable_tabs'] = True

            if section_descriptor.default_tab:
                context['default_tab'] = section_descriptor.default_tab

            # cdodge: this looks silly, but let's refetch the section_descriptor with depth=None
            # which will prefetch the children more efficiently than doing a recursive load
            section_descriptor = modulestore().get_item(section_descriptor.location, depth=None)

            # Load all descendants of the section, because we're going to display its
            # html, which in general will need all of its children
            section_field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
                course_key, user, section_descriptor, depth=None, asides=XBlockAsidesConfig.possible_asides()
            )

            # Verify that position a string is in fact an int
            if position is not None:
                try:
                    int(position)
                except ValueError:
                    raise Http404("Position {} is not an integer!".format(position))

            section_module = get_module_for_descriptor(
                request.user,
                request,
                section_descriptor,
                section_field_data_cache,
                course_key,
                position
            )

            if section_module is None:
                # User may be trying to be clever and access something
                # they don't have access to.
                raise Http404

            # Save where we are in the chapter
            save_child_position(chapter_module, section)
            context['fragment'] = section_module.render(STUDENT_VIEW)
            context['section_title'] = section_descriptor.display_name_with_default
        else:
            # section is none, so display a message
            studio_url = get_studio_url(course, 'course')
            prev_section = get_current_child(chapter_module)
            if prev_section is None:
                # Something went wrong -- perhaps this chapter has no sections visible to the user.
                # Clearing out the last-visited state and showing "first-time" view by redirecting
                # to courseware.
                course_module.position = None
                course_module.save()
                return redirect(reverse('courseware', args=[course.id.to_deprecated_string()]))
            prev_section_url = reverse('courseware_section', kwargs={
                'course_id': course_key.to_deprecated_string(),
                'chapter': chapter_descriptor.url_name,
                'section': prev_section.url_name
            })
            context['fragment'] = Fragment(content=render_to_string(
                'courseware/welcome-back.html',
                {
                    'course': course,
                    'studio_url': studio_url,
                    'chapter_module': chapter_module,
                    'prev_section': prev_section,
                    'prev_section_url': prev_section_url
                }
            ))

        result = render_to_response('courseware/courseware.html', context)
    except Exception as e:

        # Doesn't bar Unicode characters from URL, but if Unicode characters do
        # cause an error it is a graceful failure.
        if isinstance(e, UnicodeEncodeError):
            raise Http404("URL contains Unicode characters")

        if isinstance(e, Http404):
            # let it propagate
            raise

        # In production, don't want to let a 500 out for any reason
        if settings.DEBUG:
            raise
        else:
            log.exception(
                u"Error in index view: user={user}, course={course}, chapter={chapter}"
                u" section={section} position={position}".format(
                    user=user,
                    course=course,
                    chapter=chapter,
                    section=section,
                    position=position
                ))
            try:
                result = render_to_response('courseware/courseware-error.html', {
                    'staff_access': staff_access,
                    'course': course
                })
            except:
                # Let the exception propagate, relying on global config to at
                # at least return a nice error message
                log.exception("Error while rendering courseware-error page")
                raise

    return result
예제 #54
0
def index(request, course_id):
    # Palette
    color_not = '#CCCCCC'
    color_fail = '#e41a1c'
    color_ok = '#F2F20D'
    color_prof = '#4daf4a'
    problem_activity='#377eb8'
    video_activity='#ff7f00'
    video_repetition='#fdbf6f'
    course_activity='#984ea3'
    graded_time='#88419d'
    ungraded_time='#8c6bb1'
    chapter_time='#8c96c6'
    play_event='#1b9e77'
    pause_event='#d95f02'
    seek_from_event='#7570b3'
    seek_to_event='#e7298a'
    change_speed_event='#66a61e'
    morning_time='#C9C96C'
    afternoon_time ='#7F7160'
    night_time ='#50587C'
    # Request data
    course_key = get_course_key(course_id)
    course = get_course_module(course_key)
    #course2= get_course_by_id(SlashSeparatedCourseKey.from_deprecated_string(course_id))
    #user = request.user #Codigo Jose A. Gascon
    staff_access = has_access(request.user, 'staff', course).has_access#Codigo Jose A. Gascon
    instructor_access = has_access(request.user, 'instructor', course).has_access#Codigo Jose A. Gascon
    #Codigo Jose A. Gascon
    masq, user = setup_masquerade(request, course_key,staff_access, reset_masquerade_data=True)  # allow staff to toggle masquerade on info page
    user = request.user
    studio_url = get_studio_url(course, 'course_info')
    
    #reverifications = fetch_reverify_banner_info(request, course_key)
    
    #course = get_course_with_access(request.user, action='load', course_key=course_key, depth=None, check_if_enrolled=False)
    #user = User.objects.get(request.user.email)
    # Proficiency and pass limit
    pass_limit = get_course_grade_cutoff(course)
    proficiency_limit = (1 - pass_limit) / 2 + pass_limit
    usernames_in = []
    for student in CourseEnrollment.objects.users_enrolled_in(course_key):#Codigo Jose A. Gascon, se cambia la forma de llamar al metode users_enrolled_in
        usernames_in.append(student.username.encode('utf-8'))


    # Data for visualization in JSON
    user_for_charts = '#average' if (staff_access or instructor_access) else user
    kwargs = {
        'qualifiers': {'category': 'video', },
    }     
    # This returns video descriptors in the order they appear on the course
    video_descriptors = videos_problems_in(course)[0]
    #WARNINIG 
    #video_durations = get_info_videos_descriptors(video_descriptors)[2]
    #video_names, video_module_keys, video_durations = get_info_videos_descriptors(video_descriptors) # NO SE USAN LAS OTRAS VARIABLES
    video_names, video_module_keys, video_durations =get_DB_infovideos()
    video_names_sorted = video_names
    video_ids_sort = video_names_sorted

    #course_name = get_course_by_id(course_key, depth=None)
    names_students=[]
    only_students = []
    students_names = get_course_students(course_key)
    print students_names
    for student in students_names:
        staff_access_user = has_access(student, 'staff', course).has_access
        instructor_access_user = has_access(student, 'instructor', course).has_access
        if not (staff_access_user or instructor_access_user):
            names_students.append(student.username.encode('utf-8'))
            only_students.append(student)

    video_ids_str = []
    course_video_names = []
    problem_ids_str=[]
    for descriptor in video_descriptors:
        video_ids_str.append((course_key.make_usage_key('video', descriptor.location.name))._to_string())
        course_video_names.append(descriptor.display_name_with_default)
    if len(video_descriptors) > 0:
        first_video_id = course_key.make_usage_key('video', video_descriptors[0].location.name)
        # Video progress visualization. Video percentage seen total and non-overlapped.
        video_names, avg_video_time, video_percentages = get_video_time_watched(user_for_charts, course_key)  
        if avg_video_time != []:
            all_video_time_percent = map(truediv, avg_video_time, video_durations)
            all_video_time_percent = [int(round(x*100,0)) for x in all_video_time_percent]
        else:
            all_video_time_percent = avg_video_time


        column_headers = ['Video', 'Different video time', 'Total video time']
        # Codigo Javier Orcoyen
        video_prog_json = ready_for_arraytodatatable(column_headers, video_names, video_percentages, all_video_time_percent)
        video_names, all_video_time = get_module_consumption(user_for_charts, course_key, 'video')
        # Time spent on every video resource
        column_headers = ['Video', 'Time watched']
        video_distrib_json = ready_for_arraytodatatable(column_headers, video_names, all_video_time)
  
        # Video events dispersion within video length
        scatter_array = get_video_events_info(user_for_charts, first_video_id)    
  
        # Repetitions per video intervals
        user_for_vid_intervals = '#class_total_times' if user_for_charts == '#average' else user_for_charts
        video_intervals_array = get_user_video_intervals(user_for_vid_intervals, first_video_id)        

    # Case no videos in course
    else:
        video_names = None
        video_prog_json = json.dumps(None)
        video_distrib_json = json.dumps(None)
        scatter_array = json.dumps(None)
        video_intervals_array = json.dumps(None)
          
    # Time spent on every problem resource
    # Codigo Javier Orcoyen
    problem_names, time_x_problem = get_module_consumption(user_for_charts, course_key, 'problem')
    column_headers = ['Problem', 'Time on problem']
    problem_distrib_json = ready_for_arraytodatatable(column_headers, problem_names, time_x_problem)
    print 'USER'
    print user
    problems_in = videos_problems_in(course)[1]
    problem_names_sorted = [x.display_name_with_default.encode('utf-8') for x in problems_in]
    orden=[]
    orden.append(i for i, x in enumerate(problem_names_sorted))
    problem_ids_str=problem_names_sorted
    # Daily time spent on video and/or problem resources
    video_days, video_daily_time = get_daily_consumption(user_for_charts, course_key, 'video')
    problem_days, problem_daily_time = get_daily_consumption(user_for_charts, course_key, 'problem')    
    vid_and_prob_daily_time = join_video_problem_time(video_days, video_daily_time, problem_days, problem_daily_time) 
    #Analytics visualizations
    if staff_access or instructor_access:
        # Instructor access
        std_sort = get_DB_sort_course_homework(course_key)
        # Chapter time
        cs, st = get_DB_course_spent_time(course_key, student_id=ALL_STUDENTS)
        students_spent_time = chapter_time_to_js(cs, st)
        students_grades = get_DB_student_grades(course_key, student_id=ALL_STUDENTS) 
        cs, sa = course_accesses = get_DB_course_section_accesses(course_key, student_id=ALL_STUDENTS)
        students_course_accesses = course_accesses_to_js(cs, sa)
        #students_prob_vid_progress = get_DB_course_video_problem_progress(course_key, student_id=ALL_STUDENTS)# C. J. A. Gascon ERROR
        students_time_schedule = get_DB_time_schedule(course_key, student_id=ALL_STUDENTS)
    else:
        # Sort homework                    
        # Chapter time
        std_sort = None
        cs, st = get_DB_course_spent_time(course_key, user.id)
        students_spent_time = chapter_time_to_js(cs, st) 
        students_grades = get_DB_student_grades(course_key, user.id) 
        cs, sa = course_accesses = get_DB_course_section_accesses(course_key, user.id)
        students_course_accesses = course_accesses_to_js(cs, sa) 
        students_time_schedule = get_DB_time_schedule(course_key, user.id)  
        #students_prob_vid_progress = get_DB_course_video_problem_progress(course_key, user.id)  #C. J. A. Gascon ERROR

    context = {'course': course,
               'request': request,
               'user': user,
               'user_id': user.id,
               'staff_access': staff_access,
               'instructor_access': instructor_access,
               'masquerade': masq,
               'studio_url': studio_url,
               #'reverifications': reverifications,
               'course_id': course_id,
               'students': students_to_js(only_students),
               'visualizations_id': VISUALIZATIONS_ID,
               'std_grades_dump': dumps(students_grades),
               'sort_std_dump': dumps(std_sort),
               'time_dump': dumps(students_spent_time),
               'accesses_dump': dumps(students_course_accesses),
               'std_time_schedule_dumb': dumps(students_time_schedule), 
               #'vid_prob_prog_dump': dumps(students_prob_vid_progress), #C. J. A. Gascon ERROR
               'pass_limit': pass_limit,
               'prof_limit': proficiency_limit,
               'usernames_in' : usernames_in,
               'video_names' : course_video_names,
               'video_ids' : video_ids_str,
               'video_prog_json' : video_prog_json,
               'video_distrib_json' : video_distrib_json,
               'problem_distrib_json' : problem_distrib_json,
               'video_intervals_array' : video_intervals_array,
               'vid_and_prob_daily_time' : vid_and_prob_daily_time,
               'scatter_array' : scatter_array,
               'problem_names' : problem_names,
               'problem_ids' : problem_ids_str,
               'color_not' : color_not,
               'color_ok' : color_ok,
               'color_prof' : color_prof,
               'color_fail' : color_fail,
               'problem_activity' : problem_activity,
               'video_activity' : video_activity,
               'course_activity' : course_activity,
               'video_repetition' : video_repetition,
               'graded_time' : graded_time,
               'ungraded_time' : ungraded_time,
               'chapter_time' : chapter_time,
               'user_for_charts' : user_for_charts,
               'video_ids_sort' : video_ids_sort,
               'video_names_sorted' : video_names_sorted,
               'problem_names_sorted' : problem_names_sorted,
               'play_event' : play_event,
               'pause_event' : pause_event,
               'seek_from_event' : seek_from_event,
               'seek_to_event' : seek_to_event,
               'change_speed_event' : change_speed_event,
               'morning_time' : morning_time,
               'afternoon_time' : afternoon_time,
               'night_time' : night_time,
               'names_students' : names_students,}
        
    return render_to_response('learning_analytics/learning_analytics.html', context)